xref: /dragonfly/sbin/iscontrol/config.c (revision fb151170)
1 /*-
2  * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
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 THE 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 THE 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  | $Id: config.c,v 2.1 2006/11/12 08:06:51 danny Exp danny $
29  */
30 
31 #include <sys/cdefs.h>
32 
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <time.h>
40 #include <ctype.h>
41 #include <camlib.h>
42 
43 #include "iscsi.h"
44 #include "iscontrol.h"
45 
46 /*
47  | ints
48  */
49 #define OPT_port			1
50 #define OPT_tags			2
51 
52 #define OPT_maxConnections		3
53 #define OPT_maxRecvDataSegmentLength	4
54 #define OPT_maxXmitDataSegmentLength	5
55 #define OPT_maxBurstLength		6
56 #define OPT_firstBurstLength		7
57 #define OPT_defaultTime2Wait		8
58 #define OPT_defaultTime2Retain		9
59 #define OPT_maxOutstandingR2T		10
60 #define OPT_errorRecoveryLevel		11
61 #define OPT_targetPortalGroupTag	12
62 #define OPT_headerDigest		13
63 #define OPT_dataDigest			14
64 /*
65  | Booleans
66  */
67 #define OPT_initialR2T			16
68 #define OPT_immediateData		17
69 #define OPT_dataPDUInOrder		18
70 #define OPT_dataSequenceInOrder		19
71 /*
72  | strings
73  */
74 #define OPT_sessionType			15
75 
76 #define OPT_targetAddress		21
77 #define OPT_targetAlias			22
78 #define OPT_targetName			23
79 #define OPT_initiatorName		24
80 #define OPT_initiatorAlias		25
81 #define OPT_authMethod			26
82 
83 #define OPT_chapSecret			27
84 #define OPT_chapIName			28
85 #define OPT_chapDigest			29
86 #define OPT_tgtChapName			30
87 #define OPT_tgtChapSecret		31
88 #define OPT_tgtChallengeLen		32
89 /*
90  | private
91  */
92 #define OPT_maxluns			33
93 #define OPT_iqn				34
94 #define OPT_sockbufsize			35
95 
96 #define _OFF(v)	((int)&((isc_opt_t *)NULL)->v)
97 #define _E(u, s, v) {.usage=u, .scope=s, .name=#v, .tokenID=OPT_##v}
98 
99 textkey_t keyMap[] = {
100      _E(U_PR, S_PR, port),
101      _E(U_PR, S_PR, tags),
102      _E(U_PR, S_PR, maxluns),
103      _E(U_PR, S_PR, sockbufsize),
104 
105      _E(U_PR, S_PR, iqn),
106      _E(U_PR, S_PR, chapSecret),
107      _E(U_PR, S_PR, chapIName),
108      _E(U_PR, S_PR, chapDigest),
109      _E(U_PR, S_PR, tgtChapName),
110      _E(U_PR, S_PR, tgtChapSecret),
111      _E(U_PR, S_PR, tgtChallengeLen),
112 
113      _E(U_IO, S_CO, headerDigest),
114      _E(U_IO, S_CO, dataDigest),
115 
116      _E(U_IO, S_CO, authMethod),
117 
118      _E(U_LO, S_SW, maxConnections),
119      _E(U_IO, S_SW, targetName),
120 
121      _E(U_IO, S_SW, initiatorName),
122      _E(U_ALL,S_SW, targetAlias),
123      _E(U_ALL,S_SW, initiatorAlias),
124      _E(U_ALL,S_SW, targetAddress),
125 
126      _E(U_ALL,S_SW, targetPortalGroupTag),
127 
128      _E(U_LO, S_SW, initialR2T),
129      _E(U_LO, S_SW, immediateData),
130 
131      _E(U_ALL,S_CO, maxRecvDataSegmentLength),
132      _E(U_ALL,S_CO, maxXmitDataSegmentLength),
133 
134      _E(U_LO, S_SW, maxBurstLength),
135      _E(U_LO, S_SW, firstBurstLength),
136      _E(U_LO, S_SW, defaultTime2Wait),
137      _E(U_LO, S_SW, defaultTime2Retain),
138 
139      _E(U_LO, S_SW, maxOutstandingR2T),
140      _E(U_LO, S_SW, dataPDUInOrder),
141      _E(U_LO, S_SW, dataSequenceInOrder),
142 
143      _E(U_LO, S_SW, errorRecoveryLevel),
144 
145      _E(U_LO, S_SW, sessionType),
146 
147      {0, 0, 0, 0}
148 };
149 
150 #define _OPT_INT(w)	strtol((char *)w, NULL, 0)
151 #define _OPT_STR(w)	(char *)(w)
152 
153 static __inline  int
154 _OPT_BOOL(char *w)
155 {
156      if(isalpha(*w))
157 	  return strcasecmp(w, "TRUE") == 0;
158      else
159 	  return _OPT_INT(w);
160 }
161 
162 #define _CASE(k, v)	case OPT_##k: op->k = v; break
163 static void
164 setOption(isc_opt_t *op, int which, void *rval)
165 {
166      switch(which) {
167 	  _CASE(port, _OPT_INT(rval));
168 	  _CASE(tags, _OPT_INT(rval));
169 	  _CASE(maxluns, _OPT_INT(rval));
170 	  _CASE(iqn, _OPT_STR(rval));
171 	  _CASE(sockbufsize, _OPT_INT(rval));
172 
173 	  _CASE(maxConnections, _OPT_INT(rval));
174 	  _CASE(maxRecvDataSegmentLength, _OPT_INT(rval));
175 	  _CASE(maxXmitDataSegmentLength, _OPT_INT(rval));
176 	  _CASE(maxBurstLength, _OPT_INT(rval));
177 	  _CASE(firstBurstLength, _OPT_INT(rval));
178 	  _CASE(defaultTime2Wait, _OPT_INT(rval));
179 	  _CASE(defaultTime2Retain, _OPT_INT(rval));
180 	  _CASE(maxOutstandingR2T, _OPT_INT(rval));
181 	  _CASE(errorRecoveryLevel, _OPT_INT(rval));
182 	  _CASE(targetPortalGroupTag, _OPT_INT(rval));
183 	  _CASE(headerDigest, _OPT_STR(rval));
184 	  _CASE(dataDigest, _OPT_STR(rval));
185 
186 	  _CASE(targetAddress, _OPT_STR(rval));
187 	  _CASE(targetAlias, _OPT_STR(rval));
188 	  _CASE(targetName, _OPT_STR(rval));
189 	  _CASE(initiatorName, _OPT_STR(rval));
190 	  _CASE(initiatorAlias, _OPT_STR(rval));
191 	  _CASE(authMethod, _OPT_STR(rval));
192 	  _CASE(chapSecret, _OPT_STR(rval));
193 	  _CASE(chapIName, _OPT_STR(rval));
194 	  _CASE(chapDigest, _OPT_STR(rval));
195 
196 	  _CASE(tgtChapName, _OPT_STR(rval));
197 	  _CASE(tgtChapSecret, _OPT_STR(rval));
198 
199 	  _CASE(initialR2T, _OPT_BOOL(rval));
200 	  _CASE(immediateData, _OPT_BOOL(rval));
201 	  _CASE(dataPDUInOrder, _OPT_BOOL(rval));
202 	  _CASE(dataSequenceInOrder, _OPT_BOOL(rval));
203      }
204 }
205 
206 static char *
207 getline(FILE *fd)
208 {
209      static char	*sp, line[BUFSIZ];
210      char		*lp, *p;
211 
212      do {
213 	  if(sp == NULL)
214 	       sp = fgets(line, sizeof line, fd);
215 
216 	  if((lp = sp) == NULL)
217 	       break;
218 	  if((p = strchr(lp, '\n')) != NULL)
219 	       *p = 0;
220 	  if((p = strchr(lp, '#')) != NULL)
221 	       *p = 0;
222 	  if((p = strchr(lp, ';')) != NULL) {
223 	       *p++ = 0;
224 	       sp = p;
225 	  } else
226 	       sp = NULL;
227 	  if(*lp)
228 	       return lp;
229      } while (feof(fd) == 0);
230      return NULL;
231 }
232 
233 static int
234 getConfig(FILE *fd, char *key, char **Ar, int *nargs)
235 {
236      char	*lp, *p, **ar;
237      int	state, len, n;
238 
239      ar = Ar;
240      if(key)
241 	  len = strlen(key);
242      else
243 	  len = 0;
244      state = 0;
245      while((lp = getline(fd)) != NULL) {
246 	  for(; isspace(*lp); lp++)
247 	       ;
248 	  switch(state) {
249 	  case 0:
250 	       if((p = strchr(lp, '{')) != NULL) {
251 		    n = 0;
252 		    while((--p > lp) && *p && isspace(*p));
253 		    n = p - lp;
254 		    if(len && strncmp(lp, key, MAX(n, len)) == 0)
255 			 state = 2;
256 		    else
257 			 state = 1;
258 		    continue;
259 	       }
260 	       break;
261 
262 	  case 1:
263 	       if(*lp == '}')
264 		    state = 0;
265 	       continue;
266 
267 	  case 2:
268 	       if(*lp == '}')
269 		    goto done;
270 
271 	       break;
272 	  }
273 
274 
275 	  for(p = &lp[strlen(lp)-1]; isspace(*p); p--)
276 	       *p = 0;
277 	  if((*nargs)-- > 0)
278 	       *ar++ = strdup(lp);
279      }
280 
281  done:
282      if(*nargs > 0)
283 	  *ar = 0;
284      *nargs =  ar - Ar;
285      return ar - Ar;
286 }
287 
288 static textkey_t *
289 keyLookup(char *key)
290 {
291      textkey_t	*tk;
292 
293      for(tk = keyMap; tk->name; tk++) {
294 	  if(strcasecmp(key, tk->name) == 0)
295 	       return tk;
296      }
297      return NULL;
298 }
299 
300 static void
301 puke(isc_opt_t *op)
302 {
303      printf("%24s = %d\n", "port", op->port);
304      printf("%24s = %d\n", "tags", op->tags);
305      printf("%24s = %d\n", "maxluns", op->maxluns);
306      printf("%24s = %s\n", "iqn", op->iqn);
307 
308      printf("%24s = %d\n", "maxConnections", op->maxConnections);
309      printf("%24s = %d\n", "maxRecvDataSegmentLength", op->maxRecvDataSegmentLength);
310      printf("%24s = %d\n", "maxXmitDataSegmentLength", op->maxRecvDataSegmentLength);
311      printf("%24s = %d\n", "maxBurstLength", op->maxBurstLength);
312      printf("%24s = %d\n", "firstBurstLength", op->firstBurstLength);
313      printf("%24s = %d\n", "defaultTime2Wait", op->defaultTime2Wait);
314      printf("%24s = %d\n", "defaultTime2Retain", op->defaultTime2Retain);
315      printf("%24s = %d\n", "maxOutstandingR2T", op->maxOutstandingR2T);
316      printf("%24s = %d\n", "errorRecoveryLevel", op->errorRecoveryLevel);
317      printf("%24s = %d\n", "targetPortalGroupTag", op->targetPortalGroupTag);
318 
319      printf("%24s = %s\n", "headerDigest", op->headerDigest);
320      printf("%24s = %s\n", "dataDigest", op->dataDigest);
321 
322      printf("%24s = %d\n", "initialR2T", op->initialR2T);
323      printf("%24s = %d\n", "immediateData", op->immediateData);
324      printf("%24s = %d\n", "dataPDUInOrder", op->dataPDUInOrder);
325      printf("%24s = %d\n", "dataSequenceInOrder", op->dataSequenceInOrder);
326 
327      printf("%24s = %s\n", "sessionType", op->sessionType);
328      printf("%24s = %s\n", "targetAddress", op->targetAddress);
329      printf("%24s = %s\n", "targetAlias", op->targetAlias);
330      printf("%24s = %s\n", "targetName", op->targetName);
331      printf("%24s = %s\n", "initiatorName", op->initiatorName);
332      printf("%24s = %s\n", "initiatorAlias", op->initiatorAlias);
333      printf("%24s = %s\n", "authMethod", op->authMethod);
334      printf("%24s = %s\n", "chapSecret", op->chapSecret);
335      printf("%24s = %s\n", "chapIName", op->chapIName);
336      printf("%24s = %s\n", "tgtChapName", op->tgtChapName);
337      printf("%24s = %s\n", "tgtChapSecret", op->tgtChapSecret);
338      printf("%24s = %d\n", "tgttgtChallengeLen", op->tgtChallengeLen);
339 }
340 
341 void
342 parseArgs(int nargs, char **args, isc_opt_t *op)
343 {
344      char	**ar;
345      char	*p, *v;
346      textkey_t	*tk;
347 
348      for(ar = args; nargs > 0; nargs--, ar++) {
349 	  p = strchr(*ar, '=');
350 	  if(p == NULL)
351 	       continue;
352 	  *p = 0;
353 	  v = p + 1;
354 	  while(isspace(*--p))
355 	       *p = 0;
356 	  while(isspace(*v))
357 	       v++;
358 	  if((tk = keyLookup(*ar)) == NULL)
359 	       continue;
360 	  setOption(op, tk->tokenID, v);
361      }
362 }
363 
364 void
365 parseConfig(FILE *fd, char *key, isc_opt_t *op)
366 {
367      char	*Ar[256];
368      int	cc;
369 
370      cc = 256;
371      if(getConfig(fd, key, Ar, &cc))
372 	  parseArgs(cc, Ar, op);
373      if(vflag)
374 	  puke(op);
375 }
376