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