Bug Summary

File:.build-ci/../keysd/src/import.c
Warning:line 148, column 9
Potential leak of memory pointed to by 'copy'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name import.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -fcoverage-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -resource-dir /usr/bin/../lib/clang/22 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I keysd/nvme-keysd.p -I keysd -I ../keysd -I ../keysd/src -I ccan -I ../ccan -I . -I .. -I libnvme/src -I ../libnvme/src -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/bin/../lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu11 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-10-24-125112-639-1 -x c ../keysd/src/import.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * This file is part of nvme-cli.
4 * Copyright (c) 2026 Dell Technologies Inc. or its subsidiaries.
5 *
6 * Authors: Martin Belanger <martin.belanger@dell.com>
7 */
8
9#include <errno(*__errno_location ()).h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13
14#include <ccan/str/str.h>
15#include <daemon-util/log.h>
16#include <nvme/config.h>
17#include <nvme/crypto.h>
18#include <nvme/fabrics.h>
19#include <shared/cleanup-util.h>
20#include <shared/string-util.h>
21
22#include "config.h"
23#include "creds.h"
24#include "import.h"
25
26struct import_ctx {
27 struct libnvme_global_ctx *ctx;
28 const char *creds_dir;
29 const struct keysd_config *cfg;
30 struct kmip_job *jobs;
31 size_t n_jobs;
32 char *default_hostnqn; // system identity, for entries without one
33 bool_Bool default_read; // default_hostnqn was looked up
34 char **done; // "<hostnqn> <subsysnqn>" already handled
35 size_t n_done;
36};
37
38/* Look up the system host NQN only when an entry needs it. */
39static const char *default_hostnqn(struct import_ctx *ic)
40{
41 __cleanup_free__attribute__((cleanup(shr_freep))) char *hostid = NULL((void*)0);
42 int r;
43
44 if (ic->default_read)
45 return ic->default_hostnqn;
46
47 ic->default_read = true1;
48 r = libnvmf_host_get_ids(ic->ctx, NULL((void*)0), NULL((void*)0), &ic->default_hostnqn,
49 &hostid);
50 if (r < 0)
51 log_warn("no default host NQN: %s", strerror(-r))dmn_log_msg(DMN_LOG_WARN, "no default host NQN: %s", strerror
(-r))
;
52
53 return ic->default_hostnqn;
54}
55
56/*
57 * Every path of a subsystem is a connection of its own, with the same
58 * key. Return true the first time a (hostnqn, subsysnqn) pair is seen.
59 */
60static bool_Bool first_time(struct import_ctx *ic, const char *hostnqn,
61 const char *subsysnqn)
62{
63 char *pair, **p;
64 size_t i;
65
66 if (asprintf(&pair, "%s %s", hostnqn, subsysnqn) < 0)
67 return true1;
68
69 for (i = 0; i < ic->n_done; i++) {
70 if (streq(ic->done[i], pair)(strcmp((ic->done[i]),(pair)) == 0)) {
71 free(pair);
72 return false0;
73 }
74 }
75
76 p = realloc(ic->done, (ic->n_done + 1) * sizeof(*p));
77 if (!p) {
78 free(pair);
79 return true1;
80 }
81 ic->done = p;
82 ic->done[ic->n_done++] = pair;
83
84 return true1;
85}
86
87static const char *param(const struct libnvmf_params *params, const char *key)
88{
89 const char *value = libnvmf_params_get(params, key);
90
91 return (value && *value) ? value : NULL((void*)0);
92}
93
94/* A credential name is a file name in the credential directory. */
95static bool_Bool cred_name_valid(const char *name)
96{
97 return name[0] != '.' && !strchr(name, '/')_Generic (0 ? (name) : (void *) 1, const void *: (const char *
) (strchr (name, '/')), default: strchr (name, '/'))
;
98}
99
100/*
101 * Large enough for a PSK in the interchange format: a 48-byte key plus
102 * its CRC is 72 characters in base64, plus the 17-character framing.
103 */
104#define CRED_MAX128 128
105
106static void free_secret(void *p, size_t len)
107{
108 if (!p)
109 return;
110 explicit_bzero(p, len);
111 free(p);
112}
113
114struct revoke_ctx {
115 const char *hostnqn;
116 const char *subsysnqn;
117 const char *keep; // identity of the key to keep
118 char **identities;
119 size_t n;
120 int err;
121};
122
123/*
124 * A PSK description is "NVMe<v><R|G><hmac> <hostnqn> <subsysnqn>", and
125 * version 1 adds " <digest>". Collect every other key for the same pair.
126 */
127static void collect_other_key(struct libnvme_global_ctx *ctx
128 __attribute__((unused)),
129 long keyring __attribute__((unused)),
130 long key __attribute__((unused)),
131 char *desc, int desc_len __attribute__((unused)),
132 void *data)
133{
134 struct revoke_ctx *rc = data;
135 __cleanup_free__attribute__((cleanup(shr_freep))) char *copy = NULL((void*)0);
136 char *save, *host, *subsys, **p;
137
138 if (rc->err || streq(desc, rc->keep)(strcmp((desc),(rc->keep)) == 0))
1
Assuming field 'err' is 0
2
Assuming the condition is false
3
Taking false branch
139 return;
140
141 copy = strdup(desc);
4
Memory is allocated
142 if (!copy) {
5
Assuming 'copy' is non-null
6
Taking false branch
143 rc->err = -ENOMEM12;
144 return;
145 }
146 if (!strtok_r(copy, " ", &save))
7
Assuming the condition is false
8
Taking false branch
147 return;
148 host = strtok_r(NULL((void*)0), " ", &save);
9
Potential leak of memory pointed to by 'copy'
149 subsys = strtok_r(NULL((void*)0), " ", &save);
150 if (!host || !subsys || !streq(host, rc->hostnqn)(strcmp((host),(rc->hostnqn)) == 0) ||
151 !streq(subsys, rc->subsysnqn)(strcmp((subsys),(rc->subsysnqn)) == 0))
152 return;
153
154 p = realloc(rc->identities, (rc->n + 1) * sizeof(*p));
155 if (!p) {
156 rc->err = -ENOMEM12;
157 return;
158 }
159 rc->identities = p;
160 rc->identities[rc->n] = strdup(desc);
161 if (!rc->identities[rc->n]) {
162 rc->err = -ENOMEM12;
163 return;
164 }
165 rc->n++;
166}
167
168static void revoke_other_keys(struct libnvme_global_ctx *ctx,
169 const char *source, const char *keyring,
170 const char *hostnqn, const char *subsysnqn,
171 const char *keep)
172{
173 struct revoke_ctx rc = {
174 .hostnqn = hostnqn,
175 .subsysnqn = subsysnqn,
176 .keep = keep,
177 };
178 size_t i;
179 int r;
180
181 // Revoke after the scan, not while it walks the keyring.
182 r = libnvmf_scan_tls_keys(ctx, keyring, collect_other_key, &rc);
183 log_dbg("scanned %d keys, %zu to revoke", r, rc.n)dmn_log_msg(DMN_LOG_DEBUG, "%s() - " "scanned %d keys, %zu to revoke"
, __func__, r, rc.n)
;
184 if (r < 0 || rc.err)
185 log_err("%s: %s: cannot scan the keyring: %s", source,dmn_log_msg(DMN_LOG_ERR, "%s: %s: cannot scan the keyring: %s"
, source, subsysnqn, strerror(-(r < 0 ? r : rc.err)))
186 subsysnqn, strerror(-(r < 0 ? r : rc.err)))dmn_log_msg(DMN_LOG_ERR, "%s: %s: cannot scan the keyring: %s"
, source, subsysnqn, strerror(-(r < 0 ? r : rc.err)))
;
187
188 for (i = 0; i < rc.n; i++) {
189 r = libnvmf_revoke_tls_key(ctx, keyring, "psk",
190 rc.identities[i]);
191 if (r < 0)
192 log_err("cannot revoke '%s': %s", rc.identities[i],dmn_log_msg(DMN_LOG_ERR, "cannot revoke '%s': %s", rc.identities
[i], strerror(-r))
193 strerror(-r))dmn_log_msg(DMN_LOG_ERR, "cannot revoke '%s': %s", rc.identities
[i], strerror(-r))
;
194 else
195 log_info("revoked '%s'", rc.identities[i])dmn_log_msg(DMN_LOG_INFO, "revoked '%s'", rc.identities[i]);
196 free(rc.identities[i]);
197 }
198 free(rc.identities);
199}
200
201/*
202 * Put the PSK @encoded, in the interchange format, in @keyring for
203 * @hostnqn and @subsysnqn. @origin says where the PSK comes from, for the
204 * log.
205 */
206static int import_psk(struct import_ctx *ic, const char *source,
207 const char *keyring, const char *hostnqn,
208 const char *subsysnqn, const char *origin,
209 const char *encoded)
210{
211 __cleanup_free__attribute__((cleanup(shr_freep))) char *identity = NULL((void*)0);
212 enum libnvmf_hmac_alg hmac;
213 unsigned char version;
214 unsigned char *psk = NULL((void*)0);
215 size_t psk_len = 0;
216 long keyring_id, key;
217 int r;
218
219 r = libnvmf_import_tls_key_versioned(ic->ctx, encoded, &version,
220 &hmac, &psk_len, &psk);
221 if (r < 0) {
222 log_err("%s: %s: %s is not a valid PSK: %s", source,dmn_log_msg(DMN_LOG_ERR, "%s: %s: %s is not a valid PSK: %s",
source, subsysnqn, origin, strerror(-r))
223 subsysnqn, origin, strerror(-r))dmn_log_msg(DMN_LOG_ERR, "%s: %s: %s is not a valid PSK: %s",
source, subsysnqn, origin, strerror(-r))
;
224 return r;
225 }
226
227 r = libnvmf_generate_tls_key_identity(ic->ctx, hostnqn, subsysnqn,
228 version, hmac, psk, psk_len,
229 &identity);
230 if (r < 0) {
231 log_err("%s: %s: cannot derive the PSK identity: %s", source,dmn_log_msg(DMN_LOG_ERR, "%s: %s: cannot derive the PSK identity: %s"
, source, subsysnqn, strerror(-r))
232 subsysnqn, strerror(-r))dmn_log_msg(DMN_LOG_ERR, "%s: %s: cannot derive the PSK identity: %s"
, source, subsysnqn, strerror(-r))
;
233 goto out;
234 }
235
236 r = libnvmf_lookup_keyring(ic->ctx, keyring, &keyring_id);
237 if (!r)
238 r = libnvmf_set_keyring(ic->ctx, keyring_id);
239 if (r < 0) {
240 log_err("%s: %s: keyring '%s' not available: %s", source,dmn_log_msg(DMN_LOG_ERR, "%s: %s: keyring '%s' not available: %s"
, source, subsysnqn, keyring ?: ".nvme", strerror(-r))
241 subsysnqn, keyring ?: ".nvme", strerror(-r))dmn_log_msg(DMN_LOG_ERR, "%s: %s: keyring '%s' not available: %s"
, source, subsysnqn, keyring ?: ".nvme", strerror(-r))
;
242 goto out;
243 }
244
245 // The identity ends with a digest of the PSK: same identity, same key.
246 r = libnvmf_lookup_key(ic->ctx, "psk", identity, &key);
247 if (!r) {
248 log_dbg("'%s' already present", identity)dmn_log_msg(DMN_LOG_DEBUG, "%s() - " "'%s' already present", __func__
, identity)
;
249 } else {
250 log_dbg("'%s' not found: %s", identity, strerror(-r))dmn_log_msg(DMN_LOG_DEBUG, "%s() - " "'%s' not found: %s", __func__
, identity, strerror(-r))
;
251 r = libnvmf_insert_tls_key_versioned(ic->ctx, keyring, "psk",
252 hostnqn, subsysnqn,
253 version, hmac, psk,
254 psk_len, &key);
255 if (r < 0) {
256 log_err("%s: %s: cannot insert the PSK: %s", source,dmn_log_msg(DMN_LOG_ERR, "%s: %s: cannot insert the PSK: %s",
source, subsysnqn, strerror(-r))
257 subsysnqn, strerror(-r))dmn_log_msg(DMN_LOG_ERR, "%s: %s: cannot insert the PSK: %s",
source, subsysnqn, strerror(-r))
;
258 goto out;
259 }
260 log_info("imported '%s' from %s", identity, origin)dmn_log_msg(DMN_LOG_INFO, "imported '%s' from %s", identity, origin
)
;
261 }
262
263 revoke_other_keys(ic->ctx, source, keyring, hostnqn, subsysnqn,
264 identity);
265
266out:
267 free_secret(psk, psk_len);
268
269 return r;
270}
271
272static int import_cred(struct import_ctx *ic, const char *source,
273 const char *keyring, const char *hostnqn,
274 const char *subsysnqn, const char *name)
275{
276 __cleanup_free__attribute__((cleanup(shr_freep))) char *origin = NULL((void*)0);
277 __cleanup_free__attribute__((cleanup(shr_freep))) char *error = NULL((void*)0);
278 char encoded[CRED_MAX128 + 1];
279 int r;
280
281 if (!cred_name_valid(name)) {
282 log_err("%s: %s: invalid credential name '%s'", source,dmn_log_msg(DMN_LOG_ERR, "%s: %s: invalid credential name '%s'"
, source, subsysnqn, name)
283 subsysnqn, name)dmn_log_msg(DMN_LOG_ERR, "%s: %s: invalid credential name '%s'"
, source, subsysnqn, name)
;
284 return -EINVAL22;
285 }
286
287 r = creds_decrypt(ic->creds_dir, name, encoded, sizeof(encoded),
288 &error);
289 if (r < 0) {
290 explicit_bzero(encoded, sizeof(encoded));
291 log_err("%s: %s: cannot decrypt credential '%s': %s", source,dmn_log_msg(DMN_LOG_ERR, "%s: %s: cannot decrypt credential '%s': %s"
, source, subsysnqn, name, error ?: strerror(-r))
292 subsysnqn, name, error ?: strerror(-r))dmn_log_msg(DMN_LOG_ERR, "%s: %s: cannot decrypt credential '%s': %s"
, source, subsysnqn, name, error ?: strerror(-r))
;
293 return r;
294 }
295
296 if (asprintf(&origin, "credential '%s'", name) < 0)
297 r = -ENOMEM12;
298 else
299 r = import_psk(ic, source, keyring, hostnqn, subsysnqn, origin,
300 encoded);
301 explicit_bzero(encoded, sizeof(encoded));
302
303 return r;
304}
305
306static void free_job(struct kmip_job *job)
307{
308 free(job->source);
309 free(job->keyring);
310 free(job->hostnqn);
311 free(job->subsysnqn);
312 free(job->name);
313}
314
315/* Find the KMS of "kmip:<name>", or of "kmip" when there is only one. */
316static const struct keysd_kmip *find_kms(struct import_ctx *ic,
317 const char *source, const char *subsysnqn, const char *src)
318{
319 const char *name = shr_startswith(src, "kmip:");
320 const struct keysd_kmip *kms;
321
322 if (!name) {
323 if (ic->cfg->nr_kmip == 1)
324 return &ic->cfg->kmip[0];
325 if (ic->cfg->nr_kmip)
326 log_err("%s: %s: several KMSes: use tls-key-source = kmip:<name>",dmn_log_msg(DMN_LOG_ERR, "%s: %s: several KMSes: use tls-key-source = kmip:<name>"
, source, subsysnqn)
327 source, subsysnqn)dmn_log_msg(DMN_LOG_ERR, "%s: %s: several KMSes: use tls-key-source = kmip:<name>"
, source, subsysnqn)
;
328 else
329 log_err("%s: %s: tls-key-source is kmip but no KMS is configured, skipped",dmn_log_msg(DMN_LOG_ERR, "%s: %s: tls-key-source is kmip but no KMS is configured, skipped"
, source, subsysnqn)
330 source, subsysnqn)dmn_log_msg(DMN_LOG_ERR, "%s: %s: tls-key-source is kmip but no KMS is configured, skipped"
, source, subsysnqn)
;
331 return NULL((void*)0);
332 }
333
334 kms = config_find_kmip(ic->cfg, name);
335 if (!kms)
336 log_err("%s: %s: KMS '%s' is not configured", source,dmn_log_msg(DMN_LOG_ERR, "%s: %s: KMS '%s' is not configured"
, source, subsysnqn, name)
337 subsysnqn, name)dmn_log_msg(DMN_LOG_ERR, "%s: %s: KMS '%s' is not configured"
, source, subsysnqn, name)
;
338
339 return kms;
340}
341
342/* Collect a key to get from a KMS. */
343static void add_kmip_job(struct import_ctx *ic, const char *source,
344 const char *keyring, const char *hostnqn,
345 const char *subsysnqn, const char *src,
346 const char *name)
347{
348 const struct keysd_kmip *kms;
349 struct kmip_job *jobs, *job;
350
351#ifndef CONFIG_KMIP
352 log_warn("%s: %s: this build does not support tls-key-source '%s', skipped",dmn_log_msg(DMN_LOG_WARN, "%s: %s: this build does not support tls-key-source '%s', skipped"
, source, subsysnqn, src)
353 source, subsysnqn, src)dmn_log_msg(DMN_LOG_WARN, "%s: %s: this build does not support tls-key-source '%s', skipped"
, source, subsysnqn, src)
;
354 return;
355#endif
356
357 kms = find_kms(ic, source, subsysnqn, src);
358 if (!kms)
359 return;
360
361 jobs = realloc(ic->jobs, (ic->n_jobs + 1) * sizeof(*jobs));
362 if (!jobs) {
363 log_err("%s: %s: out of memory", source, subsysnqn)dmn_log_msg(DMN_LOG_ERR, "%s: %s: out of memory", source, subsysnqn
)
;
364 return;
365 }
366 ic->jobs = jobs;
367
368 job = &ic->jobs[ic->n_jobs];
369 job->kms = kms;
370 job->source = strdup(source);
371 job->keyring = shr_xstrdup(keyring);
372 job->hostnqn = strdup(hostnqn);
373 job->subsysnqn = strdup(subsysnqn);
374 job->name = strdup(name);
375 if (!job->source || (keyring && !job->keyring) || !job->hostnqn ||
376 !job->subsysnqn || !job->name) {
377 log_err("%s: %s: out of memory", source, subsysnqn)dmn_log_msg(DMN_LOG_ERR, "%s: %s: out of memory", source, subsysnqn
)
;
378 free_job(job);
379 return;
380 }
381 ic->n_jobs++;
382}
383
384int import_kmip_psk(struct import_ctx *ic, const struct kmip_job *job,
385 const char *encoded)
386{
387 __cleanup_free__attribute__((cleanup(shr_freep))) char *origin = NULL((void*)0);
388
389 if (asprintf(&origin, "KMS '%s', key '%s'", job->kms->name,
390 job->name) < 0)
391 return -ENOMEM12;
392
393 return import_psk(ic, job->source, job->keyring, job->hostnqn,
394 job->subsysnqn, origin, encoded);
395}
396
397static void import_conn(const struct libnvmf_config_conn *conn,
398 void *user_data)
399{
400 struct import_ctx *ic = user_data;
401 const struct libnvmf_params *params;
402 const char *source, *src, *name, *hostnqn, *subsysnqn;
403
404 params = libnvmf_config_conn_get_params(conn);
405 src = param(params, "tls-key-source");
406 if (!src || streq(src, "inline")(strcmp((src),("inline")) == 0))
407 return;
408
409 source = libnvmf_config_conn_get_source(conn);
410 subsysnqn = libnvmf_config_conn_get_subsysnqn(conn);
411 hostnqn = libnvmf_config_conn_get_hostnqn(conn) ?: default_hostnqn(ic);
412 if (!hostnqn) {
413 log_warn("%s: %s: no host NQN, skipped", source, subsysnqn)dmn_log_msg(DMN_LOG_WARN, "%s: %s: no host NQN, skipped", source
, subsysnqn)
;
414 return;
415 }
416 if (!first_time(ic, hostnqn, subsysnqn))
417 return;
418
419 name = param(params, "tls-key");
420 if (!name) {
421 log_warn("%s: %s: tls-key-source is %s but tls-key is not set, skipped",dmn_log_msg(DMN_LOG_WARN, "%s: %s: tls-key-source is %s but tls-key is not set, skipped"
, source, subsysnqn, src)
422 source, subsysnqn, src)dmn_log_msg(DMN_LOG_WARN, "%s: %s: tls-key-source is %s but tls-key is not set, skipped"
, source, subsysnqn, src)
;
423 return;
424 }
425
426 if (streq(src, "kmip")(strcmp((src),("kmip")) == 0) || shr_startswith(src, "kmip:"))
427 add_kmip_job(ic, source, param(params, "keyring"), hostnqn,
428 subsysnqn, src, name);
429 else if (streq(src, "systemd-creds")(strcmp((src),("systemd-creds")) == 0))
430 import_cred(ic, source, param(params, "keyring"), hostnqn,
431 subsysnqn, name);
432 else
433 log_warn("%s: %s: tls-key-source '%s' is not supported, skipped",dmn_log_msg(DMN_LOG_WARN, "%s: %s: tls-key-source '%s' is not supported, skipped"
, source, subsysnqn, src)
434 source, subsysnqn, src)dmn_log_msg(DMN_LOG_WARN, "%s: %s: tls-key-source '%s' is not supported, skipped"
, source, subsysnqn, src)
;
435}
436
437static void find_tls_key_source(const struct libnvmf_config_conn *conn,
438 void *user_data)
439{
440 const char *src;
441 bool_Bool *found = user_data;
442
443 src = param(libnvmf_config_conn_get_params(conn), "tls-key-source");
444 if (src && !streq(src, "inline")(strcmp((src),("inline")) == 0))
445 *found = true1;
446}
447
448bool_Bool import_needed(struct libnvme_global_ctx *ctx, const char *fabrics_conf)
449{
450 struct libnvmf_config *cfg;
451 bool_Bool found = false0;
452 int r;
453
454 r = libnvmf_config_read(ctx, fabrics_conf, &cfg);
455 if (r < 0) {
456 log_err("cannot read the fabrics configuration: %s",dmn_log_msg(DMN_LOG_ERR, "cannot read the fabrics configuration: %s"
, strerror(-r))
457 strerror(-r))dmn_log_msg(DMN_LOG_ERR, "cannot read the fabrics configuration: %s"
, strerror(-r))
;
458 return false0;
459 }
460
461 libnvmf_config_conn_for_each(cfg, find_tls_key_source, &found);
462 libnvmf_config_free(cfg);
463
464 return found;
465}
466
467struct import_ctx *import_new(struct libnvme_global_ctx *ctx,
468 const char *creds_dir, const struct keysd_config *cfg)
469{
470 struct import_ctx *ic;
471
472 ic = calloc(1, sizeof(*ic));
473 if (!ic)
474 return NULL((void*)0);
475 ic->ctx = ctx;
476 ic->creds_dir = creds_dir;
477 ic->cfg = cfg;
478
479 return ic;
480}
481
482void import_free(struct import_ctx *ic)
483{
484 size_t i;
485
486 if (!ic)
487 return;
488
489 for (i = 0; i < ic->n_jobs; i++)
490 free_job(&ic->jobs[i]);
491 free(ic->jobs);
492 for (i = 0; i < ic->n_done; i++)
493 free(ic->done[i]);
494 free(ic->done);
495 free(ic->default_hostnqn);
496 free(ic);
497}
498
499void import_keys(struct import_ctx *ic, const char *fabrics_conf)
500{
501 struct libnvmf_config *cfg;
502 int r;
503
504 r = libnvmf_config_read(ic->ctx, fabrics_conf, &cfg);
505 if (r < 0) {
506 log_err("cannot read the fabrics configuration: %s",dmn_log_msg(DMN_LOG_ERR, "cannot read the fabrics configuration: %s"
, strerror(-r))
507 strerror(-r))dmn_log_msg(DMN_LOG_ERR, "cannot read the fabrics configuration: %s"
, strerror(-r))
;
508 return;
509 }
510
511 libnvmf_config_conn_for_each(cfg, import_conn, ic);
512 libnvmf_config_free(cfg);
513}
514
515size_t import_kmip_jobs(struct import_ctx *ic, const struct kmip_job **jobs)
516{
517 *jobs = ic->jobs;
518
519 return ic->n_jobs;
520}