1b6364952Sagc /*
2b6364952Sagc * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
3b6364952Sagc * By downloading, copying, installing or using the software you agree
4b6364952Sagc * to this license. If you do not agree to this license, do not
5b6364952Sagc * download, install, copy or use the software.
6b6364952Sagc *
7b6364952Sagc * Intel License Agreement
8b6364952Sagc *
9b6364952Sagc * Copyright (c) 2000, Intel Corporation
10b6364952Sagc * All rights reserved.
11b6364952Sagc *
12b6364952Sagc * Redistribution and use in source and binary forms, with or without
13b6364952Sagc * modification, are permitted provided that the following conditions
14b6364952Sagc * are met:
15b6364952Sagc *
16b6364952Sagc * -Redistributions of source code must retain the above copyright
17b6364952Sagc * notice, this list of conditions and the following disclaimer.
18b6364952Sagc *
19b6364952Sagc * -Redistributions in binary form must reproduce the above copyright
20b6364952Sagc * notice, this list of conditions and the following disclaimer in the
21b6364952Sagc * documentation and/or other materials provided with the
22b6364952Sagc * distribution.
23b6364952Sagc *
24b6364952Sagc * -The name of Intel Corporation may not be used to endorse or
25b6364952Sagc * promote products derived from this software without specific prior
26b6364952Sagc * written permission.
27b6364952Sagc *
28b6364952Sagc * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29b6364952Sagc * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30b6364952Sagc * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31b6364952Sagc * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL
32b6364952Sagc * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33b6364952Sagc * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34b6364952Sagc * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
35b6364952Sagc * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
36b6364952Sagc * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
37b6364952Sagc * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
38b6364952Sagc * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39b6364952Sagc * SUCH DAMAGE.
40b6364952Sagc */
41b6364952Sagc #include "config.h"
42b6364952Sagc #include "compat.h"
43b6364952Sagc
44b6364952Sagc #ifdef HAVE_CTYPE_H
45b6364952Sagc #include <ctype.h>
46b6364952Sagc #endif
47b6364952Sagc
48b6364952Sagc #include <stdio.h>
49b6364952Sagc #include <stdlib.h>
50b6364952Sagc
51b6364952Sagc #ifdef HAVE_STRING_H
52b6364952Sagc #include <string.h>
53b6364952Sagc #endif
54b6364952Sagc
55b6364952Sagc #ifdef HAVE_NETINET_IN_H
56b6364952Sagc #include <netinet/in.h>
57b6364952Sagc #endif
58b6364952Sagc
59b6364952Sagc #include "iscsi-md5.h"
60b6364952Sagc #include "iscsiutil.h"
61b6364952Sagc #include "parameters.h"
62b6364952Sagc #include "conffile.h"
63b6364952Sagc
64b6364952Sagc
65b6364952Sagc int
param_list_add(iscsi_parameter_t ** head,int type,const char * key,const char * dflt,const char * valid)66b6364952Sagc param_list_add(iscsi_parameter_t ** head, int type, const char *key, const char *dflt, const char *valid)
67b6364952Sagc {
68b6364952Sagc iscsi_parameter_t *param;
69b6364952Sagc
70b6364952Sagc /* Allocated new parameter type */
71b6364952Sagc
72b6364952Sagc if (*head == NULL) {
73b6364952Sagc if ((*head = iscsi_malloc_atomic(sizeof(iscsi_parameter_t))) == NULL) {
745e01dafbSagc iscsi_err(__FILE__, __LINE__, "out of memory\n");
75b6364952Sagc return -1;
76b6364952Sagc }
77b6364952Sagc param = *head;
78b6364952Sagc } else {
79b6364952Sagc for (param = *head; param->next != NULL; param = param->next) {
80b6364952Sagc }
81b6364952Sagc if ((param->next = iscsi_malloc_atomic(sizeof(iscsi_parameter_t))) == NULL) {
825e01dafbSagc iscsi_err(__FILE__, __LINE__, "out of memory\n");
83b6364952Sagc return -1;
84b6364952Sagc }
85b6364952Sagc param = param->next;
86b6364952Sagc }
87b6364952Sagc
88b6364952Sagc /* Initilized parameter */
89b6364952Sagc
90b6364952Sagc param->type = type; /* type */
91b6364952Sagc (void) strlcpy(param->key, key, sizeof(param->key));/* key */
92b6364952Sagc (void) strlcpy(param->dflt, dflt, sizeof(param->dflt)); /* default value */
93b6364952Sagc (void) strlcpy(param->valid, valid, sizeof(param->valid)); /* list of valid values */
94b6364952Sagc param->tx_offer = 0; /* sent offer */
95b6364952Sagc param->rx_offer = 0; /* received offer */
96b6364952Sagc param->tx_answer = 0; /* sent answer */
97b6364952Sagc param->rx_answer = 0; /* received answer */
98b6364952Sagc param->reset = 0; /* used to erase value_l on next parse */
99b6364952Sagc param->next = NULL; /* terminate list */
100b6364952Sagc
101b6364952Sagc /* Allocated space for value list and set first item to default; and */
102b6364952Sagc /* set offer and answer lists to NULL */
103b6364952Sagc
104b6364952Sagc if ((param->value_l = iscsi_malloc_atomic(sizeof(iscsi_parameter_value_t))) == NULL) {
1055e01dafbSagc iscsi_err(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
106b6364952Sagc return -1;
107b6364952Sagc }
108b6364952Sagc param->value_l->next = NULL;
109b6364952Sagc (void) strlcpy(param->value_l->value, dflt, sizeof(param->value_l->value));
110b6364952Sagc
111b6364952Sagc /* Arg check */
112b6364952Sagc
113b6364952Sagc switch (type) {
114b6364952Sagc case ISCSI_PARAM_TYPE_DECLARATIVE:
115b6364952Sagc break;
116b6364952Sagc case ISCSI_PARAM_TYPE_DECLARE_MULTI:
117b6364952Sagc break;
118b6364952Sagc case ISCSI_PARAM_TYPE_BINARY_OR:
119b6364952Sagc if (strcmp(valid, "Yes,No") != 0 &&
120b6364952Sagc strcmp(valid, "No,Yes") != 0 &&
121b6364952Sagc strcmp(valid, "No") != 0 &&
122b6364952Sagc strcmp(valid, "Yes") != 0 &&
123b6364952Sagc strcmp(valid, "yes,no") != 0 &&
124b6364952Sagc strcmp(valid, "no,yes") != 0 &&
125b6364952Sagc strcmp(valid, "no") != 0 &&
126b6364952Sagc strcmp(valid, "yes") != 0) {
1275e01dafbSagc iscsi_err(__FILE__, __LINE__, "bad <valid> field \"%s\" for ISCSI_PARAM_TYPE_BINARY\n", valid);
128b6364952Sagc return -1;
129b6364952Sagc }
130b6364952Sagc break;
131b6364952Sagc case ISCSI_PARAM_TYPE_BINARY_AND:
132b6364952Sagc if (strcmp(valid, "Yes,No") != 0 &&
133b6364952Sagc strcmp(valid, "No,Yes") != 0 &&
134b6364952Sagc strcmp(valid, "No") != 0 &&
135b6364952Sagc strcmp(valid, "Yes") != 0 &&
136b6364952Sagc strcmp(valid, "yes,no") != 0 &&
137b6364952Sagc strcmp(valid, "no,yes") != 0 &&
138b6364952Sagc strcmp(valid, "no") != 0 &&
139b6364952Sagc strcmp(valid, "yes") != 0) {
1405e01dafbSagc iscsi_err(__FILE__, __LINE__, "bad <valid> field \"%s\" for ISCSI_PARAM_TYPE_BINARY\n", valid);
141b6364952Sagc return -1;
142b6364952Sagc }
143b6364952Sagc break;
144b6364952Sagc case ISCSI_PARAM_TYPE_NUMERICAL:
145b6364952Sagc break;
146b6364952Sagc case ISCSI_PARAM_TYPE_NUMERICAL_Z:
147b6364952Sagc break;
148b6364952Sagc case ISCSI_PARAM_TYPE_LIST:
149b6364952Sagc break;
150b6364952Sagc default:
1515e01dafbSagc iscsi_err(__FILE__, __LINE__, "unknown parameter type %d\n", type);
152b6364952Sagc return -1;
153b6364952Sagc }
154b6364952Sagc
1555e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "\"%s\": valid \"%s\", default \"%s\", current \"%s\"\n",
156b6364952Sagc param->key, param->valid, param->dflt, param->value_l->value);
157b6364952Sagc return 0;
158b6364952Sagc }
159b6364952Sagc
160b6364952Sagc int
param_list_destroy(iscsi_parameter_t * head)161b6364952Sagc param_list_destroy(iscsi_parameter_t * head)
162b6364952Sagc {
163b6364952Sagc iscsi_parameter_t *ptr, *tmp;
164b6364952Sagc iscsi_parameter_value_t *item_ptr, *next;
165b6364952Sagc
166b6364952Sagc for (ptr = head; ptr != NULL;) {
167b6364952Sagc tmp = ptr;
168b6364952Sagc ptr = ptr->next;
169b6364952Sagc if (tmp->value_l) {
170b6364952Sagc for (item_ptr = tmp->value_l; item_ptr != NULL; item_ptr = next) {
171b6364952Sagc next = item_ptr->next;
172b6364952Sagc /*
1735e01dafbSagc * iscsi_trace(TRACE_ISCSI_PARAM, "freeing \"%s\"
174b6364952Sagc * (%p)\n", item_ptr->value, item_ptr);
175b6364952Sagc */
176b6364952Sagc iscsi_free_atomic(item_ptr);
177b6364952Sagc }
178b6364952Sagc }
1795e01dafbSagc /* iscsi_trace(TRACE_ISCSI_PARAM, "freeing %p\n", tmp); */
180b6364952Sagc iscsi_free_atomic(tmp);
181b6364952Sagc }
182b6364952Sagc return 0;
183b6364952Sagc }
184b6364952Sagc
185b6364952Sagc
186b6364952Sagc iscsi_parameter_t *
param_get(iscsi_parameter_t * head,const char * key)187b6364952Sagc param_get(iscsi_parameter_t * head, const char *key)
188b6364952Sagc {
189b6364952Sagc iscsi_parameter_t *ptr;
190b6364952Sagc
191b6364952Sagc for (ptr = head; ptr != NULL; ptr = ptr->next) {
192b6364952Sagc if (strcmp(ptr->key, key) == 0) {
193b6364952Sagc return ptr;
194b6364952Sagc }
195b6364952Sagc }
1965e01dafbSagc iscsi_err(__FILE__, __LINE__, "key \"%s\" not found in param list\n", key);
197b6364952Sagc return NULL;
198b6364952Sagc }
199b6364952Sagc
200b6364952Sagc char *
param_val(iscsi_parameter_t * head,const char * key)201b6364952Sagc param_val(iscsi_parameter_t * head, const char *key)
202b6364952Sagc {
203b6364952Sagc return param_val_which(head, key, 0);
204b6364952Sagc }
205b6364952Sagc
206b6364952Sagc char *
param_val_which(iscsi_parameter_t * head,const char * key,int which)207b6364952Sagc param_val_which(iscsi_parameter_t * head, const char *key, int which)
208b6364952Sagc {
209b6364952Sagc iscsi_parameter_t *ptr;
210b6364952Sagc iscsi_parameter_value_t *item_ptr;
211b6364952Sagc int i = 0;
212b6364952Sagc
213b6364952Sagc for (ptr = head; ptr != NULL; ptr = ptr->next) {
214b6364952Sagc if (strcmp(ptr->key, key) == 0) {
215b6364952Sagc item_ptr = ptr->value_l;
216b6364952Sagc for (i = 0; i != which; i++) {
217b6364952Sagc if (item_ptr == NULL) {
2185e01dafbSagc iscsi_err(__FILE__, __LINE__, "item %d in value list is NULL\n", i);
219b6364952Sagc return NULL;
220b6364952Sagc }
221b6364952Sagc item_ptr = item_ptr->next;
222b6364952Sagc }
223b6364952Sagc if (item_ptr == NULL) {
2245e01dafbSagc iscsi_err(__FILE__, __LINE__, "item %d in value list is NULL\n", which);
225b6364952Sagc return NULL;
226b6364952Sagc }
227b6364952Sagc return item_ptr->value;
228b6364952Sagc }
229b6364952Sagc }
2305e01dafbSagc iscsi_err(__FILE__, __LINE__, "key \"%s\" not found in param list\n", key);
231b6364952Sagc return NULL;
232b6364952Sagc }
233b6364952Sagc
234b6364952Sagc static int
param_val_delete_all(iscsi_parameter_t * head,char * key)235b6364952Sagc param_val_delete_all(iscsi_parameter_t * head, char *key)
236b6364952Sagc {
237b6364952Sagc iscsi_parameter_t *ptr;
238b6364952Sagc iscsi_parameter_value_t *item_ptr, *next;
239b6364952Sagc
240b6364952Sagc for (ptr = head; ptr != NULL; ptr = ptr->next) {
241b6364952Sagc if (strcmp(ptr->key, key) == 0) {
242b6364952Sagc for (item_ptr = ptr->value_l; item_ptr != NULL; item_ptr = next) {
243b6364952Sagc next = item_ptr->next;
244b6364952Sagc iscsi_free_atomic(item_ptr);
245b6364952Sagc }
246b6364952Sagc ptr->value_l = NULL;
247b6364952Sagc return 0;
248b6364952Sagc }
249b6364952Sagc }
2505e01dafbSagc iscsi_err(__FILE__, __LINE__, "key \"%s\" not found in param list\n", key);
251b6364952Sagc return -1;
252b6364952Sagc }
253b6364952Sagc
254b6364952Sagc int
param_val_reset(iscsi_parameter_t * head,const char * key)255b6364952Sagc param_val_reset(iscsi_parameter_t * head, const char *key)
256b6364952Sagc {
257b6364952Sagc iscsi_parameter_t *ptr;
258b6364952Sagc
259b6364952Sagc for (ptr = head; ptr != NULL; ptr = ptr->next) {
260b6364952Sagc if (strcmp(ptr->key, key) == 0) {
261b6364952Sagc ptr->reset = 1;
262b6364952Sagc return 0;
263b6364952Sagc }
264b6364952Sagc }
2655e01dafbSagc iscsi_err(__FILE__, __LINE__, "key \"%s\" not found in param list\n", key);
266b6364952Sagc return -1;
267b6364952Sagc }
268b6364952Sagc
269b6364952Sagc int
param_atoi(iscsi_parameter_t * head,const char * key)270b6364952Sagc param_atoi(iscsi_parameter_t * head, const char *key)
271b6364952Sagc {
272b6364952Sagc iscsi_parameter_t *ptr;
273b6364952Sagc char *value;
274b6364952Sagc
275b6364952Sagc for (ptr = head; ptr != NULL; ptr = ptr->next) {
276b6364952Sagc if (strcmp(ptr->key, key) == 0) {
277b6364952Sagc if (ptr->value_l) {
278b6364952Sagc if ((value = param_val(head, key)) != NULL) {
279b6364952Sagc return iscsi_atoi(value);
280b6364952Sagc } else {
2815e01dafbSagc iscsi_err(__FILE__, __LINE__, "value is NULL\n");
282b6364952Sagc return 0;
283b6364952Sagc }
284b6364952Sagc } else {
2855e01dafbSagc iscsi_err(__FILE__, __LINE__, "param \"%s\" has NULL value list\n", key);
286b6364952Sagc return 0;
287b6364952Sagc }
288b6364952Sagc }
289b6364952Sagc }
2905e01dafbSagc iscsi_err(__FILE__, __LINE__, "key \"%s\" not found in param list\n", key);
291b6364952Sagc return 0;
292b6364952Sagc }
293b6364952Sagc
294b6364952Sagc int
param_equiv(iscsi_parameter_t * head,const char * key,const char * val)295b6364952Sagc param_equiv(iscsi_parameter_t * head, const char *key, const char *val)
296b6364952Sagc {
297b6364952Sagc iscsi_parameter_t *ptr;
298b6364952Sagc char *value;
299b6364952Sagc
300b6364952Sagc for (ptr = head; ptr != NULL; ptr = ptr->next) {
301b6364952Sagc if (strcmp(ptr->key, key) == 0) {
302b6364952Sagc if (ptr->value_l == NULL) {
3035e01dafbSagc iscsi_err(__FILE__, __LINE__, "param \"%s\" has NULL value list\n", key);
304b6364952Sagc return 0;
305b6364952Sagc }
306b6364952Sagc if ((value = param_val(head, key)) == NULL) {
3075e01dafbSagc iscsi_err(__FILE__, __LINE__, "key \"%s\" value is NULL\n", key);
308b6364952Sagc return 0;
309b6364952Sagc }
310b6364952Sagc return (strcmp(value, val) == 0);
311b6364952Sagc }
312b6364952Sagc }
3135e01dafbSagc iscsi_err(__FILE__, __LINE__, "key \"%s\" not found in param list\n", key);
314b6364952Sagc return -1;
315b6364952Sagc }
316b6364952Sagc
317b6364952Sagc int
param_num_vals(iscsi_parameter_t * head,char * key)318b6364952Sagc param_num_vals(iscsi_parameter_t * head, char *key)
319b6364952Sagc {
320b6364952Sagc iscsi_parameter_t *ptr;
321b6364952Sagc iscsi_parameter_value_t *item_ptr;
322b6364952Sagc int num = 0;
323b6364952Sagc
324b6364952Sagc for (ptr = head; ptr != NULL; ptr = ptr->next) {
325b6364952Sagc if (strcmp(ptr->key, key) == 0) {
326b6364952Sagc for (item_ptr = ptr->value_l; item_ptr != NULL; item_ptr = item_ptr->next) {
327b6364952Sagc num++;
328b6364952Sagc }
329b6364952Sagc return num;
330b6364952Sagc }
331b6364952Sagc }
3325e01dafbSagc iscsi_err(__FILE__, __LINE__, "key \"%s\" not found in param list\n", key);
333b6364952Sagc return -1;
334b6364952Sagc }
335b6364952Sagc
336b6364952Sagc int
param_list_print(iscsi_parameter_t * head)337b6364952Sagc param_list_print(iscsi_parameter_t * head)
338b6364952Sagc {
339b6364952Sagc iscsi_parameter_t *ptr;
340b6364952Sagc iscsi_parameter_value_t *item_ptr;
341b6364952Sagc
342b6364952Sagc for (ptr = head; ptr != NULL; ptr = ptr->next) {
343b6364952Sagc for (item_ptr = ptr->value_l; item_ptr != NULL; item_ptr = item_ptr->next) {
344b6364952Sagc printf("\"%s\"=\"%s\"\n", ptr->key, item_ptr->value);
345b6364952Sagc }
346b6364952Sagc }
347b6364952Sagc return 0;
348b6364952Sagc }
349b6364952Sagc
350b6364952Sagc int
param_text_print(char * text,uint32_t text_len)351b6364952Sagc param_text_print(char *text, uint32_t text_len)
352b6364952Sagc {
353b6364952Sagc char key[256];
354b6364952Sagc char *ptr, *eq, *value;
355b6364952Sagc
356b6364952Sagc for (ptr = text; (uint32_t)(ptr - text) < text_len; ptr += (strlen(ptr) + 1)) {
357b6364952Sagc
358b6364952Sagc /* Skip over any NULLs */
359b6364952Sagc
360b6364952Sagc while (!(*ptr) && ((uint32_t)(ptr - text) < text_len))
361b6364952Sagc ptr++;
362b6364952Sagc if ((uint32_t)(ptr - text) >= text_len)
363b6364952Sagc break;
364b6364952Sagc
365b6364952Sagc if ((eq = strchr(ptr, '=')) == NULL) {
3665e01dafbSagc iscsi_err(__FILE__, __LINE__, "delimiter \'=\' not found in token \"%s\"\n", ptr);
367b6364952Sagc return -1;
368b6364952Sagc }
369b6364952Sagc strncpy(key, ptr, (unsigned)(eq - ptr));
370b6364952Sagc key[(int)(eq - ptr)] = 0x0;
371b6364952Sagc value = eq + 1;
372b6364952Sagc printf("\"%s\"=\"%s\"\n", key, value);
373b6364952Sagc }
374b6364952Sagc return 0;
375b6364952Sagc }
376b6364952Sagc
377b6364952Sagc /* ARGSUSED */
378b6364952Sagc int
param_text_add(iscsi_parameter_t * head,const char * key,const char * value,char * text,int * len,int size,int offer)379b6364952Sagc param_text_add(iscsi_parameter_t * head, const char *key, const char *value, char *text, int *len, int size, int offer)
380b6364952Sagc {
381b6364952Sagc int cc;
382b6364952Sagc
383b6364952Sagc cc = snprintf(text + *len, (unsigned)(size - *len), "%s=%s", key, value);
384b6364952Sagc *len += cc + 1;
385b6364952Sagc return 0;
386b6364952Sagc }
387b6364952Sagc
388b6364952Sagc int
driver_atoi(const char * s)389b6364952Sagc driver_atoi(const char *s)
390b6364952Sagc {
391b6364952Sagc int k = 0;
392b6364952Sagc
393b6364952Sagc while (*s != 0x0 && *s >= '0' && *s <= '9') {
394b6364952Sagc k = 10 * k + (*s - '0');
395b6364952Sagc s++;
396b6364952Sagc }
397b6364952Sagc return k;
398b6364952Sagc }
399b6364952Sagc
400b6364952Sagc /* find the credentials for `user' and put them in `cred' */
401b6364952Sagc static int
find_credentials(iscsi_cred_t * cred,char * user,const char * auth)402b6364952Sagc find_credentials(iscsi_cred_t *cred, char *user, const char *auth)
403b6364952Sagc {
404b6364952Sagc conffile_t conf;
405b6364952Sagc const char *authtype;
406b6364952Sagc unsigned cc;
407b6364952Sagc ent_t e;
408b6364952Sagc
409b6364952Sagc (void) memset(&conf, 0x0, sizeof(conf));
410b6364952Sagc (void) memset(&e, 0x0, sizeof(e));
411b6364952Sagc
412b6364952Sagc if (!conffile_open(&conf, _PATH_ISCSI_PASSWD, "r", ":", "#")) {
4135e01dafbSagc iscsi_err(__FILE__, __LINE__, "can't open `%s'\n", _PATH_ISCSI_PASSWD);
414b6364952Sagc exit(EXIT_FAILURE);
415b6364952Sagc }
416b6364952Sagc while (conffile_getent(&conf, &e)) {
417b6364952Sagc if (strcasecmp(e.sv.v[0], user) == 0) {
418b6364952Sagc authtype = (e.sv.c == 1) ? "none" : e.sv.v[1];
419b6364952Sagc cc = strlen(authtype);
420b6364952Sagc if (auth == NULL || (strncasecmp(authtype, auth, cc) == 0 && cc == strlen(auth))) {
421b6364952Sagc cred->user = strdup(e.sv.v[0]);
422b6364952Sagc cred->auth_type = strdup(authtype);
423b6364952Sagc cred->shared_secret = (e.sv.c == 3) ? strdup(e.sv.v[2]) : NULL;
424b6364952Sagc conffile_close(&conf);
425b6364952Sagc return 1;
426b6364952Sagc }
427b6364952Sagc }
428b6364952Sagc }
429b6364952Sagc conffile_close(&conf);
430b6364952Sagc (void) fprintf(stderr, "No matching user configuration entry for `%s' was found\n", user);
431b6364952Sagc (void) fprintf(stderr, "Please add an entry for `%s' to `%s'\n", user, _PATH_ISCSI_PASSWD);
432b6364952Sagc return 0;
433b6364952Sagc }
434b6364952Sagc
435b6364952Sagc #if 0
436b6364952Sagc /* free any storage allocated in `cred' */
437b6364952Sagc static void
438b6364952Sagc free_cred(iscsi_cred_t *cred)
439b6364952Sagc {
440b6364952Sagc if (cred) {
441b6364952Sagc if (cred->user) {
442b6364952Sagc iscsi_free_atomic(cred->user);
443b6364952Sagc }
444b6364952Sagc if (cred->auth_type) {
445b6364952Sagc iscsi_free_atomic(cred->auth_type);
446b6364952Sagc }
447b6364952Sagc if (cred->shared_secret) {
448b6364952Sagc iscsi_free_atomic(cred->shared_secret);
449b6364952Sagc }
450b6364952Sagc }
451b6364952Sagc }
452b6364952Sagc #endif
453b6364952Sagc
454b6364952Sagc /* Security offering and check */
455b6364952Sagc /*
456b6364952Sagc * ret values: =0: succeed or no security >0: security negotiation in process
457b6364952Sagc * <0: failed
458b6364952Sagc */
459b6364952Sagc static int
param_parse_security(iscsi_parameter_t * head,iscsi_parameter_t * param_in,iscsi_cred_t * cred,char * text_out,int * text_len_out,int textsize)460b6364952Sagc param_parse_security(iscsi_parameter_t * head,
461b6364952Sagc iscsi_parameter_t * param_in,
462b6364952Sagc iscsi_cred_t *cred,
463b6364952Sagc char *text_out, int *text_len_out, int textsize)
464b6364952Sagc {
465b6364952Sagc
466b6364952Sagc static uint8_t idData;
467b6364952Sagc static uint8_t chapdata[ISCSI_CHAP_DATA_LENGTH];
468b6364952Sagc static uint8_t respdata[ISCSI_CHAP_DATA_LENGTH];
469b6364952Sagc char *chapstring = NULL;
470b6364952Sagc iSCSI_MD5_CTX *context = NULL;
471b6364952Sagc iscsi_parameter_t *param = NULL;
472b6364952Sagc int ret = 1;
473b6364952Sagc
474b6364952Sagc if ((chapstring = iscsi_malloc(ISCSI_CHAP_STRING_LENGTH)) == NULL) {
4755e01dafbSagc iscsi_err(__FILE__, __LINE__, "iscsi_malloc() failed\n");
476b6364952Sagc return -1;
477b6364952Sagc }
478b6364952Sagc if ((context = iscsi_malloc(sizeof(*context))) == NULL) {
4795e01dafbSagc iscsi_err(__FILE__, __LINE__, "iscsi_malloc() failed\n");
480b6364952Sagc if (chapstring != NULL)
481b6364952Sagc iscsi_free(chapstring);
482b6364952Sagc return -1;
483b6364952Sagc }
484b6364952Sagc #define PPS_CLEANUP { if (chapstring != NULL) iscsi_free(chapstring);if (context != NULL) iscsi_free(context); }
485b6364952Sagc #define PPS_ERROR { PPS_CLEANUP; return (-1); };
486b6364952Sagc
487b6364952Sagc if (strcmp(param_in->key, "AuthMethod") == 0) {
488b6364952Sagc if (param_in->rx_answer && strcmp(param_in->answer_rx, "None") == 0) {
489b6364952Sagc PPS_CLEANUP;
490b6364952Sagc return 0; /* Proposed None for
491b6364952Sagc * Authentication */
492b6364952Sagc }
493b6364952Sagc if (param_in->rx_offer && strcmp(param_in->offer_rx, "None") == 0) {
494b6364952Sagc PPS_CLEANUP;
495b6364952Sagc return 0;
496b6364952Sagc }
497b6364952Sagc if (!param_in->rx_offer) {
498b6364952Sagc param = param_get(head, "CHAP_A");
499b6364952Sagc if (param == NULL)
500b6364952Sagc PPS_ERROR;
501b6364952Sagc param->tx_offer = 1; /* sending an offer */
502b6364952Sagc param->rx_offer = 0; /* reset */
503b6364952Sagc (void) strlcpy(param->offer_tx, param->valid, sizeof(param->offer_tx));
504b6364952Sagc PARAM_TEXT_ADD(head, param->key, param->valid,
505b6364952Sagc text_out, text_len_out, textsize, 0, PPS_ERROR);
506b6364952Sagc ret++;
507b6364952Sagc }
508b6364952Sagc } else if (strcmp(param_in->key, "CHAP_A") == 0) {
509b6364952Sagc if (param_in->rx_offer) {
510b6364952Sagc PARAM_TEXT_ADD(head, param_in->key, param_in->offer_rx,
511b6364952Sagc text_out, text_len_out, textsize, 0, PPS_ERROR);
512b6364952Sagc
513b6364952Sagc if ((param = param_get(head, "CHAP_I")) == NULL) {
514b6364952Sagc PPS_ERROR;
515b6364952Sagc }
516b6364952Sagc param->tx_offer = 1; /* sending an offer */
517b6364952Sagc param->rx_offer = 0; /* reset */
518b6364952Sagc GenRandomData(&idData, 1);
519b6364952Sagc (void) snprintf(chapstring, ISCSI_CHAP_STRING_LENGTH, "%d", idData);
520b6364952Sagc (void) strlcpy(param->offer_tx, chapstring, sizeof(param->offer_tx));
521b6364952Sagc PARAM_TEXT_ADD(head, param->key, param->offer_tx,
522b6364952Sagc text_out, text_len_out, textsize, 0, PPS_ERROR);
523b6364952Sagc
524b6364952Sagc if ((param = param_get(head, "CHAP_C")) == NULL) {
525b6364952Sagc PPS_ERROR;
526b6364952Sagc }
527b6364952Sagc param->tx_offer = 1; /* sending an offer */
528b6364952Sagc param->rx_offer = 0; /* reset */
529b6364952Sagc GenRandomData(chapdata, ISCSI_CHAP_DATA_LENGTH);
530b6364952Sagc HexDataToText(chapdata, ISCSI_CHAP_DATA_LENGTH,
531b6364952Sagc chapstring, ISCSI_CHAP_STRING_LENGTH);
532b6364952Sagc (void) strlcpy(param->offer_tx, chapstring, sizeof(param->offer_tx));
533b6364952Sagc PARAM_TEXT_ADD(head, param->key, param->offer_tx,
534b6364952Sagc text_out, text_len_out, textsize, 0, PPS_ERROR);
535b6364952Sagc ret++;
536b6364952Sagc }
537b6364952Sagc } else if (strcmp(param_in->key, "CHAP_I") == 0) {
538b6364952Sagc
539b6364952Sagc idData = driver_atoi((param_in->rx_offer) ? param_in->offer_rx : param_in->answer_rx);
540b6364952Sagc ret++;
541b6364952Sagc
542b6364952Sagc } else if (strcmp(param_in->key, "CHAP_C") == 0) {
543b6364952Sagc
544b6364952Sagc HexTextToData((param_in->rx_offer) ? param_in->offer_rx : param_in->answer_rx, ISCSI_CHAP_STRING_LENGTH,
545b6364952Sagc chapdata, ISCSI_CHAP_DATA_LENGTH);
546b6364952Sagc
547b6364952Sagc if ((param = param_get(head, "CHAP_N")) == NULL) {
548b6364952Sagc PPS_ERROR;
549b6364952Sagc }
550b6364952Sagc param->tx_offer = 1; /* sending an offer */
551b6364952Sagc param->rx_offer = 0; /* reset */
552b6364952Sagc
553b6364952Sagc if (cred->shared_secret == NULL && !find_credentials(cred, cred->user, "chap")) {
5545e01dafbSagc iscsi_err(__FILE__, __LINE__, "Unknown user `%s'\n", param_in->offer_rx);
555b6364952Sagc PPS_ERROR;
556b6364952Sagc }
557b6364952Sagc
558b6364952Sagc if (cred->user) {
559b6364952Sagc (void) strlcpy(param->offer_tx, cred->user, sizeof(param->offer_tx));
560b6364952Sagc } else {
5615e01dafbSagc iscsi_err(__FILE__, __LINE__, "no valid user credentials\n");
562b6364952Sagc PPS_ERROR;
563b6364952Sagc }
564b6364952Sagc
565b6364952Sagc PARAM_TEXT_ADD(head, param->key, param->offer_tx,
566b6364952Sagc text_out, text_len_out, textsize, 0, PPS_ERROR);
567b6364952Sagc
568b6364952Sagc if ((param = param_get(head, "CHAP_R")) == NULL) {
569b6364952Sagc PPS_ERROR;
570b6364952Sagc }
571b6364952Sagc param->tx_offer = 1; /* sending an offer */
572b6364952Sagc param->rx_offer = 0; /* reset */
573b6364952Sagc iSCSI_MD5Init(context);
574b6364952Sagc iSCSI_MD5Update(context, &idData, 1);
575b6364952Sagc
576b6364952Sagc if (cred->shared_secret == NULL) {
5775e01dafbSagc iscsi_err(__FILE__, __LINE__, "null shared secret\n");
578b6364952Sagc PPS_ERROR;
579b6364952Sagc } else {
580b6364952Sagc iSCSI_MD5Update(context, (const uint8_t *)cred->shared_secret, strlen(cred->shared_secret));
581b6364952Sagc }
582b6364952Sagc
583b6364952Sagc HexDataToText(chapdata, ISCSI_CHAP_DATA_LENGTH,
584b6364952Sagc param->offer_tx, ISCSI_CHAP_STRING_LENGTH);
585b6364952Sagc iSCSI_MD5Update(context, chapdata, ISCSI_CHAP_DATA_LENGTH);
586b6364952Sagc iSCSI_MD5Final(chapdata, context);
587b6364952Sagc HexDataToText(chapdata, ISCSI_CHAP_DATA_LENGTH,
588b6364952Sagc param->offer_tx, ISCSI_CHAP_STRING_LENGTH);
589b6364952Sagc
590b6364952Sagc PARAM_TEXT_ADD(head, param->key, param->offer_tx,
591b6364952Sagc text_out, text_len_out, textsize, 0, PPS_ERROR);
592b6364952Sagc
593b6364952Sagc if (param_in->rx_offer) {
594b6364952Sagc
595b6364952Sagc if ((param = param_get(head, "CHAP_I")) == NULL) {
596b6364952Sagc PPS_ERROR;
597b6364952Sagc }
598b6364952Sagc param->tx_offer = 1; /* sending an offer */
599b6364952Sagc param->rx_offer = 0; /* reset */
600b6364952Sagc GenRandomData(&idData, 1);
601b6364952Sagc (void) snprintf(chapstring, ISCSI_CHAP_STRING_LENGTH, "%d", idData);
602b6364952Sagc (void) strlcpy(param->offer_tx, chapstring, sizeof(param->offer_tx));
603b6364952Sagc PARAM_TEXT_ADD(head, param->key, param->offer_tx,
604b6364952Sagc text_out, text_len_out, textsize, 0, PPS_ERROR);
605b6364952Sagc
606b6364952Sagc if ((param = param_get(head, "CHAP_C")) == NULL) {
607b6364952Sagc PPS_ERROR;
608b6364952Sagc }
609b6364952Sagc param->tx_offer = 1; /* sending an offer */
610b6364952Sagc param->rx_offer = 0; /* reset */
611b6364952Sagc GenRandomData(chapdata, ISCSI_CHAP_DATA_LENGTH);
612b6364952Sagc HexDataToText(chapdata, ISCSI_CHAP_DATA_LENGTH,
613b6364952Sagc chapstring, ISCSI_CHAP_STRING_LENGTH);
614b6364952Sagc (void) strlcpy(param->offer_tx, chapstring, sizeof(param->offer_tx));
615b6364952Sagc PARAM_TEXT_ADD(head, param->key, param->offer_tx,
616b6364952Sagc text_out, text_len_out, textsize, 0, PPS_ERROR);
617b6364952Sagc }
618b6364952Sagc ret++;
619b6364952Sagc
620b6364952Sagc } else if (strcmp(param_in->key, "CHAP_N") == 0) {
621b6364952Sagc char *user;
622b6364952Sagc
623b6364952Sagc user = (param_in->rx_offer) ? param_in->offer_rx : param_in->answer_rx;
624b6364952Sagc if (!find_credentials(cred, user, "chap")) {
6255e01dafbSagc iscsi_err(__FILE__, __LINE__, "Unknown user `%s'\n", user);
626b6364952Sagc PPS_ERROR;
627b6364952Sagc }
628b6364952Sagc ret++;
629b6364952Sagc
630b6364952Sagc } else if (strcmp(param_in->key, "CHAP_R") == 0) {
631b6364952Sagc
632b6364952Sagc iSCSI_MD5Init(context);
633b6364952Sagc
634b6364952Sagc iSCSI_MD5Update(context, &idData, 1);
635b6364952Sagc
636b6364952Sagc HexDataToText(&idData, 1, param_in->offer_tx, ISCSI_CHAP_STRING_LENGTH);
637b6364952Sagc HexDataToText(chapdata, ISCSI_CHAP_DATA_LENGTH,
638b6364952Sagc chapstring, ISCSI_CHAP_STRING_LENGTH);
639b6364952Sagc
640b6364952Sagc if (cred->shared_secret == NULL) {
6415e01dafbSagc iscsi_err(__FILE__, __LINE__, "Null shared secret in initiator\n");
642b6364952Sagc PPS_ERROR;
643b6364952Sagc } else {
644b6364952Sagc iSCSI_MD5Update(context, (const uint8_t *)cred->shared_secret, strlen(cred->shared_secret));
645b6364952Sagc }
646b6364952Sagc
647b6364952Sagc iSCSI_MD5Update(context, chapdata, ISCSI_CHAP_DATA_LENGTH);
648b6364952Sagc iSCSI_MD5Final(chapdata, context);
649b6364952Sagc
650b6364952Sagc HexTextToData((param_in->rx_offer) ? param_in->offer_rx : param_in->answer_rx, ISCSI_CHAP_STRING_LENGTH,
651b6364952Sagc respdata, ISCSI_CHAP_DATA_LENGTH);
652b6364952Sagc
653b6364952Sagc HexDataToText(chapdata, ISCSI_CHAP_DATA_LENGTH,
654b6364952Sagc param_in->offer_rx, ISCSI_CHAP_STRING_LENGTH);
655b6364952Sagc
656b6364952Sagc if (memcmp(respdata, chapdata, ISCSI_CHAP_DATA_LENGTH) != 0) {
6575e01dafbSagc iscsi_err(__FILE__, __LINE__, "Initiator authentication failed %x %x\n", *chapdata, *respdata);
658b6364952Sagc PPS_ERROR;
659b6364952Sagc } else {
660b6364952Sagc PPS_CLEANUP;
661b6364952Sagc }
662b6364952Sagc return 0;
663b6364952Sagc }
664b6364952Sagc PPS_CLEANUP;
665b6364952Sagc return (ret);
666b6364952Sagc }
667b6364952Sagc
668b6364952Sagc int
param_text_parse(iscsi_parameter_t * head,iscsi_cred_t * cred,char * text_in,int text_len_in,char * text_out,int * text_len_out,int textsize,int outgoing)669b6364952Sagc param_text_parse(iscsi_parameter_t * head,
670b6364952Sagc iscsi_cred_t *cred,
671b6364952Sagc char *text_in, int text_len_in,
672b6364952Sagc char *text_out, int *text_len_out,
673b6364952Sagc int textsize,
674b6364952Sagc int outgoing)
675b6364952Sagc {
676b6364952Sagc static char *key = NULL;
677b6364952Sagc char *value = NULL;
678b6364952Sagc char *ptr, *eq;
679b6364952Sagc iscsi_parameter_t *param;
680b6364952Sagc iscsi_parameter_value_t *item_ptr;
681b6364952Sagc int offer_i, answer_i, max_i, val1_i, val2_i, negotiated_i;
682b6364952Sagc char *p1, *p2, *p3, *p4;
683b6364952Sagc char *offer = NULL;
684b6364952Sagc char *valid = NULL;
685b6364952Sagc char *val1 = NULL;
686b6364952Sagc char *val2 = NULL;
687b6364952Sagc char *tmp_key = NULL;
688b6364952Sagc char c;
689b6364952Sagc int ret;
690b6364952Sagc
691b6364952Sagc /*
692b6364952Sagc * Whether incoming or outgoing, some of the params might be offers
693b6364952Sagc * and some answers. Incoming
694b6364952Sagc */
695b6364952Sagc /*
696b6364952Sagc * text has the potential for creating outgoing text - and this will
697b6364952Sagc * happen when the incoming
698b6364952Sagc */
699b6364952Sagc /* text has offers that need an answer. */
700b6364952Sagc
7015e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "parsing %d %s bytes of text parameters\n", text_len_in, outgoing ? "outgoing" : "incoming");
702b6364952Sagc
703b6364952Sagc if ((key = iscsi_malloc(ISCSI_PARAM_KEY_LEN)) == NULL) {
7045e01dafbSagc iscsi_err(__FILE__, __LINE__, "iscsi_malloc() failed\n");
705b6364952Sagc return -1;
706b6364952Sagc }
707b6364952Sagc if ((offer = iscsi_malloc(ISCSI_PARAM_MAX_LEN)) == NULL) {
7085e01dafbSagc iscsi_err(__FILE__, __LINE__, "iscsi_malloc() failed\n");
709b6364952Sagc if (key != NULL) {
710b6364952Sagc iscsi_free(key);
711b6364952Sagc }
712b6364952Sagc return -1;
713b6364952Sagc }
714b6364952Sagc if ((valid = iscsi_malloc(ISCSI_PARAM_MAX_LEN)) == NULL) {
7155e01dafbSagc iscsi_err(__FILE__, __LINE__, "iscsi_malloc() failed\n");
716b6364952Sagc if (key != NULL) {
717b6364952Sagc iscsi_free(key);
718b6364952Sagc }
719b6364952Sagc if (offer != NULL) {
720b6364952Sagc iscsi_free(offer);
721b6364952Sagc }
722b6364952Sagc return -1;
723b6364952Sagc }
724b6364952Sagc if ((val1 = iscsi_malloc(ISCSI_PARAM_MAX_LEN)) == NULL) {
7255e01dafbSagc iscsi_err(__FILE__, __LINE__, "iscsi_malloc() failed\n");
726b6364952Sagc if (key != NULL) {
727b6364952Sagc iscsi_free(key);
728b6364952Sagc }
729b6364952Sagc if (offer != NULL) {
730b6364952Sagc iscsi_free(offer);
731b6364952Sagc }
732b6364952Sagc if (valid != NULL) {
733b6364952Sagc iscsi_free(valid);
734b6364952Sagc }
735b6364952Sagc return -1;
736b6364952Sagc }
737b6364952Sagc if ((val2 = iscsi_malloc(ISCSI_PARAM_MAX_LEN)) == NULL) {
7385e01dafbSagc iscsi_err(__FILE__, __LINE__, "iscsi_malloc() failed\n");
739b6364952Sagc if (key != NULL) {
740b6364952Sagc iscsi_free(key);
741b6364952Sagc }
742b6364952Sagc if (offer != NULL) {
743b6364952Sagc iscsi_free(offer);
744b6364952Sagc }
745b6364952Sagc if (valid != NULL) {
746b6364952Sagc iscsi_free(valid);
747b6364952Sagc }
748b6364952Sagc if (val1 != NULL) {
749b6364952Sagc iscsi_free(val1);
750b6364952Sagc }
751b6364952Sagc return -1;
752b6364952Sagc }
753b6364952Sagc #define PTP_CLEANUP { if (key != NULL) iscsi_free(key); \
754b6364952Sagc if (offer != NULL) iscsi_free(offer); \
755b6364952Sagc if (valid != NULL) iscsi_free(valid); \
756b6364952Sagc if (val1 != NULL) iscsi_free(val1); \
757b6364952Sagc if (val2 != NULL) iscsi_free(val2); \
758b6364952Sagc if (tmp_key != NULL) iscsi_free(tmp_key); }
759b6364952Sagc #define PTP_ERROR {PTP_CLEANUP; return -1;}
760b6364952Sagc
761b6364952Sagc if (!outgoing) {
762b6364952Sagc *text_len_out = 0;
763b6364952Sagc }
764b6364952Sagc
765b6364952Sagc #if ISCSI_DEBUG
766b6364952Sagc printf("**************************************************\n");
767b6364952Sagc printf("* PARAMETERS NEGOTIATED *\n");
768b6364952Sagc printf("* *\n");
769b6364952Sagc #endif
770b6364952Sagc
771b6364952Sagc for (ptr = text_in; ptr - text_in < text_len_in; ptr += (strlen(ptr) + 1)) {
772b6364952Sagc
773b6364952Sagc /* Skip over any NULLs */
774b6364952Sagc
775b6364952Sagc while (!(*ptr) && ((ptr - text_in) < text_len_in)) {
776b6364952Sagc ptr++;
777b6364952Sagc }
778b6364952Sagc if ((ptr - text_in) >= text_len_in) {
779b6364952Sagc break;
780b6364952Sagc }
781b6364952Sagc
782b6364952Sagc /* Extract <key>=<value> token from text_in */
783b6364952Sagc
784b6364952Sagc if ((eq = strchr(ptr, '=')) == NULL) {
7855e01dafbSagc iscsi_err(__FILE__, __LINE__, "delimiter \'=\' not found in token \"%s\"\n", ptr);
786b6364952Sagc } else {
787b6364952Sagc if ((int)(eq - ptr) >= (ISCSI_PARAM_KEY_LEN - 1)) {
788b6364952Sagc if (!outgoing) {
789b6364952Sagc tmp_key = iscsi_malloc((unsigned)(eq - ptr));
790b6364952Sagc if (tmp_key) {
791b6364952Sagc strncpy(tmp_key, ptr, (unsigned)(eq - ptr));
792b6364952Sagc tmp_key[(int)(eq - ptr)] = 0x0;
793b6364952Sagc /* Key not understood. */
794b6364952Sagc PARAM_TEXT_ADD(head, tmp_key, "NotUnderstood", text_out, text_len_out, textsize, 0, PTP_ERROR);
795b6364952Sagc }
796b6364952Sagc } else {
797b6364952Sagc printf("ignoring \"%s\"\n", key);
798b6364952Sagc }
799b6364952Sagc goto next;
800b6364952Sagc }
801b6364952Sagc strncpy(key, ptr, (unsigned)(eq - ptr));
802b6364952Sagc key[(int)(eq - ptr)] = 0x0;
803b6364952Sagc value = eq + 1;
804b6364952Sagc }
805b6364952Sagc
806b6364952Sagc /* Find key in param list */
807b6364952Sagc
808b6364952Sagc for (param = head; param != NULL; param = param->next) {
809b6364952Sagc if (strcmp(param->key, key) == 0) {
810b6364952Sagc break;
811b6364952Sagc }
812b6364952Sagc }
813b6364952Sagc if (param == NULL) {
814b6364952Sagc if (!outgoing) {
815b6364952Sagc /* Key not understood. */
816b6364952Sagc PARAM_TEXT_ADD(head, key, "NotUnderstood", text_out, text_len_out, textsize, 0, PTP_ERROR);
817b6364952Sagc } else {
818b6364952Sagc printf("ignoring \"%s\"\n", key);
819b6364952Sagc }
820b6364952Sagc goto next;
821b6364952Sagc }
8225e01dafbSagc if (strlen(value) > ISCSI_PARAM_MAX_LEN) {
8235e01dafbSagc iscsi_err(__FILE__, __LINE__,
824*93f9555bSjoerg "strlen(value) %zu\n", strlen(value));
8255e01dafbSagc PTP_CLEANUP;
8265e01dafbSagc return -1;
8275e01dafbSagc }
828b6364952Sagc
829b6364952Sagc /* We're sending|receiving an offer|answer */
830b6364952Sagc if (outgoing) {
831b6364952Sagc if (param->rx_offer) {
832b6364952Sagc param->tx_answer = 1; /* sending an answer */
833b6364952Sagc param->rx_answer = 0; /* reset */
834b6364952Sagc param->tx_offer = 0; /* reset */
835b6364952Sagc param->rx_offer = 0; /* reset */
836b6364952Sagc (void) strlcpy(param->answer_tx, value, sizeof(param->answer_tx));
8375e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "sending answer \"%s\"=\"%s\" for offer \"%s\"\n",
838b6364952Sagc param->key, param->answer_tx, param->offer_rx);
839b6364952Sagc goto negotiate;
840b6364952Sagc } else {
841b6364952Sagc param->tx_offer = 1; /* sending an offer */
842b6364952Sagc param->tx_answer = 0;
843b6364952Sagc param->rx_answer = 0;
844b6364952Sagc (void) strlcpy(param->offer_tx, value, sizeof(param->offer_tx));
8455e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "sending offer \"%s\"=\"%s\"\n", param->key, param->offer_tx);
846b6364952Sagc if ((param->type == ISCSI_PARAM_TYPE_DECLARATIVE) ||
847b6364952Sagc (param->type == ISCSI_PARAM_TYPE_DECLARE_MULTI)) {
848b6364952Sagc goto negotiate;
849b6364952Sagc }
850b6364952Sagc goto next;
851b6364952Sagc }
852b6364952Sagc } else {
853b6364952Sagc if (param->tx_offer) {
854b6364952Sagc param->rx_answer = 1; /* received an answer */
855b6364952Sagc param->tx_answer = 0;
856b6364952Sagc param->rx_offer = 0;
857b6364952Sagc param->tx_offer = 0; /* reset */
858b6364952Sagc (void) strlcpy(param->answer_rx, value, sizeof(param->answer_rx));
8595e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "received answer \"%s\"=\"%s\" for offer \"%s\"\n",
860b6364952Sagc param->key, param->answer_rx, param->offer_tx);
861b6364952Sagc
862b6364952Sagc if ((ret = param_parse_security(head, param, cred,
863b6364952Sagc text_out, text_len_out, textsize)) > 1) {
864b6364952Sagc goto next;
865b6364952Sagc } else if (ret == 0) {
866b6364952Sagc /*
867b6364952Sagc * FIX ME Happens in initiator code
868b6364952Sagc * currently we ignore initiator
869b6364952Sagc * authentication status See comments
870b6364952Sagc * at the beginning of parse_security
871b6364952Sagc */
872b6364952Sagc goto negotiate;
873b6364952Sagc } else if (ret == 1) {
874b6364952Sagc goto negotiate;
875b6364952Sagc } else {
876b6364952Sagc PTP_CLEANUP;
877b6364952Sagc }
878b6364952Sagc return ISCSI_PARAM_STATUS_AUTH_FAILED;
879b6364952Sagc } else {
880b6364952Sagc param->rx_offer = 1; /* received an offer */
881b6364952Sagc param->rx_answer = 0;
882b6364952Sagc param->tx_answer = 0;
883b6364952Sagc (void) strlcpy(param->offer_rx, value, sizeof(param->offer_rx));
8845e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "received offer \"%s\"=\"%s\"\n", param->key, param->offer_rx);
885b6364952Sagc
886b6364952Sagc if ((ret = param_parse_security(head, param, cred,
887b6364952Sagc text_out, text_len_out, textsize)) > 1) {
888b6364952Sagc goto next;
889b6364952Sagc } else if (ret < 0) {
890b6364952Sagc iscsi_parameter_t *auth_result;
891b6364952Sagc if ((auth_result = param_get(head, "AuthResult")) != 0) {
892b6364952Sagc (void) strlcpy(auth_result->value_l->value, "Fail", sizeof(auth_result->value_l->value));
893b6364952Sagc }
894b6364952Sagc PTP_CLEANUP;
895b6364952Sagc return (ISCSI_PARAM_STATUS_AUTH_FAILED);
896b6364952Sagc } else if (ret == 0) {
897b6364952Sagc iscsi_parameter_t *auth_result;
898b6364952Sagc if ((auth_result = param_get(head, "AuthResult")) != 0) {
899b6364952Sagc (void) strlcpy(auth_result->value_l->value, "Yes", sizeof(auth_result->value_l->value));
900b6364952Sagc }
901b6364952Sagc }
902b6364952Sagc /*
903b6364952Sagc * Answer the offer if it is an inquiry or
904b6364952Sagc * the type is not DECLARATIVE
905b6364952Sagc */
906b6364952Sagc
907b6364952Sagc if ((strcmp(param->offer_rx, "?") != 0) && ((param->type == ISCSI_PARAM_TYPE_DECLARATIVE) || (param->type == ISCSI_PARAM_TYPE_DECLARE_MULTI))) {
908b6364952Sagc goto negotiate;
909b6364952Sagc } else {
910b6364952Sagc goto answer;
911b6364952Sagc }
912b6364952Sagc }
913b6364952Sagc }
914b6364952Sagc
915b6364952Sagc answer:
916b6364952Sagc
917b6364952Sagc /* Answer with current value if this is an inquiry (<key>=?) */
918b6364952Sagc
919b6364952Sagc if (strcmp(value, "?") == 0) {
9205e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "got inquiry for param \"%s\"\n", param->key);
921b6364952Sagc if (param->value_l) {
922b6364952Sagc (void) strlcpy(param->answer_tx, param->value_l->value, sizeof(param->answer_tx));
923b6364952Sagc } else {
9245e01dafbSagc iscsi_err(__FILE__, __LINE__, "param \"%s\" has NULL value_l\n", param->key);
925b6364952Sagc param->answer_tx[0] = 0x0;
926b6364952Sagc }
927b6364952Sagc goto add_answer;
928b6364952Sagc }
929b6364952Sagc /* Generate answer according to the parameter type */
930b6364952Sagc
931b6364952Sagc switch (param->type) {
932b6364952Sagc
933b6364952Sagc case ISCSI_PARAM_TYPE_BINARY_AND:
934b6364952Sagc goto binary_or;
935b6364952Sagc
936b6364952Sagc case ISCSI_PARAM_TYPE_BINARY_OR:
937b6364952Sagc binary_or:
938b6364952Sagc if (strcmp(value, "yes") != 0 &&
939b6364952Sagc strcmp(value, "no") != 0 &&
940b6364952Sagc strcmp(value, "Yes") != 0 &&
941b6364952Sagc strcmp(value, "No") != 0) {
9425e01dafbSagc iscsi_err(__FILE__, __LINE__, "\"%s\" is not a valid binary value\n", value);
943b6364952Sagc (void) strlcpy(param->answer_tx, "Reject", sizeof(param->answer_tx));
944b6364952Sagc goto add_answer;
945b6364952Sagc }
946b6364952Sagc if (strchr(param->valid, ',') != NULL) {
947b6364952Sagc (void) strlcpy(param->answer_tx, value, sizeof(param->answer_tx)); /* we accept both yes
948b6364952Sagc * and no, so answer w/
949b6364952Sagc * their offer */
950b6364952Sagc } else {
951b6364952Sagc (void) strlcpy(param->answer_tx, param->valid, sizeof(param->answer_tx)); /* answer with the only
952b6364952Sagc * value we support */
953b6364952Sagc }
954b6364952Sagc break;
955b6364952Sagc
956b6364952Sagc case ISCSI_PARAM_TYPE_LIST:
957b6364952Sagc
958b6364952Sagc /*
959b6364952Sagc * Use our default value if it's offered as one of the option
960b6364952Sagc * in the parameter list.
961b6364952Sagc *
962b6364952Sagc * We need to do this at least for CHAP because cisco's initiator
963b6364952Sagc * could be sending us a parameter value list with "CHAP,None",
964b6364952Sagc * even when it doesn't set username/password in its configration
965b6364952Sagc * file, in which case we should pick "None" as for no security instead
966b6364952Sagc * of pick the first one on the value list. "None" is the default value
967b6364952Sagc * for AuthMethod
968b6364952Sagc *
969b6364952Sagc * This fix is working well now, though is arguable. We should keep
970b6364952Sagc * this just to make us work with Cisco for now.
971b6364952Sagc */
972b6364952Sagc if (strlen(param->dflt)) {
973b6364952Sagc for (p1 = p2 = param->offer_rx; p2; p1 = p2 + 1) {
974b6364952Sagc
975b6364952Sagc if ((p2 = strchr(p1, ',')) != NULL) {
976b6364952Sagc strncpy(offer, p1, (unsigned)(p2 - p1));
977b6364952Sagc offer[(int)(p2 - p1)] = 0x0;
978b6364952Sagc } else {
979b6364952Sagc (void) strlcpy(offer, p1, ISCSI_PARAM_MAX_LEN);
980b6364952Sagc }
981b6364952Sagc
982b6364952Sagc if (strcmp(param->dflt, offer) == 0) {
983b6364952Sagc (void) strlcpy(param->answer_tx, offer, sizeof(param->answer_tx));
984b6364952Sagc goto add_answer;
985b6364952Sagc }
986b6364952Sagc }
987b6364952Sagc }
988b6364952Sagc /* Find the first valid offer that we support */
989b6364952Sagc
990b6364952Sagc for (p1 = p2 = param->offer_rx; p2; p1 = p2 + 1) {
991b6364952Sagc if ((p2 = strchr(p1, ',')) != NULL) {
992b6364952Sagc strncpy(offer, p1, (unsigned)(p2 - p1));
993b6364952Sagc offer[p2 - p1] = 0x0;
994b6364952Sagc } else {
995b6364952Sagc (void) strlcpy(offer, p1, ISCSI_PARAM_MAX_LEN);
996b6364952Sagc }
997b6364952Sagc if (strlen(param->valid)) {
998b6364952Sagc for (p3 = p4 = param->valid; p4; p3 = p4 + 1) {
999b6364952Sagc if ((p4 = strchr(p3, ',')) != NULL) {
1000b6364952Sagc strncpy(valid, p3, (unsigned)(p4 - p3));
1001b6364952Sagc valid[(int)(p4 - p3)] = 0x0;
1002b6364952Sagc } else {
1003b6364952Sagc (void) strlcpy(valid, p3, ISCSI_PARAM_MAX_LEN);
1004b6364952Sagc }
1005b6364952Sagc if (strcmp(valid, offer) == 0) {
1006b6364952Sagc (void) strlcpy(param->answer_tx, offer, sizeof(param->answer_tx));
1007b6364952Sagc goto add_answer;
1008b6364952Sagc }
1009b6364952Sagc }
1010b6364952Sagc } else {
10115e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "Valid list empty. Answering with first in offer list\n");
1012b6364952Sagc (void) strlcpy(param->answer_tx, offer, sizeof(param->answer_tx));
1013b6364952Sagc goto add_answer;
1014b6364952Sagc }
10155e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "\"%s\" is not a valid offer for key \"%s\" (must choose from \"%s\")\n", offer, param->key, param->valid);
1016b6364952Sagc }
10175e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "No Valid offers: \"%s\" is added as value for key \"%s\")\n", "Reject", param->key);
1018b6364952Sagc (void) strlcpy(param->answer_tx, "Reject", sizeof(param->answer_tx));
1019b6364952Sagc break;
1020b6364952Sagc
1021b6364952Sagc case ISCSI_PARAM_TYPE_NUMERICAL_Z:
1022b6364952Sagc goto numerical;
1023b6364952Sagc
1024b6364952Sagc case ISCSI_PARAM_TYPE_NUMERICAL:
1025b6364952Sagc numerical:
1026b6364952Sagc offer_i = iscsi_atoi(param->offer_rx);
1027b6364952Sagc max_i = iscsi_atoi(param->valid);
1028b6364952Sagc if (param->type == ISCSI_PARAM_TYPE_NUMERICAL_Z) {
1029b6364952Sagc if (max_i == 0) {
1030b6364952Sagc answer_i = offer_i; /* we support anything,
1031b6364952Sagc * so return whatever
1032b6364952Sagc * they offered */
1033b6364952Sagc } else if (offer_i == 0) {
1034b6364952Sagc answer_i = max_i; /* return only what we
1035b6364952Sagc * can support */
1036b6364952Sagc } else if (offer_i > max_i) {
1037b6364952Sagc answer_i = max_i; /* we are the lower of
1038b6364952Sagc * the two */
1039b6364952Sagc } else {
1040b6364952Sagc answer_i = offer_i; /* they are the lower of
1041b6364952Sagc * the two */
1042b6364952Sagc }
1043b6364952Sagc } else {
1044b6364952Sagc if (offer_i > max_i) {
1045b6364952Sagc answer_i = max_i; /* we are the lower of
1046b6364952Sagc * the two */
1047b6364952Sagc } else {
1048b6364952Sagc answer_i = offer_i; /* they are the lower of
1049b6364952Sagc * the two */
1050b6364952Sagc }
1051b6364952Sagc }
1052b6364952Sagc (void) snprintf(param->answer_tx, sizeof(param->answer_tx), "%d", answer_i);
1053b6364952Sagc goto add_answer;
1054b6364952Sagc
1055b6364952Sagc default:
1056b6364952Sagc goto next;
1057b6364952Sagc }
1058b6364952Sagc add_answer: PARAM_TEXT_ADD(head, key, param->answer_tx, text_out, text_len_out, textsize, 0, PTP_ERROR);
10595e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "answering \"%s\"=\"%s\"\n", param->key, param->answer_tx);
1060b6364952Sagc goto next;
1061b6364952Sagc
1062b6364952Sagc
1063b6364952Sagc /* Negotiate after receiving|sending an answer */
1064b6364952Sagc
1065b6364952Sagc negotiate:
1066b6364952Sagc switch (param->type) {
1067b6364952Sagc case ISCSI_PARAM_TYPE_DECLARE_MULTI:
1068b6364952Sagc goto declarative_negotiate;
1069b6364952Sagc case ISCSI_PARAM_TYPE_DECLARATIVE:
1070b6364952Sagc declarative_negotiate:
1071b6364952Sagc if (param->tx_answer) {
1072b6364952Sagc (void) strlcpy(param->negotiated, param->answer_tx, sizeof(param->negotiated));
1073b6364952Sagc } else if (param->tx_offer) {
1074b6364952Sagc (void) strlcpy(param->negotiated, param->offer_tx, sizeof(param->negotiated));
1075b6364952Sagc } else if (param->rx_answer) {
1076b6364952Sagc (void) strlcpy(param->negotiated, param->answer_rx, sizeof(param->negotiated));
1077b6364952Sagc } else if (param->rx_offer) {
1078b6364952Sagc (void) strlcpy(param->negotiated, param->offer_rx, sizeof(param->negotiated));
1079b6364952Sagc } else {
10805e01dafbSagc iscsi_err(__FILE__, __LINE__, "Invalid negotiation!?!?\n");
1081b6364952Sagc }
1082b6364952Sagc break;
1083b6364952Sagc case ISCSI_PARAM_TYPE_BINARY_AND:
1084b6364952Sagc goto binary_or_negotiate;
1085b6364952Sagc case ISCSI_PARAM_TYPE_BINARY_OR:
1086b6364952Sagc binary_or_negotiate:
1087b6364952Sagc if (outgoing) {
1088b6364952Sagc (void) strlcpy(val1, param->offer_rx, ISCSI_PARAM_MAX_LEN);
1089b6364952Sagc (void) strlcpy(val2, param->answer_tx, ISCSI_PARAM_MAX_LEN);
1090b6364952Sagc } else {
1091b6364952Sagc (void) strlcpy(val1, param->answer_rx, ISCSI_PARAM_MAX_LEN);
1092b6364952Sagc (void) strlcpy(val2, param->offer_tx, ISCSI_PARAM_MAX_LEN);
1093b6364952Sagc /* Make sure the answer is valid */
1094b6364952Sagc if (strcmp(val1, "Yes") != 0 &&
1095b6364952Sagc strcmp(val1, "No") != 0 &&
1096b6364952Sagc strcmp(val1, "yes") != 0 &&
1097b6364952Sagc strcmp(val1, "no") != 0 &&
1098b6364952Sagc strcmp(val1, "Irrelevant") != 0) {
1099b6364952Sagc /* Invalid value returned as answer. */
11005e01dafbSagc iscsi_err(__FILE__, __LINE__, "Invalid answer (%s) for key (%s)\n",
1101b6364952Sagc val1, key);
1102b6364952Sagc PTP_ERROR;
1103b6364952Sagc }
1104b6364952Sagc }
1105b6364952Sagc if (param->type == ISCSI_PARAM_TYPE_BINARY_OR) {
1106b6364952Sagc if (strcmp(val1, "yes") == 0 || strcmp(val2, "yes") == 0 || strcmp(val1, "Yes") == 0 || strcmp(val2, "Yes") == 0) {
1107b6364952Sagc (void) strlcpy(param->negotiated, "Yes", sizeof(param->negotiated));
1108b6364952Sagc } else {
1109b6364952Sagc (void) strlcpy(param->negotiated, "No", sizeof(param->negotiated));
1110b6364952Sagc }
1111b6364952Sagc } else {
1112b6364952Sagc if ((strcmp(val1, "yes") == 0 && strcmp(val2, "yes") == 0) || (strcmp(val1, "Yes") == 0 && strcmp(val2, "Yes") == 0)) {
1113b6364952Sagc (void) strlcpy(param->negotiated, "Yes", sizeof(param->negotiated));
1114b6364952Sagc } else {
1115b6364952Sagc (void) strlcpy(param->negotiated, "No", sizeof(param->negotiated));
1116b6364952Sagc }
1117b6364952Sagc }
1118b6364952Sagc break;
1119b6364952Sagc case ISCSI_PARAM_TYPE_NUMERICAL_Z:
1120b6364952Sagc goto numerical_negotiate;
1121b6364952Sagc case ISCSI_PARAM_TYPE_NUMERICAL:
1122b6364952Sagc numerical_negotiate:
1123b6364952Sagc if (outgoing) {
1124b6364952Sagc (void) strlcpy(val1, param->offer_rx, ISCSI_PARAM_MAX_LEN);
1125b6364952Sagc (void) strlcpy(val2, param->answer_tx, ISCSI_PARAM_MAX_LEN);
1126b6364952Sagc } else {
1127b6364952Sagc (void) strlcpy(val1, param->answer_rx, ISCSI_PARAM_MAX_LEN);
1128b6364952Sagc (void) strlcpy(val2, param->offer_tx, ISCSI_PARAM_MAX_LEN);
1129b6364952Sagc }
1130b6364952Sagc val1_i = iscsi_atoi(val1);
1131b6364952Sagc val2_i = iscsi_atoi(val2);
1132b6364952Sagc if (param->type == ISCSI_PARAM_TYPE_NUMERICAL_Z) {
1133b6364952Sagc if (val1_i == 0) {
1134b6364952Sagc negotiated_i = val2_i;
1135b6364952Sagc } else if (val2_i == 0) {
1136b6364952Sagc negotiated_i = val1_i;
1137b6364952Sagc } else if (val1_i > val2_i) {
1138b6364952Sagc negotiated_i = val2_i;
1139b6364952Sagc } else {
1140b6364952Sagc negotiated_i = val1_i;
1141b6364952Sagc }
1142b6364952Sagc } else {
1143b6364952Sagc if (val1_i > val2_i) {
1144b6364952Sagc negotiated_i = val2_i;
1145b6364952Sagc } else {
1146b6364952Sagc negotiated_i = val1_i;
1147b6364952Sagc }
1148b6364952Sagc }
1149b6364952Sagc (void) snprintf(param->negotiated, sizeof(param->negotiated), "%d", negotiated_i);
1150b6364952Sagc break;
1151b6364952Sagc case ISCSI_PARAM_TYPE_LIST:
1152b6364952Sagc if (outgoing) {
1153b6364952Sagc if (param->tx_offer) {
11545e01dafbSagc iscsi_err(__FILE__, __LINE__, "we should not be here\n"); /* error - we're sending
1155b6364952Sagc * an offer */
1156b6364952Sagc PTP_ERROR;
1157b6364952Sagc } else if (param->tx_answer) {
1158b6364952Sagc (void) strlcpy(val1, param->answer_tx, ISCSI_PARAM_MAX_LEN); /* we're sending an
1159b6364952Sagc * answer */
1160b6364952Sagc } else {
11615e01dafbSagc iscsi_err(__FILE__, __LINE__, "unexpected error\n");
1162b6364952Sagc PTP_ERROR;
1163b6364952Sagc }
1164b6364952Sagc } else {
1165b6364952Sagc if (param->rx_offer) {
11665e01dafbSagc iscsi_err(__FILE__, __LINE__, "we should not be here\n"); /* error - we received
1167b6364952Sagc * an offer */
1168b6364952Sagc PTP_ERROR;
1169b6364952Sagc } else if (param->rx_answer) {
1170b6364952Sagc (void) strlcpy(val1, param->answer_rx, ISCSI_PARAM_MAX_LEN); /* we received an answer */
1171b6364952Sagc } else {
11725e01dafbSagc iscsi_err(__FILE__, __LINE__, "unexpected error\n");
1173b6364952Sagc PTP_ERROR;
1174b6364952Sagc }
1175b6364952Sagc }
1176b6364952Sagc
1177b6364952Sagc /* Make sure incoming or outgoing answer is valid */
1178b6364952Sagc /*
1179b6364952Sagc * None, Reject, Irrelevant and NotUnderstood are
1180b6364952Sagc * valid
1181b6364952Sagc */
1182b6364952Sagc if ((strcmp(val1, "None") == 0) || (strcmp(val1, "Reject") == 0) ||
1183b6364952Sagc (strcmp(val1, "Irrelevant") == 0) || (strcmp(val1, "NotUnderstood") == 0)) {
1184b6364952Sagc goto value_ok;
1185b6364952Sagc }
1186b6364952Sagc if (strlen(param->valid) > 0) {
1187b6364952Sagc for (p3 = p4 = param->valid; p4; p3 = p4 + 1) {
1188b6364952Sagc if ((p4 = strchr(p3, ',')) != NULL) {
1189b6364952Sagc strncpy(valid, p3, (unsigned)(p4 - p3));
1190b6364952Sagc valid[(int)(p4 - p3)] = 0x0;
1191b6364952Sagc } else {
1192b6364952Sagc (void) strlcpy(valid, p3, ISCSI_PARAM_MAX_LEN);
1193b6364952Sagc }
1194b6364952Sagc if (strcmp(valid, val1) == 0) {
1195b6364952Sagc goto value_ok;
1196b6364952Sagc }
1197b6364952Sagc }
1198b6364952Sagc } else {
11995e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "Valid list empty??\n");
1200b6364952Sagc PTP_ERROR;
1201b6364952Sagc }
12025e01dafbSagc iscsi_err(__FILE__, __LINE__, "\"%s\" is not a valid value (must choose from \"%s\")\n", val1, param->valid);
1203b6364952Sagc PTP_ERROR;
1204b6364952Sagc value_ok:
1205b6364952Sagc (void) strlcpy(param->negotiated, val1, sizeof(param->negotiated));
1206b6364952Sagc break;
1207b6364952Sagc }
1208b6364952Sagc
12095e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "negotiated \"%s\"=\"%s\"\n", param->key, param->negotiated);
1210b6364952Sagc
1211b6364952Sagc /* For inquiries, we don't commit the value. */
1212b6364952Sagc
1213b6364952Sagc if (param->tx_offer && strcmp(param->offer_tx, "?") == 0) {
1214b6364952Sagc /* we're offering an inquiry */
12155e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "sending an inquiry for \"%s\"\n", param->key);
1216b6364952Sagc goto next;
1217b6364952Sagc } else if (param->rx_offer && strcmp(param->offer_rx, "?") == 0) {
1218b6364952Sagc /* we're receiving an inquiry */
12195e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "received an inquiry for \"%s\"\n", param->key);
1220b6364952Sagc goto next;
1221b6364952Sagc } else if (param->tx_answer && strcmp(param->offer_rx, "?") == 0) {
1222b6364952Sagc /* we're answering an inquiry */
12235e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "answering an inquiry for \"%s\"\n", param->key);
1224b6364952Sagc goto next;
1225b6364952Sagc } else if (param->rx_answer && strcmp(param->offer_tx, "?") == 0) {
1226b6364952Sagc /* we're receiving an answer for our inquiry */
12275e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "received an answer for inquiry on \"%s\"\n", param->key);
1228b6364952Sagc goto next;
1229b6364952Sagc }
12305e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "automatically committing \"%s\"=\"%s\"\n", param->key, param->negotiated);
1231b6364952Sagc
1232b6364952Sagc c = param->negotiated[19];
1233b6364952Sagc param->negotiated[19] = 0x0;
1234b6364952Sagc #if ISCSI_DEBUG
1235b6364952Sagc printf("* %25s:%20s *\n", param->key, param->negotiated);
1236b6364952Sagc #endif
1237b6364952Sagc param->negotiated[19] = c;
1238b6364952Sagc
1239b6364952Sagc if (param->reset) {
12405e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "deleting value list for \"%s\"\n", param->key);
1241b6364952Sagc if (param_val_delete_all(head, param->key) != 0) {
12425e01dafbSagc iscsi_err(__FILE__, __LINE__, "param_val_delete_all() failed\n");
1243b6364952Sagc PTP_ERROR;
1244b6364952Sagc }
1245b6364952Sagc param->reset = 0;
1246b6364952Sagc }
1247b6364952Sagc if (param->value_l) {
1248b6364952Sagc if (param->type == ISCSI_PARAM_TYPE_DECLARE_MULTI) {
1249b6364952Sagc for (item_ptr = param->value_l; item_ptr->next != NULL; item_ptr = item_ptr->next) {
1250b6364952Sagc }
1251b6364952Sagc if ((item_ptr->next = iscsi_malloc_atomic(sizeof(iscsi_parameter_value_t))) == NULL) {
12525e01dafbSagc iscsi_err(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
1253b6364952Sagc PTP_ERROR;
1254b6364952Sagc }
1255b6364952Sagc item_ptr = item_ptr->next;
1256b6364952Sagc item_ptr->next = NULL;
1257b6364952Sagc } else {
1258b6364952Sagc item_ptr = param->value_l;
1259b6364952Sagc }
1260b6364952Sagc } else {
12615e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "allocating value ptr\n");
1262b6364952Sagc if ((param->value_l = iscsi_malloc_atomic(sizeof(iscsi_parameter_value_t))) == NULL) {
12635e01dafbSagc iscsi_err(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
1264b6364952Sagc PTP_ERROR;
1265b6364952Sagc }
1266b6364952Sagc item_ptr = param->value_l;
1267b6364952Sagc item_ptr->next = NULL;
1268b6364952Sagc }
1269b6364952Sagc (void) strlcpy(item_ptr->value, param->negotiated, sizeof(item_ptr->value));
1270b6364952Sagc next:
1271b6364952Sagc continue;
1272b6364952Sagc }
1273b6364952Sagc if (!outgoing) {
12745e01dafbSagc iscsi_trace(TRACE_ISCSI_PARAM, "generated %d bytes response\n", *text_len_out);
1275b6364952Sagc }
1276b6364952Sagc #if ISCSI_DEBUG
1277b6364952Sagc printf("**************************************************\n");
1278b6364952Sagc #endif
1279b6364952Sagc
1280b6364952Sagc PTP_CLEANUP;
1281b6364952Sagc return 0;
1282b6364952Sagc }
1283b6364952Sagc
1284b6364952Sagc void
set_session_parameters(iscsi_parameter_t * head,iscsi_sess_param_t * sess_params)1285b6364952Sagc set_session_parameters(iscsi_parameter_t * head,
1286b6364952Sagc iscsi_sess_param_t * sess_params)
1287b6364952Sagc {
1288b6364952Sagc /* These parameters are standard and assuming that they are always */
1289b6364952Sagc /* present in the list (head). */
1290b6364952Sagc memset(sess_params, 0, sizeof(iscsi_sess_param_t));
1291b6364952Sagc sess_params->max_burst_length = param_atoi(head, "MaxBurstLength");
1292b6364952Sagc sess_params->first_burst_length = param_atoi(head, "FirstBurstLength");
12935e01dafbSagc sess_params->max_dataseg_len =
1294b6364952Sagc param_atoi(head, "MaxRecvDataSegmentLength");
1295b6364952Sagc sess_params->header_digest = (param_equiv(head, "HeaderDigest", "Yes")) ? 1 : 0;
1296b6364952Sagc sess_params->data_digest = (param_equiv(head, "DataDigest", "Yes")) ? 1 : 0;
1297b6364952Sagc sess_params->initial_r2t = (param_equiv(head, "InitialR2T", "Yes"));
1298b6364952Sagc sess_params->immediate_data = (param_equiv(head, "ImmediateData", "Yes"));
1299b6364952Sagc }
1300