xref: /spdk/test/unit/lib/iscsi/param.c/param_ut.c (revision 552e21cce6cccbf833ed9109827e08337377d7ce)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "spdk/scsi.h"
37 
38 #include "spdk_cunit.h"
39 
40 #include "../common.c"
41 #include "iscsi/param.c"
42 
43 #include "spdk_internal/mock.h"
44 
45 struct spdk_iscsi_globals g_spdk_iscsi;
46 
47 DEFINE_STUB(spdk_iscsi_find_tgt_node, struct spdk_iscsi_tgt_node *,
48 	    (const char *target_name), NULL);
49 
50 DEFINE_STUB(spdk_iscsi_tgt_node_access, bool,
51 	    (struct spdk_iscsi_conn *conn, struct spdk_iscsi_tgt_node *target,
52 	     const char *iqn, const char *addr),
53 	    false);
54 
55 DEFINE_STUB(spdk_iscsi_send_tgts, int,
56 	    (struct spdk_iscsi_conn *conn, const char *iiqn, const char *iaddr,
57 	     const char *tiqn, uint8_t *data, int alloc_len, int data_len),
58 	    0);
59 
60 static void
61 burst_length_param_negotation(int FirstBurstLength, int MaxBurstLength,
62 			      int initialR2T)
63 {
64 	struct spdk_iscsi_sess sess;
65 	struct spdk_iscsi_conn conn;
66 	struct iscsi_param *params;
67 	struct iscsi_param **params_p;
68 	char data[8192];
69 	int rc;
70 	int total, len;
71 
72 	total = 0;
73 	params = NULL;
74 	params_p = &params;
75 
76 	memset(&sess, 0, sizeof(sess));
77 	memset(&conn, 0, sizeof(conn));
78 	memset(data, 0, 8192);
79 
80 	sess.ExpCmdSN = 0;
81 	sess.MaxCmdSN = 64;
82 	sess.session_type = SESSION_TYPE_NORMAL;
83 	sess.params = NULL;
84 	sess.MaxBurstLength = 65536;
85 	sess.InitialR2T = true;
86 	sess.FirstBurstLength = SPDK_ISCSI_FIRST_BURST_LENGTH;
87 	sess.MaxOutstandingR2T = 1;
88 
89 	/* set default params */
90 	rc = spdk_iscsi_sess_params_init(&sess.params);
91 	CU_ASSERT(rc == 0);
92 
93 	rc = spdk_iscsi_param_set_int(sess.params, "FirstBurstLength",
94 				      sess.FirstBurstLength);
95 	CU_ASSERT(rc == 0);
96 
97 	rc = spdk_iscsi_param_set_int(sess.params, "MaxBurstLength",
98 				      sess.MaxBurstLength);
99 	CU_ASSERT(rc == 0);
100 
101 	rc = spdk_iscsi_param_set(sess.params, "InitialR2T",
102 				  sess.InitialR2T ? "Yes" : "No");
103 	CU_ASSERT(rc == 0);
104 
105 	conn.full_feature = 1;
106 	conn.sess = &sess;
107 	conn.MaxRecvDataSegmentLength = 65536;
108 
109 	rc = spdk_iscsi_conn_params_init(&conn.params);
110 	CU_ASSERT(rc == 0);
111 
112 	/* construct the data */
113 	len = snprintf(data + total, 8192 - total, "%s=%d",
114 		       "FirstBurstLength", FirstBurstLength);
115 	total += len + 1;
116 
117 	len = snprintf(data + total, 8192 - total, "%s=%d",
118 		       "MaxBurstLength", MaxBurstLength);
119 	total += len + 1;
120 
121 	len = snprintf(data + total, 8192 - total, "%s=%d",
122 		       "InitialR2T", initialR2T);
123 	total += len + 1;
124 
125 	/* add one extra NUL byte at the end to match real iSCSI params */
126 	total++;
127 
128 	/* store incoming parameters */
129 	rc = spdk_iscsi_parse_params(params_p, data, total, false, NULL);
130 	CU_ASSERT(rc == 0);
131 
132 	/* negotiate parameters */
133 	rc = spdk_iscsi_negotiate_params(&conn, params_p,
134 					 data, 8192, rc);
135 	CU_ASSERT(rc > 0);
136 
137 	rc = spdk_iscsi_copy_param2var(&conn);
138 	CU_ASSERT(rc == 0);
139 	CU_ASSERT(conn.sess->FirstBurstLength <= SPDK_ISCSI_FIRST_BURST_LENGTH);
140 	CU_ASSERT(conn.sess->FirstBurstLength <= conn.sess->MaxBurstLength);
141 	CU_ASSERT(conn.sess->MaxBurstLength <= SPDK_ISCSI_MAX_BURST_LENGTH);
142 	CU_ASSERT(conn.sess->MaxOutstandingR2T == 1);
143 
144 	spdk_iscsi_param_free(sess.params);
145 	spdk_iscsi_param_free(conn.params);
146 	spdk_iscsi_param_free(*params_p);
147 }
148 
149 static void
150 param_negotiation_test(void)
151 {
152 	burst_length_param_negotation(8192, 16384, 0);
153 	burst_length_param_negotation(8192, 16384, 1);
154 	burst_length_param_negotation(8192, 1024, 1);
155 	burst_length_param_negotation(8192, 1024, 0);
156 	burst_length_param_negotation(512, 1024, 1);
157 	burst_length_param_negotation(512, 1024, 0);
158 }
159 
160 static void
161 list_negotiation_test(void)
162 {
163 	int add_param_value = 0;
164 	struct iscsi_param param = {};
165 	char *new_val;
166 	char valid_list_buf[1024];
167 	char in_val_buf[1024];
168 
169 #define TEST_LIST(valid_list, in_val, expected_result) \
170 	do { \
171 		snprintf(valid_list_buf, sizeof(valid_list_buf), "%s", valid_list); \
172 		snprintf(in_val_buf, sizeof(in_val_buf), "%s", in_val); \
173 		new_val = spdk_iscsi_negotiate_param_list(&add_param_value, &param, valid_list_buf, in_val_buf, NULL); \
174 		if (expected_result) { \
175 			SPDK_CU_ASSERT_FATAL(new_val != NULL); \
176 			CU_ASSERT_STRING_EQUAL(new_val, expected_result); \
177 		} \
178 	} while (0)
179 
180 	TEST_LIST("None", "None", "None");
181 	TEST_LIST("CHAP,None", "None", "None");
182 	TEST_LIST("CHAP,None", "CHAP", "CHAP");
183 	TEST_LIST("KRB5,SRP,CHAP,None", "SRP,CHAP,None", "SRP");
184 	TEST_LIST("KRB5,SRP,CHAP,None", "CHAP,SRP,None", "CHAP");
185 	TEST_LIST("KRB5,SRP,CHAP,None", "SPKM1,SRP,CHAP,None", "SRP");
186 	TEST_LIST("KRB5,SRP,None", "CHAP,None", "None");
187 }
188 
189 #define PARSE(strconst, partial_enabled, partial_text) \
190 	data = strconst; \
191 	len = sizeof(strconst); \
192 	rc = spdk_iscsi_parse_params(&params, data, len, partial_enabled, partial_text)
193 
194 #define EXPECT_VAL(key, expected_value) \
195 	{ \
196 		const char *val = spdk_iscsi_param_get_val(params, key); \
197 		CU_ASSERT(val != NULL); \
198 		if (val != NULL) { \
199 			CU_ASSERT(strcmp(val, expected_value) == 0); \
200 		} \
201 	}
202 
203 #define EXPECT_NULL(key) \
204 	CU_ASSERT(spdk_iscsi_param_get_val(params, key) == NULL)
205 
206 static void
207 parse_valid_test(void)
208 {
209 	struct iscsi_param *params = NULL;
210 	int rc;
211 	char *data;
212 	int len;
213 	char *partial_parameter = NULL;
214 
215 	/* simple test with a single key=value */
216 	PARSE("Abc=def\0", false, NULL);
217 	CU_ASSERT(rc == 0);
218 	EXPECT_VAL("Abc", "def");
219 
220 	/* multiple key=value pairs */
221 	PARSE("Aaa=bbbbbb\0Xyz=test\0", false, NULL);
222 	CU_ASSERT(rc == 0);
223 	EXPECT_VAL("Aaa", "bbbbbb");
224 	EXPECT_VAL("Xyz", "test");
225 
226 	/* value with embedded '=' */
227 	PARSE("A=b=c\0", false, NULL);
228 	CU_ASSERT(rc == 0);
229 	EXPECT_VAL("A", "b=c");
230 
231 	/* CHAP_C=AAAA.... with value length 8192 */
232 	len = strlen("CHAP_C=") + ISCSI_TEXT_MAX_VAL_LEN + 1/* null terminators */;
233 	data = malloc(len);
234 	SPDK_CU_ASSERT_FATAL(data != NULL);
235 	memset(data, 'A', len);
236 	memcpy(data, "CHAP_C", 6);
237 	data[6] = '=';
238 	data[len - 1] = '\0';
239 	rc = spdk_iscsi_parse_params(&params, data, len, false, NULL);
240 	CU_ASSERT(rc == 0);
241 	free(data);
242 
243 	/* partial parameter: value is partial */
244 	PARSE("C=AAA\0D=B", true, &partial_parameter);
245 	SPDK_CU_ASSERT_FATAL(partial_parameter != NULL);
246 	CU_ASSERT_STRING_EQUAL(partial_parameter, "D=B");
247 	CU_ASSERT(rc == 0);
248 	EXPECT_VAL("C", "AAA");
249 	EXPECT_NULL("D");
250 	PARSE("XXXX\0E=UUUU\0", false, &partial_parameter);
251 	CU_ASSERT(rc == 0);
252 	EXPECT_VAL("D", "BXXXX");
253 	EXPECT_VAL("E", "UUUU");
254 	CU_ASSERT_PTR_NULL(partial_parameter);
255 
256 	/* partial parameter: key is partial */
257 	PARSE("IAMAFAK", true, &partial_parameter);
258 	CU_ASSERT_STRING_EQUAL(partial_parameter, "IAMAFAK");
259 	CU_ASSERT(rc == 0);
260 	EXPECT_NULL("IAMAFAK");
261 	PARSE("EDKEY=TTTT\0F=IIII", false, &partial_parameter);
262 	CU_ASSERT(rc == 0);
263 	EXPECT_VAL("IAMAFAKEDKEY", "TTTT");
264 	EXPECT_VAL("F", "IIII");
265 	CU_ASSERT_PTR_NULL(partial_parameter);
266 
267 	/* Second partial parameter is the only parameter */
268 	PARSE("OOOO", true, &partial_parameter);
269 	CU_ASSERT_STRING_EQUAL(partial_parameter, "OOOO");
270 	CU_ASSERT(rc == 0);
271 	EXPECT_NULL("OOOO");
272 	PARSE("LL=MMMM", false, &partial_parameter);
273 	CU_ASSERT(rc == 0);
274 	EXPECT_VAL("OOOOLL", "MMMM");
275 	CU_ASSERT_PTR_NULL(partial_parameter);
276 
277 	spdk_iscsi_param_free(params);
278 }
279 
280 static void
281 parse_invalid_test(void)
282 {
283 	struct iscsi_param *params = NULL;
284 	int rc;
285 	char *data;
286 	int len;
287 
288 	/* key without '=' */
289 	PARSE("Abc\0", false, NULL);
290 	CU_ASSERT(rc != 0);
291 	EXPECT_NULL("Abc");
292 
293 	/* multiple key=value pairs, one missing '=' */
294 	PARSE("Abc=def\0Xyz\0Www=test\0", false, NULL);
295 	CU_ASSERT(rc != 0);
296 	EXPECT_VAL("Abc", "def");
297 	EXPECT_NULL("Xyz");
298 	EXPECT_NULL("Www");
299 
300 	/* empty key */
301 	PARSE("=abcdef", false, NULL);
302 	CU_ASSERT(rc != 0);
303 	EXPECT_NULL("");
304 
305 	/* CHAP_C=AAAA.... with value length 8192 + 1 */
306 	len = strlen("CHAP_C=") + ISCSI_TEXT_MAX_VAL_LEN + 1 /* max value len + 1 */ +
307 	      1 /* null terminators */;
308 	data = malloc(len);
309 	SPDK_CU_ASSERT_FATAL(data != NULL);
310 	memset(data, 'A', len);
311 	memcpy(data, "CHAP_C", 6);
312 	data[6] = '=';
313 	data[len - 1] = '\0';
314 	rc = spdk_iscsi_parse_params(&params, data, len, false, NULL);
315 	free(data);
316 	CU_ASSERT(rc != 0);
317 	EXPECT_NULL("CHAP_C");
318 
319 	/* Test simple value, length of value bigger than 255 */
320 	len = strlen("A=") + ISCSI_TEXT_MAX_SIMPLE_VAL_LEN + 1 /* max simple value len + 1 */ +
321 	      1 /* null terminators */;
322 	data = malloc(len);
323 	SPDK_CU_ASSERT_FATAL(data != NULL);
324 	memset(data, 'A', len);
325 	data[1] = '=';
326 	data[len - 1] = '\0';
327 	rc = spdk_iscsi_parse_params(&params, data, len, false, NULL);
328 	free(data);
329 	CU_ASSERT(rc != 0);
330 	EXPECT_NULL("A");
331 
332 	/* key length bigger than 63 */
333 	len = ISCSI_TEXT_MAX_KEY_LEN + 1 /* max key length + 1 */ + 1 /* = */ + 1 /* A */ +
334 	      1 /* null terminators */;
335 	data = malloc(len);
336 	SPDK_CU_ASSERT_FATAL(data != NULL);
337 	memset(data, 'A', len);
338 	data[64] = '=';
339 	data[len - 1] = '\0';
340 	rc = spdk_iscsi_parse_params(&params, data, len, false, NULL);
341 	free(data);
342 	CU_ASSERT(rc != 0);
343 	EXPECT_NULL("A");
344 
345 	/* duplicated key */
346 	PARSE("B=BB", false, NULL);
347 	CU_ASSERT(rc == 0);
348 	PARSE("B=BBBB", false, NULL);
349 	CU_ASSERT(rc != 0);
350 	EXPECT_VAL("B", "BB");
351 
352 	spdk_iscsi_param_free(params);
353 }
354 
355 int
356 main(int argc, char **argv)
357 {
358 	CU_pSuite	suite = NULL;
359 	unsigned int	num_failures;
360 
361 	if (CU_initialize_registry() != CUE_SUCCESS) {
362 		return CU_get_error();
363 	}
364 
365 	suite = CU_add_suite("iscsi_suite", NULL, NULL);
366 	if (suite == NULL) {
367 		CU_cleanup_registry();
368 		return CU_get_error();
369 	}
370 
371 	if (
372 		CU_add_test(suite, "param negotiation test",
373 			    param_negotiation_test) == NULL ||
374 		CU_add_test(suite, "list negotiation test",
375 			    list_negotiation_test) == NULL ||
376 		CU_add_test(suite, "parse valid test",
377 			    parse_valid_test) == NULL ||
378 		CU_add_test(suite, "parse invalid test",
379 			    parse_invalid_test) == NULL
380 	) {
381 		CU_cleanup_registry();
382 		return CU_get_error();
383 	}
384 
385 	CU_basic_set_mode(CU_BRM_VERBOSE);
386 	CU_basic_run_tests();
387 	num_failures = CU_get_number_of_failures();
388 	CU_cleanup_registry();
389 	return num_failures;
390 }
391