From e80be76d14960524ee0e9e1cf3b90e9121b07241 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 17 Dec 2025 17:27:41 +0100 Subject: [PATCH 1/5] [WIP] tree: get global context from handle The transport handle always contains the global context, thus there is no need to walk the tree to access the host. TODO: the handle might not be present because during discovering we don't have a transport handle yet. Thus we should have a global context pointer per object? Signed-off-by: Daniel Wagner --- libnvme/src/nvme/private.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index 6b2a864805..b213fd1754 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -424,10 +424,8 @@ __nvme_msg(struct nvme_global_ctx *ctx, int level, const char *func, const char #define nvme_msg(ctx, level, format, ...) \ __nvme_msg(ctx, level, __nvme_log_func, format, ##__VA_ARGS__) -#define ctx_from_ctrl(c) ((c)->s && (c)->s->h ? (c)->s->h->ctx : NULL) -#define ctx_from_ns(n) ((n)->s && (n)->s->h ? (n)->s->h->ctx : \ - (n)->c && (n)->c->s && (n)->c->s->h ? (n)->c->s->h->ctx : \ - NULL) +#define ctx_from_ctrl(c) ((c)->hdl->ctx) +#define ctx_from_ns(n) ((n)->hdl->ctx) /* mi internal headers */ From c6bc204e60a29ae767a9f32c4d36c30cff4b222a Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 17 Dec 2025 19:16:27 +0100 Subject: [PATCH 2/5] [WIP] fabrics: do not allocate new host in lookup function It is very surprising for casual readers that the lookup function always returns a new host object. It also has the potential to hide problems. Let's split the functionality into two functions a nvme_create_host and a nvme_lookup_host. TODO: lookup ctrl too Signed-off-by: Daniel Wagner --- libnvme/src/libnvme.map | 1 + libnvme/src/nvme/fabrics.c | 28 +++++++++++++-------- libnvme/src/nvme/tree.c | 51 ++++++++++++++++++++++++++------------ libnvme/src/nvme/tree.h | 16 ++++++++++-- 4 files changed, 68 insertions(+), 28 deletions(-) diff --git a/libnvme/src/libnvme.map b/libnvme/src/libnvme.map index 4054de184f..96b869008e 100644 --- a/libnvme/src/libnvme.map +++ b/libnvme/src/libnvme.map @@ -16,6 +16,7 @@ LIBNVME_2_0 { nvme_close; nvme_create_ctrl; nvme_create_global_ctx; + nvme_create_host; nvme_ctrl_config_match; nvme_ctrl_find; nvme_ctrl_first_ns; diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index 6e8393a529..96d58c3479 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -2045,7 +2045,7 @@ static nvme_ctrl_t lookup_ctrl(nvme_host_t h, struct fabric_args *trcfg) return NULL; } -static int lookup_host(struct nvme_global_ctx *ctx, +static int lookup_or_create_host(struct nvme_global_ctx *ctx, struct nvmf_context *fctx, struct nvme_host **host) { _cleanup_free_ char *hnqn = NULL; @@ -2058,9 +2058,14 @@ static int lookup_host(struct nvme_global_ctx *ctx, return err; h = nvme_lookup_host(ctx, hnqn, hid); - if (!h) + if (h) + goto out; + + err = nvme_create_host(ctx, fctx->hostnqn, fctx->hostid, &h); + if (err) return -ENOMEM; +out: *host = h; return 0; @@ -2437,7 +2442,7 @@ int nvmf_discovery_config_json(struct nvme_global_ctx *ctx, struct nvme_ctrl *c; int ret = 0, err; - err = lookup_host(ctx, fctx, &h); + err = lookup_or_create_host(ctx, fctx, &h); if (err) return err; @@ -2486,7 +2491,7 @@ int nvmf_connect_config_json(struct nvme_global_ctx *ctx, nvme_ctrl_t c, _c; int ret = 0, err; - err = lookup_host(ctx, fctx, &h); + err = lookup_or_create_host(ctx, fctx, &h); if (err) return err; @@ -2542,7 +2547,7 @@ int nvmf_discovery_config_file(struct nvme_global_ctx *ctx, struct nvme_ctrl *c; int err; - err = lookup_host(ctx, fctx, &h); + err = lookup_or_create_host(ctx, fctx, &h); if (err) return err; @@ -2856,7 +2861,7 @@ int nvmf_discovery_nbft(struct nvme_global_ctx *ctx, struct nvme_host *h; int ret, rr, i; - ret = lookup_host(ctx, fctx, &h); + ret = lookup_or_create_host(ctx, fctx, &h); if (ret) return ret; @@ -2899,8 +2904,11 @@ int nvmf_discovery_nbft(struct nvme_global_ctx *ctx, h = nvme_lookup_host(ctx, hostnqn, hostid); if (!h) { - ret = -ENOENT; - goto out_free; + ret = nvme_create_host(ctx, hostnqn, hostid, &h); + if (ret) { + ret = -ENOENT; + goto out_free; + } } /* Subsystem Namespace Descriptor List */ @@ -3154,7 +3162,7 @@ int nvmf_discovery(struct nvme_global_ctx *ctx, struct nvmf_context *fctx, struct nvme_host *h; int ret; - ret = lookup_host(ctx, fctx, &h); + ret = lookup_or_create_host(ctx, fctx, &h); if (ret) return ret; @@ -3289,7 +3297,7 @@ int nvmf_connect(struct nvme_global_ctx *ctx, struct nvmf_context *fctx) struct nvme_ctrl *c; int err; - err = lookup_host(ctx, fctx, &h); + err = lookup_or_create_host(ctx, fctx, &h); if (err) return err; diff --git a/libnvme/src/nvme/tree.c b/libnvme/src/nvme/tree.c index 2fdde49ee2..e013675fc9 100644 --- a/libnvme/src/nvme/tree.c +++ b/libnvme/src/nvme/tree.c @@ -196,7 +196,7 @@ int nvme_host_get_ids(struct nvme_global_ctx *ctx, return 0; } -int nvme_default_host(struct nvme_global_ctx *ctx, nvme_host_t *hp) +int nvme_default_host(struct nvme_global_ctx *ctx, struct nvme_host **host) { _cleanup_free_ char *hostnqn = NULL; _cleanup_free_ char *hostid = NULL; @@ -208,11 +208,16 @@ int nvme_default_host(struct nvme_global_ctx *ctx, nvme_host_t *hp) return err; h = nvme_lookup_host(ctx, hostnqn, hostid); + if (!h) { + err = nvme_create_host(ctx, hostnqn, hostid, &h); + if (err) + return err; + } nvme_host_set_hostsymname(h, NULL); default_host = h; - *hp = h; + *host = h; return 0; } @@ -774,34 +779,48 @@ void nvme_free_host(struct nvme_host *h) __nvme_free_host(h); } -struct nvme_host *nvme_lookup_host(struct nvme_global_ctx *ctx, const char *hostnqn, - const char *hostid) +int nvme_create_host(struct nvme_global_ctx *ctx, const char *hostnqn, + const char *hostid, struct nvme_host **host) { struct nvme_host *h; - if (!hostnqn) - return NULL; - nvme_for_each_host(ctx, h) { - if (strcmp(h->hostnqn, hostnqn)) - continue; - if (hostid && (!h->hostid || - strcmp(h->hostid, hostid))) - continue; - return h; - } h = calloc(1,sizeof(*h)); if (!h) - return NULL; + return -ENOMEM; + h->hostnqn = strdup(hostnqn); if (hostid) h->hostid = strdup(hostid); + list_head_init(&h->subsystems); list_node_init(&h->entry); + h->ctx = ctx; list_add_tail(&ctx->hosts, &h->entry); ctx->modified = true; - return h; + *host = h; + + return 0; +} + +struct nvme_host *nvme_lookup_host(struct nvme_global_ctx *ctx, + const char *hostnqn, const char *hostid) +{ + struct nvme_host *h; + + if (!hostnqn) + return NULL; + nvme_for_each_host(ctx, h) { + if (strcmp(h->hostnqn, hostnqn)) + continue; + if (hostid && (!h->hostid || + strcmp(h->hostid, hostid))) + continue; + return h; + } + + return NULL; } static int nvme_subsystem_scan_namespaces(struct nvme_global_ctx *ctx, nvme_subsystem_t s) diff --git a/libnvme/src/nvme/tree.h b/libnvme/src/nvme/tree.h index 541f1c5601..ca6bcd7be0 100644 --- a/libnvme/src/nvme/tree.h +++ b/libnvme/src/nvme/tree.h @@ -96,14 +96,26 @@ nvme_host_t nvme_next_host(struct nvme_global_ctx *ctx, nvme_host_t h); */ struct nvme_global_ctx *nvme_host_get_global_ctx(nvme_host_t h); +/** + * nvme_create_host() - Lookup nvme_host_t object + * @ctx: struct nvme_global_ctx object + * @hostnqn: Host NQN + * @hostid: Host ID + * @host: Newly allocated host object + * + * Create nvme_host_t object based on @hostnqn and @hostid. + * + * Return: 0 on success or negative error code otherwise + */ +int nvme_create_host(struct nvme_global_ctx *ctx, const char *hostnqn, + const char *hostid, struct nvme_host **host); /** * nvme_lookup_host() - Lookup nvme_host_t object * @ctx: struct nvme_global_ctx object * @hostnqn: Host NQN * @hostid: Host ID * - * Lookup a nvme_host_t object based on @hostnqn and @hostid - * or create one if not found. + * Lookup a nvme_host_t object based on @hostnqn and @hostid. * * Return: &nvme_host_t object */ From 2485c4998180c912f352e1fe40fef20ca48d2116 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 17 Dec 2025 15:56:02 +0100 Subject: [PATCH 3/5] log: remove deprecated default global context functions The global context has been introduced throughout the library thus we don't need the fallback default global context anymore. Signed-off-by: Daniel Wagner --- libnvme/src/libnvme.map | 4 --- libnvme/src/nvme/log.c | 61 +++++--------------------------------- libnvme/src/nvme/log.h | 43 ++++----------------------- nvme.c | 1 - plugins/nbft/nbft-plugin.c | 1 - 5 files changed, 14 insertions(+), 96 deletions(-) diff --git a/libnvme/src/libnvme.map b/libnvme/src/libnvme.map index 96b869008e..7ae8d2551a 100644 --- a/libnvme/src/libnvme.map +++ b/libnvme/src/libnvme.map @@ -91,12 +91,10 @@ LIBNVME_2_0 { nvme_get_attr; nvme_get_ctrl_attr; nvme_get_ctrl_telemetry; - nvme_get_debug; nvme_get_directive_receive_length; nvme_get_feature_length; nvme_get_host_telemetry; nvme_get_log; - nvme_get_logging_level; nvme_get_logical_block_size; nvme_get_new_host_telemetry; nvme_get_ns_attr; @@ -126,7 +124,6 @@ LIBNVME_2_0 { nvme_init_copy_range_f3; nvme_init_ctrl; nvme_init_ctrl_list; - nvme_init_default_logging; nvme_init_dsm_range; nvme_init_logging; nvme_insert_tls_key; @@ -240,7 +237,6 @@ LIBNVME_2_0 { nvme_scan_tls_keys; nvme_scan_topology; nvme_set_application; - nvme_set_debug; nvme_set_dry_run; nvme_set_keyring; nvme_set_property; diff --git a/libnvme/src/nvme/log.c b/libnvme/src/nvme/log.c index 3cec7c2727..3bb3e93775 100644 --- a/libnvme/src/nvme/log.c +++ b/libnvme/src/nvme/log.c @@ -10,13 +10,11 @@ #include #include -#include #include #include #include #include #include -#include #define LOG_FUNCNAME 1 #include "private.h" #include "log.h" @@ -26,18 +24,11 @@ #define LOG_CLOCK CLOCK_MONOTONIC #endif -static struct nvme_log def_log = { - .fd = STDERR_FILENO, - .level = DEFAULT_LOGLEVEL, - .pid = false, - .timestamp = false, -}; - void __attribute__((format(printf, 4, 5))) __nvme_msg(struct nvme_global_ctx *ctx, int level, const char *func, const char *format, ...) { - struct nvme_log *l; + struct nvme_log *l = &ctx->log; va_list ap; char pidbuf[16]; char timebuf[32]; @@ -55,11 +46,6 @@ __nvme_msg(struct nvme_global_ctx *ctx, int level, _cleanup_free_ char *message = NULL; int idx = 0; - if (ctx) - l = &ctx->log; - else - l = &def_log; - if (level > l->level) return; @@ -96,51 +82,20 @@ __nvme_msg(struct nvme_global_ctx *ctx, int level, message ? message : ""); } -void nvme_init_logging(struct nvme_global_ctx *ctx, int lvl, bool log_pid, bool log_tstamp) +void nvme_init_logging(struct nvme_global_ctx *ctx, int lvl, + bool log_pid, bool log_tstamp) { ctx->log.level = lvl; ctx->log.pid = log_pid; ctx->log.timestamp = log_tstamp; } -int nvme_get_logging_level(struct nvme_global_ctx *ctx, bool *log_pid, bool *log_tstamp) +int nvme_get_logging_level(struct nvme_global_ctx *ctx, + bool *log_pid, bool *log_tstamp) { - struct nvme_log *l; - - if (ctx) - l = &ctx->log; - else - l = &def_log; - if (log_pid) - *log_pid = l->pid; + *log_pid = ctx->log.pid; if (log_tstamp) - *log_tstamp = l->timestamp; - return l->level; -} - -void nvme_init_default_logging(FILE *fp, int level, bool log_pid, bool log_tstamp) -{ - def_log.fd = fileno(fp); - def_log.level = level; - def_log.pid = log_pid; - def_log.timestamp = log_tstamp; -} - -void nvme_set_global_ctx(struct nvme_global_ctx *ctx) -{ - def_log.fd = ctx->log.fd; - def_log.level = ctx->log.level; - def_log.pid = ctx->log.pid; - def_log.timestamp = ctx->log.timestamp; -} - -void nvme_set_debug(bool debug) -{ - def_log.level = debug ? LOG_DEBUG : DEFAULT_LOGLEVEL; -} - -bool nvme_get_debug(void) -{ - return def_log.level == LOG_DEBUG; + *log_tstamp = ctx->log.timestamp; + return ctx->log.level; } diff --git a/libnvme/src/nvme/log.h b/libnvme/src/nvme/log.h index 7f3b8c11fb..bfeb749d59 100644 --- a/libnvme/src/nvme/log.h +++ b/libnvme/src/nvme/log.h @@ -33,7 +33,8 @@ * * Sets the default logging variables for the library. */ -void nvme_init_logging(struct nvme_global_ctx *ctx, int lvl, bool log_pid, bool log_tstamp); +void nvme_init_logging(struct nvme_global_ctx *ctx, int lvl, + bool log_pid, bool log_tstamp); /** * nvme_init_default_logging() - Initialize default (fallback) logging @@ -45,7 +46,8 @@ void nvme_init_logging(struct nvme_global_ctx *ctx, int lvl, bool log_pid, bool * Sets the default logging settings for the library in case the root object * is absent. */ -void nvme_init_default_logging(FILE *fp, int lvl, bool log_pid, bool log_tstamp); +void nvme_init_default_logging(FILE *fp, int lvl, bool log_pid, + bool log_tstamp); /** * nvme_get_logging_level() - Get current logging level @@ -59,40 +61,7 @@ void nvme_init_default_logging(FILE *fp, int lvl, bool log_pid, bool log_tstamp) * * Return: current log level value or DEFAULT_LOGLEVEL if not initialized. */ -int nvme_get_logging_level(struct nvme_global_ctx *ctx, bool *log_pid, bool *log_tstamp); - -/** - * nvme_set_global_ctx() - Set global context - * @ctx: struct nvme_global_ctx object - * - * In order to be able to log from code paths where no global context - * object is passed in via the arguments use the the default one which - * can be set via this call. When creating a new global context object - * with @nvme_create_global_ctx the global context object will be set as - * well. This means the global context object is always pointing to the - * latest created global context object. Note the first - * @nvme_free_global_ctx call will reset the global context object. - * - * This function is deprecated. Use nvme_init_default_logging or/and - * nvme_init_logging instead. - */ -void nvme_set_global_ctx(struct nvme_global_ctx *ctx) __attribute__((deprecated)); - -/** - * nvme_set_debug - Set NVMe command debugging output - * @debug: true to enable or false to disable - * - * This function is deprecated. Use nvme_init_default_logging instead. - */ -void nvme_set_debug(bool debug) __attribute__((deprecated)); - -/** - * nvme_get_debug - Get NVMe command debugging output - * - * This function is deprecated. Use nvme_get_logging_level instead. - * - * Return: false if disabled or true if enabled. - */ -bool nvme_get_debug(void) __attribute__((deprecated)); +int nvme_get_logging_level(struct nvme_global_ctx *ctx, bool *log_pid, + bool *log_tstamp); #endif /* _LOG_H */ diff --git a/nvme.c b/nvme.c index 58849c5cb8..3c8c9f4a16 100644 --- a/nvme.c +++ b/nvme.c @@ -372,7 +372,6 @@ static int parse_args(int argc, char *argv[], const char *desc, return ret; log_level = map_log_level(nvme_cfg.verbose, false); - nvme_init_default_logging(stderr, log_level, false, false); return 0; } diff --git a/plugins/nbft/nbft-plugin.c b/plugins/nbft/nbft-plugin.c index 1770bd7607..e8545f6833 100644 --- a/plugins/nbft/nbft-plugin.c +++ b/plugins/nbft/nbft-plugin.c @@ -558,7 +558,6 @@ int show_nbft(int argc, char **argv, struct command *acmd, struct plugin *plugin return ret; log_level = map_log_level(verbose, false /* quiet */); - nvme_init_default_logging(stderr, log_level, false, false); ret = validate_output_format(format, &flags); if (ret < 0) From 9f3b05e1cfdeb6bd6847badec99c2d52c10c10d1 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 17 Dec 2025 15:47:39 +0100 Subject: [PATCH 4/5] linux: add global context as first argument to crypto API Add the global context to the crypto related API. This allows to issue warnings/errors via the global context. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/fabrics.c | 3 +- libnvme/src/nvme/linux.c | 268 ++++++++++++++++++--------------- libnvme/src/nvme/linux.h | 130 +++++++++------- libnvme/src/nvme/private.h | 2 +- libnvme/test/config/psk-json.c | 8 +- libnvme/test/psk.c | 62 +++++--- nvme.c | 131 ++++++++++------ 7 files changed, 349 insertions(+), 255 deletions(-) diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index 96d58c3479..8211053210 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -732,7 +732,8 @@ static int build_options(nvme_host_t h, nvme_ctrl_t c, char **argstr) ctrlkey = nvme_ctrl_get_dhchap_key(c); if (cfg->tls) { - ret = __nvme_import_keys_from_config(h, c, &keyring_id, &key_id); + ret = __nvme_import_keys_from_config(h, c, + &keyring_id, &key_id); if (ret) return ret; diff --git a/libnvme/src/nvme/linux.c b/libnvme/src/nvme/linux.c index 8149e21bf4..3ed695a48c 100644 --- a/libnvme/src/nvme/linux.c +++ b/libnvme/src/nvme/linux.c @@ -1143,9 +1143,10 @@ static DEFINE_CLEANUP_FUNC(cleanup_evp_mac_ctx, EVP_MAC_CTX *, EVP_MAC_CTX_free) static DEFINE_CLEANUP_FUNC(cleanup_evp_mac, EVP_MAC *, EVP_MAC_free) #define _cleanup_evp_mac_ __cleanup__(cleanup_evp_mac) -int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac, - unsigned int key_len, unsigned char *secret, - unsigned char *key) +int nvme_gen_dhchap_key(struct nvme_global_ctx *ctx, + char *hostnqn, enum nvme_hmac_alg hmac, + unsigned int key_len, unsigned char *secret, + unsigned char *key) { const char hmac_seed[] = "NVMe-over-Fabrics"; _cleanup_ossl_lib_ctx_ OSSL_LIB_CTX *lib_ctx = NULL; @@ -1388,10 +1389,11 @@ static ssize_t nvme_identity_len(int hmac, int version, const char *hostnqn, return len; } -int nvme_generate_tls_key_identity(const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len, - char **ident) +int nvme_generate_tls_key_identity(struct nvme_global_ctx *ctx, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + char **ident) { _cleanup_free_ unsigned char *psk = NULL; _cleanup_free_ char *identity = NULL; @@ -1425,10 +1427,10 @@ int nvme_generate_tls_key_identity(const char *hostnqn, const char *subsysnqn, return 0; } -int nvme_generate_tls_key_identity_compat(const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len, - char **ident) +int nvme_generate_tls_key_identity_compat(struct nvme_global_ctx *ctx, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, unsigned char *configured_key, + int key_len, char **ident) { _cleanup_free_ unsigned char *psk = NULL; _cleanup_free_ char *identity = NULL; @@ -1463,7 +1465,8 @@ int nvme_generate_tls_key_identity_compat(const char *hostnqn, const char *subsy } #ifdef CONFIG_KEYUTILS -int nvme_lookup_keyring(const char *keyring, long *key) +int nvme_lookup_keyring(struct nvme_global_ctx *ctx, const char *keyring, + long *key) { key_serial_t keyring_id; @@ -1477,7 +1480,7 @@ int nvme_lookup_keyring(const char *keyring, long *key) return 0; } -char *nvme_describe_key_serial(long key_id) +char *nvme_describe_key_serial(struct nvme_global_ctx *ctx, long key_id) { _cleanup_free_ char *str = NULL; char *last; @@ -1496,7 +1499,8 @@ char *nvme_describe_key_serial(long key_id) return strdup(last); } -int nvme_lookup_key(const char *type, const char *identity, long *keyp) +int nvme_lookup_key(struct nvme_global_ctx *ctx, const char *type, + const char *identity, long *keyp) { key_serial_t key; @@ -1506,12 +1510,12 @@ int nvme_lookup_key(const char *type, const char *identity, long *keyp) return key; } -int nvme_set_keyring(long key_id) +int nvme_set_keyring(struct nvme_global_ctx *ctx, long key_id) { long err; if (key_id == 0) { - if (nvme_lookup_keyring(NULL, &key_id)) + if (nvme_lookup_keyring(ctx, NULL, &key_id)) return -ENOKEY; } @@ -1521,13 +1525,13 @@ int nvme_set_keyring(long key_id) return 0; } -int nvme_read_key(long keyring_id, long key_id, int *len, - unsigned char **key) +int nvme_read_key(struct nvme_global_ctx *ctx, long keyring_id, + long key_id, int *len, unsigned char **key) { void *buffer; int ret; - ret = nvme_set_keyring(keyring_id); + ret = nvme_set_keyring(ctx, keyring_id); if (ret < 0) return ret; @@ -1540,9 +1544,9 @@ int nvme_read_key(long keyring_id, long key_id, int *len, return 0; } -int nvme_update_key(long keyring_id, const char *key_type, - const char *identity, unsigned char *key_data, - int key_len, long *keyp) +int nvme_update_key(struct nvme_global_ctx *ctx, long keyring_id, + const char *key_type, const char *identity, + unsigned char *key_data, int key_len, long *keyp) { long key; @@ -1561,13 +1565,14 @@ int nvme_update_key(long keyring_id, const char *key_type, } struct __scan_keys_data { + struct nvme_global_ctx *ctx; nvme_scan_tls_keys_cb_t cb; key_serial_t keyring; void *data; }; -int __scan_keys_cb(key_serial_t parent, key_serial_t key, - char *desc, int desc_len, void *data) +int __scan_keys_cb(key_serial_t parent, key_serial_t key, char *desc, + int desc_len, void *data) { struct __scan_keys_data *d = data; int ver, hmac, uid, gid, perm; @@ -1595,28 +1600,29 @@ int __scan_keys_cb(key_serial_t parent, key_serial_t key, if (!ptr) return 0; /* Only use the key description for the callback */ - (d->cb)(d->keyring, key, ptr + 1, strlen(ptr) - 1, d->data); + (d->cb)(d->ctx, d->keyring, key, ptr + 1, strlen(ptr) - 1, d->data); return 1; } -int nvme_scan_tls_keys(const char *keyring, nvme_scan_tls_keys_cb_t cb, - void *data) +int nvme_scan_tls_keys(struct nvme_global_ctx *ctx, const char *keyring, + nvme_scan_tls_keys_cb_t cb, void *data) { struct __scan_keys_data d; long keyring_id; int ret; - ret = nvme_lookup_keyring(keyring, &keyring_id); + ret = nvme_lookup_keyring(ctx, keyring, &keyring_id); if (ret) return ret; if (!keyring_id) return -EINVAL; - ret = nvme_set_keyring(keyring_id); + ret = nvme_set_keyring(ctx, keyring_id); if (ret < 0) return ret; + d.ctx = ctx; d.keyring = keyring_id; d.cb = cb; d.data = data; @@ -1624,11 +1630,11 @@ int nvme_scan_tls_keys(const char *keyring, nvme_scan_tls_keys_cb_t cb, return ret; } -static int __nvme_insert_tls_key(key_serial_t keyring_id, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len, - bool compat, long *keyp) +static int __nvme_insert_tls_key(struct nvme_global_ctx *ctx, + key_serial_t keyring_id, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, unsigned char *configured_key, + int key_len, bool compat, long *keyp) { _cleanup_free_ unsigned char *psk = NULL; _cleanup_free_ char *identity = NULL; @@ -1657,7 +1663,7 @@ static int __nvme_insert_tls_key(key_serial_t keyring_id, const char *key_type, return -ENOKEY; } - ret = nvme_update_key(keyring_id, key_type, identity, + ret = nvme_update_key(ctx, keyring_id, key_type, identity, psk, key_len, &key); if (ret) return ret; @@ -1666,59 +1672,60 @@ static int __nvme_insert_tls_key(key_serial_t keyring_id, const char *key_type, return 0; } -int nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len, - long *key) +int nvme_insert_tls_key_versioned(struct nvme_global_ctx *ctx, + const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + long *key) { long keyring_id; int ret; - ret = nvme_lookup_keyring(keyring, &keyring_id); + ret = nvme_lookup_keyring(ctx, keyring, &keyring_id); if (ret) return ret; - ret = nvme_set_keyring(keyring_id); + ret = nvme_set_keyring(ctx, keyring_id); if (ret < 0) return 0; - return __nvme_insert_tls_key(keyring_id, key_type, - hostnqn, subsysnqn, - version, hmac, - configured_key, key_len, false, key); + return __nvme_insert_tls_key(ctx, keyring_id, key_type, + hostnqn, subsysnqn, version, hmac, + configured_key, key_len, false, key); } -int nvme_insert_tls_key_compat(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len, - long *key) +int nvme_insert_tls_key_compat(struct nvme_global_ctx *ctx, + const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + long *key) { long keyring_id; int ret; - ret = nvme_lookup_keyring(keyring, &keyring_id); + ret = nvme_lookup_keyring(ctx, keyring, &keyring_id); if (ret) return ret; - ret = nvme_set_keyring(keyring_id); + ret = nvme_set_keyring(ctx, keyring_id); if (ret < 0) return 0; - return __nvme_insert_tls_key(keyring_id, key_type, - hostnqn, subsysnqn, - version, hmac, - configured_key, key_len, true, key); + return __nvme_insert_tls_key(ctx, keyring_id, key_type, + hostnqn, subsysnqn, version, hmac, + configured_key, key_len, true, key); } -int nvme_revoke_tls_key(const char *keyring, const char *key_type, - const char *identity) +int nvme_revoke_tls_key(struct nvme_global_ctx *ctx, + const char *keyring, const char *key_type, + const char *identity) { long keyring_id, key; int ret; - ret = nvme_lookup_keyring(keyring, &keyring_id); + ret = nvme_lookup_keyring(ctx, keyring, &keyring_id); if (ret) return ret; @@ -1733,10 +1740,10 @@ int nvme_revoke_tls_key(const char *keyring, const char *key_type, return 0; } -static int __nvme_import_tls_key(long keyring_id, - const char *hostnqn, const char *subsysnqn, - const char *identity, const char *key, - long *keyp) +static int __nvme_import_tls_key(struct nvme_global_ctx *ctx, long keyring_id, + const char *hostnqn, const char *subsysnqn, + const char *identity, const char *key, + long *keyp) { _cleanup_free_ unsigned char *key_data = NULL; unsigned char version; @@ -1744,7 +1751,7 @@ static int __nvme_import_tls_key(long keyring_id, size_t key_len; int ret; - ret = nvme_import_tls_key_versioned(key, &version, + ret = nvme_import_tls_key_versioned(ctx, key, &version, &hmac, &key_len, &key_data); if (ret) return ret; @@ -1756,18 +1763,17 @@ static int __nvme_import_tls_key(long keyring_id, * configured key. Derive a new key and load the newly * created key into the keystore. */ - return __nvme_insert_tls_key(keyring_id, "psk", - hostnqn, subsysnqn, - version, hmac, - key_data, key_len, false, keyp); + return __nvme_insert_tls_key(ctx, keyring_id, "psk", + hostnqn, subsysnqn, version, hmac, + key_data, key_len, false, keyp); } - return nvme_update_key(keyring_id, "psk", identity, + return nvme_update_key(ctx, keyring_id, "psk", identity, key_data, key_len, keyp); } int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, - long *keyring_id, long *key_id) + long *keyring_id, long *key_id) { const char *hostnqn = nvme_host_get_hostnqn(h); const char *subsysnqn = nvme_ctrl_get_subsysnqn(c); @@ -1788,7 +1794,7 @@ int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, keyring = nvme_ctrl_get_keyring(c); if (keyring) { - ret = nvme_lookup_keyring(keyring, &kr_id); + ret = nvme_lookup_keyring(h->ctx, keyring, &kr_id); if (ret) return ret; } else @@ -1800,19 +1806,19 @@ int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, * That means we are explicitly selecting the keyring. */ if (!kr_id) { - ret = nvme_lookup_keyring(".nvme", &kr_id); + ret = nvme_lookup_keyring(h->ctx, ".nvme", &kr_id); if (ret) return ret; } - if (nvme_set_keyring(kr_id) < 0) { + if (nvme_set_keyring(h->ctx, kr_id) < 0) { nvme_msg(h->ctx, LOG_ERR, "Failed to set keyring\n"); return -errno; } identity = nvme_ctrl_get_tls_key_identity(c); if (identity) { - ret = nvme_lookup_key("psk", identity, &id); + ret = nvme_lookup_key(h->ctx, "psk", identity, &id); if (ret) { nvme_msg(h->ctx, LOG_ERR, "Failed to lookup key for identity %s, error %d\n", @@ -1822,7 +1828,7 @@ int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, } if (!id) { - ret = __nvme_import_tls_key(kr_id, hostnqn, + ret = __nvme_import_tls_key(h->ctx, kr_id, hostnqn, subsysnqn, identity, key, &id); if (ret) { nvme_msg(h->ctx, LOG_ERR, @@ -1838,79 +1844,90 @@ int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, return 0; } #else -int nvme_lookup_keyring(const char *keyring, long *key) +int nvme_lookup_keyring(struct nvme_global_ctx *ctx, const char *keyring, + long *key) { - nvme_msg(NULL, LOG_ERR, "key operations not supported; "\ + nvme_msg(ctx, LOG_ERR, "key operations not supported; "\ "recompile with keyutils support.\n"); return -ENOTSUP; } -char *nvme_describe_key_serial(long key_id) +char *nvme_describe_key_serial(struct nvme_global_ctx *ctx, long key_id) { - nvme_msg(NULL, LOG_ERR, "key operations not supported; "\ + nvme_msg(ctx, LOG_ERR, "key operations not supported; "\ "recompile with keyutils support.\n"); return NULL; } -int nvme_lookup_key(const char *type, const char *identity, long *key) +int nvme_lookup_key(struct nvme_global_ctx *ctx, const char *type, + const char *identity, long *key) { - nvme_msg(NULL, LOG_ERR, "key operations not supported; "\ + nvme_msg(ctx, LOG_ERR, "key operations not supported; "\ "recompile with keyutils support.\n"); return -ENOTSUP; } -int nvme_set_keyring(long key_id) +int nvme_set_keyring(struct nvme_global_ctx *ctx, long key_id) { - nvme_msg(NULL, LOG_ERR, "key operations not supported; "\ + nvme_msg(ctx, LOG_ERR, "key operations not supported; "\ "recompile with keyutils support.\n"); return -ENOTSUP; } -int nvme_read_key(long keyring_id, long key_id, int *len, - unsigned char **key) +int nvme_read_key(struct nvme_global_ctx *ctx, long keyring_id, + long key_id, int *len, unsigned char **key) { + nvme_msg(ctx, LOG_ERR, "key operations not supported; "\ + "recompile with keyutils support.\n"); return -ENOTSUP; } -int nvme_update_key(long keyring_id, const char *key_type, - const char *identity, unsigned char *key_data, - int key_len, long *key) +int nvme_update_key(struct nvme_global_ctx *ctx, long keyring_id, + const char *key_type, const char *identity, + unsigned char *key_data, int key_len, long *key) { + nvme_msg(ctx, LOG_ERR, "key operations not supported; "\ + "recompile with keyutils support.\n"); return -ENOTSUP; } -int nvme_scan_tls_keys(const char *keyring, nvme_scan_tls_keys_cb_t cb, - void *data) +int nvme_scan_tls_keys(struct nvme_global_ctx *ctx, const char *keyring, + nvme_scan_tls_keys_cb_t cb, void *data) { + nvme_msg(ctx, LOG_ERR, "key operations not supported; "\ + "recompile with keyutils support.\n"); return -ENOTSUP; } -int nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len, - long *keyp) +int nvme_insert_tls_key_versioned(struct nvme_global_ctx *ctx, + const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + long *keyp) { - nvme_msg(NULL, LOG_ERR, "key operations not supported; " + nvme_msg(ctx, LOG_ERR, "key operations not supported; " "recompile with keyutils support.\n"); return -ENOTSUP; } -int nvme_insert_tls_key_compat(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len, - long *keyp) +int nvme_insert_tls_key_compat(struct nvme_global_ctx *ctx, + const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + long *keyp) { - nvme_msg(NULL, LOG_ERR, "key operations not supported; " + nvme_msg(ctx, LOG_ERR, "key operations not supported; " "recompile with keyutils support.\n"); return -ENOTSUP; } -int nvme_revoke_tls_key(const char *keyring, const char *key_type, - const char *identity) +int nvme_revoke_tls_key(struct nvme_global_ctx *ctx, + const char *keyring, const char *key_type, + const char *identity) { - nvme_msg(NULL, LOG_ERR, "key operations not supported; " + nvme_msg(ctx, LOG_ERR, "key operations not supported; " "recompile with keyutils support.\n"); return -ENOTSUP; } @@ -1925,11 +1942,12 @@ int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, } #endif -int nvme_insert_tls_key(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, int hmac, - unsigned char *configured_key, int key_len, long *key) +int nvme_insert_tls_key(struct nvme_global_ctx *ctx, + const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, int hmac, + unsigned char *configured_key, int key_len, long *key) { - return nvme_insert_tls_key_versioned(keyring, key_type, + return nvme_insert_tls_key_versioned(ctx, keyring, key_type, hostnqn, subsysnqn, 0, hmac, configured_key, key_len, key); } @@ -1946,9 +1964,10 @@ int nvme_insert_tls_key(const char *keyring, const char *key_type, * s: 32 or 48 bytes binary followed by a CRC-32 of the configured PSK * (4 bytes) encoded as base64 */ -int nvme_export_tls_key_versioned(unsigned char version, unsigned char hmac, - const unsigned char *key_data, - size_t key_len, char **encoded_keyp) +int nvme_export_tls_key_versioned(struct nvme_global_ctx *ctx, + unsigned char version, unsigned char hmac, + const unsigned char *key_data, + size_t key_len, char **encoded_keyp) { unsigned int raw_len, encoded_len, len; unsigned long crc = crc32(0L, NULL, 0); @@ -1995,7 +2014,8 @@ int nvme_export_tls_key_versioned(unsigned char version, unsigned char hmac, return 0; } -int nvme_export_tls_key(const unsigned char *key_data, int key_len, char **key) +int nvme_export_tls_key(struct nvme_global_ctx *ctx, + const unsigned char *key_data, int key_len, char **key) { unsigned char hmac; @@ -2004,14 +2024,14 @@ int nvme_export_tls_key(const unsigned char *key_data, int key_len, char **key) else hmac = NVME_HMAC_ALG_SHA2_384; - return nvme_export_tls_key_versioned(1, hmac, key_data, key_len, key); + return nvme_export_tls_key_versioned(ctx, 1, hmac, key_data, + key_len, key); } -int nvme_import_tls_key_versioned(const char *encoded_key, - unsigned char *version, - unsigned char *hmac, - size_t *key_len, - unsigned char **keyp) +int nvme_import_tls_key_versioned(struct nvme_global_ctx *ctx, + const char *encoded_key, unsigned char *version, + unsigned char *hmac, size_t *key_len, + unsigned char **keyp) { unsigned char decoded_key[128], *key_data; unsigned int crc = crc32(0L, NULL, 0); @@ -2062,7 +2082,7 @@ int nvme_import_tls_key_versioned(const char *encoded_key, ((uint32_t)decoded_key[decoded_len + 2] << 16) | ((uint32_t)decoded_key[decoded_len + 3] << 24); if (key_crc != crc) { - nvme_msg(NULL, LOG_ERR, "CRC mismatch (key %08x, crc %08x)", + nvme_msg(ctx, LOG_ERR, "CRC mismatch (key %08x, crc %08x)", key_crc, crc); return -ENOKEY; } @@ -2077,15 +2097,15 @@ int nvme_import_tls_key_versioned(const char *encoded_key, return 0; } -int nvme_import_tls_key(const char *encoded_key, int *key_len, - unsigned int *hmac, unsigned char **keyp) +int nvme_import_tls_key(struct nvme_global_ctx *ctx, const char *encoded_key, + int *key_len, unsigned int *hmac, unsigned char **keyp) { unsigned char version, _hmac; unsigned char *psk; size_t len; int ret; - ret = nvme_import_tls_key_versioned(encoded_key, &version, + ret = nvme_import_tls_key_versioned(ctx, encoded_key, &version, &_hmac, &len, &psk); if (ret) return ret; diff --git a/libnvme/src/nvme/linux.h b/libnvme/src/nvme/linux.h index f136e0a011..45c2e6da07 100644 --- a/libnvme/src/nvme/linux.h +++ b/libnvme/src/nvme/linux.h @@ -227,7 +227,7 @@ int nvme_namespace_detach_ctrls(struct nvme_transport_handle *hdl, __u32 nsid, _ */ int nvme_open(struct nvme_global_ctx *ctx, const char *name, struct nvme_transport_handle **hdl); - + /** * nvme_close() - Close transport handle * @hdl: Transport handle @@ -367,6 +367,7 @@ enum nvme_hmac_alg { /** * nvme_gen_dhchap_key() - DH-HMAC-CHAP key generation + * @ctx: struct nvme_global_ctx object * @hostnqn: Host NVMe Qualified Name * @hmac: HMAC algorithm * @key_len: Output key length @@ -376,12 +377,14 @@ enum nvme_hmac_alg { * Return: If key generation was successful the function returns 0 or * a negative error code otherwise. */ -int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac, - unsigned int key_len, unsigned char *secret, - unsigned char *key); +int nvme_gen_dhchap_key(struct nvme_global_ctx *ctx, + char *hostnqn, enum nvme_hmac_alg hmac, + unsigned int key_len, unsigned char *secret, + unsigned char *key); /** * nvme_lookup_keyring() - Lookup keyring serial number + * @ctx: struct nvme_global_ctx object * @keyring: Keyring name * @key: Key serial number to return * @@ -389,10 +392,12 @@ int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac, * * Return: 0 on success or negative error code otherwise */ -int nvme_lookup_keyring(const char *keyring, long *key); +int nvme_lookup_keyring(struct nvme_global_ctx *ctx, + const char *keyring, long *key); /** * nvme_describe_key_serial() - Return key description + * @ctx: struct nvme_global_ctx object * @key_id: Key serial number * * Fetches the description of the key or keyring identified @@ -401,10 +406,12 @@ int nvme_lookup_keyring(const char *keyring, long *key); * Return: The description of @key_id or NULL on failure. * The returned string needs to be freed by the caller. */ -char *nvme_describe_key_serial(long key_id); +char *nvme_describe_key_serial(struct nvme_global_ctx *ctx, + long key_id); /** * nvme_lookup_key() - Lookup key serial number + * @ctx: struct nvme_global_ctx object * @type: Key type * @identity: Key description * @key: Key serial number to return @@ -414,10 +421,12 @@ char *nvme_describe_key_serial(long key_id); * * Return: 0 on success or negative error code otherwise */ -int nvme_lookup_key(const char *type, const char *identity, long *key); +int nvme_lookup_key(struct nvme_global_ctx *ctx, const char *type, + const char *identity, long *key); /** * nvme_set_keyring() - Link keyring for lookup + * @ctx: struct nvme_global_ctx object * @keyring_id: Keyring id * * Links @keyring_id into the session keyring such that @@ -425,10 +434,11 @@ int nvme_lookup_key(const char *type, const char *identity, long *key); * * Return: 0 on success or negative error code otherwise */ -int nvme_set_keyring(long keyring_id); +int nvme_set_keyring(struct nvme_global_ctx *ctx, long keyring_id); /** * nvme_read_key() - Read key raw data + * @ctx: struct nvme_global_ctx object * @keyring_id: Id of the keyring holding %key_id * @key_id: Key id * @len: Length of the returned data @@ -441,11 +451,12 @@ int nvme_set_keyring(long keyring_id); * * Return: 0 on success or negative error code otherwise */ -int nvme_read_key(long keyring_id, long key_id, int *len, - unsigned char **key); +int nvme_read_key(struct nvme_global_ctx *ctx, long keyring_id, + long key_id, int *len, unsigned char **key); /** * nvme_update_key() - Update key raw data + * @ctx: struct nvme_global_ctx object * @keyring_id: Id of the keyring holding %key_id * @key_type: Type of the key to insert * @identity: Key identity string @@ -460,12 +471,13 @@ int nvme_read_key(long keyring_id, long key_id, int *len, * * Return: 0 on success or negative error code otherwise */ -int nvme_update_key(long keyring_id, const char *key_type, - const char *identity, unsigned char *key_data, - int key_len, long *key); +int nvme_update_key(struct nvme_global_ctx *ctx, long keyring_id, + const char *key_type, const char *identity, + unsigned char *key_data, int key_len, long *key); /** * typedef nvme_scan_tls_keys_cb_t - Callback for iterating TLS keys + * @ctx: struct nvme_global_ctx object * @keyring: Keyring which has been iterated * @key: Key for which the callback has been invoked * @desc: Description of the key @@ -474,11 +486,12 @@ int nvme_update_key(long keyring_id, const char *key_type, * * Called for each TLS PSK in the keyring. */ -typedef void (*nvme_scan_tls_keys_cb_t)(long keyring, long key, - char *desc, int desc_len, void *data); +typedef void (*nvme_scan_tls_keys_cb_t)(struct nvme_global_ctx *ctx, + long keyring, long key, char *desc, int desc_len, void *data); /** * nvme_scan_tls_keys() - Iterate over TLS keys in a keyring + * @ctx: struct nvme_global_ctx object * @keyring: Keyring holding TLS keys * @cb: Callback function * @data: Pointer for data to be passed to @cb @@ -491,11 +504,12 @@ typedef void (*nvme_scan_tls_keys_cb_t)(long keyring, long key, * * Return: Number of keys for which @cb was called, or negative error code */ -int nvme_scan_tls_keys(const char *keyring, nvme_scan_tls_keys_cb_t cb, - void *data); +int nvme_scan_tls_keys(struct nvme_global_ctx *ctx, const char *keyring, + nvme_scan_tls_keys_cb_t cb, void *data); /** * nvme_insert_tls_key() - Derive and insert TLS key + * @ctx: struct nvme_global_ctx object * @keyring: Keyring to use * @key_type: Type of the resulting key * @hostnqn: Host NVMe Qualified Name @@ -510,12 +524,14 @@ int nvme_scan_tls_keys(const char *keyring, nvme_scan_tls_keys_cb_t cb, * * Return: 0 on success or negative error code otherwise */ -int nvme_insert_tls_key(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, int hmac, - unsigned char *configured_key, int key_len, long *key); +int nvme_insert_tls_key(struct nvme_global_ctx *ctx, const char *keyring, + const char *key_type, const char *hostnqn, + const char *subsysnqn, int hmac, unsigned char *configured_key, + int key_len, long *key); /** * nvme_insert_tls_key_versioned() - Derive and insert TLS key + * @ctx: struct nvme_global_ctx object * @keyring: Keyring to use * @key_type: Type of the resulting key * @hostnqn: Host NVMe Qualified Name @@ -532,14 +548,16 @@ int nvme_insert_tls_key(const char *keyring, const char *key_type, * * Return: 0 on success or negative error code otherwise */ -int nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len, - long *key); +int nvme_insert_tls_key_versioned(struct nvme_global_ctx *ctx, + const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + long *key); /** * nvme_insert_tls_key_compat() - Derive and insert TLS key + * @ctx: struct nvme_global_ctx object * @keyring: Keyring to use * @key_type: Type of the resulting key * @hostnqn: Host NVMe Qualified Name @@ -560,14 +578,16 @@ int nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, * Return: The key serial number if the key could be inserted into * the keyring or 0 with errno otherwise. */ -int nvme_insert_tls_key_compat(const char *keyring, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len, - long *key); +int nvme_insert_tls_key_compat(struct nvme_global_ctx *ctx, + const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + long *key); /** * nvme_generate_tls_key_identity() - Generate the TLS key identity + * @ctx: struct nvme_global_ctx object * @hostnqn: Host NVMe Qualified Name * @subsysnqn: Subsystem NVMe Qualified Name * @version: Key version to use @@ -583,13 +603,15 @@ int nvme_insert_tls_key_compat(const char *keyring, const char *key_type, * * Return: 0 on success or negative error code otherwise */ -int nvme_generate_tls_key_identity(const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len, - char **identity); +int nvme_generate_tls_key_identity(struct nvme_global_ctx *ctx, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + char **identity); /** * nvme_generate_tls_key_identity_compat() - Generate the TLS key identity + * @ctx: struct nvme_global_ctx object * @hostnqn: Host NVMe Qualified Name * @subsysnqn: Subsystem NVMe Qualified Name * @version: Key version to use @@ -608,25 +630,26 @@ int nvme_generate_tls_key_identity(const char *hostnqn, const char *subsysnqn, * * Return: 0 on success or negative error code otherwise */ -int nvme_generate_tls_key_identity_compat(const char *hostnqn, - const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, - int key_len, char **identity); +int nvme_generate_tls_key_identity_compat(struct nvme_global_ctx *ctx, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, unsigned char *configured_key, + int key_len, char **identity); /** * nvme_revoke_tls_key() - Revoke TLS key from keyring + * @ctx: struct nvme_global_ctx object * @keyring: Keyring to use * @key_type: Type of the key to revoke * @identity: Key identity string * * Return: 0 on success or negative error code otherwise */ -int nvme_revoke_tls_key(const char *keyring, const char *key_type, - const char *identity); +int nvme_revoke_tls_key(struct nvme_global_ctx *ctx, const char *keyring, + const char *key_type, const char *identity); /** * nvme_export_tls_key() - Export a TLS key + * @ctx: struct nvme_global_ctx object * @key_data: Raw data of the key * @key_len: Length of @key_data * @identity: TLS identity @@ -639,10 +662,12 @@ int nvme_revoke_tls_key(const char *keyring, const char *key_type, * * Return: 0 on success or negative error code otherwise */ -int nvme_export_tls_key(const unsigned char *key_data, int key_len, char **identity); +int nvme_export_tls_key(struct nvme_global_ctx *ctx, + const unsigned char *key_data, int key_len, char **identity); /** * nvme_export_tls_key_versioned() - Export a TLS pre-shared key + * @ctx: struct nvme_global_ctx object * @version: Indicated the representation of the TLS PSK * @hmac: HMAC algorithm used to transfor the configured PSK * in a retained PSK @@ -658,12 +683,14 @@ int nvme_export_tls_key(const unsigned char *key_data, int key_len, char **ident * * Return: 0 on success or negative error code otherwise */ -int nvme_export_tls_key_versioned(unsigned char version, unsigned char hmac, - const unsigned char *key_data, - size_t key_len, char **identity); +int nvme_export_tls_key_versioned(struct nvme_global_ctx *ctx, + unsigned char version, unsigned char hmac, + const unsigned char *key_data, + size_t key_len, char **identity); /** * nvme_import_tls_key() - Import a TLS key + * @ctx: struct nvme_global_ctx object * @encoded_key: TLS key in PSK interchange format * @key_len: Length of the resulting key data * @hmac: HMAC algorithm @@ -676,11 +703,12 @@ int nvme_export_tls_key_versioned(unsigned char version, unsigned char hmac, * * Return: 0 on success or negative error code otherwise */ -int nvme_import_tls_key(const char *encoded_key, int *key_len, - unsigned int *hmac, unsigned char **key); +int nvme_import_tls_key(struct nvme_global_ctx *ctx, const char *encoded_key, + int *key_len, unsigned int *hmac, unsigned char **key); /** * nvme_import_tls_key_versioned() - Import a TLS key + * @ctx: struct nvme_global_ctx object * @encoded_key: TLS key in PSK interchange format * @version: Indicated the representation of the TLS PSK * @hmac: HMAC algorithm used to transfor the configured @@ -695,11 +723,9 @@ int nvme_import_tls_key(const char *encoded_key, int *key_len, * * Return: 0 on success or negative error code otherwise */ -int nvme_import_tls_key_versioned(const char *encoded_key, - unsigned char *version, - unsigned char *hmac, - size_t *key_len, - unsigned char **key); +int nvme_import_tls_key_versioned(struct nvme_global_ctx *ctx, + const char *encoded_key, unsigned char *version, + unsigned char *hmac, size_t *key_len, unsigned char **key); /** * nvme_set_dry_run() - Set global dry run state diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index b213fd1754..3a16f31a78 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -531,7 +531,7 @@ void __nvme_mi_mctp_set_ops(const struct __mi_mctp_socket_ops *newops); #define SECTOR_SHIFT 9 int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, - long *keyring_id, long *key_id); + long *keyring_id, long *key_id); static inline char *xstrdup(const char *s) { diff --git a/libnvme/test/config/psk-json.c b/libnvme/test/config/psk-json.c index 1469dac520..a561705fdd 100644 --- a/libnvme/test/config/psk-json.c +++ b/libnvme/test/config/psk-json.c @@ -13,14 +13,14 @@ #include -static bool import_export_key(nvme_ctrl_t c) +static bool import_export_key(struct nvme_global_ctx *ctx, nvme_ctrl_t c) { unsigned char version, hmac, *key; char *encoded_key; size_t len; int ret; - ret = nvme_import_tls_key_versioned(nvme_ctrl_get_tls_key(c), + ret = nvme_import_tls_key_versioned(ctx, nvme_ctrl_get_tls_key(c), &version, &hmac, &len, &key); if (ret) { printf("ERROR: nvme_import_tls_key_versioned failed with %d\n", @@ -29,7 +29,7 @@ static bool import_export_key(nvme_ctrl_t c) } - ret = nvme_export_tls_key_versioned(version, hmac, key, len, + ret = nvme_export_tls_key_versioned(ctx, version, hmac, key, len, &encoded_key); free(key); if (ret) { @@ -66,7 +66,7 @@ static bool psk_json_test(char *file) nvme_for_each_host(ctx, h) nvme_for_each_subsystem(h, s) nvme_subsystem_for_each_ctrl(s, c) - if (!import_export_key(c)) + if (!import_export_key(ctx, c)) goto out; err = nvme_dump_config(ctx); diff --git a/libnvme/test/psk.c b/libnvme/test/psk.c index 3efa141607..125a7cc9a3 100644 --- a/libnvme/test/psk.c +++ b/libnvme/test/psk.c @@ -137,7 +137,8 @@ static void check_str(const char *exp, const char *res) test_rc = 1; } -static void export_test(struct test_data_psk *test) +static void export_test(struct nvme_global_ctx *ctx, + struct test_data_psk *test) { char *psk; int ret; @@ -150,7 +151,8 @@ static void export_test(struct test_data_psk *test) printf("test nvme_export_tls_key hmac %d %s\n", test->hmac, test->exported_psk); - ret = nvme_export_tls_key(test->configured_psk, test->psk_length, &psk); + ret = nvme_export_tls_key(ctx, test->configured_psk, + test->psk_length, &psk); if (ret) { test_rc = 1; printf("ERROR: nvme_export_tls_key() failed with %d\n", ret); @@ -160,7 +162,8 @@ static void export_test(struct test_data_psk *test) free(psk); } -static void import_test(struct test_data_psk *test) +static void import_test(struct nvme_global_ctx *ctx, + struct test_data_psk *test) { unsigned char *psk; int psk_length; @@ -175,7 +178,8 @@ static void import_test(struct test_data_psk *test) printf("test nvme_import_tls_key hmac %d %s\n", test->hmac, test->exported_psk); - ret = nvme_import_tls_key(test->exported_psk, &psk_length, &hmac, &psk); + ret = nvme_import_tls_key(ctx, test->exported_psk, &psk_length, + &hmac, &psk); if (ret) { test_rc = 1; printf("ERROR: nvme_import_tls_key() failed with %d\n", ret); @@ -202,7 +206,8 @@ static void import_test(struct test_data_psk *test) free(psk); } -static void export_versioned_test(struct test_data_psk *test) +static void export_versioned_test(struct nvme_global_ctx *ctx, + struct test_data_psk *test) { char *psk; int ret; @@ -213,7 +218,7 @@ static void export_versioned_test(struct test_data_psk *test) printf("test nvme_export_tls_key_versioned hmac %d %s\n", test->hmac, test->exported_psk); - ret = nvme_export_tls_key_versioned(test->version, test->hmac, + ret = nvme_export_tls_key_versioned(ctx, test->version, test->hmac, test->configured_psk, test->psk_length, &psk); if (ret) { @@ -228,7 +233,8 @@ static void export_versioned_test(struct test_data_psk *test) free(psk); } -static void import_versioned_test(struct test_data_psk *test) +static void import_versioned_test(struct nvme_global_ctx *ctx, + struct test_data_psk *test) { unsigned char *psk; unsigned char version; @@ -242,7 +248,7 @@ static void import_versioned_test(struct test_data_psk *test) printf("test nvme_import_tls_key_versioned hmac %d %s\n", test->hmac, test->exported_psk); - ret = nvme_import_tls_key_versioned(test->exported_psk, &version, + ret = nvme_import_tls_key_versioned(ctx, test->exported_psk, &version, &hmac, &psk_length, &psk); if (ret) { test_rc = 1; @@ -278,7 +284,8 @@ static void import_versioned_test(struct test_data_psk *test) free(psk); } -static void identity_test(struct test_data_identity *test) +static void identity_test(struct nvme_global_ctx *ctx, + struct test_data_identity *test) { char *id; int ret; @@ -291,10 +298,10 @@ static void identity_test(struct test_data_identity *test) printf("test nvme_generate_tls_key_identity host %s subsys %s hmac %d %s\n", test->hostnqn, test->subsysnqn, test->hmac, test->identity); - ret = nvme_generate_tls_key_identity(test->hostnqn, test->subsysnqn, - test->version, test->hmac, - (unsigned char *)test->configured_psk, - test->psk_length, &id); + ret = nvme_generate_tls_key_identity(ctx, test->hostnqn, + test->subsysnqn, test->version, test->hmac, + (unsigned char *)test->configured_psk, + test->psk_length, &id); if (ret) { if (ret == -ENOTSUP) return; @@ -306,7 +313,8 @@ static void identity_test(struct test_data_identity *test) free(id); } -static void identity_test_compat(struct test_data_identity *test) +static void identity_test_compat(struct nvme_global_ctx *ctx, + struct test_data_identity *test) { char *id; int ret; @@ -319,11 +327,10 @@ static void identity_test_compat(struct test_data_identity *test) printf("test nvme_generate_tls_key_identity_compat host %s subsys %s hmac %d %s\n", test->hostnqn, test->subsysnqn, test->hmac, test->identity); - ret = nvme_generate_tls_key_identity_compat(test->hostnqn, - test->subsysnqn, - test->version, test->hmac, - (unsigned char *)test->configured_psk, - test->psk_length, &id); + ret = nvme_generate_tls_key_identity_compat(ctx, test->hostnqn, + test->subsysnqn, test->version, test->hmac, + (unsigned char *)test->configured_psk, + test->psk_length, &id); if (ret) { if (ret == -ENOTSUP) return; @@ -337,23 +344,28 @@ static void identity_test_compat(struct test_data_identity *test) int main(void) { + struct nvme_global_ctx *ctx = + nvme_create_global_ctx(stdout, DEFAULT_LOGLEVEL); + for (int i = 0; i < ARRAY_SIZE(test_data_psk); i++) - export_test(&test_data_psk[i]); + export_test(ctx, &test_data_psk[i]); for (int i = 0; i < ARRAY_SIZE(test_data_psk); i++) - import_test(&test_data_psk[i]); + import_test(ctx, &test_data_psk[i]); for (int i = 0; i < ARRAY_SIZE(test_data_psk); i++) - export_versioned_test(&test_data_psk[i]); + export_versioned_test(ctx, &test_data_psk[i]); for (int i = 0; i < ARRAY_SIZE(test_data_psk); i++) - import_versioned_test(&test_data_psk[i]); + import_versioned_test(ctx, &test_data_psk[i]); for (int i = 0; i < ARRAY_SIZE(test_data_identity); i++) - identity_test(&test_data_identity[i]); + identity_test(ctx, &test_data_identity[i]); for (int i = 0; i < ARRAY_SIZE(test_data_identity_compat); i++) - identity_test_compat(&test_data_identity_compat[i]); + identity_test_compat(ctx, &test_data_identity_compat[i]); + + nvme_free_global_ctx(ctx); return test_rc ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/nvme.c b/nvme.c index 3c8c9f4a16..2fb2bac0c2 100644 --- a/nvme.c +++ b/nvme.c @@ -9326,6 +9326,7 @@ static int gen_dhchap_key(int argc, char **argv, struct command *acmd, struct pl "HMAC function to use for key transformation (0 = none, 1 = SHA-256, 2 = SHA-384, 3 = SHA-512)."; const char *nqn = "Host NQN to use for key transformation."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; _cleanup_free_ unsigned char *raw_secret = NULL; _cleanup_free_ char *hnqn = NULL; unsigned char key[68]; @@ -9357,6 +9358,12 @@ static int gen_dhchap_key(int argc, char **argv, struct command *acmd, struct pl if (err) return err; + ctx = nvme_create_global_ctx(stderr, log_level); + if (!ctx) { + nvme_show_error("Failed to create global context"); + return -ENOMEM; + } + if (cfg.hmac > 3) { nvme_show_error("Invalid HMAC identifier %u", cfg.hmac); return -EINVAL; @@ -9429,7 +9436,8 @@ static int gen_dhchap_key(int argc, char **argv, struct command *acmd, struct pl } } - err = nvme_gen_dhchap_key(cfg.nqn, cfg.hmac, cfg.key_len, raw_secret, key); + err = nvme_gen_dhchap_key(ctx, cfg.nqn, cfg.hmac, + cfg.key_len, raw_secret, key); if (err) return err; @@ -9535,7 +9543,8 @@ static int check_dhchap_key(int argc, char **argv, struct command *acmd, struct return 0; } -static int append_keyfile(const char *keyring, long id, const char *keyfile) +static int append_keyfile(struct nvme_global_ctx *ctx, const char *keyring, + long id, const char *keyfile) { _cleanup_free_ unsigned char *key_data = NULL; _cleanup_free_ char *exported_key = NULL; @@ -9546,14 +9555,14 @@ static int append_keyfile(const char *keyring, long id, const char *keyfile) long kr_id; char type; - err = nvme_lookup_keyring(keyring, &kr_id); + err = nvme_lookup_keyring(ctx, keyring, &kr_id); if (err) { nvme_show_error("Failed to lookup keyring '%s', %s", keyring, strerror(-err)); return err; } - identity = nvme_describe_key_serial(id); + identity = nvme_describe_key_serial(ctx, id); if (!identity) { nvme_show_error("Failed to get identity info"); return -EINVAL; @@ -9564,14 +9573,14 @@ static int append_keyfile(const char *keyring, long id, const char *keyfile) return -EINVAL; } - err = nvme_read_key(kr_id, id, &key_len, &key_data); + err = nvme_read_key(ctx, kr_id, id, &key_len, &key_data); if (err) { nvme_show_error("Failed to read back derive TLS PSK, %s", strerror(-err)); return err; } - err = nvme_export_tls_key_versioned(ver, hmac, key_data, + err = nvme_export_tls_key_versioned(ctx, ver, hmac, key_data, key_len, &exported_key); if (err) { nvme_show_error("Failed to export key, %s", @@ -9620,6 +9629,7 @@ static int gen_tls_key(int argc, char **argv, struct command *acmd, struct plugi const char *keyfile = "Update key file with the derive TLS PSK."; const char *compat = "Use non-RFC 8446 compliant algorithm for deriving TLS PSK for older implementations"; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; _cleanup_free_ unsigned char *raw_secret = NULL; _cleanup_free_ char *encoded_key = NULL; _cleanup_free_ char *hnqn = NULL; @@ -9693,6 +9703,12 @@ static int gen_tls_key(int argc, char **argv, struct command *acmd, struct plugi if (cfg.hmac == 2) key_len = 48; + ctx = nvme_create_global_ctx(stderr, log_level); + if (!ctx) { + nvme_show_error("Failed to create global context"); + return -ENOMEM; + } + raw_secret = malloc(key_len + 4); if (!raw_secret) return -ENOMEM; @@ -9720,7 +9736,7 @@ static int gen_tls_key(int argc, char **argv, struct command *acmd, struct plugi } } - err = nvme_export_tls_key(raw_secret, key_len, &encoded_key); + err = nvme_export_tls_key(ctx, raw_secret, key_len, &encoded_key); if (err) { nvme_show_error("Failed to export key, %s", strerror(-err)); return err; @@ -9729,15 +9745,15 @@ static int gen_tls_key(int argc, char **argv, struct command *acmd, struct plugi if (cfg.insert) { if (cfg.compat) - err = nvme_insert_tls_key_compat(cfg.keyring, - cfg.keytype, cfg.hostnqn, - cfg.subsysnqn, cfg.version, - cfg.hmac, raw_secret, key_len, &tls_key); + err = nvme_insert_tls_key_compat(ctx, cfg.keyring, + cfg.keytype, cfg.hostnqn, + cfg.subsysnqn, cfg.version, + cfg.hmac, raw_secret, key_len, &tls_key); else - err = nvme_insert_tls_key_versioned(cfg.keyring, - cfg.keytype, cfg.hostnqn, - cfg.subsysnqn, cfg.version, - cfg.hmac, raw_secret, key_len, &tls_key); + err = nvme_insert_tls_key_versioned(ctx, cfg.keyring, + cfg.keytype, cfg.hostnqn, + cfg.subsysnqn, cfg.version, + cfg.hmac, raw_secret, key_len, &tls_key); if (err) { nvme_show_error("Failed to insert key, error %d", err); return err; @@ -9746,7 +9762,8 @@ static int gen_tls_key(int argc, char **argv, struct command *acmd, struct plugi printf("Inserted TLS key %08x\n", (unsigned int)tls_key); if (cfg.keyfile) { - err = append_keyfile(cfg.keyring, tls_key, cfg.keyfile); + err = append_keyfile(ctx, cfg.keyring, + tls_key, cfg.keyfile); if (err) return err; } @@ -9768,6 +9785,7 @@ static int check_tls_key(int argc, char **argv, struct command *acmd, struct plu const char *keyfile = "Update key file with the derive TLS PSK."; const char *compat = "Use non-RFC 8446 compliant algorithm for checking TLS PSK for older implementations."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; _cleanup_free_ unsigned char *decoded_key = NULL; _cleanup_free_ char *hnqn = NULL; int decoded_len, err = 0; @@ -9822,7 +9840,14 @@ static int check_tls_key(int argc, char **argv, struct command *acmd, struct plu return -EINVAL; } - err = nvme_import_tls_key(cfg.keydata, &decoded_len, &hmac, &decoded_key); + ctx = nvme_create_global_ctx(stderr, log_level); + if (!ctx) { + nvme_show_error("Failed to create global context"); + return -ENOMEM; + } + + err = nvme_import_tls_key(ctx, cfg.keydata, &decoded_len, + &hmac, &decoded_key); if (err) { nvme_show_error("Key decoding failed, error %d\n", err); return err; @@ -9843,17 +9868,17 @@ static int check_tls_key(int argc, char **argv, struct command *acmd, struct plu if (cfg.insert) { if (cfg.compat) - err = nvme_insert_tls_key_compat(cfg.keyring, - cfg.keytype, cfg.hostnqn, - cfg.subsysnqn, cfg.identity, - hmac, decoded_key, decoded_len, - &tls_key); + err = nvme_insert_tls_key_compat(ctx, cfg.keyring, + cfg.keytype, cfg.hostnqn, + cfg.subsysnqn, cfg.identity, + hmac, decoded_key, decoded_len, + &tls_key); else - err = nvme_insert_tls_key_versioned(cfg.keyring, - cfg.keytype, cfg.hostnqn, - cfg.subsysnqn, cfg.identity, - hmac, decoded_key, decoded_len, - &tls_key); + err = nvme_insert_tls_key_versioned(ctx, cfg.keyring, + cfg.keytype, cfg.hostnqn, + cfg.subsysnqn, cfg.identity, + hmac, decoded_key, decoded_len, + &tls_key); if (err) { nvme_show_error("Failed to insert key, error %d", err); return err; @@ -9861,7 +9886,8 @@ static int check_tls_key(int argc, char **argv, struct command *acmd, struct plu printf("Inserted TLS key %08x\n", (unsigned int)tls_key); if (cfg.keyfile) { - err = append_keyfile(cfg.keyring, tls_key, cfg.keyfile); + err = append_keyfile(ctx, cfg.keyring, + tls_key, cfg.keyfile); if (err) return err; } @@ -9869,15 +9895,15 @@ static int check_tls_key(int argc, char **argv, struct command *acmd, struct plu _cleanup_free_ char *tls_id = NULL; if (cfg.compat) - err = nvme_generate_tls_key_identity_compat(cfg.hostnqn, - cfg.subsysnqn, cfg.identity, - hmac, decoded_key, decoded_len, - &tls_id); + err = nvme_generate_tls_key_identity_compat(ctx, + cfg.hostnqn, cfg.subsysnqn, cfg.identity, + hmac, decoded_key, decoded_len, + &tls_id); else - err = nvme_generate_tls_key_identity(cfg.hostnqn, - cfg.subsysnqn, cfg.identity, - hmac, decoded_key, decoded_len, - &tls_id); + err = nvme_generate_tls_key_identity(ctx, + cfg.hostnqn, cfg.subsysnqn, cfg.identity, + hmac, decoded_key, decoded_len, + &tls_id); if (err) { nvme_show_error("Failed to generate identity, error %d", err); @@ -9888,8 +9914,8 @@ static int check_tls_key(int argc, char **argv, struct command *acmd, struct plu return 0; } -static void __scan_tls_key(long keyring_id, long key_id, - char *desc, int desc_len, void *data) +static void __scan_tls_key(struct nvme_global_ctx *ctx, long keyring_id, + long key_id, char *desc, int desc_len, void *data) { FILE *fd = data; _cleanup_free_ unsigned char *key_data = NULL; @@ -9899,21 +9925,22 @@ static void __scan_tls_key(long keyring_id, long key_id, char type; int err; - err = nvme_read_key(keyring_id, key_id, &key_len, &key_data); + err = nvme_read_key(ctx, keyring_id, key_id, &key_len, &key_data); if (err) return; if (sscanf(desc, "NVMe%01d%c%02d %*s", &ver, &type, &hmac) != 3) return; - err = nvme_export_tls_key_versioned(ver, hmac, key_data, key_len, - &encoded_key); + err = nvme_export_tls_key_versioned(ctx, ver, hmac, key_data, key_len, + &encoded_key); if (err) return; fprintf(fd, "%s %s\n", desc, encoded_key); } -static int import_key(const char *keyring, FILE *fd) +static int import_key(struct nvme_global_ctx *ctx, const char *keyring, + FILE *fd) { long keyring_id, key; char tls_str[512]; @@ -9923,7 +9950,7 @@ static int import_key(const char *keyring, FILE *fd) int linenum = -1, key_len; int err; - err = nvme_lookup_keyring(keyring, &keyring_id); + err = nvme_lookup_keyring(ctx, keyring, &keyring_id); if (err) { nvme_show_error("Invalid keyring '%s'", keyring); return err; @@ -9940,13 +9967,13 @@ static int import_key(const char *keyring, FILE *fd) *tls_key = '\0'; tls_key++; tls_key[strcspn(tls_key, "\n")] = 0; - err = nvme_import_tls_key(tls_key, &key_len, &hmac, &psk); + err = nvme_import_tls_key(ctx, tls_key, &key_len, &hmac, &psk); if (err) { nvme_show_error("Failed to import key in line %d", linenum); continue; } - err = nvme_update_key(keyring_id, "psk", tls_str, + err = nvme_update_key(ctx, keyring_id, "psk", tls_str, psk, key_len, &key); if (err) continue; @@ -9967,6 +9994,7 @@ static int tls_key(int argc, char **argv, struct command *acmd, struct plugin *p const char *export = "Export all keys from the keyring."; const char *revoke = "Revoke key from the keyring."; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; _cleanup_file_ FILE *fd = NULL; mode_t old_umask = 0; int cnt, err = 0; @@ -10001,6 +10029,12 @@ static int tls_key(int argc, char **argv, struct command *acmd, struct plugin *p if (err) return err; + ctx = nvme_create_global_ctx(stderr, log_level); + if (!ctx) { + nvme_show_error("Failed to create global context"); + return -ENOMEM; + } + if (cfg.keyfile) { const char *mode; @@ -10033,7 +10067,7 @@ static int tls_key(int argc, char **argv, struct command *acmd, struct plugin *p nvme_show_error("Must specify either --import, --export or --revoke"); return -EINVAL; } else if (cfg.export) { - err = nvme_scan_tls_keys(cfg.keyring, __scan_tls_key, fd); + err = nvme_scan_tls_keys(ctx, cfg.keyring, __scan_tls_key, fd); if (err < 0) { nvme_show_error("Export of TLS keys failed with '%s'", nvme_strerror(err)); @@ -10045,7 +10079,7 @@ static int tls_key(int argc, char **argv, struct command *acmd, struct plugin *p return 0; } else if (cfg.import) { - err = import_key(cfg.keyring, fd); + err = import_key(ctx, cfg.keyring, fd); if (err) { nvme_show_error("Import of TLS keys failed with '%s'", nvme_strerror(err)); @@ -10055,7 +10089,8 @@ static int tls_key(int argc, char **argv, struct command *acmd, struct plugin *p if (argconfig_parse_seen(opts, "verbose")) printf("importing from %s\n", cfg.keyfile); } else { - err = nvme_revoke_tls_key(cfg.keyring, cfg.keytype, cfg.revoke); + err = nvme_revoke_tls_key(ctx, cfg.keyring, cfg.keytype, + cfg.revoke); if (err) { nvme_show_error("Failed to revoke key '%s'", nvme_strerror(err)); From f65f16a210d9d77be3238d63a5bd0cf81f30a1b7 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 17 Dec 2025 16:49:30 +0100 Subject: [PATCH 5/5] nbft: add global context as first argument to nbft API Add the global context to the nbft related API. This allows to issue warnings/errors via the global context. Signed-off-by: Daniel Wagner --- libnvme/libnvme/nvme.i | 8 +- libnvme/libnvme/tests/test-nbft.py | 4 +- libnvme/src/nvme/fabrics.c | 13 +- libnvme/src/nvme/fabrics.h | 7 +- libnvme/src/nvme/nbft.c | 383 ++++++++++++++++------------- libnvme/src/nvme/nbft.h | 7 +- libnvme/test/nbft/nbft-dump.c | 15 +- plugins/nbft/nbft-plugin.c | 13 +- 8 files changed, 264 insertions(+), 186 deletions(-) diff --git a/libnvme/libnvme/nvme.i b/libnvme/libnvme/nvme.i index 2cca7d6565..5f4417fd3f 100644 --- a/libnvme/libnvme/nvme.i +++ b/libnvme/libnvme/nvme.i @@ -1236,26 +1236,26 @@ struct nvme_ns { return output; } - PyObject *nbft_get(const char * filename) + PyObject *nbft_get(struct nvme_global_ctx *ctx, const char * filename) { struct nbft_info *nbft; PyObject *output; int ret; - ret = nvme_nbft_read(&nbft, filename); + ret = nvme_nbft_read(ctx, &nbft, filename); if (ret) { Py_RETURN_NONE; } output = nbft_to_pydict(nbft); - nvme_nbft_free(nbft); + nvme_nbft_free(ctx, nbft); return output; } %}; %feature("autodoc", "@return an NBFT table as a dict on success, None otherwise.\n" "@param filename: file to read") nbft_get; -PyObject *nbft_get(const char * filename); +PyObject *nbft_get(struct nvme_global_ctx *ctx, const char * filename); // We want to swig all the #define and enum from types.h, but none of the structs. #pragma SWIG nowarn=503 // Supress warnings about unnamed struct diff --git a/libnvme/libnvme/tests/test-nbft.py b/libnvme/libnvme/tests/test-nbft.py index 3aeeba453a..aa96745391 100755 --- a/libnvme/libnvme/tests/test-nbft.py +++ b/libnvme/libnvme/tests/test-nbft.py @@ -77,7 +77,9 @@ def setUp(self): def test_read_nbft_file(self): """Make sure we get expected data when reading from binary NBFT file""" - actual_nbft = nvme.nbft_get(args.filename) + ctx = nvme.global_ctx() + ctx.log_level('debug') + actual_nbft = nvme.nbft_get(ctx, args.filename) self.assertEqual(actual_nbft, self.expected_nbft) diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index 8211053210..e35b7c7e0c 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -2606,7 +2606,8 @@ static int nbft_filter(const struct dirent *dent) return !fnmatch(NBFT_SYSFS_FILENAME, dent->d_name, FNM_PATHNAME); } -int nvmf_nbft_read_files(char *path, struct nbft_file_entry **head) +int nvmf_nbft_read_files(struct nvme_global_ctx *ctx, char *path, + struct nbft_file_entry **head) { struct nbft_file_entry *entry = NULL; struct nbft_info *nbft; @@ -2622,7 +2623,7 @@ int nvmf_nbft_read_files(char *path, struct nbft_file_entry **head) snprintf(filename, sizeof(filename), "%s/%s", path, dent[i]->d_name); - ret = nvme_nbft_read(&nbft, filename); + ret = nvme_nbft_read(ctx, &nbft, filename); if (!ret) { struct nbft_file_entry *new; @@ -2644,12 +2645,12 @@ int nvmf_nbft_read_files(char *path, struct nbft_file_entry **head) return 0; } -void nvmf_nbft_free(struct nbft_file_entry *head) +void nvmf_nbft_free(struct nvme_global_ctx *ctx, struct nbft_file_entry *head) { while (head) { struct nbft_file_entry *next = head->next; - nvme_nbft_free(head->nbft); + nvme_nbft_free(ctx, head->nbft); free(head); head = next; @@ -2874,7 +2875,7 @@ int nvmf_discovery_nbft(struct nvme_global_ctx *ctx, /* TODO: print discovery-type info from NBFT tables */ return 0; - ret = nvmf_nbft_read_files(nbft_path, &entry); + ret = nvmf_nbft_read_files(ctx, nbft_path, &entry); if (ret) { if (ret != -ENOENT) nvme_msg(ctx, LOG_ERR, @@ -3067,7 +3068,7 @@ int nvmf_discovery_nbft(struct nvme_global_ctx *ctx, } } out_free: - nvmf_nbft_free(entry); + nvmf_nbft_free(ctx, entry); return ret; } diff --git a/libnvme/src/nvme/fabrics.h b/libnvme/src/nvme/fabrics.h index c4d0ba7fba..0935f6f2e3 100644 --- a/libnvme/src/nvme/fabrics.h +++ b/libnvme/src/nvme/fabrics.h @@ -644,6 +644,7 @@ struct nbft_file_entry { /** * nvmf_nbft_read_files() - Read NBFT files from path + * @ctx: struct nvme_global_ctx object * @path: Path to NBFT files * @head: Pointer to store linked list of NBFT file entries * @@ -651,14 +652,16 @@ struct nbft_file_entry { * * Return: 0 on success, or a negative error code on failure. */ -int nvmf_nbft_read_files(char *path, struct nbft_file_entry **head); +int nvmf_nbft_read_files(struct nvme_global_ctx *ctx, char *path, + struct nbft_file_entry **head); /** * nvmf_nbft_free() - Free NBFT file entry list + * @ctx: struct nvme_global_ctx object * @head: Head of the NBFT file entry list * * Frees all memory associated with the NBFT file entry list. */ -void nvmf_nbft_free(struct nbft_file_entry *head); +void nvmf_nbft_free(struct nvme_global_ctx *ctx, struct nbft_file_entry *head); #endif /* _LIBNVME_FABRICS_H */ diff --git a/libnvme/src/nvme/nbft.c b/libnvme/src/nvme/nbft.c index fd94a450eb..3c4b39c962 100644 --- a/libnvme/src/nvme/nbft.c +++ b/libnvme/src/nvme/nbft.c @@ -7,7 +7,6 @@ * */ -#include #include #include @@ -18,7 +17,6 @@ #include "nbft.h" #include "log.h" - #define MIN(a, b) (((a) < (b)) ? (a) : (b)) static __u8 csum(const __u8 *buffer, ssize_t length) @@ -72,27 +70,28 @@ static char *trtype_to_string(__u8 transport_type) } } -#define verify(condition, message) \ +#define verify(ctx, condition, message) \ do { \ if (!(condition)) { \ - nvme_msg(NULL, LOG_DEBUG, "file %s: " message "\n", \ + nvme_msg(ctx, LOG_DEBUG, "file %s: " message "\n", \ nbft->filename); \ return -EINVAL; \ } \ } while (0) -static int __get_heap_obj(struct nbft_header *header, const char *filename, - const char *descriptorname, const char *fieldname, - struct nbft_heap_obj obj, bool is_string, - char **output) +static int __get_heap_obj(struct nvme_global_ctx *ctx, + struct nbft_header *header, const char *filename, + const char *descriptorname, const char *fieldname, + struct nbft_heap_obj obj, bool is_string, + char **output) { if (le16_to_cpu(obj.length) == 0) return -ENOENT; if (!in_heap(header, obj)) { - nvme_msg(NULL, LOG_DEBUG, - "file %s: field '%s' in descriptor '%s' has invalid offset or length\n", - filename, fieldname, descriptorname); + nvme_msg(ctx, LOG_DEBUG, + "file %s: field '%s' in descriptor '%s' has invalid offset or length\n", + filename, fieldname, descriptorname); return -EINVAL; } @@ -100,17 +99,18 @@ static int __get_heap_obj(struct nbft_header *header, const char *filename, *output = (char *)header + le32_to_cpu(obj.offset); if (is_string) { - if (strnlen(*output, le16_to_cpu(obj.length) + 1) < le16_to_cpu(obj.length)) - nvme_msg(NULL, LOG_DEBUG, + if (strnlen(*output, le16_to_cpu(obj.length) + 1) < + le16_to_cpu(obj.length)) { + nvme_msg(ctx, LOG_DEBUG, "file %s: string '%s' in descriptor '%s' is shorter (%zd) than specified length (%d)\n", filename, fieldname, descriptorname, strnlen(*output, le16_to_cpu(obj.length) + 1), le16_to_cpu(obj.length)); - else if (strnlen(*output, le16_to_cpu(obj.length) + 1) > - le16_to_cpu(obj.length)) { - nvme_msg(NULL, LOG_DEBUG, - "file %s: string '%s' in descriptor '%s' is not zero terminated\n", - filename, fieldname, descriptorname); + } else if (strnlen(*output, le16_to_cpu(obj.length) + 1) > + le16_to_cpu(obj.length)) { + nvme_msg(ctx, LOG_DEBUG, + "file %s: string '%s' in descriptor '%s' is not zero terminated\n", + filename, fieldname, descriptorname); return -EINVAL; } } @@ -118,13 +118,14 @@ static int __get_heap_obj(struct nbft_header *header, const char *filename, return 0; } -#define get_heap_obj(descriptor, obj, is_string, output) \ - __get_heap_obj(header, nbft->filename, \ +#define get_heap_obj(ctx, descriptor, obj, is_string, output) \ + __get_heap_obj(ctx, header, nbft->filename, \ stringify(descriptor), stringify(obj), \ descriptor->obj, is_string, \ output) -static struct nbft_info_discovery *discovery_from_index(struct nbft_info *nbft, int i) +static struct nbft_info_discovery *discovery_from_index(struct nbft_info *nbft, + int i) { struct nbft_info_discovery **d; @@ -146,7 +147,8 @@ static struct nbft_info_hfi *hfi_from_index(struct nbft_info *nbft, int i) return NULL; } -static struct nbft_info_security *security_from_index(struct nbft_info *nbft, int i) +static struct nbft_info_security *security_from_index(struct nbft_info *nbft, + int i) { struct nbft_info_security **s; @@ -157,17 +159,17 @@ static struct nbft_info_security *security_from_index(struct nbft_info *nbft, in return NULL; } -static int read_ssns_exended_info(struct nbft_info *nbft, - struct nbft_info_subsystem_ns *ssns, - struct nbft_ssns_ext_info *raw_ssns_ei) +static int read_ssns_exended_info(struct nvme_global_ctx *ctx, + struct nbft_info *nbft, struct nbft_info_subsystem_ns *ssns, + struct nbft_ssns_ext_info *raw_ssns_ei) { struct nbft_header *header = (struct nbft_header *)nbft->raw_nbft; - verify(raw_ssns_ei->structure_id == NBFT_DESC_SSNS_EXT_INFO, + verify(ctx, raw_ssns_ei->structure_id == NBFT_DESC_SSNS_EXT_INFO, "invalid ID in SSNS extended info descriptor"); - verify(raw_ssns_ei->version == 1, + verify(ctx, raw_ssns_ei->version == 1, "invalid version in SSNS extended info descriptor"); - verify(le16_to_cpu(raw_ssns_ei->ssns_index) == ssns->index, + verify(ctx, le16_to_cpu(raw_ssns_ei->ssns_index) == ssns->index, "SSNS index doesn't match extended info descriptor index"); if (!(le32_to_cpu(raw_ssns_ei->flags) & NBFT_SSNS_EXT_INFO_VALID)) @@ -176,14 +178,15 @@ static int read_ssns_exended_info(struct nbft_info *nbft, if (le32_to_cpu(raw_ssns_ei->flags) & NBFT_SSNS_EXT_INFO_ADMIN_ASQSZ) ssns->asqsz = le16_to_cpu(raw_ssns_ei->asqsz); ssns->controller_id = le16_to_cpu(raw_ssns_ei->cntlid); - get_heap_obj(raw_ssns_ei, dhcp_root_path_str_obj, 1, &ssns->dhcp_root_path_string); + get_heap_obj(ctx, raw_ssns_ei, dhcp_root_path_str_obj, 1, + &ssns->dhcp_root_path_string); return 0; } -static int read_ssns(struct nbft_info *nbft, - struct nbft_ssns *raw_ssns, - struct nbft_info_subsystem_ns **s) +static int read_ssns(struct nvme_global_ctx *ctx, + struct nbft_info *nbft, struct nbft_ssns *raw_ssns, + struct nbft_info_subsystem_ns **s) { struct nbft_header *header = (struct nbft_header *)nbft->raw_nbft; struct nbft_info_subsystem_ns *ssns; @@ -194,11 +197,11 @@ static int read_ssns(struct nbft_info *nbft, if (!(le16_to_cpu(raw_ssns->flags) & NBFT_SSNS_VALID)) return -EINVAL; - verify(raw_ssns->structure_id == NBFT_DESC_SSNS, + verify(ctx,raw_ssns->structure_id == NBFT_DESC_SSNS, "invalid ID in SSNS descriptor"); /* verify transport type */ - verify(raw_ssns->trtype == NBFT_TRTYPE_TCP, + verify(ctx, raw_ssns->trtype == NBFT_TRTYPE_TCP, "invalid transport type in SSNS descriptor"); ssns = calloc(1, sizeof(*ssns)); @@ -206,35 +209,39 @@ static int read_ssns(struct nbft_info *nbft, return -ENOMEM; ssns->index = le16_to_cpu(raw_ssns->index); - strncpy(ssns->transport, trtype_to_string(raw_ssns->trtype), sizeof(ssns->transport)); + strncpy(ssns->transport, trtype_to_string(raw_ssns->trtype), + sizeof(ssns->transport)); /* transport specific flags */ if (raw_ssns->trtype == NBFT_TRTYPE_TCP) { - if (le16_to_cpu(raw_ssns->trflags) & NBFT_SSNS_PDU_HEADER_DIGEST) + if (le16_to_cpu(raw_ssns->trflags) & + NBFT_SSNS_PDU_HEADER_DIGEST) ssns->pdu_header_digest_required = true; - if (le16_to_cpu(raw_ssns->trflags) & NBFT_SSNS_DATA_DIGEST) + if (le16_to_cpu(raw_ssns->trflags) & + NBFT_SSNS_DATA_DIGEST) ssns->data_digest_required = true; } /* primary discovery controller */ if (raw_ssns->primary_discovery_ctrl_index) { ssns->discovery = discovery_from_index(nbft, - raw_ssns->primary_discovery_ctrl_index); + raw_ssns->primary_discovery_ctrl_index); if (!ssns->discovery) - nvme_msg(NULL, LOG_DEBUG, + nvme_msg(ctx, LOG_DEBUG, "file %s: namespace %d discovery controller not found\n", nbft->filename, ssns->index); } /* subsystem transport address */ - ret = get_heap_obj(raw_ssns, subsys_traddr_obj, 0, (char **)&tmp); + ret = get_heap_obj(ctx, raw_ssns, subsys_traddr_obj, 0, (char **)&tmp); if (ret) goto fail; format_ip_addr(ssns->traddr, sizeof(ssns->traddr), tmp); /* subsystem transport service identifier */ - ret = get_heap_obj(raw_ssns, subsys_trsvcid_obj, 1, &ssns->trsvcid); + ret = get_heap_obj(ctx, raw_ssns, subsys_trsvcid_obj, + 1, &ssns->trsvcid); if (ret) goto fail; @@ -254,34 +261,39 @@ static int read_ssns(struct nbft_info *nbft, /* security profile */ if (raw_ssns->security_desc_index) { - ssns->security = security_from_index(nbft, raw_ssns->security_desc_index); + ssns->security = security_from_index(nbft, + raw_ssns->security_desc_index); if (!ssns->security) - nvme_msg(NULL, LOG_DEBUG, + nvme_msg(ctx, LOG_DEBUG, "file %s: namespace %d security controller not found\n", nbft->filename, ssns->index); } /* HFI descriptors */ - ret = get_heap_obj(raw_ssns, secondary_hfi_assoc_obj, 0, (char **)&ss_hfi_indexes); + ret = get_heap_obj(ctx, raw_ssns, secondary_hfi_assoc_obj, + 0, (char **)&ss_hfi_indexes); if (ret) goto fail; - ssns->hfis = calloc(le16_to_cpu(raw_ssns->secondary_hfi_assoc_obj.length) + 2, - sizeof(*ssns->hfis)); + ssns->hfis = + calloc(le16_to_cpu(raw_ssns->secondary_hfi_assoc_obj.length) + + 2, sizeof(*ssns->hfis)); if (!ssns->hfis) { ret = -ENOMEM; goto fail; } ssns->hfis[0] = hfi_from_index(nbft, raw_ssns->primary_hfi_desc_index); if (!ssns->hfis[0]) { - nvme_msg(NULL, LOG_DEBUG, - "file %s: SSNS %d: HFI %d not found\n", - nbft->filename, ssns->index, raw_ssns->primary_hfi_desc_index); + nvme_msg(ctx, LOG_DEBUG, + "file %s: SSNS %d: HFI %d not found\n", + nbft->filename, ssns->index, + raw_ssns->primary_hfi_desc_index); ret = -EINVAL; goto fail; } ssns->num_hfis = 1; - for (i = 0; i < le16_to_cpu(raw_ssns->secondary_hfi_assoc_obj.length); i++) { + for (i = 0; i < le16_to_cpu(raw_ssns->secondary_hfi_assoc_obj.length); + i++) { bool duplicate = false; int j; @@ -297,23 +309,24 @@ static int read_ssns(struct nbft_info *nbft, duplicate = true; if (duplicate) { - nvme_msg(NULL, LOG_DEBUG, - "file %s: SSNS %d skipping duplicate HFI index %d\n", - nbft->filename, ssns->index, ss_hfi_indexes[i]); + nvme_msg(ctx, LOG_DEBUG, + "file %s: SSNS %d skipping duplicate HFI index %d\n", + nbft->filename, ssns->index, ss_hfi_indexes[i]); continue; } ssns->hfis[i + 1] = hfi_from_index(nbft, ss_hfi_indexes[i]); if (ss_hfi_indexes[i] && !ssns->hfis[i + 1]) - nvme_msg(NULL, LOG_DEBUG, - "file %s: SSNS %d HFI %d not found\n", - nbft->filename, ssns->index, ss_hfi_indexes[i]); + nvme_msg(ctx, LOG_DEBUG, + "file %s: SSNS %d HFI %d not found\n", + nbft->filename, ssns->index, ss_hfi_indexes[i]); else ssns->num_hfis++; } /* SSNS NQN */ - ret = get_heap_obj(raw_ssns, subsys_ns_nqn_obj, 1, &ssns->subsys_nqn); + ret = get_heap_obj(ctx, raw_ssns, subsys_ns_nqn_obj, + 1, &ssns->subsys_nqn); if (ret) goto fail; @@ -321,9 +334,11 @@ static int read_ssns(struct nbft_info *nbft, if (le16_to_cpu(raw_ssns->flags) & NBFT_SSNS_EXTENDED_INFO_IN_USE) { struct nbft_ssns_ext_info *ssns_extended_info; - if (!get_heap_obj(raw_ssns, ssns_extended_info_desc_obj, 0, - (char **)&ssns_extended_info)) - read_ssns_exended_info(nbft, ssns, ssns_extended_info); + if (!get_heap_obj(ctx, raw_ssns, ssns_extended_info_desc_obj, + 0, (char **)&ssns_extended_info)) { + read_ssns_exended_info(ctx, nbft, ssns, + ssns_extended_info); + } } *s = ssns; @@ -334,57 +349,59 @@ static int read_ssns(struct nbft_info *nbft, return ret; } -static int read_hfi_info_tcp(struct nbft_info *nbft, - struct nbft_hfi_info_tcp *raw_hfi_info_tcp, - struct nbft_info_hfi *hfi) +static int read_hfi_info_tcp(struct nvme_global_ctx *ctx, + struct nbft_info *nbft, + struct nbft_hfi_info_tcp *raw_hfi_info_tcp, + struct nbft_info_hfi *hfi) { struct nbft_header *header = (struct nbft_header *)nbft->raw_nbft; if ((raw_hfi_info_tcp->flags & NBFT_HFI_INFO_TCP_VALID) == 0) return -EINVAL; - verify(raw_hfi_info_tcp->structure_id == NBFT_DESC_HFI_TRINFO, + verify(ctx, raw_hfi_info_tcp->structure_id == NBFT_DESC_HFI_TRINFO, "invalid ID in HFI transport descriptor"); - verify(raw_hfi_info_tcp->version == 1, + verify(ctx, raw_hfi_info_tcp->version == 1, "invalid version in HFI transport descriptor"); if (le16_to_cpu(raw_hfi_info_tcp->hfi_index) != hfi->index) - nvme_msg(NULL, LOG_DEBUG, - "file %s: HFI descriptor index %d does not match index in HFI transport descriptor\n", - nbft->filename, hfi->index); + nvme_msg(ctx, LOG_DEBUG, + "file %s: HFI descriptor index %d does not match index in HFI transport descriptor\n", + nbft->filename, hfi->index); hfi->tcp_info.pci_sbdf = le32_to_cpu(raw_hfi_info_tcp->pci_sbdf); memcpy(hfi->tcp_info.mac_addr, raw_hfi_info_tcp->mac_addr, - sizeof(raw_hfi_info_tcp->mac_addr)); + sizeof(raw_hfi_info_tcp->mac_addr)); hfi->tcp_info.vlan = le16_to_cpu(raw_hfi_info_tcp->vlan); hfi->tcp_info.ip_origin = raw_hfi_info_tcp->ip_origin; format_ip_addr(hfi->tcp_info.ipaddr, sizeof(hfi->tcp_info.ipaddr), - raw_hfi_info_tcp->ip_address); + raw_hfi_info_tcp->ip_address); hfi->tcp_info.subnet_mask_prefix = raw_hfi_info_tcp->subnet_mask_prefix; - format_ip_addr(hfi->tcp_info.gateway_ipaddr, sizeof(hfi->tcp_info.ipaddr), - raw_hfi_info_tcp->ip_gateway); - hfi->tcp_info.route_metric = le16_to_cpu(raw_hfi_info_tcp->route_metric); + format_ip_addr(hfi->tcp_info.gateway_ipaddr, + sizeof(hfi->tcp_info.ipaddr), raw_hfi_info_tcp->ip_gateway); + hfi->tcp_info.route_metric = + le16_to_cpu(raw_hfi_info_tcp->route_metric); format_ip_addr(hfi->tcp_info.primary_dns_ipaddr, - sizeof(hfi->tcp_info.primary_dns_ipaddr), - raw_hfi_info_tcp->primary_dns); + sizeof(hfi->tcp_info.primary_dns_ipaddr), + raw_hfi_info_tcp->primary_dns); format_ip_addr(hfi->tcp_info.secondary_dns_ipaddr, - sizeof(hfi->tcp_info.secondary_dns_ipaddr), - raw_hfi_info_tcp->secondary_dns); + sizeof(hfi->tcp_info.secondary_dns_ipaddr), + raw_hfi_info_tcp->secondary_dns); if (raw_hfi_info_tcp->flags & NBFT_HFI_INFO_TCP_DHCP_OVERRIDE) { hfi->tcp_info.dhcp_override = true; format_ip_addr(hfi->tcp_info.dhcp_server_ipaddr, - sizeof(hfi->tcp_info.dhcp_server_ipaddr), - raw_hfi_info_tcp->dhcp_server); + sizeof(hfi->tcp_info.dhcp_server_ipaddr), + raw_hfi_info_tcp->dhcp_server); } - get_heap_obj(raw_hfi_info_tcp, host_name_obj, 1, &hfi->tcp_info.host_name); + get_heap_obj(ctx, raw_hfi_info_tcp, host_name_obj, + 1, &hfi->tcp_info.host_name); if (raw_hfi_info_tcp->flags & NBFT_HFI_INFO_TCP_GLOBAL_ROUTE) hfi->tcp_info.this_hfi_is_default_route = true; return 0; } -static int read_hfi(struct nbft_info *nbft, - struct nbft_hfi *raw_hfi, - struct nbft_info_hfi **h) +static int read_hfi(struct nvme_global_ctx *ctx, struct nbft_info *nbft, + struct nbft_hfi *raw_hfi, struct nbft_info_hfi **h) { int ret; struct nbft_info_hfi *hfi; @@ -393,8 +410,8 @@ static int read_hfi(struct nbft_info *nbft, if (!(raw_hfi->flags & NBFT_HFI_VALID)) return -EINVAL; - verify(raw_hfi->structure_id == NBFT_DESC_HFI, - "invalid ID in HFI descriptor"); + verify(ctx, raw_hfi->structure_id == NBFT_DESC_HFI, + "invalid ID in HFI descriptor"); hfi = calloc(1, sizeof(struct nbft_info_hfi)); if (!hfi) @@ -412,15 +429,16 @@ static int read_hfi(struct nbft_info *nbft, strncpy(hfi->transport, trtype_to_string(raw_hfi->trtype), sizeof(hfi->transport)); - ret = get_heap_obj(raw_hfi, trinfo_obj, 0, (char **)&raw_hfi_info_tcp); + ret = get_heap_obj(ctx, raw_hfi, trinfo_obj, + 0, (char **)&raw_hfi_info_tcp); if (ret) goto fail; - ret = read_hfi_info_tcp(nbft, raw_hfi_info_tcp, hfi); + ret = read_hfi_info_tcp(ctx, nbft, raw_hfi_info_tcp, hfi); if (ret) goto fail; } else { - nvme_msg(NULL, LOG_DEBUG, + nvme_msg(ctx, LOG_DEBUG, "file %s: invalid transport type %d\n", nbft->filename, raw_hfi->trtype); ret = -EINVAL; @@ -435,9 +453,10 @@ static int read_hfi(struct nbft_info *nbft, return ret; } -static int read_discovery(struct nbft_info *nbft, - struct nbft_discovery *raw_discovery, - struct nbft_info_discovery **d) +static int read_discovery(struct nvme_global_ctx *ctx, + struct nbft_info *nbft, + struct nbft_discovery *raw_discovery, + struct nbft_info_discovery **d) { struct nbft_info_discovery *discovery = NULL; struct nbft_header *header = (struct nbft_header *)nbft->raw_nbft; @@ -446,7 +465,7 @@ static int read_discovery(struct nbft_info *nbft, if (!(raw_discovery->flags & NBFT_DISCOVERY_VALID)) goto error; - verify(raw_discovery->structure_id == NBFT_DESC_DISCOVERY, + verify(ctx, raw_discovery->structure_id == NBFT_DESC_DISCOVERY, "invalid ID in discovery descriptor"); discovery = calloc(1, sizeof(struct nbft_info_discovery)); @@ -457,21 +476,24 @@ static int read_discovery(struct nbft_info *nbft, discovery->index = raw_discovery->index; - if (get_heap_obj(raw_discovery, discovery_ctrl_addr_obj, 1, &discovery->uri)) + if (get_heap_obj(ctx, raw_discovery, discovery_ctrl_addr_obj, + 1, &discovery->uri)) goto error; - if (get_heap_obj(raw_discovery, discovery_ctrl_nqn_obj, 1, &discovery->nqn)) + if (get_heap_obj(ctx, raw_discovery, discovery_ctrl_nqn_obj, + 1, &discovery->nqn)) goto error; discovery->hfi = hfi_from_index(nbft, raw_discovery->hfi_index); if (raw_discovery->hfi_index && !discovery->hfi) - nvme_msg(NULL, LOG_DEBUG, + nvme_msg(ctx, LOG_DEBUG, "file %s: discovery %d HFI not found\n", nbft->filename, discovery->index); - discovery->security = security_from_index(nbft, raw_discovery->sec_index); + discovery->security = + security_from_index(nbft, raw_discovery->sec_index); if (raw_discovery->sec_index && !discovery->security) - nvme_msg(NULL, LOG_DEBUG, + nvme_msg(ctx, LOG_DEBUG, "file %s: discovery %d security descriptor not found\n", nbft->filename, discovery->index); @@ -484,57 +506,68 @@ static int read_discovery(struct nbft_info *nbft, return r; } -static int read_security(struct nbft_info *nbft, - struct nbft_security *raw_security, - struct nbft_info_security **s) +static int read_security(struct nvme_global_ctx *ctx, struct nbft_info *nbft, + struct nbft_security *raw_security, + struct nbft_info_security **s) { return -EINVAL; } -static void read_hfi_descriptors(struct nbft_info *nbft, int num_hfi, - struct nbft_hfi *raw_hfi_array, int hfi_len) +static void read_hfi_descriptors(struct nvme_global_ctx *ctx, + struct nbft_info *nbft, int num_hfi, + struct nbft_hfi *raw_hfi_array, int hfi_len) { int i, cnt; nbft->hfi_list = calloc(num_hfi + 1, sizeof(struct nbft_info_hfi)); for (i = 0, cnt = 0; i < num_hfi; i++) { - if (read_hfi(nbft, &raw_hfi_array[i], &nbft->hfi_list[cnt]) == 0) + if (read_hfi(ctx, nbft, &raw_hfi_array[i], + &nbft->hfi_list[cnt]) == 0) cnt++; } } -static void read_security_descriptors(struct nbft_info *nbft, int num_sec, - struct nbft_security *raw_sec_array, int sec_len) +static void read_security_descriptors(struct nvme_global_ctx *ctx, + struct nbft_info *nbft, int num_sec, + struct nbft_security *raw_sec_array, int sec_len) { int i, cnt; - nbft->security_list = calloc(num_sec + 1, sizeof(struct nbft_info_security)); + nbft->security_list = calloc(num_sec + 1, + sizeof(struct nbft_info_security)); for (i = 0, cnt = 0; i < num_sec; i++) { - if (read_security(nbft, &raw_sec_array[i], &nbft->security_list[cnt]) == 0) + if (read_security(ctx, nbft, &raw_sec_array[i], + &nbft->security_list[cnt]) == 0) cnt++; } } -static void read_discovery_descriptors(struct nbft_info *nbft, int num_disc, - struct nbft_discovery *raw_disc_array, int disc_len) +static void read_discovery_descriptors(struct nvme_global_ctx *ctx, + struct nbft_info *nbft, int num_disc, + struct nbft_discovery *raw_disc_array, int disc_len) { int i, cnt; - nbft->discovery_list = calloc(num_disc + 1, sizeof(struct nbft_info_discovery)); + nbft->discovery_list = + calloc(num_disc + 1, sizeof(struct nbft_info_discovery)); for (i = 0, cnt = 0; i < num_disc; i++) { - if (read_discovery(nbft, &raw_disc_array[i], &nbft->discovery_list[cnt]) == 0) + if (read_discovery(ctx,nbft, &raw_disc_array[i], + &nbft->discovery_list[cnt]) == 0) cnt++; } } -static void read_ssns_descriptors(struct nbft_info *nbft, int num_ssns, - struct nbft_ssns *raw_ssns_array, int ssns_len) +static void read_ssns_descriptors(struct nvme_global_ctx *ctx, + struct nbft_info *nbft, int num_ssns, + struct nbft_ssns *raw_ssns_array, int ssns_len) { int i, cnt; - nbft->subsystem_ns_list = calloc(num_ssns + 1, sizeof(struct nbft_info_subsystem_ns)); + nbft->subsystem_ns_list = + calloc(num_ssns + 1, sizeof(struct nbft_info_subsystem_ns)); for (i = 0, cnt = 0; i < num_ssns; i++) { - if (read_ssns(nbft, &raw_ssns_array[i], &nbft->subsystem_ns_list[cnt]) == 0) + if (read_ssns(ctx, nbft, &raw_ssns_array[i], + &nbft->subsystem_ns_list[cnt]) == 0) cnt++; } } @@ -545,7 +578,7 @@ static void read_ssns_descriptors(struct nbft_info *nbft, int num_ssns, * * Returns 0 on success, errno otherwise. */ -static int parse_raw_nbft(struct nbft_info *nbft) +static int parse_raw_nbft(struct nvme_global_ctx *ctx, struct nbft_info *nbft) { __u8 *raw_nbft = nbft->raw_nbft; int raw_nbft_size = nbft->raw_nbft_size; @@ -554,48 +587,60 @@ static int parse_raw_nbft(struct nbft_info *nbft) struct nbft_control *control; struct nbft_host *host; - verify(raw_nbft_size >= sizeof(struct nbft_header) + sizeof(struct nbft_control), + verify(ctx, raw_nbft_size >= + sizeof(struct nbft_header) + sizeof(struct nbft_control), "table is too short"); - verify(csum(raw_nbft, raw_nbft_size) == 0, "invalid checksum"); + verify(ctx, csum(raw_nbft, raw_nbft_size) == 0, "invalid checksum"); /* * header */ header = (struct nbft_header *)raw_nbft; - verify(strncmp(header->signature, NBFT_HEADER_SIG, 4) == 0, "invalid signature"); - verify(le32_to_cpu(header->length) <= raw_nbft_size, "length in header exceeds table length"); - verify(header->major_revision == 1, "unsupported major revision"); - verify(header->minor_revision == 0, "unsupported minor revision"); - verify(le32_to_cpu(header->heap_length) + le32_to_cpu(header->heap_offset) <= - le32_to_cpu(header->length), "heap exceeds table length"); + verify(ctx, strncmp(header->signature, NBFT_HEADER_SIG, 4) == 0, + "invalid signature"); + verify(ctx, le32_to_cpu(header->length) <= raw_nbft_size, + "length in header exceeds table length"); + verify(ctx, header->major_revision == 1, + "unsupported major revision"); + verify(ctx, header->minor_revision == 0, + "unsupported minor revision"); + verify(ctx, le32_to_cpu(header->heap_length) + + le32_to_cpu(header->heap_offset) <= le32_to_cpu(header->length), + "heap exceeds table length"); /* * control */ - control = (struct nbft_control *)(raw_nbft + sizeof(struct nbft_header)); + control = + (struct nbft_control *)(raw_nbft + sizeof(struct nbft_header)); if ((control->flags & NBFT_CONTROL_VALID) == 0) return 0; - verify(control->structure_id == NBFT_DESC_CONTROL, + verify(ctx, control->structure_id == NBFT_DESC_CONTROL, "invalid ID in control structure"); /* * host */ - verify(le32_to_cpu(control->hdesc.offset) + sizeof(struct nbft_host) <= - le32_to_cpu(header->length) && - le32_to_cpu(control->hdesc.offset) >= sizeof(struct nbft_host), - "host descriptor offset/length is invalid"); - host = (struct nbft_host *)(raw_nbft + le32_to_cpu(control->hdesc.offset)); - - verify(host->flags & NBFT_HOST_VALID, "host descriptor valid flag not set"); - verify(host->structure_id == NBFT_DESC_HOST, "invalid ID in HOST descriptor"); + verify(ctx, le32_to_cpu(control->hdesc.offset) + + sizeof(struct nbft_host) <= le32_to_cpu(header->length) && + le32_to_cpu(control->hdesc.offset) >= sizeof(struct nbft_host), + "host descriptor offset/length is invalid"); + host = (struct nbft_host *)(raw_nbft + + le32_to_cpu(control->hdesc.offset)); + + verify(ctx, host->flags & NBFT_HOST_VALID, + "host descriptor valid flag not set"); + verify(ctx, host->structure_id == NBFT_DESC_HOST, + "invalid ID in HOST descriptor"); nbft->host.id = (unsigned char *) &(host->host_id); - if (get_heap_obj(host, host_nqn_obj, 1, &nbft->host.nqn) != 0) + if (get_heap_obj(ctx, host, host_nqn_obj, 1, &nbft->host.nqn) != 0) return -EINVAL; - nbft->host.host_id_configured = host->flags & NBFT_HOST_HOSTID_CONFIGURED; - nbft->host.host_nqn_configured = host->flags & NBFT_HOST_HOSTNQN_CONFIGURED; + nbft->host.host_id_configured = + host->flags & NBFT_HOST_HOSTID_CONFIGURED; + nbft->host.host_nqn_configured = + host->flags & NBFT_HOST_HOSTNQN_CONFIGURED; /* * HFI @@ -603,11 +648,13 @@ static int parse_raw_nbft(struct nbft_info *nbft) if (control->num_hfi > 0) { struct nbft_hfi *raw_hfi_array; - verify(le32_to_cpu(control->hfio) + sizeof(struct nbft_hfi) * - control->num_hfi <= le32_to_cpu(header->length), + verify(ctx, le32_to_cpu(control->hfio) + + sizeof(struct nbft_hfi) * control->num_hfi <= + le32_to_cpu(header->length), "invalid hfi descriptor list offset"); - raw_hfi_array = (struct nbft_hfi *)(raw_nbft + le32_to_cpu(control->hfio)); - read_hfi_descriptors(nbft, control->num_hfi, raw_hfi_array, + raw_hfi_array = (struct nbft_hfi *)(raw_nbft + + le32_to_cpu(control->hfio)); + read_hfi_descriptors(ctx, nbft, control->num_hfi, raw_hfi_array, le16_to_cpu(control->hfil)); } @@ -617,12 +664,13 @@ static int parse_raw_nbft(struct nbft_info *nbft) if (control->num_sec > 0) { struct nbft_security *raw_security_array; - verify(le32_to_cpu(control->seco) + le16_to_cpu(control->secl) * - control->num_sec <= le32_to_cpu(header->length), + verify(ctx, le32_to_cpu(control->seco) + + le16_to_cpu(control->secl) * control->num_sec <= + le32_to_cpu(header->length), "invalid security profile desciptor list offset"); raw_security_array = (struct nbft_security *)(raw_nbft + le32_to_cpu(control->seco)); - read_security_descriptors(nbft, control->num_sec, + read_security_descriptors(ctx, nbft, control->num_sec, raw_security_array, le16_to_cpu(control->secl)); } @@ -633,13 +681,14 @@ static int parse_raw_nbft(struct nbft_info *nbft) if (control->num_disc > 0) { struct nbft_discovery *raw_discovery_array; - verify(le32_to_cpu(control->disco) + le16_to_cpu(control->discl) * - control->num_disc <= le32_to_cpu(header->length), + verify(ctx, le32_to_cpu(control->disco) + + le16_to_cpu(control->discl) * control->num_disc <= + le32_to_cpu(header->length), "invalid discovery profile descriptor list offset"); raw_discovery_array = (struct nbft_discovery *)(raw_nbft + - le32_to_cpu(control->disco)); - read_discovery_descriptors(nbft, control->num_disc, raw_discovery_array, - le16_to_cpu(control->discl)); + le32_to_cpu(control->disco)); + read_discovery_descriptors(ctx, nbft, control->num_disc, + raw_discovery_array, le16_to_cpu(control->discl)); } /* @@ -648,19 +697,20 @@ static int parse_raw_nbft(struct nbft_info *nbft) if (control->num_ssns > 0) { struct nbft_ssns *raw_ssns_array; - verify(le32_to_cpu(control->ssnso) + le16_to_cpu(control->ssnsl) * - control->num_ssns <= le32_to_cpu(header->length), + verify(ctx, le32_to_cpu(control->ssnso) + + le16_to_cpu(control->ssnsl) * control->num_ssns <= + le32_to_cpu(header->length), "invalid subsystem namespace descriptor list offset"); raw_ssns_array = (struct nbft_ssns *)(raw_nbft + - le32_to_cpu(control->ssnso)); - read_ssns_descriptors(nbft, control->num_ssns, raw_ssns_array, - le16_to_cpu(control->ssnsl)); + le32_to_cpu(control->ssnso)); + read_ssns_descriptors(ctx, nbft, control->num_ssns, + raw_ssns_array, le16_to_cpu(control->ssnsl)); } return 0; } -void nvme_nbft_free(struct nbft_info *nbft) +void nvme_nbft_free(struct nvme_global_ctx *ctx, struct nbft_info *nbft) { struct nbft_info_hfi **hfi; struct nbft_info_security **sec; @@ -686,7 +736,8 @@ void nvme_nbft_free(struct nbft_info *nbft) free(nbft); } -int nvme_nbft_read(struct nbft_info **nbft, const char *filename) +int nvme_nbft_read(struct nvme_global_ctx *ctx, struct nbft_info **nbft, + const char *filename) { __u8 *raw_nbft = NULL; size_t raw_nbft_size; @@ -698,14 +749,14 @@ int nvme_nbft_read(struct nbft_info **nbft, const char *filename) */ raw_nbft_fp = fopen(filename, "rb"); if (raw_nbft_fp == NULL) { - nvme_msg(NULL, LOG_ERR, "Failed to open %s: %s\n", + nvme_msg(ctx, LOG_ERR, "Failed to open %s: %s\n", filename, strerror(errno)); return -EINVAL; } i = fseek(raw_nbft_fp, 0L, SEEK_END); if (i) { - nvme_msg(NULL, LOG_ERR, "Failed to read from %s: %s\n", + nvme_msg(ctx, LOG_ERR, "Failed to read from %s: %s\n", filename, strerror(errno)); fclose(raw_nbft_fp); return -EINVAL; @@ -716,14 +767,15 @@ int nvme_nbft_read(struct nbft_info **nbft, const char *filename) raw_nbft = malloc(raw_nbft_size); if (!raw_nbft) { - nvme_msg(NULL, LOG_ERR, "Failed to allocate memory for NBFT table"); + nvme_msg(ctx, LOG_ERR, + "Failed to allocate memory for NBFT table"); fclose(raw_nbft_fp); return -ENOMEM; } i = fread(raw_nbft, sizeof(*raw_nbft), raw_nbft_size, raw_nbft_fp); if (i != raw_nbft_size) { - nvme_msg(NULL, LOG_ERR, "Failed to read from %s: %s\n", + nvme_msg(ctx, LOG_ERR, "Failed to read from %s: %s\n", filename, strerror(errno)); fclose(raw_nbft_fp); free(raw_nbft); @@ -732,11 +784,12 @@ int nvme_nbft_read(struct nbft_info **nbft, const char *filename) fclose(raw_nbft_fp); /* - * alloc new struct nbft_info, add raw nbft & filename to it, and add it to the list + * alloc new struct nbft_info, add raw nbft & filename to it, + * and add it to the list */ *nbft = calloc(1, sizeof(struct nbft_info)); if (!*nbft) { - nvme_msg(NULL, LOG_ERR, "Could not allocate memory for NBFT\n"); + nvme_msg(ctx, LOG_ERR, "Could not allocate memory for NBFT\n"); free(raw_nbft); return -ENOMEM; } @@ -745,9 +798,9 @@ int nvme_nbft_read(struct nbft_info **nbft, const char *filename) (*nbft)->raw_nbft = raw_nbft; (*nbft)->raw_nbft_size = raw_nbft_size; - if (parse_raw_nbft(*nbft)) { - nvme_msg(NULL, LOG_ERR, "Failed to parse %s\n", filename); - nvme_nbft_free(*nbft); + if (parse_raw_nbft(ctx, *nbft)) { + nvme_msg(ctx, LOG_ERR, "Failed to parse %s\n", filename); + nvme_nbft_free(ctx, *nbft); return -EINVAL; } return 0; diff --git a/libnvme/src/nvme/nbft.h b/libnvme/src/nvme/nbft.h index 424d6504e1..871c05ac59 100644 --- a/libnvme/src/nvme/nbft.h +++ b/libnvme/src/nvme/nbft.h @@ -1234,6 +1234,7 @@ struct nbft_info { /** * nvme_nbft_read() - Read and parse contents of an ACPI NBFT table * + * @ctx: struct nvme_global_ctx object * @nbft: Parsed NBFT table data. * @filename: Filename of the raw NBFT table to read. * @@ -1242,12 +1243,14 @@ struct nbft_info { * * Return: 0 on success, errno otherwise. */ -int nvme_nbft_read(struct nbft_info **nbft, const char *filename); +int nvme_nbft_read(struct nvme_global_ctx *ctx, struct nbft_info **nbft, + const char *filename); /** * nvme_nbft_free() - Free the struct nbft_info and its contents + * @ctx: struct nvme_global_ctx object * @nbft: Parsed NBFT table data. */ -void nvme_nbft_free(struct nbft_info *nbft); +void nvme_nbft_free(struct nvme_global_ctx *ctx, struct nbft_info *nbft); #endif diff --git a/libnvme/test/nbft/nbft-dump.c b/libnvme/test/nbft/nbft-dump.c index 5fb2f2e9bf..1d6cc124fb 100644 --- a/libnvme/test/nbft/nbft-dump.c +++ b/libnvme/test/nbft/nbft-dump.c @@ -104,20 +104,29 @@ static void print_nbft(struct nbft_info *table) int main(int argc, char **argv) { struct nbft_info *table = NULL; - + struct nvme_global_ctx *ctx; + if (argc < 2) { fprintf(stderr, "Usage: %s TABLE\n", argv[0]); return 1; } - if (nvme_nbft_read(&table, argv[1]) != 0) { + ctx = nvme_create_global_ctx(stderr, false); + if (!ctx) { + fprintf(stderr, "Failed to create global context"); + return 1; + } + + if (nvme_nbft_read(ctx, &table, argv[1]) != 0) { fprintf(stderr, "Error parsing the NBFT table %s: %m\n", argv[1]); + nvme_free_global_ctx(ctx); return 2; } print_nbft(table); - nvme_nbft_free(table); + nvme_nbft_free(ctx, table); + nvme_free_global_ctx(ctx); return 0; } diff --git a/plugins/nbft/nbft-plugin.c b/plugins/nbft/nbft-plugin.c index e8545f6833..4f21689e91 100644 --- a/plugins/nbft/nbft-plugin.c +++ b/plugins/nbft/nbft-plugin.c @@ -534,13 +534,14 @@ static void normal_show_nbfts(struct nbft_file_entry *head, bool show_subsys, int show_nbft(int argc, char **argv, struct command *acmd, struct plugin *plugin) { const char *desc = "Display contents of the ACPI NBFT files."; + bool show_subsys = false, show_hfi = false, show_discovery = false; + _cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL; struct nbft_file_entry *head = NULL; struct list_head nbft_list; char *format = "normal"; char *nbft_path = NBFT_SYSFS_PATH; nvme_print_flags_t flags; int ret; - bool show_subsys = false, show_hfi = false, show_discovery = false; unsigned int verbose = 0; OPT_ARGS(opts) = { @@ -563,11 +564,17 @@ int show_nbft(int argc, char **argv, struct command *acmd, struct plugin *plugin if (ret < 0) return ret; + ctx = nvme_create_global_ctx(stderr, log_level); + if (!ctx) { + nvme_show_error("Failed to create global context"); + return -ENOMEM; + } + if (!(show_subsys || show_hfi || show_discovery)) show_subsys = show_hfi = show_discovery = true; list_head_init(&nbft_list); - ret = nvmf_nbft_read_files(nbft_path, &head); + ret = nvmf_nbft_read_files(ctx, nbft_path, &head); if (!ret && head) { if (flags == NORMAL) normal_show_nbfts(head, show_subsys, @@ -575,7 +582,7 @@ int show_nbft(int argc, char **argv, struct command *acmd, struct plugin *plugin else if (flags == JSON) ret = json_show_nbfts(head, show_subsys, show_hfi, show_discovery); - nvmf_nbft_free(head); + nvmf_nbft_free(ctx, head); } return ret; }