Branch data Line data Source code
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 : 7513 : iscsi_param_free(struct iscsi_param *params)
27 : : {
28 : : struct iscsi_param *param, *next_param;
29 : :
30 [ + + ]: 7513 : if (params == NULL) {
31 : 3985 : return;
32 : : }
33 [ + + ]: 32882 : for (param = params; param != NULL; param = next_param) {
34 : 29354 : next_param = param->next;
35 [ + + ]: 29354 : if (param->list) {
36 : 18931 : free(param->list);
37 : : }
38 : 29354 : free(param->val);
39 : 29354 : free(param->key);
40 : 29354 : free(param);
41 : : }
42 : : }
43 : :
44 : : static int
45 : 28882 : iscsi_find_key_in_array(const char *key, const char *array[])
46 : : {
47 : : int i;
48 : :
49 [ + + ]: 122438 : for (i = 0; array[i] != NULL; i++) {
50 [ + + - + : 95006 : if (strcasecmp(key, array[i]) == 0) {
+ + ]
51 : 1450 : return 1;
52 : : }
53 : : }
54 : 27432 : return 0;
55 : : }
56 : :
57 : : struct iscsi_param *
58 : 153582 : iscsi_param_find(struct iscsi_param *params, const char *key)
59 : : {
60 : : struct iscsi_param *param;
61 : :
62 [ + + - + ]: 153582 : if (params == NULL || key == NULL) {
63 : 8617 : return NULL;
64 : : }
65 [ + + ]: 1214137 : for (param = params; param != NULL; param = param->next) {
66 [ + + + + ]: 1168450 : if (param->key != NULL && param->key[0] == key[0]
67 [ + + - + : 226535 : && strcasecmp(param->key, key) == 0) {
+ + ]
68 : 99278 : return param;
69 : : }
70 : : }
71 : 45687 : return NULL;
72 : : }
73 : :
74 : : int
75 : 602 : iscsi_param_del(struct iscsi_param **params, const char *key)
76 : : {
77 : 602 : struct iscsi_param *param, *prev_param = NULL;
78 : :
79 [ - + - + ]: 602 : SPDK_DEBUGLOG(iscsi, "del %s\n", key);
80 [ + - - + ]: 602 : if (params == NULL || key == NULL) {
81 : 0 : return 0;
82 : : }
83 [ + - ]: 5840 : for (param = *params; param != NULL; param = param->next) {
84 [ + - + + ]: 5840 : if (param->key != NULL && param->key[0] == key[0]
85 [ + + - + : 602 : && strcasecmp(param->key, key) == 0) {
+ - ]
86 [ + + ]: 602 : if (prev_param != NULL) {
87 : 566 : prev_param->next = param->next;
88 : : } else {
89 : 36 : *params = param->next;
90 : : }
91 : 602 : param->next = NULL;
92 : 602 : iscsi_param_free(param);
93 : 602 : return 0;
94 : : }
95 : 5238 : prev_param = param;
96 : : }
97 : 0 : return -1;
98 : : }
99 : :
100 : : int
101 : 29354 : 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 [ - + - + ]: 29354 : SPDK_DEBUGLOG(iscsi, "add %s=%s, list=[%s], type=%d\n",
107 : : key, val, list, type);
108 [ - + ]: 29354 : if (key == NULL) {
109 : 0 : return -1;
110 : : }
111 : :
112 : 29354 : param = iscsi_param_find(*params, key);
113 [ + + ]: 29354 : if (param != NULL) {
114 : 432 : iscsi_param_del(params, key);
115 : : }
116 : :
117 : 29354 : param = calloc(1, sizeof(*param));
118 [ - + ]: 29354 : if (!param) {
119 : 0 : SPDK_ERRLOG("calloc() failed for parameter\n");
120 : 0 : return -ENOMEM;
121 : : }
122 : :
123 : 29354 : param->next = NULL;
124 [ + - - + ]: 29354 : param->key = xstrdup(key);
125 [ + - - + ]: 29354 : param->val = xstrdup(val);
126 [ + + - + ]: 29354 : param->list = xstrdup(list);
127 : 29354 : param->type = type;
128 : :
129 : 29354 : last_param = *params;
130 [ + + ]: 29354 : if (last_param != NULL) {
131 [ + + ]: 202354 : while (last_param->next != NULL) {
132 : 175926 : last_param = last_param->next;
133 : : }
134 : 26428 : last_param->next = param;
135 : : } else {
136 : 2926 : *params = param;
137 : : }
138 : :
139 : 29354 : return 0;
140 : : }
141 : :
142 : : int
143 : 12574 : iscsi_param_set(struct iscsi_param *params, const char *key,
144 : : const char *val)
145 : : {
146 : : struct iscsi_param *param;
147 : :
148 [ - + - + ]: 12574 : SPDK_DEBUGLOG(iscsi, "set %s=%s\n", key, val);
149 : 12574 : param = iscsi_param_find(params, key);
150 [ - + ]: 12574 : if (param == NULL) {
151 : 0 : SPDK_ERRLOG("no key %s\n", key);
152 : 0 : return -1;
153 : : }
154 : :
155 : 12574 : free(param->val);
156 : :
157 [ + - - + ]: 12574 : param->val = xstrdup(val);
158 : :
159 : 12574 : return 0;
160 : : }
161 : :
162 : : int
163 : 4631 : iscsi_param_set_int(struct iscsi_param *params, const char *key, uint32_t val)
164 : : {
165 : 60 : char buf[MAX_TMPBUF];
166 : : struct iscsi_param *param;
167 : :
168 [ - + - + ]: 4631 : SPDK_DEBUGLOG(iscsi, "set %s=%d\n", key, val);
169 : 4631 : param = iscsi_param_find(params, key);
170 [ - + ]: 4631 : if (param == NULL) {
171 : 0 : SPDK_ERRLOG("no key %s\n", key);
172 : 0 : return -1;
173 : : }
174 : :
175 : 4631 : free(param->val);
176 [ - + ]: 4631 : snprintf(buf, sizeof buf, "%d", val);
177 : :
178 [ - + ]: 4631 : param->val = strdup(buf);
179 : :
180 : 4631 : return 0;
181 : : }
182 : :
183 : : /**
184 : : * Parse a single KEY=VAL pair
185 : : *
186 : : * data = "KEY=VAL<NUL>"
187 : : */
188 : : static int
189 : 10035 : 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 [ - + ]: 10035 : data_len = strnlen(data, data_len);
198 : : /* No such thing as strnchr so use memchr instead. */
199 [ - + ]: 10035 : key_end = memchr(data, '=', data_len);
200 [ + + ]: 10035 : if (!key_end) {
201 : 12 : SPDK_ERRLOG("'=' not found\n");
202 : 12 : return -1;
203 : : }
204 : :
205 : 10023 : key_len = key_end - data;
206 [ + + ]: 10023 : if (key_len == 0) {
207 : 6 : SPDK_ERRLOG("Empty key\n");
208 : 6 : return -1;
209 : : }
210 : : /*
211 : : * RFC 7143 6.1
212 : : */
213 [ + + ]: 10017 : if (key_len > ISCSI_TEXT_MAX_KEY_LEN) {
214 : 6 : SPDK_ERRLOG("Key name length is bigger than 63\n");
215 : 6 : return -1;
216 : : }
217 : :
218 : 10011 : key_copy = malloc(key_len + 1);
219 [ - + ]: 10011 : if (!key_copy) {
220 : 0 : SPDK_ERRLOG("malloc() failed for key_copy\n");
221 : 0 : return -ENOMEM;
222 : : }
223 : :
224 [ - + - + ]: 10011 : memcpy(key_copy, data, key_len);
225 : 10011 : key_copy[key_len] = '\0';
226 : : /* check whether this key is duplicated */
227 [ + + ]: 10011 : if (NULL != iscsi_param_find(*params, key_copy)) {
228 : 6 : SPDK_ERRLOG("Duplicated Key %s\n", key_copy);
229 : 6 : free(key_copy);
230 : 6 : return -1;
231 : : }
232 : :
233 [ - + ]: 10005 : 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 : 10005 : max_len = iscsi_find_key_in_array(key_copy, non_simple_value_params) ?
245 [ + + ]: 10005 : ISCSI_TEXT_MAX_VAL_LEN : ISCSI_TEXT_MAX_SIMPLE_VAL_LEN;
246 [ + + ]: 10005 : if (val_len > max_len) {
247 : 14 : SPDK_ERRLOG("Overflow Val %d\n", val_len);
248 : 14 : free(key_copy);
249 : 14 : return -1;
250 : : }
251 : :
252 : 9991 : val_copy = calloc(1, val_len + 1);
253 [ - + ]: 9991 : if (val_copy == NULL) {
254 : 0 : SPDK_ERRLOG("Could not allocate value string\n");
255 : 0 : free(key_copy);
256 : 0 : return -1;
257 : : }
258 : :
259 [ - + - + ]: 9991 : memcpy(val_copy, key_end + 1, val_len);
260 : :
261 : 9991 : rc = iscsi_param_add(params, key_copy, val_copy, NULL, 0);
262 : 9991 : free(val_copy);
263 : 9991 : free(key_copy);
264 [ - + ]: 9991 : if (rc < 0) {
265 : 0 : SPDK_ERRLOG("iscsi_param_add() failed\n");
266 : 0 : return -1;
267 : : }
268 : :
269 : : /* return number of bytes consumed
270 : : * +1 for '=' and +1 for NUL
271 : : */
272 : 9991 : 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 : 5795 : iscsi_parse_params(struct iscsi_param **params, const uint8_t *data,
285 : : int len, bool cbit_enabled, char **partial_parameter)
286 : : {
287 : 5795 : 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 [ + + ]: 5795 : if (len == 0) {
296 : 3965 : return 0;
297 : : }
298 : :
299 [ - + ]: 1830 : assert(data != NULL);
300 : :
301 : : /* strip the partial text parameters if previous PDU have C enabled */
302 [ + + + + ]: 1830 : if (partial_parameter && *partial_parameter) {
303 [ + + + + ]: 204 : for (i = 0; i < len && data[i] != '\0'; i++) {
304 : : ;
305 : : }
306 : 24 : p = spdk_sprintf_alloc("%s%s", *partial_parameter, (const char *)data);
307 [ - + ]: 24 : if (!p) {
308 : 0 : return -1;
309 : : }
310 [ - + ]: 24 : rc = iscsi_parse_param(params, p, i + strlen(*partial_parameter));
311 : 24 : free(p);
312 [ - + ]: 24 : if (rc < 0) {
313 : 0 : return -1;
314 : : }
315 : 24 : free(*partial_parameter);
316 : 24 : *partial_parameter = NULL;
317 : :
318 : 24 : data = data + i + 1;
319 : 24 : len = len - (i + 1);
320 : : }
321 : :
322 : : /* strip the partial text parameters if C bit is enabled */
323 [ + + ]: 1830 : if (cbit_enabled) {
324 [ - + ]: 24 : if (partial_parameter == NULL) {
325 : 0 : SPDK_ERRLOG("C bit set but no partial parameters provided\n");
326 : 0 : return -1;
327 : : }
328 : :
329 : : /*
330 : : * reverse iterate the string from the tail not including '\0'
331 : : */
332 [ + + + + ]: 132 : for (i = len - 1; data[i] != '\0' && i > 0; i--) {
333 : : ;
334 : : }
335 [ + + ]: 24 : if (i != 0) {
336 : : /* We found a NULL character - don't copy it into the
337 : : * partial parameter.
338 : : */
339 : 6 : i++;
340 : : }
341 : :
342 : 24 : *partial_parameter = calloc(1, len - i + 1);
343 [ - + ]: 24 : if (*partial_parameter == NULL) {
344 : 0 : SPDK_ERRLOG("could not allocate partial parameter\n");
345 : 0 : return -1;
346 : : }
347 [ - + - + ]: 24 : memcpy(*partial_parameter, &data[i], len - i);
348 [ + + ]: 24 : if (i == 0) {
349 : : /* No full parameters to parse - so return now. */
350 : 18 : return 0;
351 : : } else {
352 : 6 : len = i - 1;
353 : : }
354 : : }
355 : :
356 [ + + + + ]: 11779 : while (offset < len && data[offset] != '\0') {
357 : 10011 : rc = iscsi_parse_param(params, data + offset, len - offset);
358 [ + + ]: 10011 : if (rc < 0) {
359 : 44 : return -1;
360 : : }
361 : 9967 : offset += rc;
362 : : }
363 : 1768 : return 0;
364 : : }
365 : :
366 : : char *
367 : 51273 : iscsi_param_get_val(struct iscsi_param *params, const char *key)
368 : : {
369 : : struct iscsi_param *param;
370 : :
371 : 51273 : param = iscsi_param_find(params, key);
372 [ + + ]: 51273 : if (param == NULL) {
373 : 5481 : return NULL;
374 : : }
375 : 45792 : return param->val;
376 : : }
377 : :
378 : : int
379 : 4424 : iscsi_param_eq_val(struct iscsi_param *params, const char *key,
380 : : const char *val)
381 : : {
382 : : struct iscsi_param *param;
383 : :
384 : 4424 : param = iscsi_param_find(params, key);
385 [ + + ]: 4424 : if (param == NULL) {
386 : 6 : return 0;
387 : : }
388 [ - + - + : 4418 : if (strcasecmp(param->val, val) == 0) {
+ + ]
389 : 459 : return 1;
390 : : }
391 : 3959 : 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 : 1212 : 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 [ + + ]: 19973 : for (i = 0; table[i].key != NULL; i++) {
453 : 18947 : rc = iscsi_param_add(params, table[i].key, table[i].val,
454 : 18947 : table[i].list, table[i].type);
455 [ - + ]: 18761 : if (rc < 0) {
456 : 0 : SPDK_ERRLOG("iscsi_param_add() failed\n");
457 : 0 : return -1;
458 : : }
459 : 18761 : param = iscsi_param_find(*params, table[i].key);
460 [ + - ]: 18761 : if (param != NULL) {
461 : 18761 : param->state_index = i;
462 : : } else {
463 : 0 : SPDK_ERRLOG("iscsi_param_find() failed\n");
464 : 0 : return -1;
465 : : }
466 : : }
467 : :
468 : 1212 : return 0;
469 : : }
470 : :
471 : : int
472 : 611 : iscsi_conn_params_init(struct iscsi_param **params)
473 : : {
474 : 611 : return iscsi_params_init_internal(params, &conn_param_table[0]);
475 : : }
476 : :
477 : : int
478 : 601 : iscsi_sess_params_init(struct iscsi_param **params)
479 : : {
480 : 601 : 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 : 8682 : 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 : 8682 : val = malloc(ISCSI_TEXT_MAX_VAL_LEN + 1);
537 [ - + ]: 8682 : if (!val) {
538 : 0 : SPDK_ERRLOG("malloc() failed for temporary buffer\n");
539 : 0 : return -ENOMEM;
540 : : }
541 : :
542 [ - + + + ]: 8682 : 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 [ - + ]: 459 : if (alloc_len - total < 1) {
553 : 0 : SPDK_ERRLOG("data space small %d\n", alloc_len);
554 : 0 : free(val);
555 : 0 : return -1;
556 : : }
557 : :
558 [ - + - + ]: 459 : SPDK_DEBUGLOG(iscsi,
559 : : "returning MaxRecvDataSegmentLength=%d\n",
560 : : SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
561 : 459 : len = snprintf((char *)data + total, alloc_len - total,
562 : : "MaxRecvDataSegmentLength=%d",
563 : : SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
564 : 459 : total += len + 1;
565 : : }
566 : :
567 [ + + + + ]: 8682 : if (strcasecmp(param->key, "MaxBurstLength") == 0 &&
568 [ + + ]: 438 : !FirstBurstLength_flag) {
569 [ - + ]: 2 : if (alloc_len - total < 1) {
570 : 0 : SPDK_ERRLOG("data space small %d\n", alloc_len);
571 : 0 : free(val);
572 : 0 : return -1;
573 : : }
574 : :
575 : 2 : param_first = iscsi_param_find(conn->sess->params,
576 : : "FirstBurstLength");
577 [ + - ]: 2 : if (param_first != NULL) {
578 [ - + ]: 2 : FirstBurstLength = (uint32_t)strtol(param_first->val, NULL, 10);
579 : : } else {
580 : 0 : FirstBurstLength = SPDK_ISCSI_FIRST_BURST_LENGTH;
581 : : }
582 : 2 : param_max = iscsi_param_find(conn->sess->params,
583 : : "MaxBurstLength");
584 [ + - ]: 2 : if (param_max != NULL) {
585 [ - + ]: 2 : MaxBurstLength = (uint32_t)strtol(param_max->val, NULL, 10);
586 : : } else {
587 : 0 : MaxBurstLength = SPDK_ISCSI_MAX_BURST_LENGTH;
588 : : }
589 : :
590 [ + - ]: 2 : if (FirstBurstLength > MaxBurstLength) {
591 : 2 : FirstBurstLength = MaxBurstLength;
592 [ + - ]: 2 : if (param_first != NULL) {
593 : 2 : free(param_first->val);
594 : 2 : snprintf(val, ISCSI_TEXT_MAX_VAL_LEN, "%d",
595 : : FirstBurstLength);
596 [ + - - + ]: 2 : param_first->val = xstrdup(val);
597 : : }
598 : : }
599 : 2 : len = snprintf((char *)data + total, alloc_len - total,
600 : : "FirstBurstLength=%d", FirstBurstLength);
601 : 2 : total += len + 1;
602 : : }
603 : :
604 : 8682 : free(val);
605 : 8682 : 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 : 8682 : 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 [ + + ]: 8682 : if (param->type != ISPT_DECLARATIVE &&
621 [ + + ]: 6834 : param->type != ISPT_NUMERICAL_DECLARATIVE) {
622 [ - + ]: 6375 : if (alloc_len - total < 1) {
623 : 0 : SPDK_ERRLOG("data space small %d\n", alloc_len);
624 : 0 : return -1;
625 : : }
626 : :
627 [ - + - + ]: 6375 : SPDK_DEBUGLOG(iscsi, "negotiated %s=%s\n",
628 : : param->key, new_val);
629 [ - + ]: 6375 : len = snprintf((char *)data + total, alloc_len - total, "%s=%s",
630 : : param->key, new_val);
631 : 6375 : total += len + 1;
632 : : }
633 : 8682 : 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 : 1456 : 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 : 1456 : int flag = 0;
650 : :
651 [ - + ]: 1456 : if (add_param_value == NULL) {
652 : 0 : return NULL;
653 : : }
654 : :
655 : 1456 : in_start = in_val;
656 : : do {
657 [ + + + + ]: 1468 : if ((in_end = strchr(in_start, (int)',')) != NULL) {
658 : 400 : *in_end = '\0';
659 : : }
660 : 1468 : val_start = valid_list;
661 : : do {
662 [ + + + + ]: 2570 : if ((val_end = strchr(val_start, (int)',')) != NULL) {
663 : 1502 : *val_end = '\0';
664 : : }
665 [ + + - + : 2570 : if (strcasecmp(in_start, val_start) == 0) {
+ + ]
666 [ - + - + ]: 1456 : SPDK_DEBUGLOG(iscsi, "match %s\n",
667 : : val_start);
668 : 1456 : flag = 1;
669 : 1456 : break;
670 : : }
671 [ + + ]: 1114 : if (val_end) {
672 : 1102 : *val_end = ',';
673 : 1102 : val_start = val_end + 1;
674 : : }
675 [ + + ]: 1114 : } while (val_end);
676 [ + + ]: 1468 : if (flag) {
677 : 1456 : break;
678 : : }
679 [ + - ]: 12 : if (in_end) {
680 : 12 : *in_end = ',';
681 : 12 : in_start = in_end + 1;
682 : : }
683 [ + - ]: 12 : } while (in_end);
684 : :
685 [ + - ]: 1456 : 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 : 3362 : 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 : 60 : char *valid_next;
700 : 3362 : 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 [ - + ]: 3362 : if (add_param_value == NULL) {
706 : 0 : return NULL;
707 : : }
708 : :
709 [ - + ]: 3362 : val_i = (int)strtol(param->val, NULL, 10);
710 : : /* check whether the key is FirstBurstLength, if that we use in_val */
711 [ + + + + ]: 3362 : if (strcasecmp(param->key, "FirstBurstLength") == 0) {
712 [ - + ]: 438 : val_i = (int)strtol(in_val, NULL, 10);
713 : : }
714 : :
715 [ - + ]: 3362 : cur_val_i = (int)strtol(cur_val, NULL, 10);
716 : 3362 : valid_next = valid_list;
717 : 3362 : min_val = spdk_strsepq(&valid_next, ",");
718 : 3362 : max_val = spdk_strsepq(&valid_next, ",");
719 [ + - - + ]: 3362 : min_i = (min_val != NULL) ? (int)strtol(min_val, NULL, 10) : 0;
720 [ + - - + ]: 3362 : max_i = (max_val != NULL) ? (int)strtol(max_val, NULL, 10) : 0;
721 [ + + + + ]: 3362 : if (val_i < min_i || val_i > max_i) {
722 [ - + - + ]: 16 : SPDK_DEBUGLOG(iscsi, "key %.64s reject\n", param->key);
723 : 16 : new_val = NULL;
724 : : } else {
725 [ + + + ]: 3346 : switch (param->type) {
726 : 2462 : case ISPT_NUMERICAL_MIN:
727 [ + + ]: 2462 : if (val_i > cur_val_i) {
728 : 321 : val_i = cur_val_i;
729 : : }
730 : 2462 : break;
731 : 425 : case ISPT_NUMERICAL_MAX:
732 [ - + ]: 425 : if (val_i < cur_val_i) {
733 : 0 : val_i = cur_val_i;
734 : : }
735 : 425 : break;
736 : 459 : default:
737 : 459 : break;
738 : : }
739 : 3346 : snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN, "%d", val_i);
740 : 3346 : new_val = in_val;
741 : : }
742 : :
743 : 3362 : 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 : 2062 : 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 : 2062 : char *new_val = NULL;
758 : :
759 [ - + ]: 2062 : if (add_param_value == NULL) {
760 : 0 : return NULL;
761 : : }
762 : :
763 : : /* Make sure the val is Yes or No */
764 [ + + + + ]: 2062 : if (!((strcasecmp(in_val, "Yes") == 0) ||
765 [ + + + + ]: 700 : (strcasecmp(in_val, "No") == 0))) {
766 : : /* unknown value */
767 : 46 : snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", "Reject");
768 : 46 : new_val = in_val;
769 : 46 : *add_param_value = 1;
770 : 46 : return new_val;
771 : : }
772 : :
773 [ - + - + : 2016 : if (strcasecmp(cur_val, value) == 0) {
+ + ]
774 : 1586 : snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", value);
775 : 1586 : new_val = in_val;
776 : : } else {
777 : 430 : new_val = param->val;
778 : : }
779 : :
780 : 2016 : 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 : 8686 : 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 [ + + + + : 8686 : switch (param->type) {
+ ]
793 : 1414 : case ISPT_LIST:
794 : 1414 : new_val = iscsi_negotiate_param_list(add_param_value,
795 : : param,
796 : : valid_list,
797 : : in_val,
798 : : cur_val);
799 : 1414 : break;
800 : :
801 : 3362 : case ISPT_NUMERICAL_MIN:
802 : : case ISPT_NUMERICAL_MAX:
803 : : case ISPT_NUMERICAL_DECLARATIVE:
804 : 3362 : new_val = iscsi_negotiate_param_numerical(add_param_value,
805 : : param,
806 : : valid_list,
807 : : in_val,
808 : : cur_val);
809 : 3362 : break;
810 : :
811 : 1234 : case ISPT_BOOLEAN_OR:
812 : 1234 : new_val = iscsi_negotiate_param_boolean(add_param_value,
813 : : param,
814 : : in_val,
815 : : cur_val,
816 : : "Yes");
817 : 1234 : break;
818 : 828 : case ISPT_BOOLEAN_AND:
819 : 828 : new_val = iscsi_negotiate_param_boolean(add_param_value,
820 : : param,
821 : : in_val,
822 : : cur_val,
823 : : "No");
824 : 828 : break;
825 : :
826 : 1848 : default:
827 [ - + ]: 1848 : snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", param->val);
828 : 1848 : new_val = in_val;
829 : 1848 : break;
830 : : }
831 : :
832 : 8686 : 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 : 8706 : 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 : 8706 : *cur_param_p = iscsi_param_find(*params_dst_p, param->key);
848 [ + + ]: 8706 : if (*cur_param_p == NULL) {
849 : 6431 : *params_dst_p = conn->sess->params;
850 : 6431 : *cur_param_p = iscsi_param_find(*params_dst_p, param->key);
851 [ + + ]: 6431 : if (*cur_param_p == NULL) {
852 [ - + + + ]: 12 : if ((strncasecmp(param->key, "X-", 2) == 0) ||
853 [ - + - + ]: 10 : (strncasecmp(param->key, "X#", 2) == 0)) {
854 : : /* Extension Key */
855 [ - + - + ]: 2 : SPDK_DEBUGLOG(iscsi,
856 : : "extension key %.64s\n",
857 : : param->key);
858 : : } else {
859 : 10 : SPDK_ERRLOG("unknown key %.64s\n", param->key);
860 : : }
861 : 12 : return 1;
862 : : } else {
863 : 6419 : index = (*cur_param_p)->state_index;
864 [ - + - + : 6419 : if (conn->sess_param_state_negotiated[index] &&
- - ]
865 : 0 : !iscsi_find_key_in_array(param->key,
866 : : target_declarative_params)) {
867 : 0 : return SPDK_ISCSI_PARAMETER_EXCHANGE_NOT_ONCE;
868 : : }
869 : 6419 : conn->sess_param_state_negotiated[index] = true;
870 : : }
871 : : } else {
872 : 2275 : index = (*cur_param_p)->state_index;
873 [ - + + + : 2283 : if (conn->conn_param_state_negotiated[index] &&
+ + ]
874 : 8 : !iscsi_find_key_in_array(param->key,
875 : : multi_negot_conn_params)) {
876 : 4 : return SPDK_ISCSI_PARAMETER_EXCHANGE_NOT_ONCE;
877 : : }
878 : 2271 : conn->conn_param_state_negotiated[index] = true;
879 : : }
880 : :
881 : 8690 : return 0;
882 : : }
883 : :
884 : : int
885 : 5659 : 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 : 35 : 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 : 5659 : bool FirstBurstLength_flag = false;
900 : : int type;
901 : :
902 : 5659 : total = data_len;
903 [ - + ]: 5659 : if (data_len < 0) {
904 : 0 : assert(false);
905 : : return -EINVAL;
906 : : }
907 [ + + ]: 5659 : if (alloc_len < 1) {
908 : 6 : return 0;
909 : : }
910 [ - + ]: 5653 : if (total > alloc_len) {
911 : 0 : total = alloc_len;
912 : 0 : data[total - 1] = '\0';
913 : 0 : return total;
914 : : }
915 : :
916 [ + + ]: 5653 : if (*params == NULL) {
917 : : /* no input */
918 : 3955 : return total;
919 : : }
920 : :
921 : : /* discovery? */
922 : 1698 : discovery = 0;
923 : 1698 : cur_param = iscsi_param_find(*params, "SessionType");
924 [ + + ]: 1698 : if (cur_param == NULL) {
925 : 1133 : cur_param = iscsi_param_find(conn->sess->params, "SessionType");
926 [ + - ]: 1133 : if (cur_param == NULL) {
927 : : /* no session type */
928 : : } else {
929 [ - + + + ]: 1133 : if (strcasecmp(cur_param->val, "Discovery") == 0) {
930 : 49 : discovery = 1;
931 : : }
932 : : }
933 : : } else {
934 [ - + + + ]: 565 : if (strcasecmp(cur_param->val, "Discovery") == 0) {
935 : 39 : discovery = 1;
936 : : }
937 : : }
938 : :
939 : : /* for temporary store */
940 : 1698 : valid_list = malloc(ISCSI_TEXT_MAX_VAL_LEN + 1);
941 [ - + ]: 1698 : if (!valid_list) {
942 : 0 : SPDK_ERRLOG("malloc() failed for valid_list\n");
943 : 0 : return -ENOMEM;
944 : : }
945 : :
946 : 1698 : in_val = malloc(ISCSI_TEXT_MAX_VAL_LEN + 1);
947 [ - + ]: 1698 : if (!in_val) {
948 : 0 : SPDK_ERRLOG("malloc() failed for in_val\n");
949 : 0 : free(valid_list);
950 : 0 : return -ENOMEM;
951 : : }
952 : :
953 : 1698 : cur_val = malloc(ISCSI_TEXT_MAX_VAL_LEN + 1);
954 [ - + ]: 1698 : if (!cur_val) {
955 : 0 : SPDK_ERRLOG("malloc() failed for cur_val\n");
956 : 0 : free(valid_list);
957 : 0 : free(in_val);
958 : 0 : 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 : 1698 : param = iscsi_param_find(*params, "MaxBurstLength");
965 [ + + ]: 1698 : if (param != NULL) {
966 : 440 : param = iscsi_param_find(*params, "FirstBurstLength");
967 : :
968 : : /* check the existence of FirstBurstLength */
969 [ + + ]: 440 : if (param != NULL) {
970 : 436 : FirstBurstLength_flag = true;
971 [ + + ]: 436 : if (param->next != NULL) {
972 : 432 : snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", param->val);
973 : 432 : type = param->type;
974 : 432 : iscsi_param_add(params, "FirstBurstLength",
975 : : in_val, NULL, type);
976 : : }
977 : : }
978 : : }
979 : :
980 [ + + ]: 11487 : for (param = *params; param != NULL; param = param->next) {
981 : 9813 : struct iscsi_param *params_dst = conn->params;
982 : 9813 : int add_param_value = 0;
983 : 9813 : new_val = NULL;
984 : 9813 : param->type = ISPT_INVALID;
985 : :
986 : : /* sendtargets is special */
987 [ - + + + ]: 9813 : if (strcasecmp(param->key, "SendTargets") == 0) {
988 : 1107 : continue;
989 : : }
990 : : /* CHAP keys */
991 [ + + ]: 9778 : if (iscsi_find_key_in_array(param->key, chap_type)) {
992 : 1072 : continue;
993 : : }
994 : :
995 : : /* 12.2, 12.10, 12.11, 12.13, 12.14, 12.17, 12.18, 12.19 */
996 [ + + - + ]: 9111 : if (discovery &&
997 : 405 : iscsi_find_key_in_array(param->key, discovery_ignored_param)) {
998 : 0 : snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", "Irrelevant");
999 : 0 : new_val = in_val;
1000 : 0 : add_param_value = 1;
1001 : : } else {
1002 : 8706 : rc = iscsi_negotiate_param_init(conn,
1003 : : &cur_param,
1004 : : ¶ms_dst,
1005 : : param);
1006 [ + + ]: 8706 : if (rc < 0) {
1007 : 4 : free(valid_list);
1008 : 4 : free(in_val);
1009 : 4 : free(cur_val);
1010 : 8 : return rc;
1011 [ + + ]: 8702 : } else if (rc > 0) {
1012 : 12 : snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", "NotUnderstood");
1013 : 12 : new_val = in_val;
1014 : 12 : add_param_value = 1;
1015 : : } else {
1016 : 8690 : snprintf(valid_list, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", cur_param->list);
1017 : 8690 : snprintf(cur_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", cur_param->val);
1018 : 8690 : param->type = cur_param->type;
1019 : : }
1020 : : }
1021 : :
1022 [ + + ]: 8702 : if (param->type > 0) {
1023 : 8690 : snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", param->val);
1024 : :
1025 : : /* "NotUnderstood" value shouldn't be assigned to "Understood" key */
1026 [ - + + + ]: 8690 : if (strcasecmp(in_val, "NotUnderstood") == 0) {
1027 : 4 : free(in_val);
1028 : 4 : free(valid_list);
1029 : 4 : free(cur_val);
1030 : 4 : return SPDK_ISCSI_LOGIN_ERROR_PARAMETER;
1031 : : }
1032 : :
1033 [ + + + + ]: 8686 : if (strcasecmp(param->key, "FirstBurstLength") == 0) {
1034 [ - + ]: 438 : FirstBurstLength = (uint32_t)strtol(param->val, NULL,
1035 : : 10);
1036 : 438 : new_val = iscsi_param_get_val(conn->sess->params,
1037 : : "MaxBurstLength");
1038 [ + - ]: 438 : if (new_val != NULL) {
1039 [ - + ]: 438 : MaxBurstLength = (uint32_t) strtol(new_val, NULL,
1040 : : 10);
1041 : : } else {
1042 : 0 : MaxBurstLength = SPDK_ISCSI_MAX_BURST_LENGTH;
1043 : : }
1044 [ + + + + ]: 438 : if (FirstBurstLength < SPDK_ISCSI_MAX_FIRST_BURST_LENGTH &&
1045 : : FirstBurstLength > MaxBurstLength) {
1046 : 16 : FirstBurstLength = MaxBurstLength;
1047 : 16 : 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 [ + + ]: 8686 : if (iscsi_find_key_in_array(param->key, target_declarative_params)) {
1054 : 2 : add_param_value = 1;
1055 : : }
1056 : :
1057 : 8686 : 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 [ + + ]: 8698 : if (new_val != NULL) {
1066 : : /* add_param_value = 0 means updating the value of
1067 : : * existed key in the connection's parameters
1068 : : */
1069 [ + + ]: 8682 : if (add_param_value == 0) {
1070 : 8622 : iscsi_param_set(params_dst, param->key, new_val);
1071 : : }
1072 : 8682 : total = iscsi_construct_data_from_param(param,
1073 : : new_val,
1074 : : data,
1075 : : alloc_len,
1076 : : total);
1077 [ - + ]: 8682 : if (total < 0) {
1078 : 0 : goto final_return;
1079 : : }
1080 : :
1081 : 8682 : total = iscsi_special_param_construction(conn,
1082 : : param,
1083 : : FirstBurstLength_flag,
1084 : : data,
1085 : : alloc_len,
1086 : : total);
1087 [ - + ]: 8682 : if (total < 0) {
1088 : 0 : goto final_return;
1089 : : }
1090 : : } else {
1091 : 16 : total = -1;
1092 : 16 : break;
1093 : : }
1094 : : }
1095 : :
1096 : 1674 : final_return:
1097 : 1690 : free(valid_list);
1098 : 1690 : free(in_val);
1099 : 1690 : free(cur_val);
1100 : :
1101 : 1690 : return total;
1102 : : }
1103 : :
1104 : : int
1105 : 4541 : iscsi_copy_param2var(struct spdk_iscsi_conn *conn)
1106 : : {
1107 : : const char *val;
1108 : :
1109 : 4541 : val = iscsi_param_get_val(conn->params, "MaxRecvDataSegmentLength");
1110 [ - + ]: 4541 : if (val == NULL) {
1111 : 0 : SPDK_ERRLOG("Getval MaxRecvDataSegmentLength failed\n");
1112 : 0 : return -1;
1113 : : }
1114 [ - + - + ]: 4541 : SPDK_DEBUGLOG(iscsi,
1115 : : "copy MaxRecvDataSegmentLength=%s\n", val);
1116 [ - + ]: 4541 : conn->MaxRecvDataSegmentLength = (int)strtol(val, NULL, 10);
1117 [ + + ]: 4541 : if (conn->MaxRecvDataSegmentLength > SPDK_BDEV_LARGE_BUF_MAX_SIZE) {
1118 : 4113 : conn->MaxRecvDataSegmentLength = SPDK_BDEV_LARGE_BUF_MAX_SIZE;
1119 : : }
1120 : :
1121 : 4541 : val = iscsi_param_get_val(conn->params, "HeaderDigest");
1122 [ - + ]: 4541 : if (val == NULL) {
1123 : 0 : SPDK_ERRLOG("Getval HeaderDigest failed\n");
1124 : 0 : return -1;
1125 : : }
1126 [ - + + + ]: 4541 : if (strcasecmp(val, "CRC32C") == 0) {
1127 [ - + - + ]: 8 : SPDK_DEBUGLOG(iscsi, "set HeaderDigest=1\n");
1128 : 8 : conn->header_digest = 1;
1129 : : } else {
1130 [ - + - + ]: 4533 : SPDK_DEBUGLOG(iscsi, "set HeaderDigest=0\n");
1131 : 4533 : conn->header_digest = 0;
1132 : : }
1133 : 4541 : val = iscsi_param_get_val(conn->params, "DataDigest");
1134 [ - + ]: 4541 : if (val == NULL) {
1135 : 0 : SPDK_ERRLOG("Getval DataDigest failed\n");
1136 : 0 : return -1;
1137 : : }
1138 [ - + - + ]: 4541 : if (strcasecmp(val, "CRC32C") == 0) {
1139 [ # # # # ]: 0 : SPDK_DEBUGLOG(iscsi, "set DataDigest=1\n");
1140 : 0 : conn->data_digest = 1;
1141 : : } else {
1142 [ - + - + ]: 4541 : SPDK_DEBUGLOG(iscsi, "set DataDigest=0\n");
1143 : 4541 : conn->data_digest = 0;
1144 : : }
1145 : :
1146 : 4541 : val = iscsi_param_get_val(conn->sess->params, "MaxConnections");
1147 [ - + ]: 4541 : if (val == NULL) {
1148 : 0 : SPDK_ERRLOG("Getval MaxConnections failed\n");
1149 : 0 : return -1;
1150 : : }
1151 [ - + - + ]: 4541 : SPDK_DEBUGLOG(iscsi, "copy MaxConnections=%s\n", val);
1152 [ - + ]: 4541 : conn->sess->MaxConnections = (uint32_t) strtol(val, NULL, 10);
1153 : 4541 : val = iscsi_param_get_val(conn->sess->params, "MaxOutstandingR2T");
1154 [ - + ]: 4541 : if (val == NULL) {
1155 : 0 : SPDK_ERRLOG("Getval MaxOutstandingR2T failed\n");
1156 : 0 : return -1;
1157 : : }
1158 [ - + - + ]: 4541 : SPDK_DEBUGLOG(iscsi, "copy MaxOutstandingR2T=%s\n", val);
1159 [ - + ]: 4541 : conn->sess->MaxOutstandingR2T = (uint32_t) strtol(val, NULL, 10);
1160 : 4541 : val = iscsi_param_get_val(conn->sess->params, "FirstBurstLength");
1161 [ - + ]: 4541 : if (val == NULL) {
1162 : 0 : SPDK_ERRLOG("Getval FirstBurstLength failed\n");
1163 : 0 : return -1;
1164 : : }
1165 [ - + - + ]: 4541 : SPDK_DEBUGLOG(iscsi, "copy FirstBurstLength=%s\n", val);
1166 [ - + ]: 4541 : conn->sess->FirstBurstLength = (uint32_t) strtol(val, NULL, 10);
1167 : 4541 : val = iscsi_param_get_val(conn->sess->params, "MaxBurstLength");
1168 [ - + ]: 4541 : if (val == NULL) {
1169 : 0 : SPDK_ERRLOG("Getval MaxBurstLength failed\n");
1170 : 0 : return -1;
1171 : : }
1172 [ - + - + ]: 4541 : SPDK_DEBUGLOG(iscsi, "copy MaxBurstLength=%s\n", val);
1173 [ - + ]: 4541 : conn->sess->MaxBurstLength = (uint32_t) strtol(val, NULL, 10);
1174 : 4541 : val = iscsi_param_get_val(conn->sess->params, "InitialR2T");
1175 [ - + ]: 4541 : if (val == NULL) {
1176 : 0 : SPDK_ERRLOG("Getval InitialR2T failed\n");
1177 : 0 : return -1;
1178 : : }
1179 [ + + + - ]: 4541 : if (strcasecmp(val, "Yes") == 0) {
1180 [ - + - + ]: 4541 : SPDK_DEBUGLOG(iscsi, "set InitialR2T=1\n");
1181 : 4541 : conn->sess->InitialR2T = true;
1182 : : } else {
1183 [ # # # # ]: 0 : SPDK_DEBUGLOG(iscsi, "set InitialR2T=0\n");
1184 : 0 : conn->sess->InitialR2T = false;
1185 : : }
1186 : 4541 : val = iscsi_param_get_val(conn->sess->params, "ImmediateData");
1187 [ - + ]: 4541 : if (val == NULL) {
1188 : 0 : SPDK_ERRLOG("Getval ImmediateData failed\n");
1189 : 0 : return -1;
1190 : : }
1191 [ + + + + ]: 4541 : if (strcasecmp(val, "Yes") == 0) {
1192 [ - + - + ]: 4461 : SPDK_DEBUGLOG(iscsi, "set ImmediateData=1\n");
1193 : 4461 : conn->sess->ImmediateData = true;
1194 : : } else {
1195 [ - + - + ]: 80 : SPDK_DEBUGLOG(iscsi, "set ImmediateData=0\n");
1196 : 80 : conn->sess->ImmediateData = false;
1197 : : }
1198 : 4541 : return 0;
1199 : : }
|