1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 8 #include "spdk/scsi.h" 9 10 #include "spdk_cunit.h" 11 12 #include "../common.c" 13 #include "iscsi/param.c" 14 15 #include "spdk_internal/mock.h" 16 17 struct spdk_iscsi_globals g_iscsi; 18 19 DEFINE_STUB(iscsi_find_tgt_node, struct spdk_iscsi_tgt_node *, 20 (const char *target_name), NULL); 21 22 DEFINE_STUB(iscsi_tgt_node_access, bool, 23 (struct spdk_iscsi_conn *conn, struct spdk_iscsi_tgt_node *target, 24 const char *iqn, const char *addr), 25 false); 26 27 DEFINE_STUB(iscsi_send_tgts, int, 28 (struct spdk_iscsi_conn *conn, const char *iiqn, const char *iaddr, 29 const char *tiqn, uint8_t *data, int alloc_len, int data_len), 30 0); 31 32 static void 33 burst_length_param_negotiation(int FirstBurstLength, int MaxBurstLength, 34 int initialR2T) 35 { 36 struct spdk_iscsi_sess sess; 37 struct spdk_iscsi_conn conn; 38 struct iscsi_param *params; 39 struct iscsi_param **params_p; 40 char data[8192]; 41 int rc; 42 int total, len; 43 44 total = 0; 45 params = NULL; 46 params_p = ¶ms; 47 48 memset(&sess, 0, sizeof(sess)); 49 memset(&conn, 0, sizeof(conn)); 50 memset(data, 0, 8192); 51 52 sess.ExpCmdSN = 0; 53 sess.MaxCmdSN = 64; 54 sess.session_type = SESSION_TYPE_NORMAL; 55 sess.params = NULL; 56 sess.MaxBurstLength = 65536; 57 sess.InitialR2T = true; 58 sess.FirstBurstLength = SPDK_ISCSI_FIRST_BURST_LENGTH; 59 sess.MaxOutstandingR2T = 1; 60 61 /* set default params */ 62 rc = iscsi_sess_params_init(&sess.params); 63 CU_ASSERT(rc == 0); 64 65 rc = iscsi_param_set_int(sess.params, "FirstBurstLength", 66 sess.FirstBurstLength); 67 CU_ASSERT(rc == 0); 68 69 rc = iscsi_param_set_int(sess.params, "MaxBurstLength", 70 sess.MaxBurstLength); 71 CU_ASSERT(rc == 0); 72 73 rc = iscsi_param_set(sess.params, "InitialR2T", 74 sess.InitialR2T ? "Yes" : "No"); 75 CU_ASSERT(rc == 0); 76 77 conn.full_feature = 1; 78 conn.sess = &sess; 79 conn.MaxRecvDataSegmentLength = 65536; 80 81 rc = iscsi_conn_params_init(&conn.params); 82 CU_ASSERT(rc == 0); 83 84 /* construct the data */ 85 len = snprintf(data + total, 8192 - total, "%s=%d", 86 "FirstBurstLength", FirstBurstLength); 87 total += len + 1; 88 89 len = snprintf(data + total, 8192 - total, "%s=%d", 90 "MaxBurstLength", MaxBurstLength); 91 total += len + 1; 92 93 len = snprintf(data + total, 8192 - total, "%s=%d", 94 "InitialR2T", initialR2T); 95 total += len + 1; 96 97 /* add one extra NUL byte at the end to match real iSCSI params */ 98 total++; 99 100 /* store incoming parameters */ 101 rc = iscsi_parse_params(params_p, data, total, false, NULL); 102 CU_ASSERT(rc == 0); 103 104 /* negotiate parameters */ 105 rc = iscsi_negotiate_params(&conn, params_p, 106 data, 8192, rc); 107 CU_ASSERT(rc > 0); 108 109 rc = iscsi_copy_param2var(&conn); 110 CU_ASSERT(rc == 0); 111 CU_ASSERT(conn.sess->FirstBurstLength <= SPDK_ISCSI_FIRST_BURST_LENGTH); 112 CU_ASSERT(conn.sess->FirstBurstLength <= conn.sess->MaxBurstLength); 113 CU_ASSERT(conn.sess->MaxBurstLength <= SPDK_ISCSI_MAX_BURST_LENGTH); 114 CU_ASSERT(conn.sess->MaxOutstandingR2T == 1); 115 116 iscsi_param_free(sess.params); 117 iscsi_param_free(conn.params); 118 iscsi_param_free(*params_p); 119 } 120 121 static void 122 param_negotiation_test(void) 123 { 124 burst_length_param_negotiation(8192, 16384, 0); 125 burst_length_param_negotiation(8192, 16384, 1); 126 burst_length_param_negotiation(8192, 1024, 1); 127 burst_length_param_negotiation(8192, 1024, 0); 128 burst_length_param_negotiation(512, 1024, 1); 129 burst_length_param_negotiation(512, 1024, 0); 130 } 131 132 static void 133 list_negotiation_test(void) 134 { 135 int add_param_value = 0; 136 struct iscsi_param param = {}; 137 char *new_val; 138 char valid_list_buf[1024]; 139 char in_val_buf[1024]; 140 141 #define TEST_LIST(valid_list, in_val, expected_result) \ 142 do { \ 143 snprintf(valid_list_buf, sizeof(valid_list_buf), "%s", valid_list); \ 144 snprintf(in_val_buf, sizeof(in_val_buf), "%s", in_val); \ 145 new_val = iscsi_negotiate_param_list(&add_param_value, ¶m, valid_list_buf, in_val_buf, NULL); \ 146 if (expected_result) { \ 147 SPDK_CU_ASSERT_FATAL(new_val != NULL); \ 148 CU_ASSERT_STRING_EQUAL(new_val, expected_result); \ 149 } \ 150 } while (0) 151 152 TEST_LIST("None", "None", "None"); 153 TEST_LIST("CHAP,None", "None", "None"); 154 TEST_LIST("CHAP,None", "CHAP", "CHAP"); 155 TEST_LIST("KRB5,SRP,CHAP,None", "SRP,CHAP,None", "SRP"); 156 TEST_LIST("KRB5,SRP,CHAP,None", "CHAP,SRP,None", "CHAP"); 157 TEST_LIST("KRB5,SRP,CHAP,None", "SPKM1,SRP,CHAP,None", "SRP"); 158 TEST_LIST("KRB5,SRP,None", "CHAP,None", "None"); 159 } 160 161 #define PARSE(strconst, partial_enabled, partial_text) \ 162 data = strconst; \ 163 len = sizeof(strconst) - 1; \ 164 rc = iscsi_parse_params(¶ms, data, len, partial_enabled, partial_text) 165 166 #define EXPECT_VAL(key, expected_value) \ 167 { \ 168 const char *val = iscsi_param_get_val(params, key); \ 169 CU_ASSERT(val != NULL); \ 170 if (val != NULL) { \ 171 CU_ASSERT(strcmp(val, expected_value) == 0); \ 172 } \ 173 } 174 175 #define EXPECT_NULL(key) \ 176 CU_ASSERT(iscsi_param_get_val(params, key) == NULL) 177 178 static void 179 parse_valid_test(void) 180 { 181 struct iscsi_param *params = NULL; 182 int rc; 183 char *data; 184 int len; 185 char *partial_parameter = NULL; 186 187 /* simple test with a single key=value */ 188 PARSE("Abc=def\0", false, NULL); 189 CU_ASSERT(rc == 0); 190 EXPECT_VAL("Abc", "def"); 191 192 /* multiple key=value pairs */ 193 PARSE("Aaa=bbbbbb\0Xyz=test\0", false, NULL); 194 CU_ASSERT(rc == 0); 195 EXPECT_VAL("Aaa", "bbbbbb"); 196 EXPECT_VAL("Xyz", "test"); 197 198 /* value with embedded '=' */ 199 PARSE("A=b=c\0", false, NULL); 200 CU_ASSERT(rc == 0); 201 EXPECT_VAL("A", "b=c"); 202 203 /* CHAP_C=AAAA.... with value length 8192 */ 204 len = strlen("CHAP_C=") + ISCSI_TEXT_MAX_VAL_LEN + 1/* null terminators */; 205 data = malloc(len); 206 SPDK_CU_ASSERT_FATAL(data != NULL); 207 memset(data, 'A', len); 208 memcpy(data, "CHAP_C", 6); 209 data[6] = '='; 210 data[len - 1] = '\0'; 211 rc = iscsi_parse_params(¶ms, data, len, false, NULL); 212 CU_ASSERT(rc == 0); 213 free(data); 214 215 /* partial parameter: value is partial */ 216 PARSE("C=AAA\0D=B", true, &partial_parameter); 217 SPDK_CU_ASSERT_FATAL(partial_parameter != NULL); 218 CU_ASSERT_STRING_EQUAL(partial_parameter, "D=B"); 219 CU_ASSERT(rc == 0); 220 EXPECT_VAL("C", "AAA"); 221 EXPECT_NULL("D"); 222 PARSE("XXXX\0E=UUUU\0", false, &partial_parameter); 223 CU_ASSERT(rc == 0); 224 EXPECT_VAL("D", "BXXXX"); 225 EXPECT_VAL("E", "UUUU"); 226 CU_ASSERT_PTR_NULL(partial_parameter); 227 228 /* partial parameter: key is partial */ 229 PARSE("IAMAFAK", true, &partial_parameter); 230 CU_ASSERT_STRING_EQUAL(partial_parameter, "IAMAFAK"); 231 CU_ASSERT(rc == 0); 232 EXPECT_NULL("IAMAFAK"); 233 PARSE("EDKEY=TTTT\0F=IIII", false, &partial_parameter); 234 CU_ASSERT(rc == 0); 235 EXPECT_VAL("IAMAFAKEDKEY", "TTTT"); 236 EXPECT_VAL("F", "IIII"); 237 CU_ASSERT_PTR_NULL(partial_parameter); 238 239 /* partial parameter: NULL data */ 240 /* It is technically allowed to have a TEXT PDU with no data, yet 241 * CONTINUE bit is enabled - make sure we handle that case correctly. 242 */ 243 rc = iscsi_parse_params(¶ms, NULL, 0, true, &partial_parameter); 244 CU_ASSERT(rc == 0); 245 CU_ASSERT_PTR_NULL(partial_parameter); 246 247 /* Second partial parameter is the only parameter */ 248 PARSE("OOOO", true, &partial_parameter); 249 CU_ASSERT_STRING_EQUAL(partial_parameter, "OOOO"); 250 CU_ASSERT(rc == 0); 251 EXPECT_NULL("OOOO"); 252 PARSE("LL=MMMM", false, &partial_parameter); 253 CU_ASSERT(rc == 0); 254 EXPECT_VAL("OOOOLL", "MMMM"); 255 CU_ASSERT_PTR_NULL(partial_parameter); 256 257 partial_parameter = NULL; 258 data = "PartialKey="; 259 len = 7; 260 rc = iscsi_parse_params(¶ms, data, len, true, &partial_parameter); 261 CU_ASSERT(rc == 0); 262 CU_ASSERT_STRING_EQUAL(partial_parameter, "Partial"); 263 EXPECT_NULL("PartialKey"); 264 PARSE("Key=Value", false, &partial_parameter); 265 CU_ASSERT(rc == 0); 266 EXPECT_VAL("PartialKey", "Value"); 267 CU_ASSERT_PTR_NULL(partial_parameter); 268 269 iscsi_param_free(params); 270 } 271 272 static void 273 parse_invalid_test(void) 274 { 275 struct iscsi_param *params = NULL; 276 int rc; 277 char *data; 278 int len; 279 280 /* key without '=' */ 281 PARSE("Abc\0", false, NULL); 282 CU_ASSERT(rc != 0); 283 EXPECT_NULL("Abc"); 284 285 /* multiple key=value pairs, one missing '=' */ 286 PARSE("Abc=def\0Xyz\0Www=test\0", false, NULL); 287 CU_ASSERT(rc != 0); 288 EXPECT_VAL("Abc", "def"); 289 EXPECT_NULL("Xyz"); 290 EXPECT_NULL("Www"); 291 292 /* empty key */ 293 PARSE("=abcdef", false, NULL); 294 CU_ASSERT(rc != 0); 295 EXPECT_NULL(""); 296 297 /* CHAP_C=AAAA.... with value length 8192 + 1 */ 298 len = strlen("CHAP_C=") + ISCSI_TEXT_MAX_VAL_LEN + 1 /* max value len + 1 */ + 299 1 /* null terminators */; 300 data = malloc(len); 301 SPDK_CU_ASSERT_FATAL(data != NULL); 302 memset(data, 'A', len); 303 memcpy(data, "CHAP_C", 6); 304 data[6] = '='; 305 data[len - 1] = '\0'; 306 rc = iscsi_parse_params(¶ms, data, len, false, NULL); 307 free(data); 308 CU_ASSERT(rc != 0); 309 EXPECT_NULL("CHAP_C"); 310 311 /* Test simple value, length of value bigger than 255 */ 312 len = strlen("A=") + ISCSI_TEXT_MAX_SIMPLE_VAL_LEN + 1 /* max simple value len + 1 */ + 313 1 /* null terminators */; 314 data = malloc(len); 315 SPDK_CU_ASSERT_FATAL(data != NULL); 316 memset(data, 'A', len); 317 data[1] = '='; 318 data[len - 1] = '\0'; 319 rc = iscsi_parse_params(¶ms, data, len, false, NULL); 320 free(data); 321 CU_ASSERT(rc != 0); 322 EXPECT_NULL("A"); 323 324 /* key length bigger than 63 */ 325 len = ISCSI_TEXT_MAX_KEY_LEN + 1 /* max key length + 1 */ + 1 /* = */ + 1 /* A */ + 326 1 /* null terminators */; 327 data = malloc(len); 328 SPDK_CU_ASSERT_FATAL(data != NULL); 329 memset(data, 'A', len); 330 data[64] = '='; 331 data[len - 1] = '\0'; 332 rc = iscsi_parse_params(¶ms, data, len, false, NULL); 333 free(data); 334 CU_ASSERT(rc != 0); 335 EXPECT_NULL("A"); 336 337 /* duplicated key */ 338 PARSE("B=BB", false, NULL); 339 CU_ASSERT(rc == 0); 340 PARSE("B=BBBB", false, NULL); 341 CU_ASSERT(rc != 0); 342 EXPECT_VAL("B", "BB"); 343 344 /* Test where data buffer has non-NULL characters past the end of 345 * the valid data region. This can happen with SPDK iSCSI target, 346 * since data buffers are reused and we do not zero the data buffers 347 * after they are freed since it would be too expensive. Added as 348 * part of fixing an intermittent Calsoft failure that triggered this 349 * bug. 350 */ 351 data = "MaxRecvDataSegmentLength=81928"; 352 len = strlen(data) - 1; 353 rc = iscsi_parse_params(¶ms, data, len, false, NULL); 354 EXPECT_VAL("MaxRecvDataSegmentLength", "8192"); 355 CU_ASSERT(rc == 0); 356 iscsi_param_free(params); 357 } 358 359 int 360 main(int argc, char **argv) 361 { 362 CU_pSuite suite = NULL; 363 unsigned int num_failures; 364 365 CU_set_error_action(CUEA_ABORT); 366 CU_initialize_registry(); 367 368 suite = CU_add_suite("iscsi_suite", NULL, NULL); 369 370 CU_ADD_TEST(suite, param_negotiation_test); 371 CU_ADD_TEST(suite, list_negotiation_test); 372 CU_ADD_TEST(suite, parse_valid_test); 373 CU_ADD_TEST(suite, parse_invalid_test); 374 375 CU_basic_set_mode(CU_BRM_VERBOSE); 376 CU_basic_run_tests(); 377 num_failures = CU_get_number_of_failures(); 378 CU_cleanup_registry(); 379 return num_failures; 380 } 381