config.c revision 185289
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: head/sbin/iscontrol/config.c 185289 2008-11-25 07:17:11Z scottl $");
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
100textkey_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
154static __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
164static void
165setOption(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
207static char *
208getline(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
234static int
235getConfig(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
289static textkey_t *
290keyLookup(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
301static void
302puke(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
342void
343parseArgs(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
365void
366parseConfig(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}
377