1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 3 * Copyright (C) 2016 Intel Corporation. 4 * All rights reserved. 5 */ 6 7 #include "spdk/stdinc.h" 8 9 #include "spdk/string.h" 10 #include "iscsi/iscsi.h" 11 #include "iscsi/param.h" 12 #include "iscsi/conn.h" 13 14 #include "spdk/log.h" 15 16 #define MAX_TMPBUF 1024 17 18 /* whose value may be bigger than 255 */ 19 static const char *non_simple_value_params[] = { 20 "CHAP_C", 21 "CHAP_R", 22 NULL, 23 }; 24 25 void 26 iscsi_param_free(struct iscsi_param *params) 27 { 28 struct iscsi_param *param, *next_param; 29 30 if (params == NULL) { 31 return; 32 } 33 for (param = params; param != NULL; param = next_param) { 34 next_param = param->next; 35 if (param->list) { 36 free(param->list); 37 } 38 free(param->val); 39 free(param->key); 40 free(param); 41 } 42 } 43 44 static int 45 iscsi_find_key_in_array(const char *key, const char *array[]) 46 { 47 int i; 48 49 for (i = 0; array[i] != NULL; i++) { 50 if (strcasecmp(key, array[i]) == 0) { 51 return 1; 52 } 53 } 54 return 0; 55 } 56 57 struct iscsi_param * 58 iscsi_param_find(struct iscsi_param *params, const char *key) 59 { 60 struct iscsi_param *param; 61 62 if (params == NULL || key == NULL) { 63 return NULL; 64 } 65 for (param = params; param != NULL; param = param->next) { 66 if (param->key != NULL && param->key[0] == key[0] 67 && strcasecmp(param->key, key) == 0) { 68 return param; 69 } 70 } 71 return NULL; 72 } 73 74 int 75 iscsi_param_del(struct iscsi_param **params, const char *key) 76 { 77 struct iscsi_param *param, *prev_param = NULL; 78 79 SPDK_DEBUGLOG(iscsi, "del %s\n", key); 80 if (params == NULL || key == NULL) { 81 return 0; 82 } 83 for (param = *params; param != NULL; param = param->next) { 84 if (param->key != NULL && param->key[0] == key[0] 85 && strcasecmp(param->key, key) == 0) { 86 if (prev_param != NULL) { 87 prev_param->next = param->next; 88 } else { 89 *params = param->next; 90 } 91 param->next = NULL; 92 iscsi_param_free(param); 93 return 0; 94 } 95 prev_param = param; 96 } 97 return -1; 98 } 99 100 int 101 iscsi_param_add(struct iscsi_param **params, const char *key, 102 const char *val, const char *list, int type) 103 { 104 struct iscsi_param *param, *last_param; 105 106 SPDK_DEBUGLOG(iscsi, "add %s=%s, list=[%s], type=%d\n", 107 key, val, list, type); 108 if (key == NULL) { 109 return -1; 110 } 111 112 param = iscsi_param_find(*params, key); 113 if (param != NULL) { 114 iscsi_param_del(params, key); 115 } 116 117 param = calloc(1, sizeof(*param)); 118 if (!param) { 119 SPDK_ERRLOG("calloc() failed for parameter\n"); 120 return -ENOMEM; 121 } 122 123 param->next = NULL; 124 param->key = xstrdup(key); 125 param->val = xstrdup(val); 126 param->list = xstrdup(list); 127 param->type = type; 128 129 last_param = *params; 130 if (last_param != NULL) { 131 while (last_param->next != NULL) { 132 last_param = last_param->next; 133 } 134 last_param->next = param; 135 } else { 136 *params = param; 137 } 138 139 return 0; 140 } 141 142 int 143 iscsi_param_set(struct iscsi_param *params, const char *key, 144 const char *val) 145 { 146 struct iscsi_param *param; 147 148 SPDK_DEBUGLOG(iscsi, "set %s=%s\n", key, val); 149 param = iscsi_param_find(params, key); 150 if (param == NULL) { 151 SPDK_ERRLOG("no key %s\n", key); 152 return -1; 153 } 154 155 free(param->val); 156 157 param->val = xstrdup(val); 158 159 return 0; 160 } 161 162 int 163 iscsi_param_set_int(struct iscsi_param *params, const char *key, uint32_t val) 164 { 165 char buf[MAX_TMPBUF]; 166 struct iscsi_param *param; 167 168 SPDK_DEBUGLOG(iscsi, "set %s=%d\n", key, val); 169 param = iscsi_param_find(params, key); 170 if (param == NULL) { 171 SPDK_ERRLOG("no key %s\n", key); 172 return -1; 173 } 174 175 free(param->val); 176 snprintf(buf, sizeof buf, "%d", val); 177 178 param->val = strdup(buf); 179 180 return 0; 181 } 182 183 /** 184 * Parse a single KEY=VAL pair 185 * 186 * data = "KEY=VAL<NUL>" 187 */ 188 static int 189 iscsi_parse_param(struct iscsi_param **params, const uint8_t *data, uint32_t data_len) 190 { 191 int rc; 192 uint8_t *key_copy, *val_copy; 193 const uint8_t *key_end; 194 int key_len, val_len; 195 int max_len; 196 197 data_len = strnlen(data, data_len); 198 /* No such thing as strnchr so use memchr instead. */ 199 key_end = memchr(data, '=', data_len); 200 if (!key_end) { 201 SPDK_ERRLOG("'=' not found\n"); 202 return -1; 203 } 204 205 key_len = key_end - data; 206 if (key_len == 0) { 207 SPDK_ERRLOG("Empty key\n"); 208 return -1; 209 } 210 /* 211 * RFC 7143 6.1 212 */ 213 if (key_len > ISCSI_TEXT_MAX_KEY_LEN) { 214 SPDK_ERRLOG("Key name length is bigger than 63\n"); 215 return -1; 216 } 217 218 key_copy = malloc(key_len + 1); 219 if (!key_copy) { 220 SPDK_ERRLOG("malloc() failed for key_copy\n"); 221 return -ENOMEM; 222 } 223 224 memcpy(key_copy, data, key_len); 225 key_copy[key_len] = '\0'; 226 /* check whether this key is duplicated */ 227 if (NULL != iscsi_param_find(*params, key_copy)) { 228 SPDK_ERRLOG("Duplicated Key %s\n", key_copy); 229 free(key_copy); 230 return -1; 231 } 232 233 val_len = strnlen(key_end + 1, data_len - key_len - 1); 234 /* 235 * RFC 3720 5.1 236 * If not otherwise specified, the maximum length of a simple-value 237 * (not its encoded representation) is 255 bytes, not including the delimiter 238 * (comma or zero byte). 239 */ 240 /* 241 * comma or zero is counted in, otherwise we need to iterate each parameter 242 * value 243 */ 244 max_len = iscsi_find_key_in_array(key_copy, non_simple_value_params) ? 245 ISCSI_TEXT_MAX_VAL_LEN : ISCSI_TEXT_MAX_SIMPLE_VAL_LEN; 246 if (val_len > max_len) { 247 SPDK_ERRLOG("Overflow Val %d\n", val_len); 248 free(key_copy); 249 return -1; 250 } 251 252 val_copy = calloc(1, val_len + 1); 253 if (val_copy == NULL) { 254 SPDK_ERRLOG("Could not allocate value string\n"); 255 free(key_copy); 256 return -1; 257 } 258 259 memcpy(val_copy, key_end + 1, val_len); 260 261 rc = iscsi_param_add(params, key_copy, val_copy, NULL, 0); 262 free(val_copy); 263 free(key_copy); 264 if (rc < 0) { 265 SPDK_ERRLOG("iscsi_param_add() failed\n"); 266 return -1; 267 } 268 269 /* return number of bytes consumed 270 * +1 for '=' and +1 for NUL 271 */ 272 return key_len + 1 + val_len + 1; 273 } 274 275 /** 276 * Parse a sequence of KEY=VAL pairs. 277 * 278 * \param data "KEY=VAL<NUL>KEY=VAL<NUL>..." 279 * \param len length of data in bytes 280 * 281 * Data must point to a valid pointer if len > 0. 282 */ 283 int 284 iscsi_parse_params(struct iscsi_param **params, const uint8_t *data, 285 int len, bool cbit_enabled, char **partial_parameter) 286 { 287 int rc, offset = 0; 288 char *p; 289 int i; 290 291 /* Spec does not disallow TEXT PDUs with zero length, just return 292 * immediately in that case, since there is no param data to parse 293 * and any existing partial parameter would remain as-is. 294 */ 295 if (len == 0) { 296 return 0; 297 } 298 299 assert(data != NULL); 300 301 /* strip the partial text parameters if previous PDU have C enabled */ 302 if (partial_parameter && *partial_parameter) { 303 for (i = 0; i < len && data[i] != '\0'; i++) { 304 ; 305 } 306 p = spdk_sprintf_alloc("%s%s", *partial_parameter, (const char *)data); 307 if (!p) { 308 return -1; 309 } 310 rc = iscsi_parse_param(params, p, i + strlen(*partial_parameter)); 311 free(p); 312 if (rc < 0) { 313 return -1; 314 } 315 free(*partial_parameter); 316 *partial_parameter = NULL; 317 318 data = data + i + 1; 319 len = len - (i + 1); 320 } 321 322 /* strip the partial text parameters if C bit is enabled */ 323 if (cbit_enabled) { 324 if (partial_parameter == NULL) { 325 SPDK_ERRLOG("C bit set but no partial parameters provided\n"); 326 return -1; 327 } 328 329 /* 330 * reverse iterate the string from the tail not including '\0' 331 */ 332 for (i = len - 1; data[i] != '\0' && i > 0; i--) { 333 ; 334 } 335 if (i != 0) { 336 /* We found a NULL character - don't copy it into the 337 * partial parameter. 338 */ 339 i++; 340 } 341 342 *partial_parameter = calloc(1, len - i + 1); 343 if (*partial_parameter == NULL) { 344 SPDK_ERRLOG("could not allocate partial parameter\n"); 345 return -1; 346 } 347 memcpy(*partial_parameter, &data[i], len - i); 348 if (i == 0) { 349 /* No full parameters to parse - so return now. */ 350 return 0; 351 } else { 352 len = i - 1; 353 } 354 } 355 356 while (offset < len && data[offset] != '\0') { 357 rc = iscsi_parse_param(params, data + offset, len - offset); 358 if (rc < 0) { 359 return -1; 360 } 361 offset += rc; 362 } 363 return 0; 364 } 365 366 char * 367 iscsi_param_get_val(struct iscsi_param *params, const char *key) 368 { 369 struct iscsi_param *param; 370 371 param = iscsi_param_find(params, key); 372 if (param == NULL) { 373 return NULL; 374 } 375 return param->val; 376 } 377 378 int 379 iscsi_param_eq_val(struct iscsi_param *params, const char *key, 380 const char *val) 381 { 382 struct iscsi_param *param; 383 384 param = iscsi_param_find(params, key); 385 if (param == NULL) { 386 return 0; 387 } 388 if (strcasecmp(param->val, val) == 0) { 389 return 1; 390 } 391 return 0; 392 } 393 394 struct iscsi_param_table { 395 const char *key; 396 const char *val; 397 const char *list; 398 int type; 399 }; 400 401 static const struct iscsi_param_table conn_param_table[] = { 402 { "HeaderDigest", "None", "CRC32C,None", ISPT_LIST }, 403 { "DataDigest", "None", "CRC32C,None", ISPT_LIST }, 404 { "MaxRecvDataSegmentLength", "8192", "512,16777215", ISPT_NUMERICAL_DECLARATIVE }, 405 { "OFMarker", "No", "Yes,No", ISPT_BOOLEAN_AND }, 406 { "IFMarker", "No", "Yes,No", ISPT_BOOLEAN_AND }, 407 { "OFMarkInt", "1", "1,65535", ISPT_NUMERICAL_MIN }, 408 { "IFMarkInt", "1", "1,65535", ISPT_NUMERICAL_MIN }, 409 { "AuthMethod", "None", "CHAP,None", ISPT_LIST }, 410 { "CHAP_A", "5", "5", ISPT_LIST }, 411 { "CHAP_N", "", "", ISPT_DECLARATIVE }, 412 { "CHAP_R", "", "", ISPT_DECLARATIVE }, 413 { "CHAP_I", "", "", ISPT_DECLARATIVE }, 414 { "CHAP_C", "", "", ISPT_DECLARATIVE }, 415 { NULL, NULL, NULL, ISPT_INVALID }, 416 }; 417 418 static const struct iscsi_param_table sess_param_table[] = { 419 { "MaxConnections", "1", "1,65535", ISPT_NUMERICAL_MIN }, 420 #if 0 421 /* need special handling */ 422 { "SendTargets", "", "", ISPT_DECLARATIVE }, 423 #endif 424 { "TargetName", "", "", ISPT_DECLARATIVE }, 425 { "InitiatorName", "", "", ISPT_DECLARATIVE }, 426 { "TargetAlias", "", "", ISPT_DECLARATIVE }, 427 { "InitiatorAlias", "", "", ISPT_DECLARATIVE }, 428 { "TargetAddress", "", "", ISPT_DECLARATIVE }, 429 { "TargetPortalGroupTag", "1", "1,65535", ISPT_NUMERICAL_DECLARATIVE }, 430 { "InitialR2T", "Yes", "Yes,No", ISPT_BOOLEAN_OR }, 431 { "ImmediateData", "Yes", "Yes,No", ISPT_BOOLEAN_AND }, 432 { "MaxBurstLength", "262144", "512,16777215", ISPT_NUMERICAL_MIN }, 433 { "FirstBurstLength", "65536", "512,16777215", ISPT_NUMERICAL_MIN }, 434 { "DefaultTime2Wait", "2", "0,3600", ISPT_NUMERICAL_MAX }, 435 { "DefaultTime2Retain", "20", "0,3600", ISPT_NUMERICAL_MIN }, 436 { "MaxOutstandingR2T", "1", "1,65536", ISPT_NUMERICAL_MIN }, 437 { "DataPDUInOrder", "Yes", "Yes,No", ISPT_BOOLEAN_OR }, 438 { "DataSequenceInOrder", "Yes", "Yes,No", ISPT_BOOLEAN_OR }, 439 { "ErrorRecoveryLevel", "0", "0,2", ISPT_NUMERICAL_MIN }, 440 { "SessionType", "Normal", "Normal,Discovery", ISPT_DECLARATIVE }, 441 { NULL, NULL, NULL, ISPT_INVALID }, 442 }; 443 444 static int 445 iscsi_params_init_internal(struct iscsi_param **params, 446 const struct iscsi_param_table *table) 447 { 448 int rc; 449 int i; 450 struct iscsi_param *param; 451 452 for (i = 0; table[i].key != NULL; i++) { 453 rc = iscsi_param_add(params, table[i].key, table[i].val, 454 table[i].list, table[i].type); 455 if (rc < 0) { 456 SPDK_ERRLOG("iscsi_param_add() failed\n"); 457 return -1; 458 } 459 param = iscsi_param_find(*params, table[i].key); 460 if (param != NULL) { 461 param->state_index = i; 462 } else { 463 SPDK_ERRLOG("iscsi_param_find() failed\n"); 464 return -1; 465 } 466 } 467 468 return 0; 469 } 470 471 int 472 iscsi_conn_params_init(struct iscsi_param **params) 473 { 474 return iscsi_params_init_internal(params, &conn_param_table[0]); 475 } 476 477 int 478 iscsi_sess_params_init(struct iscsi_param **params) 479 { 480 return iscsi_params_init_internal(params, &sess_param_table[0]); 481 } 482 483 static const char *chap_type[] = { 484 "CHAP_A", 485 "CHAP_N", 486 "CHAP_R", 487 "CHAP_I", 488 "CHAP_C", 489 NULL, 490 }; 491 492 static const char *discovery_ignored_param[] = { 493 "MaxConnections", 494 "InitialR2T", 495 "ImmediateData", 496 "MaxBurstLength", 497 "FirstBurstLength", 498 "MaxOutstandingR2T", 499 "DataPDUInOrder", 500 "DataSequenceInOrder", 501 NULL, 502 }; 503 504 static const char *multi_negot_conn_params[] = { 505 "MaxRecvDataSegmentLength", 506 NULL, 507 }; 508 509 /* The following params should be declared by target */ 510 static const char *target_declarative_params[] = { 511 "TargetAlias", 512 "TargetAddress", 513 "TargetPortalGroupTag", 514 NULL, 515 }; 516 517 /* This function is used to construct the data from the special param (e.g., 518 * MaxRecvDataSegmentLength) 519 * return: 520 * normal: the total len of the data 521 * error: -1 522 */ 523 static int 524 iscsi_special_param_construction(struct spdk_iscsi_conn *conn, 525 struct iscsi_param *param, 526 bool FirstBurstLength_flag, char *data, 527 int alloc_len, int total) 528 { 529 int len; 530 struct iscsi_param *param_first; 531 struct iscsi_param *param_max; 532 uint32_t FirstBurstLength; 533 uint32_t MaxBurstLength; 534 char *val; 535 536 val = malloc(ISCSI_TEXT_MAX_VAL_LEN + 1); 537 if (!val) { 538 SPDK_ERRLOG("malloc() failed for temporary buffer\n"); 539 return -ENOMEM; 540 } 541 542 if (strcasecmp(param->key, "MaxRecvDataSegmentLength") == 0) { 543 /* 544 * MaxRecvDataSegmentLength is sent by both 545 * initiator and target, but is declarative - meaning 546 * each direction can have different values. 547 * So when MaxRecvDataSegmentLength is found in the 548 * the parameter set sent from the initiator, add SPDK 549 * iscsi target's MaxRecvDataSegmentLength value to 550 * the returned parameter list. 551 */ 552 if (alloc_len - total < 1) { 553 SPDK_ERRLOG("data space small %d\n", alloc_len); 554 free(val); 555 return -1; 556 } 557 558 SPDK_DEBUGLOG(iscsi, 559 "returning MaxRecvDataSegmentLength=%d\n", 560 SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH); 561 len = snprintf((char *)data + total, alloc_len - total, 562 "MaxRecvDataSegmentLength=%d", 563 SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH); 564 total += len + 1; 565 } 566 567 if (strcasecmp(param->key, "MaxBurstLength") == 0 && 568 !FirstBurstLength_flag) { 569 if (alloc_len - total < 1) { 570 SPDK_ERRLOG("data space small %d\n", alloc_len); 571 free(val); 572 return -1; 573 } 574 575 param_first = iscsi_param_find(conn->sess->params, 576 "FirstBurstLength"); 577 if (param_first != NULL) { 578 FirstBurstLength = (uint32_t)strtol(param_first->val, NULL, 10); 579 } else { 580 FirstBurstLength = SPDK_ISCSI_FIRST_BURST_LENGTH; 581 } 582 param_max = iscsi_param_find(conn->sess->params, 583 "MaxBurstLength"); 584 if (param_max != NULL) { 585 MaxBurstLength = (uint32_t)strtol(param_max->val, NULL, 10); 586 } else { 587 MaxBurstLength = SPDK_ISCSI_MAX_BURST_LENGTH; 588 } 589 590 if (FirstBurstLength > MaxBurstLength) { 591 FirstBurstLength = MaxBurstLength; 592 if (param_first != NULL) { 593 free(param_first->val); 594 snprintf(val, ISCSI_TEXT_MAX_VAL_LEN, "%d", 595 FirstBurstLength); 596 param_first->val = xstrdup(val); 597 } 598 } 599 len = snprintf((char *)data + total, alloc_len - total, 600 "FirstBurstLength=%d", FirstBurstLength); 601 total += len + 1; 602 } 603 604 free(val); 605 return total; 606 607 } 608 609 /** 610 * iscsi_construct_data_from_param: 611 * To construct the data which will be returned to the initiator 612 * return: length of the negotiated data, -1 indicates error; 613 */ 614 static int 615 iscsi_construct_data_from_param(struct iscsi_param *param, char *new_val, 616 char *data, int alloc_len, int total) 617 { 618 int len; 619 620 if (param->type != ISPT_DECLARATIVE && 621 param->type != ISPT_NUMERICAL_DECLARATIVE) { 622 if (alloc_len - total < 1) { 623 SPDK_ERRLOG("data space small %d\n", alloc_len); 624 return -1; 625 } 626 627 SPDK_DEBUGLOG(iscsi, "negotiated %s=%s\n", 628 param->key, new_val); 629 len = snprintf((char *)data + total, alloc_len - total, "%s=%s", 630 param->key, new_val); 631 total += len + 1; 632 } 633 return total; 634 } 635 636 /** 637 * To negotiate param with 638 * type = ISPT_LIST 639 * return: the negotiated value of the key 640 */ 641 static char * 642 iscsi_negotiate_param_list(int *add_param_value, 643 struct iscsi_param *param, 644 char *valid_list, char *in_val, 645 char *cur_val) 646 { 647 char *val_start, *val_end; 648 char *in_start, *in_end; 649 int flag = 0; 650 651 if (add_param_value == NULL) { 652 return NULL; 653 } 654 655 in_start = in_val; 656 do { 657 if ((in_end = strchr(in_start, (int)',')) != NULL) { 658 *in_end = '\0'; 659 } 660 val_start = valid_list; 661 do { 662 if ((val_end = strchr(val_start, (int)',')) != NULL) { 663 *val_end = '\0'; 664 } 665 if (strcasecmp(in_start, val_start) == 0) { 666 SPDK_DEBUGLOG(iscsi, "match %s\n", 667 val_start); 668 flag = 1; 669 break; 670 } 671 if (val_end) { 672 *val_end = ','; 673 val_start = val_end + 1; 674 } 675 } while (val_end); 676 if (flag) { 677 break; 678 } 679 if (in_end) { 680 *in_end = ','; 681 in_start = in_end + 1; 682 } 683 } while (in_end); 684 685 return flag ? val_start : NULL; 686 } 687 688 /** 689 * To negotiate param with 690 * type = ISPT_NUMERICAL_MIN/MAX, ISPT_NUMERICAL_DECLARATIVE 691 * return: the negotiated value of the key 692 */ 693 static char * 694 iscsi_negotiate_param_numerical(int *add_param_value, 695 struct iscsi_param *param, 696 char *valid_list, char *in_val, 697 char *cur_val) 698 { 699 char *valid_next; 700 char *new_val = NULL; 701 char *min_val, *max_val; 702 int val_i, cur_val_i; 703 int min_i, max_i; 704 705 if (add_param_value == NULL) { 706 return NULL; 707 } 708 709 val_i = (int)strtol(param->val, NULL, 10); 710 /* check whether the key is FirstBurstLength, if that we use in_val */ 711 if (strcasecmp(param->key, "FirstBurstLength") == 0) { 712 val_i = (int)strtol(in_val, NULL, 10); 713 } 714 715 cur_val_i = (int)strtol(cur_val, NULL, 10); 716 valid_next = valid_list; 717 min_val = spdk_strsepq(&valid_next, ","); 718 max_val = spdk_strsepq(&valid_next, ","); 719 min_i = (min_val != NULL) ? (int)strtol(min_val, NULL, 10) : 0; 720 max_i = (max_val != NULL) ? (int)strtol(max_val, NULL, 10) : 0; 721 if (val_i < min_i || val_i > max_i) { 722 SPDK_DEBUGLOG(iscsi, "key %.64s reject\n", param->key); 723 new_val = NULL; 724 } else { 725 switch (param->type) { 726 case ISPT_NUMERICAL_MIN: 727 if (val_i > cur_val_i) { 728 val_i = cur_val_i; 729 } 730 break; 731 case ISPT_NUMERICAL_MAX: 732 if (val_i < cur_val_i) { 733 val_i = cur_val_i; 734 } 735 break; 736 default: 737 break; 738 } 739 snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN, "%d", val_i); 740 new_val = in_val; 741 } 742 743 return new_val; 744 } 745 746 /** 747 * To negotiate param with 748 * type = ISPT_BOOLEAN_OR, ISPT_BOOLEAN_AND 749 * return: the negotiated value of the key 750 */ 751 static char * 752 iscsi_negotiate_param_boolean(int *add_param_value, 753 struct iscsi_param *param, 754 char *in_val, char *cur_val, 755 const char *value) 756 { 757 char *new_val = NULL; 758 759 if (add_param_value == NULL) { 760 return NULL; 761 } 762 763 /* Make sure the val is Yes or No */ 764 if (!((strcasecmp(in_val, "Yes") == 0) || 765 (strcasecmp(in_val, "No") == 0))) { 766 /* unknown value */ 767 snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", "Reject"); 768 new_val = in_val; 769 *add_param_value = 1; 770 return new_val; 771 } 772 773 if (strcasecmp(cur_val, value) == 0) { 774 snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", value); 775 new_val = in_val; 776 } else { 777 new_val = param->val; 778 } 779 780 return new_val; 781 } 782 783 /** 784 * The entry function to handle each type of the param 785 * return value: the new negotiated value 786 */ 787 static char * 788 iscsi_negotiate_param_all(int *add_param_value, struct iscsi_param *param, 789 char *valid_list, char *in_val, char *cur_val) 790 { 791 char *new_val; 792 switch (param->type) { 793 case ISPT_LIST: 794 new_val = iscsi_negotiate_param_list(add_param_value, 795 param, 796 valid_list, 797 in_val, 798 cur_val); 799 break; 800 801 case ISPT_NUMERICAL_MIN: 802 case ISPT_NUMERICAL_MAX: 803 case ISPT_NUMERICAL_DECLARATIVE: 804 new_val = iscsi_negotiate_param_numerical(add_param_value, 805 param, 806 valid_list, 807 in_val, 808 cur_val); 809 break; 810 811 case ISPT_BOOLEAN_OR: 812 new_val = iscsi_negotiate_param_boolean(add_param_value, 813 param, 814 in_val, 815 cur_val, 816 "Yes"); 817 break; 818 case ISPT_BOOLEAN_AND: 819 new_val = iscsi_negotiate_param_boolean(add_param_value, 820 param, 821 in_val, 822 cur_val, 823 "No"); 824 break; 825 826 default: 827 snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", param->val); 828 new_val = in_val; 829 break; 830 } 831 832 return new_val; 833 } 834 835 /** 836 * This function is used to judge whether the param is in session's params or 837 * connection's params 838 */ 839 static int 840 iscsi_negotiate_param_init(struct spdk_iscsi_conn *conn, 841 struct iscsi_param **cur_param_p, 842 struct iscsi_param **params_dst_p, 843 struct iscsi_param *param) 844 { 845 int index; 846 847 *cur_param_p = iscsi_param_find(*params_dst_p, param->key); 848 if (*cur_param_p == NULL) { 849 *params_dst_p = conn->sess->params; 850 *cur_param_p = iscsi_param_find(*params_dst_p, param->key); 851 if (*cur_param_p == NULL) { 852 if ((strncasecmp(param->key, "X-", 2) == 0) || 853 (strncasecmp(param->key, "X#", 2) == 0)) { 854 /* Extension Key */ 855 SPDK_DEBUGLOG(iscsi, 856 "extension key %.64s\n", 857 param->key); 858 } else { 859 SPDK_ERRLOG("unknown key %.64s\n", param->key); 860 } 861 return 1; 862 } else { 863 index = (*cur_param_p)->state_index; 864 if (conn->sess_param_state_negotiated[index] && 865 !iscsi_find_key_in_array(param->key, 866 target_declarative_params)) { 867 return SPDK_ISCSI_PARAMETER_EXCHANGE_NOT_ONCE; 868 } 869 conn->sess_param_state_negotiated[index] = true; 870 } 871 } else { 872 index = (*cur_param_p)->state_index; 873 if (conn->conn_param_state_negotiated[index] && 874 !iscsi_find_key_in_array(param->key, 875 multi_negot_conn_params)) { 876 return SPDK_ISCSI_PARAMETER_EXCHANGE_NOT_ONCE; 877 } 878 conn->conn_param_state_negotiated[index] = true; 879 } 880 881 return 0; 882 } 883 884 int 885 iscsi_negotiate_params(struct spdk_iscsi_conn *conn, 886 struct iscsi_param **params, uint8_t *data, int alloc_len, 887 int data_len) 888 { 889 struct iscsi_param *param; 890 struct iscsi_param *cur_param; 891 char *valid_list, *in_val; 892 char *cur_val; 893 char *new_val; 894 int discovery; 895 int total; 896 int rc; 897 uint32_t FirstBurstLength; 898 uint32_t MaxBurstLength; 899 bool FirstBurstLength_flag = false; 900 int type; 901 902 total = data_len; 903 if (data_len < 0) { 904 assert(false); 905 return -EINVAL; 906 } 907 if (alloc_len < 1) { 908 return 0; 909 } 910 if (total > alloc_len) { 911 total = alloc_len; 912 data[total - 1] = '\0'; 913 return total; 914 } 915 916 if (*params == NULL) { 917 /* no input */ 918 return total; 919 } 920 921 /* discovery? */ 922 discovery = 0; 923 cur_param = iscsi_param_find(*params, "SessionType"); 924 if (cur_param == NULL) { 925 cur_param = iscsi_param_find(conn->sess->params, "SessionType"); 926 if (cur_param == NULL) { 927 /* no session type */ 928 } else { 929 if (strcasecmp(cur_param->val, "Discovery") == 0) { 930 discovery = 1; 931 } 932 } 933 } else { 934 if (strcasecmp(cur_param->val, "Discovery") == 0) { 935 discovery = 1; 936 } 937 } 938 939 /* for temporary store */ 940 valid_list = malloc(ISCSI_TEXT_MAX_VAL_LEN + 1); 941 if (!valid_list) { 942 SPDK_ERRLOG("malloc() failed for valid_list\n"); 943 return -ENOMEM; 944 } 945 946 in_val = malloc(ISCSI_TEXT_MAX_VAL_LEN + 1); 947 if (!in_val) { 948 SPDK_ERRLOG("malloc() failed for in_val\n"); 949 free(valid_list); 950 return -ENOMEM; 951 } 952 953 cur_val = malloc(ISCSI_TEXT_MAX_VAL_LEN + 1); 954 if (!cur_val) { 955 SPDK_ERRLOG("malloc() failed for cur_val\n"); 956 free(valid_list); 957 free(in_val); 958 return -ENOMEM; 959 } 960 961 /* To adjust the location of FirstBurstLength location and put it to 962 * the end, then we can always firstly determine the MaxBurstLength 963 */ 964 param = iscsi_param_find(*params, "MaxBurstLength"); 965 if (param != NULL) { 966 param = iscsi_param_find(*params, "FirstBurstLength"); 967 968 /* check the existence of FirstBurstLength */ 969 if (param != NULL) { 970 FirstBurstLength_flag = true; 971 if (param->next != NULL) { 972 snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", param->val); 973 type = param->type; 974 iscsi_param_add(params, "FirstBurstLength", 975 in_val, NULL, type); 976 } 977 } 978 } 979 980 for (param = *params; param != NULL; param = param->next) { 981 struct iscsi_param *params_dst = conn->params; 982 int add_param_value = 0; 983 new_val = NULL; 984 param->type = ISPT_INVALID; 985 986 /* sendtargets is special */ 987 if (strcasecmp(param->key, "SendTargets") == 0) { 988 continue; 989 } 990 /* CHAP keys */ 991 if (iscsi_find_key_in_array(param->key, chap_type)) { 992 continue; 993 } 994 995 /* 12.2, 12.10, 12.11, 12.13, 12.14, 12.17, 12.18, 12.19 */ 996 if (discovery && 997 iscsi_find_key_in_array(param->key, discovery_ignored_param)) { 998 snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", "Irrelevant"); 999 new_val = in_val; 1000 add_param_value = 1; 1001 } else { 1002 rc = iscsi_negotiate_param_init(conn, 1003 &cur_param, 1004 ¶ms_dst, 1005 param); 1006 if (rc < 0) { 1007 free(valid_list); 1008 free(in_val); 1009 free(cur_val); 1010 return rc; 1011 } else if (rc > 0) { 1012 snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", "NotUnderstood"); 1013 new_val = in_val; 1014 add_param_value = 1; 1015 } else { 1016 snprintf(valid_list, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", cur_param->list); 1017 snprintf(cur_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", cur_param->val); 1018 param->type = cur_param->type; 1019 } 1020 } 1021 1022 if (param->type > 0) { 1023 snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", param->val); 1024 1025 /* "NotUnderstood" value shouldn't be assigned to "Understood" key */ 1026 if (strcasecmp(in_val, "NotUnderstood") == 0) { 1027 free(in_val); 1028 free(valid_list); 1029 free(cur_val); 1030 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER; 1031 } 1032 1033 if (strcasecmp(param->key, "FirstBurstLength") == 0) { 1034 FirstBurstLength = (uint32_t)strtol(param->val, NULL, 1035 10); 1036 new_val = iscsi_param_get_val(conn->sess->params, 1037 "MaxBurstLength"); 1038 if (new_val != NULL) { 1039 MaxBurstLength = (uint32_t) strtol(new_val, NULL, 1040 10); 1041 } else { 1042 MaxBurstLength = SPDK_ISCSI_MAX_BURST_LENGTH; 1043 } 1044 if (FirstBurstLength < SPDK_ISCSI_MAX_FIRST_BURST_LENGTH && 1045 FirstBurstLength > MaxBurstLength) { 1046 FirstBurstLength = MaxBurstLength; 1047 snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN, "%d", 1048 FirstBurstLength); 1049 } 1050 } 1051 1052 /* prevent target's declarative params from being changed by initiator */ 1053 if (iscsi_find_key_in_array(param->key, target_declarative_params)) { 1054 add_param_value = 1; 1055 } 1056 1057 new_val = iscsi_negotiate_param_all(&add_param_value, 1058 param, 1059 valid_list, 1060 in_val, 1061 cur_val); 1062 } 1063 1064 /* check the negotiated value of the key */ 1065 if (new_val != NULL) { 1066 /* add_param_value = 0 means updating the value of 1067 * existed key in the connection's parameters 1068 */ 1069 if (add_param_value == 0) { 1070 iscsi_param_set(params_dst, param->key, new_val); 1071 } 1072 total = iscsi_construct_data_from_param(param, 1073 new_val, 1074 data, 1075 alloc_len, 1076 total); 1077 if (total < 0) { 1078 goto final_return; 1079 } 1080 1081 total = iscsi_special_param_construction(conn, 1082 param, 1083 FirstBurstLength_flag, 1084 data, 1085 alloc_len, 1086 total); 1087 if (total < 0) { 1088 goto final_return; 1089 } 1090 } else { 1091 total = -1; 1092 break; 1093 } 1094 } 1095 1096 final_return: 1097 free(valid_list); 1098 free(in_val); 1099 free(cur_val); 1100 1101 return total; 1102 } 1103 1104 int 1105 iscsi_copy_param2var(struct spdk_iscsi_conn *conn) 1106 { 1107 const char *val; 1108 1109 val = iscsi_param_get_val(conn->params, "MaxRecvDataSegmentLength"); 1110 if (val == NULL) { 1111 SPDK_ERRLOG("Getval MaxRecvDataSegmentLength failed\n"); 1112 return -1; 1113 } 1114 SPDK_DEBUGLOG(iscsi, 1115 "copy MaxRecvDataSegmentLength=%s\n", val); 1116 conn->MaxRecvDataSegmentLength = (int)strtol(val, NULL, 10); 1117 if (conn->MaxRecvDataSegmentLength > SPDK_BDEV_LARGE_BUF_MAX_SIZE) { 1118 conn->MaxRecvDataSegmentLength = SPDK_BDEV_LARGE_BUF_MAX_SIZE; 1119 } 1120 1121 val = iscsi_param_get_val(conn->params, "HeaderDigest"); 1122 if (val == NULL) { 1123 SPDK_ERRLOG("Getval HeaderDigest failed\n"); 1124 return -1; 1125 } 1126 if (strcasecmp(val, "CRC32C") == 0) { 1127 SPDK_DEBUGLOG(iscsi, "set HeaderDigest=1\n"); 1128 conn->header_digest = 1; 1129 } else { 1130 SPDK_DEBUGLOG(iscsi, "set HeaderDigest=0\n"); 1131 conn->header_digest = 0; 1132 } 1133 val = iscsi_param_get_val(conn->params, "DataDigest"); 1134 if (val == NULL) { 1135 SPDK_ERRLOG("Getval DataDigest failed\n"); 1136 return -1; 1137 } 1138 if (strcasecmp(val, "CRC32C") == 0) { 1139 SPDK_DEBUGLOG(iscsi, "set DataDigest=1\n"); 1140 conn->data_digest = 1; 1141 } else { 1142 SPDK_DEBUGLOG(iscsi, "set DataDigest=0\n"); 1143 conn->data_digest = 0; 1144 } 1145 1146 val = iscsi_param_get_val(conn->sess->params, "MaxConnections"); 1147 if (val == NULL) { 1148 SPDK_ERRLOG("Getval MaxConnections failed\n"); 1149 return -1; 1150 } 1151 SPDK_DEBUGLOG(iscsi, "copy MaxConnections=%s\n", val); 1152 conn->sess->MaxConnections = (uint32_t) strtol(val, NULL, 10); 1153 val = iscsi_param_get_val(conn->sess->params, "MaxOutstandingR2T"); 1154 if (val == NULL) { 1155 SPDK_ERRLOG("Getval MaxOutstandingR2T failed\n"); 1156 return -1; 1157 } 1158 SPDK_DEBUGLOG(iscsi, "copy MaxOutstandingR2T=%s\n", val); 1159 conn->sess->MaxOutstandingR2T = (uint32_t) strtol(val, NULL, 10); 1160 val = iscsi_param_get_val(conn->sess->params, "FirstBurstLength"); 1161 if (val == NULL) { 1162 SPDK_ERRLOG("Getval FirstBurstLength failed\n"); 1163 return -1; 1164 } 1165 SPDK_DEBUGLOG(iscsi, "copy FirstBurstLength=%s\n", val); 1166 conn->sess->FirstBurstLength = (uint32_t) strtol(val, NULL, 10); 1167 val = iscsi_param_get_val(conn->sess->params, "MaxBurstLength"); 1168 if (val == NULL) { 1169 SPDK_ERRLOG("Getval MaxBurstLength failed\n"); 1170 return -1; 1171 } 1172 SPDK_DEBUGLOG(iscsi, "copy MaxBurstLength=%s\n", val); 1173 conn->sess->MaxBurstLength = (uint32_t) strtol(val, NULL, 10); 1174 val = iscsi_param_get_val(conn->sess->params, "InitialR2T"); 1175 if (val == NULL) { 1176 SPDK_ERRLOG("Getval InitialR2T failed\n"); 1177 return -1; 1178 } 1179 if (strcasecmp(val, "Yes") == 0) { 1180 SPDK_DEBUGLOG(iscsi, "set InitialR2T=1\n"); 1181 conn->sess->InitialR2T = true; 1182 } else { 1183 SPDK_DEBUGLOG(iscsi, "set InitialR2T=0\n"); 1184 conn->sess->InitialR2T = false; 1185 } 1186 val = iscsi_param_get_val(conn->sess->params, "ImmediateData"); 1187 if (val == NULL) { 1188 SPDK_ERRLOG("Getval ImmediateData failed\n"); 1189 return -1; 1190 } 1191 if (strcasecmp(val, "Yes") == 0) { 1192 SPDK_DEBUGLOG(iscsi, "set ImmediateData=1\n"); 1193 conn->sess->ImmediateData = true; 1194 } else { 1195 SPDK_DEBUGLOG(iscsi, "set ImmediateData=0\n"); 1196 conn->sess->ImmediateData = false; 1197 } 1198 return 0; 1199 } 1200