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