xref: /spdk/test/unit/lib/iscsi/param.c/param_ut.c (revision 7506a7aa53d239f533af3bc768f0d2af55e735fe)
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_iscsi;
46 
47 DEFINE_STUB(iscsi_find_tgt_node, struct spdk_iscsi_tgt_node *,
48 	    (const char *target_name), NULL);
49 
50 DEFINE_STUB(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(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_negotiation(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 = iscsi_sess_params_init(&sess.params);
91 	CU_ASSERT(rc == 0);
92 
93 	rc = iscsi_param_set_int(sess.params, "FirstBurstLength",
94 				 sess.FirstBurstLength);
95 	CU_ASSERT(rc == 0);
96 
97 	rc = iscsi_param_set_int(sess.params, "MaxBurstLength",
98 				 sess.MaxBurstLength);
99 	CU_ASSERT(rc == 0);
100 
101 	rc = 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 = 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 = iscsi_parse_params(params_p, data, total, false, NULL);
130 	CU_ASSERT(rc == 0);
131 
132 	/* negotiate parameters */
133 	rc = iscsi_negotiate_params(&conn, params_p,
134 				    data, 8192, rc);
135 	CU_ASSERT(rc > 0);
136 
137 	rc = 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 	iscsi_param_free(sess.params);
145 	iscsi_param_free(conn.params);
146 	iscsi_param_free(*params_p);
147 }
148 
149 static void
150 param_negotiation_test(void)
151 {
152 	burst_length_param_negotiation(8192, 16384, 0);
153 	burst_length_param_negotiation(8192, 16384, 1);
154 	burst_length_param_negotiation(8192, 1024, 1);
155 	burst_length_param_negotiation(8192, 1024, 0);
156 	burst_length_param_negotiation(512, 1024, 1);
157 	burst_length_param_negotiation(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 = 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) - 1; \
192 	rc = iscsi_parse_params(&params, data, len, partial_enabled, partial_text)
193 
194 #define EXPECT_VAL(key, expected_value) \
195 	{ \
196 		const char *val = 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(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 = 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 	/* partial parameter: NULL data */
268 	/* It is technically allowed to have a TEXT PDU with no data, yet
269 	 * CONTINUE bit is enabled - make sure we handle that case correctly.
270 	 */
271 	rc = iscsi_parse_params(&params, NULL, 0, true, &partial_parameter);
272 	CU_ASSERT(rc == 0);
273 	CU_ASSERT_PTR_NULL(partial_parameter);
274 
275 	/* Second partial parameter is the only parameter */
276 	PARSE("OOOO", true, &partial_parameter);
277 	CU_ASSERT_STRING_EQUAL(partial_parameter, "OOOO");
278 	CU_ASSERT(rc == 0);
279 	EXPECT_NULL("OOOO");
280 	PARSE("LL=MMMM", false, &partial_parameter);
281 	CU_ASSERT(rc == 0);
282 	EXPECT_VAL("OOOOLL", "MMMM");
283 	CU_ASSERT_PTR_NULL(partial_parameter);
284 
285 	partial_parameter = NULL;
286 	data = "PartialKey=";
287 	len = 7;
288 	rc = iscsi_parse_params(&params, data, len, true, &partial_parameter);
289 	CU_ASSERT(rc == 0);
290 	CU_ASSERT_STRING_EQUAL(partial_parameter, "Partial");
291 	EXPECT_NULL("PartialKey");
292 	PARSE("Key=Value", false, &partial_parameter);
293 	CU_ASSERT(rc == 0);
294 	EXPECT_VAL("PartialKey", "Value");
295 	CU_ASSERT_PTR_NULL(partial_parameter);
296 
297 	iscsi_param_free(params);
298 }
299 
300 static void
301 parse_invalid_test(void)
302 {
303 	struct iscsi_param *params = NULL;
304 	int rc;
305 	char *data;
306 	int len;
307 
308 	/* key without '=' */
309 	PARSE("Abc\0", false, NULL);
310 	CU_ASSERT(rc != 0);
311 	EXPECT_NULL("Abc");
312 
313 	/* multiple key=value pairs, one missing '=' */
314 	PARSE("Abc=def\0Xyz\0Www=test\0", false, NULL);
315 	CU_ASSERT(rc != 0);
316 	EXPECT_VAL("Abc", "def");
317 	EXPECT_NULL("Xyz");
318 	EXPECT_NULL("Www");
319 
320 	/* empty key */
321 	PARSE("=abcdef", false, NULL);
322 	CU_ASSERT(rc != 0);
323 	EXPECT_NULL("");
324 
325 	/* CHAP_C=AAAA.... with value length 8192 + 1 */
326 	len = strlen("CHAP_C=") + ISCSI_TEXT_MAX_VAL_LEN + 1 /* max value len + 1 */ +
327 	      1 /* null terminators */;
328 	data = malloc(len);
329 	SPDK_CU_ASSERT_FATAL(data != NULL);
330 	memset(data, 'A', len);
331 	memcpy(data, "CHAP_C", 6);
332 	data[6] = '=';
333 	data[len - 1] = '\0';
334 	rc = iscsi_parse_params(&params, data, len, false, NULL);
335 	free(data);
336 	CU_ASSERT(rc != 0);
337 	EXPECT_NULL("CHAP_C");
338 
339 	/* Test simple value, length of value bigger than 255 */
340 	len = strlen("A=") + ISCSI_TEXT_MAX_SIMPLE_VAL_LEN + 1 /* max simple value len + 1 */ +
341 	      1 /* null terminators */;
342 	data = malloc(len);
343 	SPDK_CU_ASSERT_FATAL(data != NULL);
344 	memset(data, 'A', len);
345 	data[1] = '=';
346 	data[len - 1] = '\0';
347 	rc = iscsi_parse_params(&params, data, len, false, NULL);
348 	free(data);
349 	CU_ASSERT(rc != 0);
350 	EXPECT_NULL("A");
351 
352 	/* key length bigger than 63 */
353 	len = ISCSI_TEXT_MAX_KEY_LEN + 1 /* max key length + 1 */ + 1 /* = */ + 1 /* A */ +
354 	      1 /* null terminators */;
355 	data = malloc(len);
356 	SPDK_CU_ASSERT_FATAL(data != NULL);
357 	memset(data, 'A', len);
358 	data[64] = '=';
359 	data[len - 1] = '\0';
360 	rc = iscsi_parse_params(&params, data, len, false, NULL);
361 	free(data);
362 	CU_ASSERT(rc != 0);
363 	EXPECT_NULL("A");
364 
365 	/* duplicated key */
366 	PARSE("B=BB", false, NULL);
367 	CU_ASSERT(rc == 0);
368 	PARSE("B=BBBB", false, NULL);
369 	CU_ASSERT(rc != 0);
370 	EXPECT_VAL("B", "BB");
371 
372 	/* Test where data buffer has non-NULL characters past the end of
373 	 * the valid data region.  This can happen with SPDK iSCSI target,
374 	 * since data buffers are reused and we do not zero the data buffers
375 	 * after they are freed since it would be too expensive.  Added as
376 	 * part of fixing an intermittent Calsoft failure that triggered this
377 	 * bug.
378 	 */
379 	data = "MaxRecvDataSegmentLength=81928";
380 	len = strlen(data) - 1;
381 	rc = iscsi_parse_params(&params, data, len, false, NULL);
382 	EXPECT_VAL("MaxRecvDataSegmentLength", "8192");
383 	CU_ASSERT(rc == 0);
384 	iscsi_param_free(params);
385 }
386 
387 int
388 main(int argc, char **argv)
389 {
390 	CU_pSuite	suite = NULL;
391 	unsigned int	num_failures;
392 
393 	CU_set_error_action(CUEA_ABORT);
394 	CU_initialize_registry();
395 
396 	suite = CU_add_suite("iscsi_suite", NULL, NULL);
397 
398 	CU_ADD_TEST(suite, param_negotiation_test);
399 	CU_ADD_TEST(suite, list_negotiation_test);
400 	CU_ADD_TEST(suite, parse_valid_test);
401 	CU_ADD_TEST(suite, parse_invalid_test);
402 
403 	CU_basic_set_mode(CU_BRM_VERBOSE);
404 	CU_basic_run_tests();
405 	num_failures = CU_get_number_of_failures();
406 	CU_cleanup_registry();
407 	return num_failures;
408 }
409