4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
5 * Copyright (c) Intel Corporation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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
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.
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.
35 #include "spdk/stdinc.h"
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"
43 #include "spdk_internal/log.h"
45 #define MAX_TMPBUF 1024
47 /* whose value may be bigger than 255 */
48 static const char *non_simple_value_params
[] = {
55 spdk_iscsi_param_free(struct iscsi_param
*params
)
57 struct iscsi_param
*param
, *next_param
;
62 for (param
= params
; param
!= NULL
; param
= next_param
) {
63 next_param
= param
->next
;
74 spdk_iscsi_find_key_in_array(const char *key
, const char *array
[])
78 for (i
= 0; array
[i
] != NULL
; i
++) {
79 if (strcasecmp(key
, array
[i
]) == 0) {
87 spdk_iscsi_param_find(struct iscsi_param
*params
, const char *key
)
89 struct iscsi_param
*param
;
91 if (params
== NULL
|| key
== NULL
) {
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) {
104 spdk_iscsi_param_del(struct iscsi_param
**params
, const char *key
)
106 struct iscsi_param
*param
, *prev_param
= NULL
;
108 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "del %s\n", key
);
109 if (params
== NULL
|| key
== NULL
) {
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
;
118 *params
= param
->next
;
121 spdk_iscsi_param_free(param
);
130 spdk_iscsi_param_add(struct iscsi_param
**params
, const char *key
,
131 const char *val
, const char *list
, int type
)
133 struct iscsi_param
*param
, *last_param
;
135 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "add %s=%s, list=[%s], type=%d\n",
136 key
, val
, list
, type
);
141 param
= spdk_iscsi_param_find(*params
, key
);
143 spdk_iscsi_param_del(params
, key
);
146 param
= calloc(1, sizeof(*param
));
148 SPDK_ERRLOG("calloc() failed for parameter\n");
153 param
->key
= xstrdup(key
);
154 param
->val
= xstrdup(val
);
155 param
->list
= xstrdup(list
);
158 last_param
= *params
;
159 if (last_param
!= NULL
) {
160 while (last_param
->next
!= NULL
) {
161 last_param
= last_param
->next
;
163 last_param
->next
= param
;
172 spdk_iscsi_param_set(struct iscsi_param
*params
, const char *key
,
175 struct iscsi_param
*param
;
177 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "set %s=%s\n", key
, val
);
178 param
= spdk_iscsi_param_find(params
, key
);
180 SPDK_ERRLOG("no key %s\n", key
);
186 param
->val
= xstrdup(val
);
192 spdk_iscsi_param_set_int(struct iscsi_param
*params
, const char *key
, uint32_t val
)
194 char buf
[MAX_TMPBUF
];
195 struct iscsi_param
*param
;
197 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "set %s=%d\n", key
, val
);
198 param
= spdk_iscsi_param_find(params
, key
);
200 SPDK_ERRLOG("no key %s\n", key
);
205 snprintf(buf
, sizeof buf
, "%d", val
);
207 param
->val
= strdup(buf
);
213 * Parse a single KEY=VAL pair
215 * data = "KEY=VAL<NUL>"
218 spdk_iscsi_parse_param(struct iscsi_param
**params
, const uint8_t *data
)
222 const uint8_t *key_end
, *val
;
223 int key_len
, val_len
;
226 key_end
= strchr(data
, '=');
228 SPDK_ERRLOG("'=' not found\n");
232 key_len
= key_end
- data
;
234 SPDK_ERRLOG("Empty key\n");
240 if (key_len
> ISCSI_TEXT_MAX_KEY_LEN
) {
241 SPDK_ERRLOG("Key name length is bigger than 63\n");
245 key_copy
= malloc(key_len
+ 1);
247 SPDK_ERRLOG("malloc() failed for key_copy\n");
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
);
260 val
= key_end
+ 1; /* +1 to skip over the '=' */
261 val_len
= strlen(val
);
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).
269 * comma or zero is counted in, otherwise we need to iterate each parameter
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
);
280 rc
= spdk_iscsi_param_add(params
, key_copy
, val
, NULL
, 0);
283 SPDK_ERRLOG("iscsi_param_add() failed\n");
287 /* return number of bytes consumed
288 * +1 for '=' and +1 for NUL
290 return key_len
+ 1 + val_len
+ 1;
294 * Parse a sequence of KEY=VAL pairs.
296 * \param data "KEY=VAL<NUL>KEY=VAL<NUL>..."
297 * \param len length of data in bytes
300 spdk_iscsi_parse_params(struct iscsi_param
**params
, const uint8_t *data
,
301 int len
, bool cbit_enabled
, char **partial_parameter
)
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
++) {
312 p
= spdk_sprintf_alloc("%s%s", *partial_parameter
, (const char *)data
);
316 rc
= spdk_iscsi_parse_param(params
, p
);
321 free(*partial_parameter
);
322 *partial_parameter
= NULL
;
328 /* strip the partial text parameters if C bit is enabled */
330 if (partial_parameter
== NULL
) {
331 SPDK_ERRLOG("C bit set but no partial parameters provided\n");
336 * reverse iterate the string from the tail not including '\0'
337 * index of last '\0' is len -1.
339 for (i
= len
- 2; data
[i
] != '\0' && i
> 0; i
--) {
342 *partial_parameter
= xstrdup(&data
[i
== 0 ? 0 : i
+ 1]);
343 len
= (i
== 0 ? 0 : i
+ 1);
346 while (offset
< len
&& data
[offset
] != '\0') {
347 rc
= spdk_iscsi_parse_param(params
, data
+ offset
);
357 spdk_iscsi_param_get_val(struct iscsi_param
*params
, const char *key
)
359 struct iscsi_param
*param
;
361 param
= spdk_iscsi_param_find(params
, key
);
369 spdk_iscsi_param_eq_val(struct iscsi_param
*params
, const char *key
,
372 struct iscsi_param
*param
;
374 param
= spdk_iscsi_param_find(params
, key
);
378 if (strcasecmp(param
->val
, val
) == 0) {
384 struct iscsi_param_table
{
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
},
408 static const struct iscsi_param_table sess_param_table
[] = {
409 { "MaxConnections", "1", "1,65535", ISPT_NUMERICAL_MIN
},
411 /* need special handling */
412 { "SendTargets", "", "", ISPT_DECLARATIVE
},
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
},
435 spdk_iscsi_params_init_internal(struct iscsi_param
**params
,
436 const struct iscsi_param_table
*table
)
440 struct iscsi_param
*param
;
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
);
446 SPDK_ERRLOG("iscsi_param_add() failed\n");
449 param
= spdk_iscsi_param_find(*params
, table
[i
].key
);
451 param
->state_index
= i
;
453 SPDK_ERRLOG("spdk_iscsi_param_find() failed\n");
462 spdk_iscsi_conn_params_init(struct iscsi_param
**params
)
464 return spdk_iscsi_params_init_internal(params
, &conn_param_table
[0]);
468 spdk_iscsi_sess_params_init(struct iscsi_param
**params
)
470 return spdk_iscsi_params_init_internal(params
, &sess_param_table
[0]);
473 static const char *chap_type
[] = {
482 static const char *discovery_ignored_param
[] = {
493 static const char *multi_negot_conn_params
[] = {
494 "MaxRecvDataSegmentLength",
498 /* The following params should be declared by target */
499 static const char *target_declarative_params
[] = {
502 "TargetPortalGroupTag",
506 /* This function is used to construct the data from the special param (e.g.,
507 * MaxRecvDataSegmentLength)
509 * normal: the total len of the data
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
)
519 struct iscsi_param
*param_first
;
520 struct iscsi_param
*param_max
;
521 uint32_t FirstBurstLength
;
522 uint32_t MaxBurstLength
;
525 val
= malloc(ISCSI_TEXT_MAX_VAL_LEN
+ 1);
527 SPDK_ERRLOG("malloc() failed for temporary buffer\n");
531 if (strcasecmp(param
->key
, "MaxRecvDataSegmentLength") == 0) {
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.
541 if (alloc_len
- total
< 1) {
542 SPDK_ERRLOG("data space small %d\n", alloc_len
);
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
);
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
);
564 param_first
= spdk_iscsi_param_find(conn
->sess
->params
,
566 if (param_first
!= NULL
) {
567 FirstBurstLength
= (uint32_t)strtol(param_first
->val
, NULL
, 10);
569 FirstBurstLength
= SPDK_ISCSI_FIRST_BURST_LENGTH
;
571 param_max
= spdk_iscsi_param_find(conn
->sess
->params
,
573 if (param_max
!= NULL
) {
574 MaxBurstLength
= (uint32_t)strtol(param_max
->val
, NULL
, 10);
576 MaxBurstLength
= SPDK_ISCSI_MAX_BURST_LENGTH
;
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",
585 param_first
->val
= xstrdup(val
);
588 len
= snprintf((char *)data
+ total
, alloc_len
- total
,
589 "FirstBurstLength=%d", FirstBurstLength
);
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;
604 spdk_iscsi_construct_data_from_param(struct iscsi_param
*param
, char *new_val
,
605 char *data
, int alloc_len
, int total
)
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
);
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
);
626 * To negotiate param with
628 * return: the negotiated value of the key
630 static char *spdk_iscsi_negotiate_param_list(int *add_param_value
,
631 struct iscsi_param
*param
,
632 char *valid_list
, char *in_val
,
635 char *val_start
, *val_end
;
636 char *in_start
, *in_end
;
639 if (add_param_value
== NULL
) {
645 if ((in_end
= strchr(in_start
, (int)',')) != NULL
) {
648 val_start
= valid_list
;
650 if ((val_end
= strchr(val_start
, (int)',')) != NULL
) {
653 if (strcasecmp(in_start
, val_start
) == 0) {
654 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "match %s\n",
661 val_start
= val_end
+ 1;
669 in_start
= in_end
+ 1;
673 return flag
? val_start
: NULL
;
677 * To negotiate param with
678 * type = ISPT_NUMERICAL_MIN/MAX, ISPT_NUMERICAL_DECLARATIVE
679 * return: the negotiated value of the key
681 static char *spdk_iscsi_negotiate_param_numerical(int *add_param_value
,
682 struct iscsi_param
*param
,
683 char *valid_list
, char *in_val
,
687 char *new_val
= NULL
;
688 char *min_val
, *max_val
;
689 int val_i
, cur_val_i
;
692 if (add_param_value
== NULL
) {
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);
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
);
712 switch (param
->type
) {
713 case ISPT_NUMERICAL_MIN
:
714 if (val_i
> cur_val_i
) {
718 case ISPT_NUMERICAL_MAX
:
719 if (val_i
< cur_val_i
) {
726 snprintf(in_val
, ISCSI_TEXT_MAX_VAL_LEN
, "%d", val_i
);
734 * To negotiate param with
735 * type = ISPT_BOOLEAN_OR, ISPT_BOOLEAN_AND
736 * return: the negotiated value of the key
738 static char *spdk_iscsi_negotiate_param_boolean(int *add_param_value
,
739 struct iscsi_param
*param
,
740 char *in_val
, char *cur_val
,
743 char *new_val
= NULL
;
745 if (add_param_value
== NULL
) {
749 /* Make sure the val is Yes or No */
750 if (!((strcasecmp(in_val
, "Yes") == 0) ||
751 (strcasecmp(in_val
, "No") == 0))) {
753 snprintf(in_val
, ISCSI_TEXT_MAX_VAL_LEN
+ 1, "%s", "Reject");
755 *add_param_value
= 1;
759 if (strcasecmp(cur_val
, value
) == 0) {
760 snprintf(in_val
, ISCSI_TEXT_MAX_VAL_LEN
+ 1, "%s", value
);
763 new_val
= param
->val
;
770 * The entry function to handle each type of the param
771 * return value: the new negotiated value
774 spdk_iscsi_negotiate_param_all(int *add_param_value
, struct iscsi_param
*param
,
775 char *valid_list
, char *in_val
, char *cur_val
)
778 switch (param
->type
) {
780 new_val
= spdk_iscsi_negotiate_param_list(add_param_value
,
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
,
797 case ISPT_BOOLEAN_OR
:
798 new_val
= spdk_iscsi_negotiate_param_boolean(add_param_value
,
804 case ISPT_BOOLEAN_AND
:
805 new_val
= spdk_iscsi_negotiate_param_boolean(add_param_value
,
813 snprintf(in_val
, ISCSI_TEXT_MAX_VAL_LEN
+ 1, "%s", param
->val
);
822 * This function is used to judge whether the param is in session's params or
823 * connection's params
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
)
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)) {
841 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
,
842 "extension key %.64s\n",
845 SPDK_ERRLOG("unknown key %.64s\n", param
->key
);
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
;
855 conn
->sess_param_state_negotiated
[index
] = true;
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
;
864 conn
->conn_param_state_negotiated
[index
] = true;
871 spdk_iscsi_negotiate_params(struct spdk_iscsi_conn
*conn
,
872 struct iscsi_param
**params
, uint8_t *data
, int alloc_len
,
875 struct iscsi_param
*param
;
876 struct iscsi_param
*cur_param
;
877 char *valid_list
, *in_val
;
883 uint32_t FirstBurstLength
;
884 uint32_t MaxBurstLength
;
885 bool FirstBurstLength_flag
= false;
892 if (total
> alloc_len
) {
894 data
[total
- 1] = '\0';
898 if (*params
== NULL
) {
905 cur_param
= spdk_iscsi_param_find(*params
, "SessionType");
906 if (cur_param
== NULL
) {
907 cur_param
= spdk_iscsi_param_find(conn
->sess
->params
, "SessionType");
908 if (cur_param
== NULL
) {
909 /* no session type */
911 if (strcasecmp(cur_param
->val
, "Discovery") == 0) {
916 if (strcasecmp(cur_param
->val
, "Discovery") == 0) {
921 /* for temporary store */
922 valid_list
= malloc(ISCSI_TEXT_MAX_VAL_LEN
+ 1);
924 SPDK_ERRLOG("malloc() failed for valid_list\n");
928 in_val
= malloc(ISCSI_TEXT_MAX_VAL_LEN
+ 1);
930 SPDK_ERRLOG("malloc() failed for in_val\n");
935 cur_val
= malloc(ISCSI_TEXT_MAX_VAL_LEN
+ 1);
937 SPDK_ERRLOG("malloc() failed for cur_val\n");
943 /* To adjust the location of FirstBurstLength location and put it to
944 * the end, then we can always firstly determine the MaxBurstLength
946 param
= spdk_iscsi_param_find(*params
, "MaxBurstLength");
948 param
= spdk_iscsi_param_find(*params
, "FirstBurstLength");
950 /* check the existence of FirstBurstLength */
952 FirstBurstLength_flag
= true;
953 if (param
->next
!= NULL
) {
954 snprintf(in_val
, ISCSI_TEXT_MAX_VAL_LEN
+ 1, "%s", param
->val
);
956 spdk_iscsi_param_add(params
, "FirstBurstLength",
962 for (param
= *params
; param
!= NULL
; param
= param
->next
) {
963 struct iscsi_param
*params_dst
= conn
->params
;
964 int add_param_value
= 0;
966 param
->type
= ISPT_INVALID
;
968 /* sendtargets is special */
969 if (strcasecmp(param
->key
, "SendTargets") == 0) {
973 if (spdk_iscsi_find_key_in_array(param
->key
, chap_type
)) {
977 /* 12.2, 12.10, 12.11, 12.13, 12.14, 12.17, 12.18, 12.19 */
979 spdk_iscsi_find_key_in_array(param
->key
,
980 discovery_ignored_param
)) {
981 snprintf(in_val
, ISCSI_TEXT_MAX_VAL_LEN
+ 1, "%s", "Irrelevant");
985 rc
= spdk_iscsi_negotiate_param_init(conn
,
995 snprintf(in_val
, ISCSI_TEXT_MAX_VAL_LEN
+ 1, "%s", "NotUnderstood");
999 snprintf(valid_list
, ISCSI_TEXT_MAX_VAL_LEN
+ 1, "%s", cur_param
->list
);
1000 snprintf(cur_val
, ISCSI_TEXT_MAX_VAL_LEN
+ 1, "%s", cur_param
->val
);
1001 param
->type
= cur_param
->type
;
1005 if (param
->type
> 0) {
1006 snprintf(in_val
, ISCSI_TEXT_MAX_VAL_LEN
+ 1, "%s", param
->val
);
1008 /* "NotUnderstood" value shouldn't be assigned to "Understood" key */
1009 if (strcasecmp(in_val
, "NotUnderstood") == 0) {
1013 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER
;
1016 if (strcasecmp(param
->key
, "FirstBurstLength") == 0) {
1017 FirstBurstLength
= (uint32_t)strtol(param
->val
, NULL
,
1019 new_val
= spdk_iscsi_param_get_val(conn
->sess
->params
,
1021 if (new_val
!= NULL
) {
1022 MaxBurstLength
= (uint32_t) strtol(new_val
, NULL
,
1025 MaxBurstLength
= SPDK_ISCSI_MAX_BURST_LENGTH
;
1027 if (FirstBurstLength
< MAX_FIRSTBURSTLENGTH
&&
1028 FirstBurstLength
> MaxBurstLength
) {
1029 FirstBurstLength
= MaxBurstLength
;
1030 snprintf(in_val
, ISCSI_TEXT_MAX_VAL_LEN
, "%d",
1035 /* prevent target's declarative params from being changed by initiator */
1036 if (spdk_iscsi_find_key_in_array(param
->key
, target_declarative_params
)) {
1037 add_param_value
= 1;
1040 new_val
= spdk_iscsi_negotiate_param_all(&add_param_value
,
1047 /* check the negotiated value of the key */
1048 if (new_val
!= NULL
) {
1049 /* add_param_value = 0 means updating the value of
1050 * existed key in the connection's parameters
1052 if (add_param_value
== 0) {
1053 spdk_iscsi_param_set(params_dst
, param
->key
, new_val
);
1055 total
= spdk_iscsi_construct_data_from_param(param
,
1064 total
= spdk_iscsi_special_param_construction(conn
,
1066 FirstBurstLength_flag
,
1088 spdk_iscsi_copy_param2var(struct spdk_iscsi_conn
*conn
)
1092 val
= spdk_iscsi_param_get_val(conn
->params
, "MaxRecvDataSegmentLength");
1094 SPDK_ERRLOG("Getval MaxRecvDataSegmentLength failed\n");
1097 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
,
1098 "copy MaxRecvDataSegmentLength=%s\n", val
);
1099 conn
->MaxRecvDataSegmentLength
= (int)strtol(val
, NULL
, 10);
1100 if (conn
->MaxRecvDataSegmentLength
> SPDK_ISCSI_MAX_SEND_DATA_SEGMENT_LENGTH
) {
1101 conn
->MaxRecvDataSegmentLength
= SPDK_ISCSI_MAX_SEND_DATA_SEGMENT_LENGTH
;
1104 val
= spdk_iscsi_param_get_val(conn
->params
, "HeaderDigest");
1106 SPDK_ERRLOG("Getval HeaderDigest failed\n");
1109 if (strcasecmp(val
, "CRC32C") == 0) {
1110 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "set HeaderDigest=1\n");
1111 conn
->header_digest
= 1;
1113 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "set HeaderDigest=0\n");
1114 conn
->header_digest
= 0;
1116 val
= spdk_iscsi_param_get_val(conn
->params
, "DataDigest");
1118 SPDK_ERRLOG("Getval DataDigest failed\n");
1121 if (strcasecmp(val
, "CRC32C") == 0) {
1122 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "set DataDigest=1\n");
1123 conn
->data_digest
= 1;
1125 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "set DataDigest=0\n");
1126 conn
->data_digest
= 0;
1129 val
= spdk_iscsi_param_get_val(conn
->sess
->params
, "MaxConnections");
1131 SPDK_ERRLOG("Getval MaxConnections failed\n");
1134 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "copy MaxConnections=%s\n", val
);
1135 conn
->sess
->MaxConnections
= (uint32_t) strtol(val
, NULL
, 10);
1136 val
= spdk_iscsi_param_get_val(conn
->sess
->params
, "MaxOutstandingR2T");
1138 SPDK_ERRLOG("Getval MaxOutstandingR2T failed\n");
1141 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "copy MaxOutstandingR2T=%s\n", val
);
1142 conn
->sess
->MaxOutstandingR2T
= (uint32_t) strtol(val
, NULL
, 10);
1143 val
= spdk_iscsi_param_get_val(conn
->sess
->params
, "FirstBurstLength");
1145 SPDK_ERRLOG("Getval FirstBurstLength failed\n");
1148 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "copy FirstBurstLength=%s\n", val
);
1149 conn
->sess
->FirstBurstLength
= (uint32_t) strtol(val
, NULL
, 10);
1150 val
= spdk_iscsi_param_get_val(conn
->sess
->params
, "MaxBurstLength");
1152 SPDK_ERRLOG("Getval MaxBurstLength failed\n");
1155 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "copy MaxBurstLength=%s\n", val
);
1156 conn
->sess
->MaxBurstLength
= (uint32_t) strtol(val
, NULL
, 10);
1157 val
= spdk_iscsi_param_get_val(conn
->sess
->params
, "InitialR2T");
1159 SPDK_ERRLOG("Getval InitialR2T failed\n");
1162 if (strcasecmp(val
, "Yes") == 0) {
1163 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "set InitialR2T=1\n");
1164 conn
->sess
->InitialR2T
= true;
1166 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "set InitialR2T=0\n");
1167 conn
->sess
->InitialR2T
= false;
1169 val
= spdk_iscsi_param_get_val(conn
->sess
->params
, "ImmediateData");
1171 SPDK_ERRLOG("Getval ImmediateData failed\n");
1174 if (strcasecmp(val
, "Yes") == 0) {
1175 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "set ImmediateData=1\n");
1176 conn
->sess
->ImmediateData
= true;
1178 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "set ImmediateData=0\n");
1179 conn
->sess
->ImmediateData
= false;