1 /*
2 * Copyright (C) 2008-2010 Daisuke Aoyama <aoyama@peach.ne.jp>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include <stdint.h>
33 #include <inttypes.h>
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "istgt.h"
40 #include "istgt_log.h"
41 #include "istgt_misc.h"
42 #include "istgt_iscsi.h"
43 #include "istgt_iscsi_param.h"
44
45 void
istgt_iscsi_param_free(ISCSI_PARAM * params)46 istgt_iscsi_param_free(ISCSI_PARAM *params)
47 {
48 ISCSI_PARAM *param, *next_param;
49
50 if (params == NULL)
51 return;
52 for (param = params; param != NULL; param = next_param) {
53 next_param = param->next;
54 xfree(param->list);
55 xfree(param->val);
56 xfree(param->key);
57 xfree(param);
58 }
59 }
60
61 ISCSI_PARAM *
istgt_iscsi_param_find(ISCSI_PARAM * params,const char * key)62 istgt_iscsi_param_find(ISCSI_PARAM *params, const char *key)
63 {
64 ISCSI_PARAM *param;
65
66 if (params == NULL || key == NULL)
67 return NULL;
68 for (param = params; param != NULL; param = param->next) {
69 if (param->key != NULL && param->key[0] == key[0]
70 && strcasecmp(param->key, key) == 0) {
71 return param;
72 }
73 }
74 return NULL;
75 }
76
77 int
istgt_iscsi_param_del(ISCSI_PARAM ** params,const char * key)78 istgt_iscsi_param_del(ISCSI_PARAM **params, const char *key)
79 {
80 ISCSI_PARAM *param, *prev_param = NULL;
81
82 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "del %s\n", key);
83 if (params == NULL || key == NULL)
84 return 0;
85 for (param = *params; param != NULL; param = param->next) {
86 if (param->key != NULL && param->key[0] == key[0]
87 && strcasecmp(param->key, key) == 0) {
88 if (prev_param != NULL) {
89 prev_param->next = param->next;
90 } else {
91 *params = param->next;
92 }
93 param->next = NULL;
94 istgt_iscsi_param_free(param);
95 return 0;
96 }
97 prev_param = param;
98 }
99 return -1;
100 }
101
102 int
istgt_iscsi_param_add(ISCSI_PARAM ** params,const char * key,const char * val,const char * list,int type)103 istgt_iscsi_param_add(ISCSI_PARAM **params, const char *key, const char *val, const char *list, int type)
104 {
105 ISCSI_PARAM *param, *last_param;
106
107 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "add %s=%s, list=[%s], type=%d\n",
108 key, val, list, type);
109 if (key == NULL)
110 return -1;
111 param = istgt_iscsi_param_find(*params, key);
112 if (param != NULL) {
113 istgt_iscsi_param_del(params, key);
114 }
115 param = xmalloc(sizeof *param);
116 memset(param, 0, sizeof *param);
117 param->next = NULL;
118 param->key = xstrdup(key);
119 param->val = xstrdup(val);
120 param->list = xstrdup(list);
121 param->type = type;
122
123 last_param = *params;
124 if (last_param != NULL) {
125 while (last_param->next != NULL) {
126 last_param = last_param->next;
127 }
128 last_param->next = param;
129 } else {
130 *params = param;
131 }
132
133 return 0;
134 }
135
136 int
istgt_iscsi_param_set(ISCSI_PARAM * params,const char * key,const char * val)137 istgt_iscsi_param_set(ISCSI_PARAM *params, const char *key, const char *val)
138 {
139 ISCSI_PARAM *param;
140
141 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "set %s=%s\n", key, val);
142 param = istgt_iscsi_param_find(params, key);
143 if (param == NULL) {
144 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "no key %s\n", key);
145 return -1;
146 }
147
148 xfree(param->val);
149 param->val = xstrdup(val);
150
151 return 0;
152 }
153
154 int
istgt_iscsi_param_set_int(ISCSI_PARAM * params,const char * key,int val)155 istgt_iscsi_param_set_int(ISCSI_PARAM *params, const char *key, int val)
156 {
157 char buf[MAX_TMPBUF];
158 ISCSI_PARAM *param;
159
160 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "set %s=%d\n", key, val);
161 param = istgt_iscsi_param_find(params, key);
162 if (param == NULL) {
163 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "no key %s\n", key);
164 return -1;
165 }
166
167 xfree(param->val);
168 snprintf(buf, sizeof buf, "%d", val);
169 param->val = xstrdup(buf);
170
171 return 0;
172 }
173
174 int
istgt_iscsi_parse_params(ISCSI_PARAM ** params,const uint8_t * data,int len)175 istgt_iscsi_parse_params(ISCSI_PARAM **params, const uint8_t *data, int len)
176 {
177 const uint8_t *p, *q;
178 const uint8_t *last;
179 char *key = NULL;
180 char *val = NULL;
181 int rc;
182 int n;
183
184 /* for each key/val temporary store */
185 key = xmalloc(ISCSI_TEXT_MAX_KEY_LEN + 1);
186 val = xmalloc(ISCSI_TEXT_MAX_VAL_LEN + 1);
187
188 /* data = "KEY=VAL<NUL>KEY=VAL<NUL>..." */
189 p = data;
190 last = data + len;
191 while (p < last && *p != '\0') {
192 q = p;
193 /* q = "KEY=VAL<NUL>" */
194 while (q < last && *q != '\0') {
195 if (*q == '=') {
196 break;
197 }
198 q++;
199 }
200 if (q >= last || *q == '\0') {
201 ISTGT_ERRLOG("'=' not found\n");
202 error_return:
203 xfree(key);
204 xfree(val);
205 return -1;
206 }
207 n = q - p;
208 if (n > ISCSI_TEXT_MAX_KEY_LEN) {
209 ISTGT_ERRLOG("Overflow Key %d\n", n);
210 goto error_return;
211 }
212 memcpy(key, p, n);
213 key[n] = '\0';
214
215 p = q + 1;
216 q = p;
217 /* q = "VAL<NUL>" */
218 while (q < last && *q != '\0') {
219 q++;
220 }
221 n = q - p;
222 if (n > ISCSI_TEXT_MAX_VAL_LEN) {
223 ISTGT_ERRLOG("Overflow Val %d\n", n);
224 goto error_return;
225 }
226 memcpy(val, p, n);
227 val[n] = '\0';
228
229 rc = istgt_iscsi_param_add(params, key, val, NULL, 0);
230 if (rc < 0) {
231 ISTGT_ERRLOG("iscsi_param_add() failed\n");
232 goto error_return;
233 }
234
235 p = q + 1;
236 while (p < last && *p == '\0') {
237 p++;
238 }
239 }
240
241 xfree(key);
242 xfree(val);
243 return 0;
244 }
245