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_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 = ¶ms; 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_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 = iscsi_negotiate_param_list(&add_param_value, ¶m, 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(¶ms, 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(¶ms, 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 partial_parameter = NULL; 278 data = "PartialKey="; 279 len = 7; 280 rc = iscsi_parse_params(¶ms, data, len, true, &partial_parameter); 281 CU_ASSERT(rc == 0); 282 CU_ASSERT_STRING_EQUAL(partial_parameter, "Partial"); 283 EXPECT_NULL("PartialKey"); 284 PARSE("Key=Value", false, &partial_parameter); 285 CU_ASSERT(rc == 0); 286 EXPECT_VAL("PartialKey", "Value"); 287 CU_ASSERT_PTR_NULL(partial_parameter); 288 289 iscsi_param_free(params); 290 } 291 292 static void 293 parse_invalid_test(void) 294 { 295 struct iscsi_param *params = NULL; 296 int rc; 297 char *data; 298 int len; 299 300 /* key without '=' */ 301 PARSE("Abc\0", false, NULL); 302 CU_ASSERT(rc != 0); 303 EXPECT_NULL("Abc"); 304 305 /* multiple key=value pairs, one missing '=' */ 306 PARSE("Abc=def\0Xyz\0Www=test\0", false, NULL); 307 CU_ASSERT(rc != 0); 308 EXPECT_VAL("Abc", "def"); 309 EXPECT_NULL("Xyz"); 310 EXPECT_NULL("Www"); 311 312 /* empty key */ 313 PARSE("=abcdef", false, NULL); 314 CU_ASSERT(rc != 0); 315 EXPECT_NULL(""); 316 317 /* CHAP_C=AAAA.... with value length 8192 + 1 */ 318 len = strlen("CHAP_C=") + ISCSI_TEXT_MAX_VAL_LEN + 1 /* max value len + 1 */ + 319 1 /* null terminators */; 320 data = malloc(len); 321 SPDK_CU_ASSERT_FATAL(data != NULL); 322 memset(data, 'A', len); 323 memcpy(data, "CHAP_C", 6); 324 data[6] = '='; 325 data[len - 1] = '\0'; 326 rc = iscsi_parse_params(¶ms, data, len, false, NULL); 327 free(data); 328 CU_ASSERT(rc != 0); 329 EXPECT_NULL("CHAP_C"); 330 331 /* Test simple value, length of value bigger than 255 */ 332 len = strlen("A=") + ISCSI_TEXT_MAX_SIMPLE_VAL_LEN + 1 /* max simple value len + 1 */ + 333 1 /* null terminators */; 334 data = malloc(len); 335 SPDK_CU_ASSERT_FATAL(data != NULL); 336 memset(data, 'A', len); 337 data[1] = '='; 338 data[len - 1] = '\0'; 339 rc = iscsi_parse_params(¶ms, data, len, false, NULL); 340 free(data); 341 CU_ASSERT(rc != 0); 342 EXPECT_NULL("A"); 343 344 /* key length bigger than 63 */ 345 len = ISCSI_TEXT_MAX_KEY_LEN + 1 /* max key length + 1 */ + 1 /* = */ + 1 /* A */ + 346 1 /* null terminators */; 347 data = malloc(len); 348 SPDK_CU_ASSERT_FATAL(data != NULL); 349 memset(data, 'A', len); 350 data[64] = '='; 351 data[len - 1] = '\0'; 352 rc = iscsi_parse_params(¶ms, data, len, false, NULL); 353 free(data); 354 CU_ASSERT(rc != 0); 355 EXPECT_NULL("A"); 356 357 /* duplicated key */ 358 PARSE("B=BB", false, NULL); 359 CU_ASSERT(rc == 0); 360 PARSE("B=BBBB", false, NULL); 361 CU_ASSERT(rc != 0); 362 EXPECT_VAL("B", "BB"); 363 364 /* Test where data buffer has non-NULL characters past the end of 365 * the valid data region. This can happen with SPDK iSCSI target, 366 * since data buffers are reused and we do not zero the data buffers 367 * after they are freed since it would be too expensive. Added as 368 * part of fixing an intermittent Calsoft failure that triggered this 369 * bug. 370 */ 371 data = "MaxRecvDataSegmentLength=81928"; 372 len = strlen(data) - 1; 373 rc = iscsi_parse_params(¶ms, data, len, false, NULL); 374 EXPECT_VAL("MaxRecvDataSegmentLength", "8192"); 375 CU_ASSERT(rc == 0); 376 iscsi_param_free(params); 377 } 378 379 int 380 main(int argc, char **argv) 381 { 382 CU_pSuite suite = NULL; 383 unsigned int num_failures; 384 385 CU_set_error_action(CUEA_ABORT); 386 CU_initialize_registry(); 387 388 suite = CU_add_suite("iscsi_suite", NULL, NULL); 389 390 CU_ADD_TEST(suite, param_negotiation_test); 391 CU_ADD_TEST(suite, list_negotiation_test); 392 CU_ADD_TEST(suite, parse_valid_test); 393 CU_ADD_TEST(suite, parse_invalid_test); 394 395 CU_basic_set_mode(CU_BRM_VERBOSE); 396 CU_basic_run_tests(); 397 num_failures = CU_get_number_of_failures(); 398 CU_cleanup_registry(); 399 return num_failures; 400 } 401