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