Bug Summary

File:.build-ci/../libnvme/tests/config-api.c
Warning:line 554, column 6
Value of 'errno' was not checked and may be overwritten by function 'fread'

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 config-api.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 libnvme/tests/test-config-api.p -I libnvme/tests -I ../libnvme/tests -I . -I .. -I ccan -I ../ccan -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 ../libnvme/tests/config-api.c
1// SPDX-License-Identifier: LGPL-2.1-or-later
2/**
3 * This file is part of libnvme.
4 * Copyright (c) 2026 Dell Technologies Inc. or its subsidiaries.
5 * Authors: Martin Belanger <martin.belanger@dell.com>
6 *
7 * Tests for the public connection-config API (<nvme/config.h>). Linked
8 * against the real shared library, so it also proves every symbol is
9 * exported by the version script.
10 */
11
12#include <shared/assert-util.h>
13#include <errno(*__errno_location ()).h>
14#include <stdbool.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18
19#include <sys/stat.h>
20#include <unistd.h>
21
22#include <ccan/array_size/array_size.h>
23
24#include <shared/string-util.h>
25
26#include <nvme/lib.h>
27#include <nvme/config.h>
28#include <nvme/fabrics.h>
29#include <nvme/nvme-types-fabrics.h>
30#include <nvme/tid.h>
31
32static void write_file(const char *dir, const char *name, const char *text)
33{
34 char path[512];
35 FILE *fp;
36
37 snprintf(path, sizeof(path), "%s/%s", dir, name);
38 fp = fopen(path, "w");
39 shr_assert(fp)((void)((fp) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 39, "fp"), 0)))
;
40 shr_assert(fputs(text, fp) >= 0)((void)((fputs(text, fp) >= 0) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 40, "fputs(text, fp) >= 0"), 0)))
;
41 fclose(fp);
42}
43
44static void rm_file(const char *dir, const char *name)
45{
46 char path[512];
47
48 snprintf(path, sizeof(path), "%s/%s", dir, name);
49 unlink(path);
50}
51
52/*
53 * The shared fixture: a main file with per-type defaults, one DC and one
54 * subsystem, plus a second-persona drop-in.
55 */
56static const char main_text[] =
57 "[Discovery Controller Defaults]\n"
58 "ctrl-loss-tmo = 600\n"
59 "keep-alive-tmo = 30\n"
60 "[I/O Controller Defaults]\n"
61 "ctrl-loss-tmo = 600\n"
62 "keep-alive-tmo = 5\n"
63 "[Discovery Controller]\n"
64 "controller = transport=tcp;traddr=10.0.0.5;trsvcid=8009\n"
65 "[Subsystem]\n"
66 "nqn = nqn.2014-08.org.nvmexpress:main-vol\n"
67 "tls = true\n"
68 "data-digest = no\n"
69 "controller = transport=tcp;traddr=10.0.0.9;trsvcid=4420\n";
70
71static const char prod_text[] =
72 "[Host]\n"
73 "hostnqn = nqn.2014-08.org.nvmexpress:prod-host\n"
74 "hostid = 46ba5037-7ce5-41fa-9452-48477bf00080\n"
75 "hostsymname = prod\n"
76 "[Subsystem]\n"
77 "nqn = nqn.2014-08.org.nvmexpress:prod-vol\n"
78 "reconnect-delay =\n"
79 "controller = transport=tcp;traddr=10.0.0.7;trsvcid=4420;ctrl-loss-tmo=1800\n";
80
81struct fixture {
82 char dir[32];
83 char main_path[288];
84 char dropin_dir[288];
85};
86
87static void fixture_create(struct fixture *fx)
88{
89 snprintf(fx->dir, sizeof(fx->dir), "/tmp/nvme-config-api-XXXXXX");
90 shr_assert(mkdtemp(fx->dir))((void)((mkdtemp(fx->dir)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 90, "mkdtemp(fx->dir)"), 0)))
;
91 snprintf(fx->main_path, sizeof(fx->main_path), "%s/nvme-fabrics.conf",
92 fx->dir);
93 snprintf(fx->dropin_dir, sizeof(fx->dropin_dir),
94 "%s/nvme-fabrics.conf.d", fx->dir);
95 shr_assert(mkdir(fx->dropin_dir, 0755) == 0)((void)((mkdir(fx->dropin_dir, 0755) == 0) || (shr_assert_fail
("../libnvme/tests/config-api.c", 95, "mkdir(fx->dropin_dir, 0755) == 0"
), 0)))
;
96 write_file(fx->dir, "nvme-fabrics.conf", main_text);
97 write_file(fx->dropin_dir, "10-prod.conf", prod_text);
98}
99
100static void fixture_destroy(struct fixture *fx)
101{
102 rm_file(fx->dropin_dir, "10-prod.conf");
103 rmdir(fx->dropin_dir);
104 rm_file(fx->dir, "nvme-fabrics.conf");
105 rmdir(fx->dir);
106}
107
108struct conn_list {
109 const struct libnvmf_config_conn *conn[8];
110 size_t n;
111};
112
113static void collect(const struct libnvmf_config_conn *conn, void *user_data)
114{
115 struct conn_list *list = user_data;
116
117 shr_assert(list->n < 8)((void)((list->n < 8) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 117, "list->n < 8"), 0)))
;
118 list->conn[list->n++] = conn;
119}
120
121static bool_Bool test_read(struct libnvme_global_ctx *ctx, const struct fixture *fx)
122{
123 const struct libnvmf_config_conn *dc, *mv, *pv;
124 struct conn_list list = { 0 };
125 const struct libnvmf_params *params;
126 struct libnvmf_config *config;
127 bool_Bool pass = true1;
128
129 printf("test_read:\n");
130
131 if (libnvmf_config_read(ctx, fx->main_path, &config)) {
132 printf(" - read failed [FAIL]\n");
133 return false0;
134 }
135
136 libnvmf_config_conn_for_each(config, collect, &list);
137 if (list.n != 3) {
138 printf(" - expected 3 connections, got %zu [FAIL]\n", list.n);
139 libnvmf_config_free(config);
140 return false0;
141 }
142 printf(" - 3 connections resolved [PASS]\n");
143
144 /* Main file first (DC, then subsystem), then the drop-in. */
145 dc = list.conn[0];
146 mv = list.conn[1];
147 pv = list.conn[2];
148
149 if (!libnvmf_config_conn_is_dc(dc) || libnvmf_config_conn_is_dc(mv) ||
150 libnvmf_config_conn_is_dc(pv)) {
151 printf(" - connection roles [FAIL]\n");
152 pass = false0;
153 } else {
154 printf(" - roles: DC + two subsystems [PASS]\n");
155 }
156
157 if (strcmp(libnvmf_config_conn_get_transport(dc), "tcp") ||
158 strcmp(libnvmf_config_conn_get_traddr(dc), "10.0.0.5") ||
159 strcmp(libnvmf_config_conn_get_subsysnqn(dc),
160 NVME_DISC_SUBSYS_NAME"nqn.2014-08.org.nvmexpress.discovery")) {
161 printf(" - DC addressing + well-known NQN [FAIL]\n");
162 pass = false0;
163 } else {
164 printf(" - DC addressing + well-known NQN [PASS]\n");
165 }
166
167 if (strcmp(libnvmf_config_conn_get_subsysnqn(pv), "nqn.2014-08.org.nvmexpress:prod-vol") ||
168 strcmp(libnvmf_config_conn_get_hostnqn(pv), "nqn.2014-08.org.nvmexpress:prod-host") ||
169 strcmp(libnvmf_config_conn_get_hostid(pv),
170 "46ba5037-7ce5-41fa-9452-48477bf00080")) {
171 printf(" - drop-in persona identity [FAIL]\n");
172 pass = false0;
173 } else {
174 printf(" - drop-in persona identity raw [PASS]\n");
175 }
176
177 if (libnvmf_config_conn_get_hostnqn(mv) ||
178 libnvmf_config_conn_get_hostsymname(mv)) {
179 printf(" - main persona left to system default [FAIL]\n");
180 pass = false0;
181 } else {
182 printf(" - main persona left to system default [PASS]\n");
183 }
184
185 if (!libnvmf_config_conn_get_hostsymname(pv) ||
186 strcmp(libnvmf_config_conn_get_hostsymname(pv), "prod")) {
187 printf(" - hostsymname [FAIL]\n");
188 pass = false0;
189 } else {
190 printf(" - hostsymname carried on the drop-in persona [PASS]\n");
191 }
192
193 params = libnvmf_config_conn_get_params(mv);
194 if (!params || strcmp(libnvmf_params_get(params, "ctrl-loss-tmo"), "600") ||
195 strcmp(libnvmf_params_get(params, "keep-alive-tmo"), "5") ||
196 strcmp(libnvmf_params_get(params, "tls"), "true") ||
197 libnvmf_params_get(params, "reconnect-delay")) {
198 printf(" - main subsystem cascade [FAIL]\n");
199 pass = false0;
200 } else {
201 printf(" - main cascade: defaults + section [PASS]\n");
202 }
203
204 params = libnvmf_config_conn_get_params(pv);
205 if (!params ||
206 strcmp(libnvmf_params_get(params, "ctrl-loss-tmo"), "1800") ||
207 strcmp(libnvmf_params_get(params, "keep-alive-tmo"), "5")) {
208 printf(" - per-path override [FAIL]\n");
209 pass = false0;
210 } else {
211 printf(" - per-path override beats the type default [PASS]\n");
212 }
213
214 if (!strstr(libnvmf_config_conn_get_source(dc), "nvme-fabrics.conf")_Generic (0 ? (libnvmf_config_conn_get_source(dc)) : (void *)
1, const void *: (const char *) (strstr (libnvmf_config_conn_get_source
(dc), "nvme-fabrics.conf")), default: strstr (libnvmf_config_conn_get_source
(dc), "nvme-fabrics.conf"))
||
215 !strstr(libnvmf_config_conn_get_source(pv), "10-prod.conf")_Generic (0 ? (libnvmf_config_conn_get_source(pv)) : (void *)
1, const void *: (const char *) (strstr (libnvmf_config_conn_get_source
(pv), "10-prod.conf")), default: strstr (libnvmf_config_conn_get_source
(pv), "10-prod.conf"))
) {
216 printf(" - source provenance [FAIL]\n");
217 pass = false0;
218 } else {
219 printf(" - source names the originating file [PASS]\n");
220 }
221
222 libnvmf_config_free(config);
223
224 return pass;
225}
226
227static bool_Bool test_resolve_discovered(struct libnvme_global_ctx *ctx,
228 const struct fixture *fx)
229{
230 const struct libnvmf_params *params;
231 struct conn_list list = { 0 };
232 struct libnvmf_config *config;
233 bool_Bool pass = true1;
234
235 printf("test_resolve_discovered:\n");
236
237 shr_assert(!libnvmf_config_read(ctx, fx->main_path, &config))((void)((!libnvmf_config_read(ctx, fx->main_path, &config
)) || (shr_assert_fail("../libnvme/tests/config-api.c", 237, "!libnvmf_config_read(ctx, fx->main_path, &config)"
), 0)))
;
238 libnvmf_config_conn_for_each(config, collect, &list);
239 shr_assert(list.n == 3 && libnvmf_config_conn_is_dc(list.conn[0]))((void)((list.n == 3 && libnvmf_config_conn_is_dc(list
.conn[0])) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 239, "list.n == 3 && libnvmf_config_conn_is_dc(list.conn[0])"
), 0)))
;
240
241 /* A DLP IOC discovered via the configured DC: that DC's file scope. */
242 params = libnvmf_config_resolve_discovered(config, list.conn[0], false0);
243 if (!params || strcmp(libnvmf_params_get(params, "keep-alive-tmo"), "5") ||
244 strcmp(libnvmf_params_get(params, "ctrl-loss-tmo"), "600") ||
245 libnvmf_params_get(params, "tls")) {
246 printf(" - DLP IOC scope via DC [FAIL]\n");
247 pass = false0;
248 } else {
249 printf(" - DLP IOC draws the DC's file scope [PASS]\n");
250 }
251
252 /* A referral DC discovered via the configured DC. */
253 params = libnvmf_config_resolve_discovered(config, list.conn[0], true1);
254 if (!params ||
255 strcmp(libnvmf_params_get(params, "keep-alive-tmo"), "30")) {
256 printf(" - referral DC scope via DC [FAIL]\n");
257 pass = false0;
258 } else {
259 printf(" - referral DC draws the DC-defaults scope [PASS]\n");
260 }
261
262 /* No configured origin (an mDNS-found DC): the top-level scope. */
263 params = libnvmf_config_resolve_discovered(config, NULL((void*)0), true1);
264 if (!params ||
265 strcmp(libnvmf_params_get(params, "keep-alive-tmo"), "30") ||
266 strcmp(libnvmf_params_get(params, "ctrl-loss-tmo"), "600")) {
267 printf(" - top-level scope [FAIL]\n");
268 pass = false0;
269 } else {
270 printf(" - no origin falls back to the top-level scope [PASS]\n");
271 }
272
273 /* An IOC is not a discovery origin. */
274 if (libnvmf_config_resolve_discovered(config, list.conn[1], false0)) {
275 printf(" - IOC as origin rejected [FAIL]\n");
276 pass = false0;
277 } else {
278 printf(" - an IOC connection is not a discovery origin [PASS]\n");
279 }
280
281 libnvmf_config_free(config);
282
283 return pass;
284}
285
286/*
287 * Sections that supply the KX-HMAC-CHAP secrets of discovered controllers.
288 * sub1 has no controller= line, sub2 has one. The drop-in is another
289 * persona with its own secret for sub1.
290 */
291static const char keys_text[] =
292 "[I/O Controller Defaults]\n"
293 "ctrl-loss-tmo = 600\n"
294 "kxchap-secret = DHHC-1:00:default:\n"
295 "[Discovery Controller]\n"
296 "controller = transport=tcp;traddr=10.0.0.5;trsvcid=8009\n"
297 "[Subsystem]\n"
298 "nqn = nqn.2014-08.org.nvmexpress:sub1\n"
299 "kxchap-secret = DHHC-1:00:sub1-host:\n"
300 "kxchap-ctrl-secret = DHHC-1:00:sub1-ctrl:\n"
301 "[Subsystem]\n"
302 "nqn = nqn.2014-08.org.nvmexpress:sub2\n"
303 "kxchap-ctrl-secret = DHHC-1:00:sub2-ctrl:\n"
304 "controller = transport=tcp;traddr=10.0.0.9;trsvcid=4420\n"
305 "[Subsystem]\n"
306 "nqn = nqn.2014-08.org.nvmexpress:sub3\n"
307 "kxchap-secret =\n"
308 "[Subsystem]\n"
309 "nqn = nqn.2014-08.org.nvmexpress:sub4\n"
310 "tls = true\n"
311 "[Discovery Controller]\n"
312 "nqn = nqn.2014-08.org.nvmexpress:cdc\n"
313 "kxchap-secret = DHHC-1:00:cdc-host:\n"
314 "kxchap-ctrl-secret = DHHC-1:00:cdc-ctrl:\n"
315 "[Discovery Controller]\n"
316 "nqn = " NVME_DISC_SUBSYS_NAME"nqn.2014-08.org.nvmexpress.discovery" "\n"
317 "kxchap-secret = DHHC-1:00:wk-host:\n";
318
319static const char keys_dropin_text[] =
320 "[Host]\n"
321 "hostnqn = nqn.2014-08.org.nvmexpress:other-host\n"
322 "hostid = 2b6f1a0e-4d39-4c5a-9a0e-0b8a3f2c1d00\n"
323 "[Discovery Controller]\n"
324 "controller = transport=tcp;traddr=10.0.0.6;trsvcid=8009\n"
325 "[Subsystem]\n"
326 "nqn = nqn.2014-08.org.nvmexpress:sub1\n"
327 "kxchap-secret = DHHC-1:00:other-host:\n";
328
329/* The parameters of a discovered controller, NULL on error. */
330static const struct libnvmf_params *discovered(
331 const struct libnvmf_config *config, const char *hostnqn,
332 bool_Bool is_dc, const char *nqn)
333{
334 const struct libnvmf_params *params;
335
336 if (libnvmf_config_get_discovered_params(config, hostnqn, is_dc, nqn,
337 &params))
338 return NULL((void*)0);
339
340 return params;
341}
342
343static bool_Bool expect_keys(const char *what, const struct libnvmf_params *params,
344 const char *hostkey, const char *ctrlkey)
345{
346 const char *h = libnvmf_params_get(params, "kxchap-secret");
347 const char *c = libnvmf_params_get(params, "kxchap-ctrl-secret");
348
349 if (!params || !shr_streq0(h, hostkey) || !shr_streq0(c, ctrlkey)) {
350 printf(" - %s: secret %s, ctrl secret %s [FAIL]\n",
351 what, h ? h : "(unset)", c ? c : "(unset)");
352 return false0;
353 }
354 printf(" - %s [PASS]\n", what);
355
356 return true1;
357}
358
359static bool_Bool test_get_discovered_params(struct libnvme_global_ctx *ctx,
360 const struct fixture *fx)
361{
362 const char *top, *other, *sub1 = "nqn.2014-08.org.nvmexpress:sub1";
363 const char *cdc = "nqn.2014-08.org.nvmexpress:cdc";
364 const struct libnvmf_params *params;
365 struct conn_list list = { 0 };
366 struct libnvmf_config *config;
367 char path[352], dropin_dir[356];
368 bool_Bool pass = true1;
369
370 printf("test_get_discovered_params:\n");
371
372 write_file(fx->dir, "keys.conf", keys_text);
373 snprintf(path, sizeof(path), "%s/keys.conf", fx->dir);
374 snprintf(dropin_dir, sizeof(dropin_dir), "%s.d", path);
375 shr_assert(mkdir(dropin_dir, 0755) == 0)((void)((mkdir(dropin_dir, 0755) == 0) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 375, "mkdir(dropin_dir, 0755) == 0"), 0)))
;
376 write_file(dropin_dir, "10-other.conf", keys_dropin_text);
377
378 shr_assert(!libnvmf_config_read(ctx, path, &config))((void)((!libnvmf_config_read(ctx, path, &config)) || (shr_assert_fail
("../libnvme/tests/config-api.c", 378, "!libnvmf_config_read(ctx, path, &config)"
), 0)))
;
379 libnvmf_config_conn_for_each(config, collect, &list);
380 shr_assert(list.n == 3)((void)((list.n == 3) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 380, "list.n == 3"), 0)))
;
381 shr_assert(libnvmf_config_conn_is_dc(list.conn[0]) &&((void)((libnvmf_config_conn_is_dc(list.conn[0]) && libnvmf_config_conn_is_dc
(list.conn[2])) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 382, "libnvmf_config_conn_is_dc(list.conn[0]) && libnvmf_config_conn_is_dc(list.conn[2])"
), 0)))
382 libnvmf_config_conn_is_dc(list.conn[2]))((void)((libnvmf_config_conn_is_dc(list.conn[0]) && libnvmf_config_conn_is_dc
(list.conn[2])) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 382, "libnvmf_config_conn_is_dc(list.conn[0]) && libnvmf_config_conn_is_dc(list.conn[2])"
), 0)))
;
383
384 /* The persona of a DC connection, as nvme-discoverd passes it. */
385 top = libnvmf_config_conn_get_hostnqn(list.conn[0]);
386 other = libnvmf_config_conn_get_hostnqn(list.conn[2]);
387 shr_assert(!top && other)((void)((!top && other) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 387, "!top && other"), 0)))
;
388
389 params = discovered(config, top, false0, sub1);
390 pass &= expect_keys("a section without controller= matches", params,
391 "DHHC-1:00:sub1-host:", "DHHC-1:00:sub1-ctrl:");
392 if (!shr_streq0(libnvmf_params_get(params, "ctrl-loss-tmo"), "600")) {
393 printf(" - the file scope defaults are kept [FAIL]\n");
394 pass = false0;
395 }
396
397 pass &= expect_keys("a section with controller= matches, scope secret",
398 discovered(config, top, false0,
399 "nqn.2014-08.org.nvmexpress:sub2"),
400 "DHHC-1:00:default:", "DHHC-1:00:sub2-ctrl:");
401 pass &= expect_keys("a reset secret stays reset",
402 discovered(config, top, false0,
403 "nqn.2014-08.org.nvmexpress:sub3"),
404 "", NULL((void*)0));
405 pass &= expect_keys("a section without a secret does not match",
406 discovered(config, top, false0,
407 "nqn.2014-08.org.nvmexpress:sub4"),
408 "DHHC-1:00:default:", NULL((void*)0));
409 pass &= expect_keys("no section: the file scope",
410 discovered(config, top, false0,
411 "nqn.2014-08.org.nvmexpress:unknown"),
412 "DHHC-1:00:default:", NULL((void*)0));
413 pass &= expect_keys("no NQN: the file scope",
414 discovered(config, top, false0,
415 NULL((void*)0)),
416 "DHHC-1:00:default:", NULL((void*)0));
417 pass &= expect_keys("a [Subsystem] does not match a DC",
418 discovered(config, top, true1, sub1),
419 NULL((void*)0), NULL((void*)0));
420
421 pass &= expect_keys("a DC with a unique NQN",
422 discovered(config, top, true1, cdc),
423 "DHHC-1:00:cdc-host:", "DHHC-1:00:cdc-ctrl:");
424 pass &= expect_keys("the well-known NQN never matches",
425 discovered(config, top, true1,
426 NVME_DISC_SUBSYS_NAME"nqn.2014-08.org.nvmexpress.discovery"),
427 NULL((void*)0), NULL((void*)0));
428
429 pass &= expect_keys("another persona uses the section of its file",
430 discovered(config, other, false0,
431 sub1),
432 "DHHC-1:00:other-host:", NULL((void*)0));
433 pass &= expect_keys("another persona's section does not match",
434 discovered(config, other, false0,
435 "nqn.2014-08.org.nvmexpress:sub2"),
436 "DHHC-1:00:default:", NULL((void*)0));
437
438 if (libnvmf_config_get_discovered_params(config,
439 "nqn.2014-08.org.nvmexpress:no-such-host", false0,
440 sub1, &params) != -ENOENT2) {
441 printf(" - an unknown persona [FAIL]\n");
442 pass = false0;
443 } else {
444 printf(" - an unknown persona has none [PASS]\n");
445 }
446
447 libnvmf_config_free(config);
448 rm_file(dropin_dir, "10-other.conf");
449 rmdir(dropin_dir);
450 rm_file(fx->dir, "keys.conf");
451
452 return pass;
453}
454
455/* Two sections with the same NQN: their secrets are combined. */
456static const char dup_text[] =
457 "[Subsystem]\n"
458 "nqn = nqn.2014-08.org.nvmexpress:dup\n"
459 "kxchap-secret = DHHC-1:00:dup-host:\n"
460 "controller = transport=tcp;traddr=10.0.0.9;trsvcid=4420\n"
461 "[Subsystem]\n"
462 "nqn = nqn.2014-08.org.nvmexpress:dup\n"
463 "kxchap-secret = DHHC-1:00:dup-host:\n"
464 "kxchap-ctrl-secret = DHHC-1:00:dup-ctrl:\n"
465 "controller = transport=tcp;traddr=10.0.0.10;trsvcid=4420\n"
466 "[Discovery Controller]\n"
467 "controller = transport=tcp;traddr=10.0.0.5;trsvcid=8009\n"
468 "[Discovery Controller]\n"
469 "controller = transport=tcp;traddr=10.0.0.6;trsvcid=8009\n";
470
471static const char dup_conflict_text[] =
472 "[Subsystem]\n"
473 "nqn = nqn.2014-08.org.nvmexpress:dup\n"
474 "kxchap-secret = DHHC-1:00:dup-host:\n"
475 "[Subsystem]\n"
476 "nqn = nqn.2014-08.org.nvmexpress:dup\n"
477 "kxchap-secret = DHHC-1:00:other:\n";
478
479static bool_Bool test_duplicate_nqn(struct libnvme_global_ctx *ctx,
480 const struct fixture *fx)
481{
482 struct libnvmf_config *config;
483 char path[352];
484 bool_Bool pass = true1;
485
486 printf("test_duplicate_nqn:\n");
487
488 snprintf(path, sizeof(path), "%s/dup.conf", fx->dir);
489
490 write_file(fx->dir, "dup.conf", dup_text);
491 if (libnvmf_config_read(ctx, path, &config)) {
492 printf(" - same NQN, same secrets is accepted [FAIL]\n");
493 pass = false0;
494 } else {
495 pass &= expect_keys("same NQN, same secrets: combined",
496 discovered(config, NULL((void*)0),
497 false0, "nqn.2014-08.org.nvmexpress:dup"),
498 "DHHC-1:00:dup-host:", "DHHC-1:00:dup-ctrl:");
499 libnvmf_config_free(config);
500 }
501
502 write_file(fx->dir, "dup.conf", dup_conflict_text);
503 if (libnvmf_config_read(ctx, path, &config) != -EINVAL22) {
504 printf(" - same NQN, different secrets [FAIL]\n");
505 pass = false0;
506 } else {
507 printf(" - same NQN, different secrets is rejected [PASS]\n");
508 }
509 rm_file(fx->dir, "dup.conf");
510
511 return pass;
512}
513
514/* Only unidirectional authentication with the well-known discovery NQN */
515static const char wk_ctrl_secret_text[] =
516 "[Discovery Controller]\n"
517 "kxchap-secret = DHHC-1:00:wk-host:\n"
518 "kxchap-ctrl-secret = DHHC-1:00:wk-ctrl:\n"
519 "controller = transport=tcp;traddr=10.0.0.5;trsvcid=8009\n"
520 "[Discovery Controller]\n"
521 "nqn = " NVME_DISC_SUBSYS_NAME"nqn.2014-08.org.nvmexpress.discovery" "\n"
522 "kxchap-ctrl-secret = DHHC-1:00:wk-ctrl:\n"
523 "[Discovery Controller]\n"
524 "nqn = " NVME_DISC_SUBSYS_NAME"nqn.2014-08.org.nvmexpress.discovery" "\n"
525 "kxchap-secret = DHHC-1:00:wk-host:\n"
526 "kxchap-ctrl-secret =\n"
527 "[Discovery Controller]\n"
528 "nqn = nqn.2014-08.org.nvmexpress:cdc\n"
529 "kxchap-ctrl-secret = DHHC-1:00:cdc-ctrl:\n";
530
531static bool_Bool test_wellknown_ctrl_secret(struct libnvme_global_ctx *ctx,
532 const struct fixture *fx)
533{
534 struct libnvmf_config *config = NULL((void*)0);
535 char path[352], log[1024] = "";
536 unsigned int warnings = 0;
537 const char *p;
538 bool_Bool pass = true1;
539 FILE *fp;
540 int ret;
541
542 printf("test_wellknown_ctrl_secret:\n");
543
544 snprintf(path, sizeof(path), "%s/wk.conf", fx->dir);
545 write_file(fx->dir, "wk.conf", wk_ctrl_secret_text);
546
547 /* The log goes to the file descriptor, not to the FILE buffer */
548 fp = tmpfile();
549 shr_assert(fp)((void)((fp) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 549, "fp"), 0)))
;
550 libnvme_set_logging_file(ctx, fp);
551 ret = libnvmf_config_read(ctx, path, &config);
552 libnvme_set_logging_file(ctx, NULL((void*)0));
553 rewind(fp);
1
After calling 'rewind' reading 'errno' is required to find out if the call has failed
554 log[fread(log, 1, sizeof(log) - 1, fp)] = '\0';
2
Value of 'errno' was not checked and may be overwritten by function 'fread'
555 fclose(fp);
556
557 if (ret) {
558 printf(" - well-known DC with a ctrl secret loads [FAIL]\n");
559 pass = false0;
560 } else {
561 printf(" - well-known DC with a ctrl secret loads [PASS]\n");
562 }
563
564 for (p = log; (p = strstr(p, "kxchap-ctrl-secret is not")_Generic (0 ? (p) : (void *) 1, const void *: (const char *) (
strstr (p, "kxchap-ctrl-secret is not")), default: strstr (p,
"kxchap-ctrl-secret is not"))
); p++)
565 warnings++;
566 if (warnings != 2 || !strstr(log, "line 1:")_Generic (0 ? (log) : (void *) 1, const void *: (const char *
) (strstr (log, "line 1:")), default: strstr (log, "line 1:")
)
||
567 !strstr(log, "line 5:")_Generic (0 ? (log) : (void *) 1, const void *: (const char *
) (strstr (log, "line 5:")), default: strstr (log, "line 5:")
)
) {
568 printf(" - warned for lines 1 and 5 only [FAIL]\n%s", log);
569 pass = false0;
570 } else {
571 printf(" - warned for lines 1 and 5 only [PASS]\n");
572 }
573
574 libnvmf_config_free(config);
575 rm_file(fx->dir, "wk.conf");
576
577 return pass;
578}
579
580static const char host_only_text[] =
581 "[Host]\n"
582 "hostnqn = nqn.2014-08.org.nvmexpress:solo-host\n"
583 "hostid = 8b6b8b6b-0000-4000-8000-00000000dead\n"
584 "hostsymname = solo\n";
585
586static bool_Bool test_top_level_host(struct libnvme_global_ctx *ctx,
587 const struct fixture *fx)
588{
589 struct conn_list list = { 0 };
590 struct libnvmf_config *config;
591 char path[352];
592 bool_Bool pass = true1;
593
594 printf("test_top_level_host:\n");
595
596 /*
597 * The fixture's main file carries no [Host]; only the drop-in does.
598 * A drop-in's persona belongs to that drop-in's own connections and
599 * must not be reported as the configuration's identity.
600 */
601 shr_assert(!libnvmf_config_read(ctx, fx->main_path, &config))((void)((!libnvmf_config_read(ctx, fx->main_path, &config
)) || (shr_assert_fail("../libnvme/tests/config-api.c", 601, "!libnvmf_config_read(ctx, fx->main_path, &config)"
), 0)))
;
602 if (libnvmf_config_get_hostnqn(config) ||
603 libnvmf_config_get_hostid(config) ||
604 libnvmf_config_get_hostsymname(config)) {
605 printf(" - a drop-in persona must not be reported [FAIL]\n");
606 pass = false0;
607 } else {
608 printf(" - drop-in persona is not the top-level one [PASS]\n");
609 }
610 libnvmf_config_free(config);
611
612 /*
613 * A [Host] and nothing else: no connections, but an identity. This is
614 * the host that connects only what it discovers.
615 */
616 write_file(fx->dir, "host-only.conf", host_only_text);
617 snprintf(path, sizeof(path), "%s/host-only.conf", fx->dir);
618 shr_assert(!libnvmf_config_read(ctx, path, &config))((void)((!libnvmf_config_read(ctx, path, &config)) || (shr_assert_fail
("../libnvme/tests/config-api.c", 618, "!libnvmf_config_read(ctx, path, &config)"
), 0)))
;
619
620 libnvmf_config_conn_for_each(config, collect, &list);
621 if (list.n) {
622 printf(" - expected no connections, got %zu [FAIL]\n", list.n);
623 pass = false0;
624 }
625
626 if (!libnvmf_config_get_hostnqn(config) ||
627 strcmp(libnvmf_config_get_hostnqn(config),
628 "nqn.2014-08.org.nvmexpress:solo-host") ||
629 !libnvmf_config_get_hostid(config) ||
630 strcmp(libnvmf_config_get_hostid(config),
631 "8b6b8b6b-0000-4000-8000-00000000dead") ||
632 !libnvmf_config_get_hostsymname(config) ||
633 strcmp(libnvmf_config_get_hostsymname(config), "solo")) {
634 printf(" - identity of a connection-less config [FAIL]\n");
635 pass = false0;
636 } else {
637 printf(" - identity without connections [PASS]\n");
638 }
639 libnvmf_config_free(config);
640 rm_file(fx->dir, "host-only.conf");
641
642 return pass;
643}
644
645static bool_Bool test_persona_validation(struct libnvme_global_ctx *ctx,
646 const struct fixture *fx)
647{
648 struct libnvmf_config *config;
649 char path[352];
650 bool_Bool pass = true1;
651
652 printf("test_persona_validation:\n");
653
654 /* A drop-in persona with a hostnqn but no hostid. */
655 write_file(fx->dropin_dir, "20-no-hostid.conf",
656 "[Host]\n"
657 "hostnqn = nqn.2014-08.org.nvmexpress:no-hostid\n");
658 if (libnvmf_config_read(ctx, fx->main_path, &config) != -EINVAL22) {
659 printf(" - drop-in hostnqn without hostid [FAIL]\n");
660 pass = false0;
661 } else {
662 printf(" - drop-in hostnqn without hostid rejected [PASS]\n");
663 }
664 rm_file(fx->dropin_dir, "20-no-hostid.conf");
665
666 /* The same shape on a top-level file's own [Host] section. */
667 write_file(fx->dir, "top-no-hostid.conf",
668 "[Host]\n"
669 "hostnqn = nqn.2014-08.org.nvmexpress:top-no-hostid\n");
670 snprintf(path, sizeof(path), "%s/top-no-hostid.conf", fx->dir);
671 if (libnvmf_config_read(ctx, path, &config) != -EINVAL22) {
672 printf(" - top-level hostnqn without hostid [FAIL]\n");
673 pass = false0;
674 } else {
675 printf(" - top-level hostnqn without hostid rejected [PASS]\n");
676 }
677 rm_file(fx->dir, "top-no-hostid.conf");
678
679 /* A uuid:-form hostnqn is not derived into a hostid either. */
680 write_file(fx->dropin_dir, "20-uuid-no-hostid.conf",
681 "[Host]\n"
682 "hostnqn = nqn.2014-08.org.nvmexpress:"
683 "uuid:8b6b8b6b-0000-4000-8000-00000000dead\n");
684 if (libnvmf_config_read(ctx, fx->main_path, &config) != -EINVAL22) {
685 printf(" - uuid: hostnqn without hostid [FAIL]\n");
686 pass = false0;
687 } else {
688 printf(" - uuid: hostnqn without hostid rejected too [PASS]\n");
689 }
690 rm_file(fx->dropin_dir, "20-uuid-no-hostid.conf");
691
692 /* Regression: hostnqn and hostid together is still unaffected. */
693 if (libnvmf_config_read(ctx, fx->main_path, &config)) {
694 printf(" - hostnqn+hostid persona still valid [FAIL]\n");
695 pass = false0;
696 } else {
697 printf(" - hostnqn+hostid persona still valid [PASS]\n");
698 libnvmf_config_free(config);
699 }
700
701 return pass;
702}
703
704static bool_Bool test_validate(struct libnvme_global_ctx *ctx,
705 const struct fixture *fx)
706{
707 struct libnvmf_config *config;
708 char missing[320];
709 bool_Bool pass = true1;
710
711 printf("test_validate:\n");
712
713 if (libnvmf_config_validate(ctx, fx->main_path)) {
714 printf(" - valid tree [FAIL]\n");
715 pass = false0;
716 } else {
717 printf(" - valid tree validates clean [PASS]\n");
718 }
719
720 /* An absent configuration is a valid (empty) configuration. */
721 snprintf(missing, sizeof(missing), "%s/no-such.conf", fx->dir);
722 if (libnvmf_config_validate(ctx, missing)) {
723 printf(" - absent config [FAIL]\n");
724 pass = false0;
725 } else {
726 printf(" - absent config is valid and empty [PASS]\n");
727 }
728
729 /* A Tier 1 problem in any file fails the tree as a unit. */
730 write_file(fx->dropin_dir, "99-bad.conf", "not a key value line\n");
731 if (libnvmf_config_validate(ctx, fx->main_path) >= 0) {
732 printf(" - Tier 1 error detected [FAIL]\n");
733 pass = false0;
734 } else {
735 printf(" - Tier 1 error fails the tree as a unit [PASS]\n");
736 }
737 if (!libnvmf_config_read(ctx, fx->main_path, &config)) {
738 printf(" - read refuses a broken tree [FAIL]\n");
739 pass = false0;
740 libnvmf_config_free(config);
741 } else {
742 printf(" - read refuses a broken tree [PASS]\n");
743 }
744 rm_file(fx->dropin_dir, "99-bad.conf");
745
746 return pass;
747}
748
749struct arg_list {
750 char args[16][96];
751 size_t n;
752};
753
754static void collect_arg(const char *arg, void *user_data)
755{
756 struct arg_list *list = user_data;
757
758 shr_assert(list->n < 16)((void)((list->n < 16) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 758, "list->n < 16"), 0)))
;
759 snprintf(list->args[list->n++], sizeof(list->args[0]), "%s", arg);
760}
761
762static bool_Bool args_match(const struct arg_list *list,
763 const char * const *expect, size_t n)
764{
765 size_t i;
766
767 if (list->n != n)
768 return false0;
769 for (i = 0; i < n; i++) {
770 if (strcmp(list->args[i], expect[i]))
771 return false0;
772 }
773
774 return true1;
775}
776
777/*
778 * A connection's addressing is raw strings, not a TID (see config.h) -- an
779 * emitter caller resolves (traddr here is already numeric) and builds the
780 * TID itself, exactly like this.
781 */
782static struct libnvmf_tid *build_tid(const struct libnvmf_config_conn *conn)
783{
784 struct libnvmf_tid *tid;
785
786 libnvmf_tid_from_fields(
787 libnvmf_config_conn_get_transport(conn),
788 libnvmf_config_conn_get_traddr(conn),
789 libnvmf_config_conn_get_trsvcid(conn),
790 libnvmf_config_conn_get_subsysnqn(conn),
791 libnvmf_config_conn_get_host_traddr(conn),
792 libnvmf_config_conn_get_host_iface(conn),
793 libnvmf_config_conn_get_hostnqn(conn),
794 libnvmf_config_conn_get_hostid(conn), &tid);
795 return tid;
796}
797
798static bool_Bool test_emit(struct libnvme_global_ctx *ctx, const struct fixture *fx)
799{
800 static const char * const mv_expect[] = {
801 "--transport=tcp",
802 "--traddr=10.0.0.9",
803 "--trsvcid=4420",
804 "--nqn=nqn.2014-08.org.nvmexpress:main-vol",
805 "--ctrl-loss-tmo=600",
806 "--keep-alive-tmo=5",
807 "--tls",
808 };
809 static const char * const pv_expect[] = {
810 "--transport=tcp",
811 "--traddr=10.0.0.7",
812 "--trsvcid=4420",
813 "--nqn=nqn.2014-08.org.nvmexpress:prod-vol",
814 "--hostnqn=nqn.2014-08.org.nvmexpress:prod-host",
815 "--hostid=46ba5037-7ce5-41fa-9452-48477bf00080",
816 "--ctrl-loss-tmo=1800",
817 "--keep-alive-tmo=5",
818 };
819 const struct libnvmf_config_conn *mv, *pv;
820 struct conn_list conns = { 0 };
821 struct arg_list args = { 0 };
822 struct libnvmf_config *config;
823 struct libnvmf_tid *mv_tid, *pv_tid;
824 bool_Bool pass = true1;
825
826 printf("test_emit:\n");
827
828 shr_assert(!libnvmf_config_read(ctx, fx->main_path, &config))((void)((!libnvmf_config_read(ctx, fx->main_path, &config
)) || (shr_assert_fail("../libnvme/tests/config-api.c", 828, "!libnvmf_config_read(ctx, fx->main_path, &config)"
), 0)))
;
829 libnvmf_config_conn_for_each(config, collect, &conns);
830 shr_assert(conns.n == 3)((void)((conns.n == 3) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 830, "conns.n == 3"), 0)))
;
831 mv = conns.conn[1];
832 pv = conns.conn[2];
833
834 mv_tid = build_tid(mv);
835 pv_tid = build_tid(pv);
836 shr_assert(mv_tid && pv_tid)((void)((mv_tid && pv_tid) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 836, "mv_tid && pv_tid"), 0)))
;
837
838 /* TID fields in fixed order, then params; true bool = bare flag. */
839 if (libnvmf_connect_args_emit(mv_tid,
840 libnvmf_config_conn_get_params(mv),
841 collect_arg, &args) ||
842 !args_match(&args, mv_expect, ARRAY_SIZE(mv_expect)(sizeof(mv_expect) / sizeof((mv_expect)[0]) + 0))) {
843 printf(" - main subsystem args [FAIL]\n");
844 pass = false0;
845 } else {
846 printf(" - TID first, params after; bool flags bare [PASS]\n");
847 }
848
849 /* Persona identity emitted; per-path override wins; reset skipped. */
850 memset(&args, 0, sizeof(args));
851 if (libnvmf_connect_args_emit(pv_tid,
852 libnvmf_config_conn_get_params(pv),
853 collect_arg, &args) ||
854 !args_match(&args, pv_expect, ARRAY_SIZE(pv_expect)(sizeof(pv_expect) / sizeof((pv_expect)[0]) + 0))) {
855 printf(" - drop-in subsystem args [FAIL]\n");
856 pass = false0;
857 } else {
858 printf(" - persona identity kept, reset skipped [PASS]\n");
859 }
860
861 /* Each half is optional. */
862 memset(&args, 0, sizeof(args));
863 if (libnvmf_connect_args_emit(NULL((void*)0),
864 libnvmf_config_conn_get_params(pv),
865 collect_arg, &args) ||
866 !args_match(&args, &pv_expect[6], 2)) {
867 printf(" - params-only emission [FAIL]\n");
868 pass = false0;
869 } else {
870 printf(" - params-only emission (NULL TID) [PASS]\n");
871 }
872
873 memset(&args, 0, sizeof(args));
874 if (libnvmf_connect_args_emit(mv_tid, NULL((void*)0), collect_arg, &args) ||
875 !args_match(&args, mv_expect, 4)) {
876 printf(" - TID-only emission [FAIL]\n");
877 pass = false0;
878 } else {
879 printf(" - TID-only emission (NULL params) [PASS]\n");
880 }
881
882 /* A discovery controller setting is not emitted. */
883 {
884 struct libnvmf_params *dc = libnvmf_params_new();
885
886 memset(&args, 0, sizeof(args));
887 shr_assert(dc &&((void)((dc && !libnvmf_params_set(dc, "persistent", "force"
) && !libnvmf_params_set(dc, "keep-alive-tmo", "5")) ||
(shr_assert_fail("../libnvme/tests/config-api.c", 889, "dc && !libnvmf_params_set(dc, \"persistent\", \"force\") && !libnvmf_params_set(dc, \"keep-alive-tmo\", \"5\")"
), 0)))
888 !libnvmf_params_set(dc, "persistent", "force") &&((void)((dc && !libnvmf_params_set(dc, "persistent", "force"
) && !libnvmf_params_set(dc, "keep-alive-tmo", "5")) ||
(shr_assert_fail("../libnvme/tests/config-api.c", 889, "dc && !libnvmf_params_set(dc, \"persistent\", \"force\") && !libnvmf_params_set(dc, \"keep-alive-tmo\", \"5\")"
), 0)))
889 !libnvmf_params_set(dc, "keep-alive-tmo", "5"))((void)((dc && !libnvmf_params_set(dc, "persistent", "force"
) && !libnvmf_params_set(dc, "keep-alive-tmo", "5")) ||
(shr_assert_fail("../libnvme/tests/config-api.c", 889, "dc && !libnvmf_params_set(dc, \"persistent\", \"force\") && !libnvmf_params_set(dc, \"keep-alive-tmo\", \"5\")"
), 0)))
;
890 if (libnvmf_connect_args_emit(NULL((void*)0), dc, collect_arg, &args) ||
891 !args_match(&args, &mv_expect[5], 1)) {
892 printf(" - persistent not emitted [FAIL]\n");
893 pass = false0;
894 } else {
895 printf(" - persistent not emitted [PASS]\n");
896 }
897 libnvmf_params_free(dc);
898 }
899
900 if (libnvmf_connect_args_emit(NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)) != -EINVAL22) {
901 printf(" - NULL callback [FAIL]\n");
902 pass = false0;
903 } else {
904 printf(" - NULL callback rejected [PASS]\n");
905 }
906
907 libnvmf_tid_free(mv_tid);
908 libnvmf_tid_free(pv_tid);
909 libnvmf_config_free(config);
910
911 return pass;
912}
913
914/* Built ad hoc, not from the fixture files, to cover every key class in
915 * one pass: ints, bools, an explicit reset, and the five crypto keys
916 * that share one setter.
917 */
918static bool_Bool test_apply_params(struct libnvme_global_ctx *ctx)
919{
920 struct libnvmf_context *fctx;
921 struct libnvmf_params *params;
922 bool_Bool pass = true1;
923
924 printf("test_apply_params:\n");
925
926 params = libnvmf_params_new();
927 shr_assert(params)((void)((params) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 927, "params"), 0)))
;
928 /* Hex, matching check_int()'s own base-0 parsing (config-ini.c). */
929 shr_assert(!libnvmf_params_set(params, "nr-io-queues", "0x10"))((void)((!libnvmf_params_set(params, "nr-io-queues", "0x10"))
|| (shr_assert_fail("../libnvme/tests/config-api.c", 929, "!libnvmf_params_set(params, \"nr-io-queues\", \"0x10\")"
), 0)))
;
930 shr_assert(!libnvmf_params_set(params, "keep-alive-tmo", "30"))((void)((!libnvmf_params_set(params, "keep-alive-tmo", "30"))
|| (shr_assert_fail("../libnvme/tests/config-api.c", 930, "!libnvmf_params_set(params, \"keep-alive-tmo\", \"30\")"
), 0)))
;
931 shr_assert(!libnvmf_params_set(params, "tls", "true"))((void)((!libnvmf_params_set(params, "tls", "true")) || (shr_assert_fail
("../libnvme/tests/config-api.c", 931, "!libnvmf_params_set(params, \"tls\", \"true\")"
), 0)))
;
932 shr_assert(!libnvmf_params_set(params, "hdr-digest", "false"))((void)((!libnvmf_params_set(params, "hdr-digest", "false")) ||
(shr_assert_fail("../libnvme/tests/config-api.c", 932, "!libnvmf_params_set(params, \"hdr-digest\", \"false\")"
), 0)))
;
933 shr_assert(!libnvmf_params_set(params, "persistent", "force"))((void)((!libnvmf_params_set(params, "persistent", "force")) ||
(shr_assert_fail("../libnvme/tests/config-api.c", 933, "!libnvmf_params_set(params, \"persistent\", \"force\")"
), 0)))
;
934 /* Explicit resets: must be skipped, not applied as "0". */
935 shr_assert(!libnvmf_params_set(params, "tos", ""))((void)((!libnvmf_params_set(params, "tos", "")) || (shr_assert_fail
("../libnvme/tests/config-api.c", 935, "!libnvmf_params_set(params, \"tos\", \"\")"
), 0)))
;
936 shr_assert(!libnvmf_params_set(params, "ctrl-loss-tmo", ""))((void)((!libnvmf_params_set(params, "ctrl-loss-tmo", "")) ||
(shr_assert_fail("../libnvme/tests/config-api.c", 936, "!libnvmf_params_set(params, \"ctrl-loss-tmo\", \"\")"
), 0)))
;
937 /* The five crypto keys: one shared setter, must not clobber. */
938 shr_assert(!libnvmf_params_set(params, "keyring", "my-keyring"))((void)((!libnvmf_params_set(params, "keyring", "my-keyring")
) || (shr_assert_fail("../libnvme/tests/config-api.c", 938, "!libnvmf_params_set(params, \"keyring\", \"my-keyring\")"
), 0)))
;
939 shr_assert(!libnvmf_params_set(params, "tls-key", "deadbeef"))((void)((!libnvmf_params_set(params, "tls-key", "deadbeef")) ||
(shr_assert_fail("../libnvme/tests/config-api.c", 939, "!libnvmf_params_set(params, \"tls-key\", \"deadbeef\")"
), 0)))
;
940 shr_assert(!libnvmf_params_set(params, "tls-key-identity",((void)((!libnvmf_params_set(params, "tls-key-identity", "NVMe1R02 my-id"
)) || (shr_assert_fail("../libnvme/tests/config-api.c", 941, "!libnvmf_params_set(params, \"tls-key-identity\", \"NVMe1R02 my-id\")"
), 0)))
941 "NVMe1R02 my-id"))((void)((!libnvmf_params_set(params, "tls-key-identity", "NVMe1R02 my-id"
)) || (shr_assert_fail("../libnvme/tests/config-api.c", 941, "!libnvmf_params_set(params, \"tls-key-identity\", \"NVMe1R02 my-id\")"
), 0)))
;
942 shr_assert(!libnvmf_params_set(params, "kxchap-secret", "DHHC-1:00:host:"))((void)((!libnvmf_params_set(params, "kxchap-secret", "DHHC-1:00:host:"
)) || (shr_assert_fail("../libnvme/tests/config-api.c", 942, "!libnvmf_params_set(params, \"kxchap-secret\", \"DHHC-1:00:host:\")"
), 0)))
;
943 shr_assert(!libnvmf_params_set(params, "kxchap-ctrl-secret",((void)((!libnvmf_params_set(params, "kxchap-ctrl-secret", "DHHC-1:00:ctrl:"
)) || (shr_assert_fail("../libnvme/tests/config-api.c", 944, "!libnvmf_params_set(params, \"kxchap-ctrl-secret\", \"DHHC-1:00:ctrl:\")"
), 0)))
944 "DHHC-1:00:ctrl:"))((void)((!libnvmf_params_set(params, "kxchap-ctrl-secret", "DHHC-1:00:ctrl:"
)) || (shr_assert_fail("../libnvme/tests/config-api.c", 944, "!libnvmf_params_set(params, \"kxchap-ctrl-secret\", \"DHHC-1:00:ctrl:\")"
), 0)))
;
945
946 shr_assert(!libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx))((void)((!libnvmf_context_create(ctx, ((void*)0), ((void*)0),
((void*)0), ((void*)0), &fctx)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 946, "!libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx)"
), 0)))
;
947
948 if (libnvmf_context_apply_params(fctx, params)) {
949 printf(" - apply failed [FAIL]\n");
950 pass = false0;
951 goto out;
952 }
953
954 if (libnvmf_context_get_nr_io_queues(fctx) != 0x10 ||
955 libnvmf_context_get_keep_alive_tmo(fctx) != 30) {
956 printf(" - int fields (hex + decimal) [FAIL]\n");
957 pass = false0;
958 } else {
959 printf(" - int fields applied (hex + decimal) [PASS]\n");
960 }
961
962 {
963 const char *p = libnvmf_context_get_persistent(fctx);
964
965 if (!libnvmf_context_get_tls(fctx) ||
966 libnvmf_context_get_hdr_digest(fctx) ||
967 !shr_streq0(p, "force")) {
968 printf(" - bool fields [FAIL]\n");
969 pass = false0;
970 } else {
971 printf(" - bool fields applied [PASS]\n");
972 }
973 }
974
975 /* A fresh context starts at tos=-1, ctrl-loss-tmo=600 (see
976 * libnvmf_default_config()); a reset must leave both untouched,
977 * not overwrite them with 0.
978 */
979 if (libnvmf_context_get_tos(fctx) != -1 ||
980 libnvmf_context_get_ctrl_loss_tmo(fctx) != NVMF_DEF_CTRL_LOSS_TMO600) {
981 printf(" - reset skipped, library default kept [FAIL]\n");
982 pass = false0;
983 } else {
984 printf(" - reset skipped, library default kept [PASS]\n");
985 }
986
987 if (strcmp(libnvmf_context_get_keyring(fctx), "my-keyring") ||
988 strcmp(libnvmf_context_get_tls_key(fctx), "deadbeef") ||
989 strcmp(libnvmf_context_get_tls_key_identity(fctx),
990 "NVMe1R02 my-id") ||
991 strcmp(libnvmf_context_get_hostkey(fctx), "DHHC-1:00:host:") ||
992 strcmp(libnvmf_context_get_ctrlkey(fctx), "DHHC-1:00:ctrl:")) {
993 printf(" - crypto fields (shared setter, no clobber) [FAIL]\n");
994 pass = false0;
995 } else {
996 printf(" - crypto fields (shared setter, no clobber) [PASS]\n");
997 }
998
999out:
1000 if (libnvmf_context_apply_params(NULL((void*)0), params) != -EINVAL22 ||
1001 libnvmf_context_apply_params(fctx, NULL((void*)0)) != -EINVAL22) {
1002 printf(" - NULL rejected [FAIL]\n");
1003 pass = false0;
1004 } else {
1005 printf(" - NULL rejected [PASS]\n");
1006 }
1007
1008 libnvmf_context_free(fctx);
1009 libnvmf_params_free(params);
1010 return pass;
1011}
1012
1013static bool_Bool has_arg(const struct arg_list *list, const char *arg)
1014{
1015 size_t i;
1016
1017 for (i = 0; i < list->n; i++) {
1018 if (!strcmp(list->args[i], arg))
1019 return true1;
1020 }
1021
1022 return false0;
1023}
1024
1025/*
1026 * With tls-key-source other than "inline", tls-key is a name for nvme-keysd.
1027 * Neither connect path may use it as the key. tls-key-source itself is never
1028 * an "nvme connect" option.
1029 */
1030static bool_Bool test_tls_key_source(struct libnvme_global_ctx *ctx)
1031{
1032 struct libnvmf_context *fctx;
1033 struct libnvmf_params *params;
1034 struct arg_list args = { 0 };
1035 bool_Bool pass = true1;
1036
1037 printf("test_tls_key_source:\n");
1038
1039 params = libnvmf_params_new();
1040 shr_assert(params)((void)((params) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1040, "params"), 0)))
;
1041
1042 shr_assert(!libnvmf_params_set(params, "tls", "true"))((void)((!libnvmf_params_set(params, "tls", "true")) || (shr_assert_fail
("../libnvme/tests/config-api.c", 1042, "!libnvmf_params_set(params, \"tls\", \"true\")"
), 0)))
;
1043 shr_assert(!libnvmf_params_set(params, "tls-key", "cred_vol1-psk"))((void)((!libnvmf_params_set(params, "tls-key", "cred_vol1-psk"
)) || (shr_assert_fail("../libnvme/tests/config-api.c", 1043,
"!libnvmf_params_set(params, \"tls-key\", \"cred_vol1-psk\")"
), 0)))
;
1044 shr_assert(!libnvmf_params_set(params, "tls-key-source",((void)((!libnvmf_params_set(params, "tls-key-source", "systemd-creds"
)) || (shr_assert_fail("../libnvme/tests/config-api.c", 1045,
"!libnvmf_params_set(params, \"tls-key-source\", \"systemd-creds\")"
), 0)))
1045 "systemd-creds"))((void)((!libnvmf_params_set(params, "tls-key-source", "systemd-creds"
)) || (shr_assert_fail("../libnvme/tests/config-api.c", 1045,
"!libnvmf_params_set(params, \"tls-key-source\", \"systemd-creds\")"
), 0)))
;
1046
1047 shr_assert(!libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx))((void)((!libnvmf_context_create(ctx, ((void*)0), ((void*)0),
((void*)0), ((void*)0), &fctx)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1047, "!libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx)"
), 0)))
;
1048 shr_assert(!libnvmf_context_apply_params(fctx, params))((void)((!libnvmf_context_apply_params(fctx, params)) || (shr_assert_fail
("../libnvme/tests/config-api.c", 1048, "!libnvmf_context_apply_params(fctx, params)"
), 0)))
;
1049 if (libnvmf_context_get_tls_key(fctx) ||
1050 !libnvmf_context_get_tls(fctx)) {
1051 printf(" - systemd-creds: apply drops tls-key [FAIL]\n");
1052 pass = false0;
1053 } else {
1054 printf(" - systemd-creds: apply drops tls-key [PASS]\n");
1055 }
1056 libnvmf_context_free(fctx);
1057
1058 shr_assert(!libnvmf_connect_args_emit(NULL, params, collect_arg,((void)((!libnvmf_connect_args_emit(((void*)0), params, collect_arg
, &args)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1059, "!libnvmf_connect_args_emit(NULL, params, collect_arg, &args)"
), 0)))
1059 &args))((void)((!libnvmf_connect_args_emit(((void*)0), params, collect_arg
, &args)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1059, "!libnvmf_connect_args_emit(NULL, params, collect_arg, &args)"
), 0)))
;
1060 if (args.n != 1 || !has_arg(&args, "--tls")) {
1061 printf(" - systemd-creds: emit has --tls only [FAIL]\n");
1062 pass = false0;
1063 } else {
1064 printf(" - systemd-creds: emit has --tls only [PASS]\n");
1065 }
1066
1067 shr_assert(!libnvmf_params_set(params, "tls-key-source", "inline"))((void)((!libnvmf_params_set(params, "tls-key-source", "inline"
)) || (shr_assert_fail("../libnvme/tests/config-api.c", 1067,
"!libnvmf_params_set(params, \"tls-key-source\", \"inline\")"
), 0)))
;
1068
1069 shr_assert(!libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx))((void)((!libnvmf_context_create(ctx, ((void*)0), ((void*)0),
((void*)0), ((void*)0), &fctx)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1069, "!libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx)"
), 0)))
;
1070 shr_assert(!libnvmf_context_apply_params(fctx, params))((void)((!libnvmf_context_apply_params(fctx, params)) || (shr_assert_fail
("../libnvme/tests/config-api.c", 1070, "!libnvmf_context_apply_params(fctx, params)"
), 0)))
;
1071 if (!shr_streq0(libnvmf_context_get_tls_key(fctx), "cred_vol1-psk")) {
1072 printf(" - inline: apply keeps tls-key [FAIL]\n");
1073 pass = false0;
1074 } else {
1075 printf(" - inline: apply keeps tls-key [PASS]\n");
1076 }
1077 libnvmf_context_free(fctx);
1078
1079 args.n = 0;
1080 shr_assert(!libnvmf_connect_args_emit(NULL, params, collect_arg,((void)((!libnvmf_connect_args_emit(((void*)0), params, collect_arg
, &args)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1081, "!libnvmf_connect_args_emit(NULL, params, collect_arg, &args)"
), 0)))
1081 &args))((void)((!libnvmf_connect_args_emit(((void*)0), params, collect_arg
, &args)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1081, "!libnvmf_connect_args_emit(NULL, params, collect_arg, &args)"
), 0)))
;
1082 if (args.n != 2 || !has_arg(&args, "--tls") ||
1083 !has_arg(&args, "--tls-key=cred_vol1-psk")) {
1084 printf(" - inline: emit has --tls and --tls-key [FAIL]\n");
1085 pass = false0;
1086 } else {
1087 printf(" - inline: emit has --tls and --tls-key [PASS]\n");
1088 }
1089
1090 libnvmf_params_free(params);
1091
1092 return pass;
1093}
1094
1095/*
1096 * persistent must distinguish "not configured" (UNSET, the library default
1097 * derived elsewhere, e.g. from the discovery log page) from an explicit
1098 * "no" -- a plain bool cannot represent that third state.
1099 */
1100static bool_Bool test_persistent_tristate(struct libnvme_global_ctx *ctx)
1101{
1102 struct libnvmf_context *fctx;
1103 struct libnvmf_params *params;
1104 bool_Bool pass = true1;
1105
1106 printf("test_persistent_tristate:\n");
1107
1108 shr_assert(!libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx))((void)((!libnvmf_context_create(ctx, ((void*)0), ((void*)0),
((void*)0), ((void*)0), &fctx)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1108, "!libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx)"
), 0)))
;
1109
1110 if (libnvmf_context_get_persistent(fctx) != NULL((void*)0)) {
1111 printf(" - fresh context defaults to unset [FAIL]\n");
1112 pass = false0;
1113 } else {
1114 printf(" - fresh context defaults to unset [PASS]\n");
1115 }
1116
1117 params = libnvmf_params_new();
1118 shr_assert(params)((void)((params) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1118, "params"), 0)))
;
1119 shr_assert(!libnvmf_params_set(params, "persistent", "no"))((void)((!libnvmf_params_set(params, "persistent", "no")) || (
shr_assert_fail("../libnvme/tests/config-api.c", 1119, "!libnvmf_params_set(params, \"persistent\", \"no\")"
), 0)))
;
1120 shr_assert(!libnvmf_context_apply_params(fctx, params))((void)((!libnvmf_context_apply_params(fctx, params)) || (shr_assert_fail
("../libnvme/tests/config-api.c", 1120, "!libnvmf_context_apply_params(fctx, params)"
), 0)))
;
1121
1122 {
1123 const char *p = libnvmf_context_get_persistent(fctx);
1124
1125 if (!shr_streq0(p, "no")) {
1126 printf(" - explicit \"no\" != unset [FAIL]\n");
1127 pass = false0;
1128 } else {
1129 printf(" - explicit \"no\" != unset [PASS]\n");
1130 }
1131 }
1132
1133 libnvmf_context_free(fctx);
1134 libnvmf_params_free(params);
1135
1136 return pass;
1137}
1138
1139/*
1140 * The public API leaves hostnqn/hostid resolution to the caller (see
1141 * libnvmf_config_conn_get_hostnqn()'s kdoc) -- this drives that fallback the
1142 * same way a caller (e.g. nvme-cli's build_conn_tid()) does: a connection's
1143 * own value wins, else a caller-supplied default. mv leaves its identity to
1144 * the system default (see test_read()); pv sets its own. Exercises the real
1145 * public-API precedence, not a copy of any one caller's logic.
1146 */
1147static bool_Bool test_hostnqn_precedence(struct libnvme_global_ctx *ctx,
1148 const struct fixture *fx)
1149{
1150 static const char default_hostnqn[] =
1151 "nqn.2014-08.org.nvmexpress:uuid:00000000-0000-0000-0000-000000000000";
1152 static const char default_hostid[] =
1153 "00000000-0000-0000-0000-000000000000";
1154 const struct libnvmf_config_conn *mv, *pv;
1155 struct conn_list conns = { 0 };
1156 struct libnvmf_config *config;
1157 struct libnvmf_tid *mv_tid, *pv_tid;
1158 const char *hostnqn, *hostid;
1159 bool_Bool pass = true1;
1160
1161 printf("test_hostnqn_precedence:\n");
1162
1163 shr_assert(!libnvmf_config_read(ctx, fx->main_path, &config))((void)((!libnvmf_config_read(ctx, fx->main_path, &config
)) || (shr_assert_fail("../libnvme/tests/config-api.c", 1163,
"!libnvmf_config_read(ctx, fx->main_path, &config)"),
0)))
;
1164 libnvmf_config_conn_for_each(config, collect, &conns);
1165 shr_assert(conns.n == 3)((void)((conns.n == 3) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1165, "conns.n == 3"), 0)))
;
1166 mv = conns.conn[1];
1167 pv = conns.conn[2];
1168
1169 hostnqn = libnvmf_config_conn_get_hostnqn(mv);
1170 shr_assert(!hostnqn)((void)((!hostnqn) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1170, "!hostnqn"), 0)))
;
1171 hostnqn = default_hostnqn;
1172 hostid = libnvmf_config_conn_get_hostid(mv);
1173 shr_assert(!hostid)((void)((!hostid) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1173, "!hostid"), 0)))
;
1174 hostid = default_hostid;
1175 shr_assert(!libnvmf_tid_from_fields(((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid
(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr
(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid
, &mv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1182, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid, &mv_tid)"
), 0)))
1176 libnvmf_config_conn_get_transport(mv),((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid
(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr
(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid
, &mv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1182, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid, &mv_tid)"
), 0)))
1177 libnvmf_config_conn_get_traddr(mv),((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid
(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr
(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid
, &mv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1182, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid, &mv_tid)"
), 0)))
1178 libnvmf_config_conn_get_trsvcid(mv),((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid
(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr
(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid
, &mv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1182, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid, &mv_tid)"
), 0)))
1179 libnvmf_config_conn_get_subsysnqn(mv),((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid
(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr
(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid
, &mv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1182, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid, &mv_tid)"
), 0)))
1180 libnvmf_config_conn_get_host_traddr(mv),((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid
(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr
(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid
, &mv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1182, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid, &mv_tid)"
), 0)))
1181 libnvmf_config_conn_get_host_iface(mv),((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid
(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr
(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid
, &mv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1182, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid, &mv_tid)"
), 0)))
1182 hostnqn, hostid, &mv_tid))((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid
(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr
(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid
, &mv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1182, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(mv), libnvmf_config_conn_get_traddr(mv), libnvmf_config_conn_get_trsvcid(mv), libnvmf_config_conn_get_subsysnqn(mv), libnvmf_config_conn_get_host_traddr(mv), libnvmf_config_conn_get_host_iface(mv), hostnqn, hostid, &mv_tid)"
), 0)))
;
1183
1184 if (strcmp(libnvmf_tid_get_hostnqn(mv_tid), default_hostnqn) ||
1185 strcmp(libnvmf_tid_get_hostid(mv_tid), default_hostid)) {
1186 printf(" - unset identity inherits caller default [FAIL]\n");
1187 pass = false0;
1188 } else {
1189 printf(" - unset identity inherits caller default [PASS]\n");
1190 }
1191
1192 hostnqn = libnvmf_config_conn_get_hostnqn(pv);
1193 shr_assert(hostnqn)((void)((hostnqn) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1193, "hostnqn"), 0)))
;
1194 hostid = libnvmf_config_conn_get_hostid(pv);
1195 shr_assert(hostid)((void)((hostid) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1195, "hostid"), 0)))
;
1196 shr_assert(!libnvmf_tid_from_fields(((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid
(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr
(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid
, &pv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1203, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid, &pv_tid)"
), 0)))
1197 libnvmf_config_conn_get_transport(pv),((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid
(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr
(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid
, &pv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1203, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid, &pv_tid)"
), 0)))
1198 libnvmf_config_conn_get_traddr(pv),((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid
(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr
(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid
, &pv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1203, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid, &pv_tid)"
), 0)))
1199 libnvmf_config_conn_get_trsvcid(pv),((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid
(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr
(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid
, &pv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1203, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid, &pv_tid)"
), 0)))
1200 libnvmf_config_conn_get_subsysnqn(pv),((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid
(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr
(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid
, &pv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1203, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid, &pv_tid)"
), 0)))
1201 libnvmf_config_conn_get_host_traddr(pv),((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid
(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr
(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid
, &pv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1203, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid, &pv_tid)"
), 0)))
1202 libnvmf_config_conn_get_host_iface(pv),((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid
(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr
(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid
, &pv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1203, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid, &pv_tid)"
), 0)))
1203 hostnqn, hostid, &pv_tid))((void)((!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport
(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid
(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr
(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid
, &pv_tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1203, "!libnvmf_tid_from_fields( libnvmf_config_conn_get_transport(pv), libnvmf_config_conn_get_traddr(pv), libnvmf_config_conn_get_trsvcid(pv), libnvmf_config_conn_get_subsysnqn(pv), libnvmf_config_conn_get_host_traddr(pv), libnvmf_config_conn_get_host_iface(pv), hostnqn, hostid, &pv_tid)"
), 0)))
;
1204
1205 if (strcmp(libnvmf_tid_get_hostnqn(pv_tid),
1206 "nqn.2014-08.org.nvmexpress:prod-host") ||
1207 strcmp(libnvmf_tid_get_hostid(pv_tid),
1208 "46ba5037-7ce5-41fa-9452-48477bf00080")) {
1209 printf(" - own identity overrides caller default [FAIL]\n");
1210 pass = false0;
1211 } else {
1212 printf(" - own identity overrides caller default [PASS]\n");
1213 }
1214
1215 libnvmf_tid_free(mv_tid);
1216 libnvmf_tid_free(pv_tid);
1217 libnvmf_config_free(config);
1218
1219 return pass;
1220}
1221
1222static bool_Bool test_set_connection_from_tid(struct libnvme_global_ctx *ctx)
1223{
1224 struct libnvmf_context *fctx;
1225 struct libnvmf_tid *tid;
1226 bool_Bool pass = true1;
1227
1228 printf("test_set_connection_from_tid:\n");
1229
1230 shr_assert(!libnvmf_tid_from_fields("tcp", "10.0.0.9", "4420",((void)((!libnvmf_tid_from_fields("tcp", "10.0.0.9", "4420", "nqn.2014-08.org.nvmexpress:subsys"
, "10.0.0.1", "eth0", "nqn.2014-08.org.nvmexpress:host", "2cd2c43b-a90a-45c1-a8cd-86b33ab273b5"
, &tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1234, "!libnvmf_tid_from_fields(\"tcp\", \"10.0.0.9\", \"4420\", \"nqn.2014-08.org.nvmexpress:subsys\", \"10.0.0.1\", \"eth0\", \"nqn.2014-08.org.nvmexpress:host\", \"2cd2c43b-a90a-45c1-a8cd-86b33ab273b5\", &tid)"
), 0)))
1231 "nqn.2014-08.org.nvmexpress:subsys",((void)((!libnvmf_tid_from_fields("tcp", "10.0.0.9", "4420", "nqn.2014-08.org.nvmexpress:subsys"
, "10.0.0.1", "eth0", "nqn.2014-08.org.nvmexpress:host", "2cd2c43b-a90a-45c1-a8cd-86b33ab273b5"
, &tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1234, "!libnvmf_tid_from_fields(\"tcp\", \"10.0.0.9\", \"4420\", \"nqn.2014-08.org.nvmexpress:subsys\", \"10.0.0.1\", \"eth0\", \"nqn.2014-08.org.nvmexpress:host\", \"2cd2c43b-a90a-45c1-a8cd-86b33ab273b5\", &tid)"
), 0)))
1232 "10.0.0.1", "eth0",((void)((!libnvmf_tid_from_fields("tcp", "10.0.0.9", "4420", "nqn.2014-08.org.nvmexpress:subsys"
, "10.0.0.1", "eth0", "nqn.2014-08.org.nvmexpress:host", "2cd2c43b-a90a-45c1-a8cd-86b33ab273b5"
, &tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1234, "!libnvmf_tid_from_fields(\"tcp\", \"10.0.0.9\", \"4420\", \"nqn.2014-08.org.nvmexpress:subsys\", \"10.0.0.1\", \"eth0\", \"nqn.2014-08.org.nvmexpress:host\", \"2cd2c43b-a90a-45c1-a8cd-86b33ab273b5\", &tid)"
), 0)))
1233 "nqn.2014-08.org.nvmexpress:host",((void)((!libnvmf_tid_from_fields("tcp", "10.0.0.9", "4420", "nqn.2014-08.org.nvmexpress:subsys"
, "10.0.0.1", "eth0", "nqn.2014-08.org.nvmexpress:host", "2cd2c43b-a90a-45c1-a8cd-86b33ab273b5"
, &tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1234, "!libnvmf_tid_from_fields(\"tcp\", \"10.0.0.9\", \"4420\", \"nqn.2014-08.org.nvmexpress:subsys\", \"10.0.0.1\", \"eth0\", \"nqn.2014-08.org.nvmexpress:host\", \"2cd2c43b-a90a-45c1-a8cd-86b33ab273b5\", &tid)"
), 0)))
1234 "2cd2c43b-a90a-45c1-a8cd-86b33ab273b5", &tid))((void)((!libnvmf_tid_from_fields("tcp", "10.0.0.9", "4420", "nqn.2014-08.org.nvmexpress:subsys"
, "10.0.0.1", "eth0", "nqn.2014-08.org.nvmexpress:host", "2cd2c43b-a90a-45c1-a8cd-86b33ab273b5"
, &tid)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1234, "!libnvmf_tid_from_fields(\"tcp\", \"10.0.0.9\", \"4420\", \"nqn.2014-08.org.nvmexpress:subsys\", \"10.0.0.1\", \"eth0\", \"nqn.2014-08.org.nvmexpress:host\", \"2cd2c43b-a90a-45c1-a8cd-86b33ab273b5\", &tid)"
), 0)))
;
1235
1236 shr_assert(!libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx))((void)((!libnvmf_context_create(ctx, ((void*)0), ((void*)0),
((void*)0), ((void*)0), &fctx)) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1236, "!libnvmf_context_create(ctx, NULL, NULL, NULL, NULL, &fctx)"
), 0)))
;
1237
1238 if (libnvmf_context_set_connection_from_tid(fctx, tid)) {
1239 printf(" - set failed [FAIL]\n");
1240 pass = false0;
1241 goto out;
1242 }
1243
1244 if (strcmp(libnvmf_context_get_transport(fctx), "tcp") ||
1245 strcmp(libnvmf_context_get_traddr(fctx), "10.0.0.9") ||
1246 strcmp(libnvmf_context_get_trsvcid(fctx), "4420") ||
1247 strcmp(libnvmf_context_get_subsysnqn(fctx),
1248 "nqn.2014-08.org.nvmexpress:subsys") ||
1249 strcmp(libnvmf_context_get_host_traddr(fctx), "10.0.0.1") ||
1250 strcmp(libnvmf_context_get_host_iface(fctx), "eth0")) {
1251 printf(" - addressing fields [FAIL]\n");
1252 pass = false0;
1253 } else {
1254 printf(" - addressing fields applied [PASS]\n");
1255 }
1256
1257 if (strcmp(libnvmf_context_get_hostnqn(fctx),
1258 "nqn.2014-08.org.nvmexpress:host") ||
1259 strcmp(libnvmf_context_get_hostid(fctx),
1260 "2cd2c43b-a90a-45c1-a8cd-86b33ab273b5")) {
1261 printf(" - identity fields [FAIL]\n");
1262 pass = false0;
1263 } else {
1264 printf(" - identity fields applied [PASS]\n");
1265 }
1266
1267out:
1268 if (libnvmf_context_set_connection_from_tid(NULL((void*)0), tid) != -EINVAL22 ||
1269 libnvmf_context_set_connection_from_tid(fctx, NULL((void*)0)) != -EINVAL22) {
1270 printf(" - NULL rejected [FAIL]\n");
1271 pass = false0;
1272 } else {
1273 printf(" - NULL rejected [PASS]\n");
1274 }
1275
1276 libnvmf_context_free(fctx);
1277 libnvmf_tid_free(tid);
1278
1279 return pass;
1280}
1281
1282static bool_Bool test_edge_cases(struct libnvme_global_ctx *ctx,
1283 const struct fixture *fx)
1284{
1285 const struct libnvmf_params *params;
1286 struct conn_list list = { 0 };
1287 struct libnvmf_config *config;
1288 char missing[320];
1289 bool_Bool pass = true1;
1290
1291 printf("test_edge_cases:\n");
1292
1293 if (!libnvmf_config_read(NULL((void*)0), fx->main_path, &config) ||
1294 libnvmf_config_validate(NULL((void*)0), fx->main_path) != -EINVAL22) {
1295 printf(" - NULL ctx [FAIL]\n");
1296 pass = false0;
1297 } else {
1298 printf(" - NULL ctx rejected [PASS]\n");
1299 }
1300
1301 /* Reading an absent configuration yields an empty connection list. */
1302 snprintf(missing, sizeof(missing), "%s/no-such.conf", fx->dir);
1303 if (libnvmf_config_read(ctx, missing, &config)) {
1304 printf(" - absent config read [FAIL]\n");
1305 pass = false0;
1306 } else {
1307 libnvmf_config_conn_for_each(config, collect, &list);
1308 if (list.n) {
1309 printf(" - absent config not empty [FAIL]\n");
1310 pass = false0;
1311 } else {
1312 printf(" - absent config reads as empty [PASS]\n");
1313 }
1314 }
1315 libnvmf_config_free(config);
1316
1317 /* Everything is NULL-tolerant on the way out. */
1318 if (libnvmf_config_conn_is_dc(NULL((void*)0)) ||
1319 libnvmf_config_conn_get_transport(NULL((void*)0)) ||
1320 libnvmf_config_conn_get_traddr(NULL((void*)0)) ||
1321 libnvmf_config_conn_get_trsvcid(NULL((void*)0)) ||
1322 libnvmf_config_conn_get_subsysnqn(NULL((void*)0)) ||
1323 libnvmf_config_conn_get_host_traddr(NULL((void*)0)) ||
1324 libnvmf_config_conn_get_host_iface(NULL((void*)0)) ||
1325 libnvmf_config_conn_get_hostnqn(NULL((void*)0)) ||
1326 libnvmf_config_conn_get_hostid(NULL((void*)0)) ||
1327 libnvmf_config_conn_get_params(NULL((void*)0)) ||
1328 libnvmf_config_conn_get_hostsymname(NULL((void*)0)) ||
1329 libnvmf_config_conn_get_source(NULL((void*)0)) ||
1330 libnvmf_config_resolve_discovered(NULL((void*)0), NULL((void*)0), true1) ||
1331 libnvmf_config_get_hostnqn(NULL((void*)0)) ||
1332 libnvmf_config_get_hostid(NULL((void*)0)) ||
1333 libnvmf_config_get_hostsymname(NULL((void*)0)) ||
1334 libnvmf_params_get(NULL((void*)0), "tos")) {
1335 printf(" - NULL tolerance [FAIL]\n");
1336 pass = false0;
1337 } else {
1338 printf(" - NULL-tolerant getters [PASS]\n");
1339 }
1340 if (libnvmf_config_get_discovered_params(NULL((void*)0), NULL((void*)0), true1, "nqn",
1341 &params) != -EINVAL22) {
1342 printf(" - discovered params of a NULL config [FAIL]\n");
1343 pass = false0;
1344 } else {
1345 printf(" - discovered params of a NULL config: -EINVAL [PASS]\n");
1346 }
1347 libnvmf_config_conn_for_each(NULL((void*)0), collect, NULL((void*)0));
1348 libnvmf_params_for_each(NULL((void*)0), NULL((void*)0), NULL((void*)0));
1349 libnvmf_config_free(NULL((void*)0));
1350 libnvmf_context_set_config(NULL((void*)0), NULL((void*)0), NULL((void*)0));
1351 printf(" - NULL iteration and free are no-ops [PASS]\n");
1352
1353 return pass;
1354}
1355
1356int main(void)
1357{
1358 struct libnvme_global_ctx *ctx;
1359 struct fixture fx;
1360 bool_Bool pass = true1;
1361
1362 ctx = libnvme_create_global_ctx();
1363 shr_assert(ctx)((void)((ctx) || (shr_assert_fail("../libnvme/tests/config-api.c"
, 1363, "ctx"), 0)))
;
1364 fixture_create(&fx);
1365
1366 pass &= test_read(ctx, &fx);
1367 pass &= test_resolve_discovered(ctx, &fx);
1368 pass &= test_get_discovered_params(ctx, &fx);
1369 pass &= test_duplicate_nqn(ctx, &fx);
1370 pass &= test_wellknown_ctrl_secret(ctx, &fx);
1371 pass &= test_top_level_host(ctx, &fx);
1372 pass &= test_persona_validation(ctx, &fx);
1373 pass &= test_validate(ctx, &fx);
1374 pass &= test_emit(ctx, &fx);
1375 pass &= test_hostnqn_precedence(ctx, &fx);
1376 pass &= test_apply_params(ctx);
1377 pass &= test_persistent_tristate(ctx);
1378 pass &= test_tls_key_source(ctx);
1379 pass &= test_set_connection_from_tid(ctx);
1380 pass &= test_edge_cases(ctx, &fx);
1381
1382 fixture_destroy(&fx);
1383 libnvme_free_global_ctx(ctx);
1384
1385 fflush(stdoutstdout);
1386 exit(pass ? EXIT_SUCCESS0 : EXIT_FAILURE1);
1387}