1171568Sscottl /*-
2211095Sdes * Copyright (c) 2005-2009 Daniel Braniss <danny@cs.huji.ac.il>
3171568Sscottl * All rights reserved.
4171568Sscottl *
5171568Sscottl * Redistribution and use in source and binary forms, with or without
6171568Sscottl * modification, are permitted provided that the following conditions
7171568Sscottl * are met:
8171568Sscottl * 1. Redistributions of source code must retain the above copyright
9171568Sscottl *    notice, this list of conditions and the following disclaimer.
10171568Sscottl * 2. Redistributions in binary form must reproduce the above copyright
11171568Sscottl *    notice, this list of conditions and the following disclaimer in the
12171568Sscottl *    documentation and/or other materials provided with the distribution.
13171568Sscottl *
14171568Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15171568Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16171568Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17171568Sscottl * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18171568Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19171568Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20171568Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21171568Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22171568Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23171568Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24171568Sscottl * SUCH DAMAGE.
25171568Sscottl *
26171568Sscottl */
27171568Sscottl/*
28171568Sscottl | $Id: config.c,v 2.1 2006/11/12 08:06:51 danny Exp danny $
29171568Sscottl */
30171568Sscottl
31171568Sscottl#include <sys/cdefs.h>
32171568Sscottl__FBSDID("$FreeBSD$");
33171568Sscottl
34171568Sscottl#include <stdlib.h>
35171568Sscottl#include <unistd.h>
36171568Sscottl#include <stdio.h>
37171568Sscottl#include <string.h>
38171568Sscottl#include <errno.h>
39171568Sscottl#include <fcntl.h>
40171568Sscottl#include <time.h>
41171568Sscottl#include <ctype.h>
42171568Sscottl#include <camlib.h>
43171568Sscottl
44211095Sdes#include <dev/iscsi/initiator/iscsi.h>
45171568Sscottl#include "iscontrol.h"
46171568Sscottl
47171568Sscottl/*
48171568Sscottl | ints
49171568Sscottl */
50171568Sscottl#define OPT_port			1
51171568Sscottl#define OPT_tags			2
52171568Sscottl
53171568Sscottl#define OPT_maxConnections		3
54171568Sscottl#define OPT_maxRecvDataSegmentLength	4
55171568Sscottl#define OPT_maxXmitDataSegmentLength	5
56171568Sscottl#define OPT_maxBurstLength		6
57171568Sscottl#define OPT_firstBurstLength		7
58171568Sscottl#define OPT_defaultTime2Wait		8
59171568Sscottl#define OPT_defaultTime2Retain		9
60171568Sscottl#define OPT_maxOutstandingR2T		10
61171568Sscottl#define OPT_errorRecoveryLevel		11
62171568Sscottl#define OPT_targetPortalGroupTag	12
63171568Sscottl#define OPT_headerDigest		13
64171568Sscottl#define OPT_dataDigest			14
65171568Sscottl/*
66171568Sscottl | Booleans
67171568Sscottl */
68171568Sscottl#define OPT_initialR2T			16
69171568Sscottl#define OPT_immediateData		17
70171568Sscottl#define OPT_dataPDUInOrder		18
71171568Sscottl#define OPT_dataSequenceInOrder		19
72171568Sscottl/*
73171568Sscottl | strings
74171568Sscottl */
75171568Sscottl#define OPT_sessionType			15
76171568Sscottl
77171568Sscottl#define OPT_targetAddress		21
78171568Sscottl#define OPT_targetAlias			22
79171568Sscottl#define OPT_targetName			23
80171568Sscottl#define OPT_initiatorName		24
81171568Sscottl#define OPT_initiatorAlias		25
82171568Sscottl#define OPT_authMethod			26
83171568Sscottl
84171568Sscottl#define OPT_chapSecret			27
85171568Sscottl#define OPT_chapIName			28
86171568Sscottl#define OPT_chapDigest			29
87171568Sscottl#define OPT_tgtChapName			30
88171568Sscottl#define OPT_tgtChapSecret		31
89171568Sscottl#define OPT_tgtChallengeLen		32
90171568Sscottl/*
91171568Sscottl | private
92171568Sscottl */
93171568Sscottl#define OPT_maxluns			33
94171568Sscottl#define OPT_iqn				34
95171568Sscottl#define OPT_sockbufsize			35
96171568Sscottl
97211095Sdes/*
98211095Sdes | sentinel
99211095Sdes */
100211095Sdes#define OPT_end				0
101211095Sdes
102171568Sscottl#define _OFF(v)	((int)&((isc_opt_t *)NULL)->v)
103171568Sscottl#define _E(u, s, v) {.usage=u, .scope=s, .name=#v, .tokenID=OPT_##v}
104171568Sscottl
105171568Sscottltextkey_t keyMap[] = {
106171568Sscottl     _E(U_PR, S_PR, port),
107171568Sscottl     _E(U_PR, S_PR, tags),
108171568Sscottl     _E(U_PR, S_PR, maxluns),
109171568Sscottl     _E(U_PR, S_PR, sockbufsize),
110171568Sscottl
111171568Sscottl     _E(U_PR, S_PR, iqn),
112171568Sscottl     _E(U_PR, S_PR, chapSecret),
113171568Sscottl     _E(U_PR, S_PR, chapIName),
114171568Sscottl     _E(U_PR, S_PR, chapDigest),
115171568Sscottl     _E(U_PR, S_PR, tgtChapName),
116171568Sscottl     _E(U_PR, S_PR, tgtChapSecret),
117171568Sscottl     _E(U_PR, S_PR, tgtChallengeLen),
118171568Sscottl
119171568Sscottl     _E(U_IO, S_CO, headerDigest),
120171568Sscottl     _E(U_IO, S_CO, dataDigest),
121171568Sscottl
122171568Sscottl     _E(U_IO, S_CO, authMethod),
123171568Sscottl
124171568Sscottl     _E(U_LO, S_SW, maxConnections),
125171568Sscottl     _E(U_IO, S_SW, targetName),
126171568Sscottl
127171568Sscottl     _E(U_IO, S_SW, initiatorName),
128171568Sscottl     _E(U_ALL,S_SW, targetAlias),
129171568Sscottl     _E(U_ALL,S_SW, initiatorAlias),
130171568Sscottl     _E(U_ALL,S_SW, targetAddress),
131171568Sscottl
132171568Sscottl     _E(U_ALL,S_SW, targetPortalGroupTag),
133171568Sscottl
134171568Sscottl     _E(U_LO, S_SW, initialR2T),
135171568Sscottl     _E(U_LO, S_SW, immediateData),
136171568Sscottl
137171568Sscottl     _E(U_ALL,S_CO, maxRecvDataSegmentLength),
138171568Sscottl     _E(U_ALL,S_CO, maxXmitDataSegmentLength),
139171568Sscottl
140171568Sscottl     _E(U_LO, S_SW, maxBurstLength),
141171568Sscottl     _E(U_LO, S_SW, firstBurstLength),
142171568Sscottl     _E(U_LO, S_SW, defaultTime2Wait),
143171568Sscottl     _E(U_LO, S_SW, defaultTime2Retain),
144171568Sscottl
145171568Sscottl     _E(U_LO, S_SW, maxOutstandingR2T),
146171568Sscottl     _E(U_LO, S_SW, dataPDUInOrder),
147171568Sscottl     _E(U_LO, S_SW, dataSequenceInOrder),
148171568Sscottl
149171568Sscottl     _E(U_LO, S_SW, errorRecoveryLevel),
150171568Sscottl
151171568Sscottl     _E(U_LO, S_SW, sessionType),
152171568Sscottl
153211095Sdes     _E(0, 0, end)
154171568Sscottl};
155171568Sscottl
156171568Sscottl#define _OPT_INT(w)	strtol((char *)w, NULL, 0)
157171568Sscottl#define _OPT_STR(w)	(char *)(w)
158171568Sscottl
159171568Sscottlstatic __inline  int
160171568Sscottl_OPT_BOOL(char *w)
161171568Sscottl{
162211095Sdes     if(isalpha((unsigned char)*w))
163171568Sscottl	  return strcasecmp(w, "TRUE") == 0;
164171568Sscottl     else
165171568Sscottl	  return _OPT_INT(w);
166171568Sscottl}
167171568Sscottl
168171568Sscottl#define _CASE(k, v)	case OPT_##k: op->k = v; break
169171568Sscottlstatic void
170171568SscottlsetOption(isc_opt_t *op, int which, void *rval)
171171568Sscottl{
172171568Sscottl     switch(which) {
173171568Sscottl	  _CASE(port, _OPT_INT(rval));
174171568Sscottl	  _CASE(tags, _OPT_INT(rval));
175171568Sscottl	  _CASE(maxluns, _OPT_INT(rval));
176171568Sscottl	  _CASE(iqn, _OPT_STR(rval));
177171568Sscottl	  _CASE(sockbufsize, _OPT_INT(rval));
178171568Sscottl
179171568Sscottl	  _CASE(maxConnections, _OPT_INT(rval));
180171568Sscottl	  _CASE(maxRecvDataSegmentLength, _OPT_INT(rval));
181171568Sscottl	  _CASE(maxXmitDataSegmentLength, _OPT_INT(rval));
182171568Sscottl	  _CASE(maxBurstLength, _OPT_INT(rval));
183171568Sscottl	  _CASE(firstBurstLength, _OPT_INT(rval));
184171568Sscottl	  _CASE(defaultTime2Wait, _OPT_INT(rval));
185171568Sscottl	  _CASE(defaultTime2Retain, _OPT_INT(rval));
186171568Sscottl	  _CASE(maxOutstandingR2T, _OPT_INT(rval));
187171568Sscottl	  _CASE(errorRecoveryLevel, _OPT_INT(rval));
188171568Sscottl	  _CASE(targetPortalGroupTag, _OPT_INT(rval));
189171568Sscottl	  _CASE(headerDigest, _OPT_STR(rval));
190171568Sscottl	  _CASE(dataDigest, _OPT_STR(rval));
191171568Sscottl
192171568Sscottl	  _CASE(targetAddress, _OPT_STR(rval));
193171568Sscottl	  _CASE(targetAlias, _OPT_STR(rval));
194171568Sscottl	  _CASE(targetName, _OPT_STR(rval));
195171568Sscottl	  _CASE(initiatorName, _OPT_STR(rval));
196171568Sscottl	  _CASE(initiatorAlias, _OPT_STR(rval));
197171568Sscottl	  _CASE(authMethod, _OPT_STR(rval));
198171568Sscottl	  _CASE(chapSecret, _OPT_STR(rval));
199171568Sscottl	  _CASE(chapIName, _OPT_STR(rval));
200171568Sscottl	  _CASE(chapDigest, _OPT_STR(rval));
201171568Sscottl
202171568Sscottl	  _CASE(tgtChapName, _OPT_STR(rval));
203171568Sscottl	  _CASE(tgtChapSecret, _OPT_STR(rval));
204171568Sscottl
205171568Sscottl	  _CASE(initialR2T, _OPT_BOOL(rval));
206171568Sscottl	  _CASE(immediateData, _OPT_BOOL(rval));
207171568Sscottl	  _CASE(dataPDUInOrder, _OPT_BOOL(rval));
208171568Sscottl	  _CASE(dataSequenceInOrder, _OPT_BOOL(rval));
209171568Sscottl     }
210171568Sscottl}
211171568Sscottl
212171568Sscottlstatic char *
213171568Sscottlgetline(FILE *fd)
214171568Sscottl{
215171568Sscottl     static char	*sp, line[BUFSIZ];
216171568Sscottl     char		*lp, *p;
217171568Sscottl
218171568Sscottl     do {
219171568Sscottl	  if(sp == NULL)
220171568Sscottl	       sp = fgets(line, sizeof line, fd);
221171568Sscottl
222171568Sscottl	  if((lp = sp) == NULL)
223171568Sscottl	       break;
224171568Sscottl	  if((p = strchr(lp, '\n')) != NULL)
225171568Sscottl	       *p = 0;
226171568Sscottl	  if((p = strchr(lp, '#')) != NULL)
227171568Sscottl	       *p = 0;
228171568Sscottl	  if((p = strchr(lp, ';')) != NULL) {
229171568Sscottl	       *p++ = 0;
230171568Sscottl	       sp = p;
231171568Sscottl	  } else
232171568Sscottl	       sp = NULL;
233171568Sscottl	  if(*lp)
234171568Sscottl	       return lp;
235171568Sscottl     } while (feof(fd) == 0);
236171568Sscottl     return NULL;
237171568Sscottl}
238171568Sscottl
239171568Sscottlstatic int
240171568SscottlgetConfig(FILE *fd, char *key, char **Ar, int *nargs)
241171568Sscottl{
242171568Sscottl     char	*lp, *p, **ar;
243171568Sscottl     int	state, len, n;
244171568Sscottl
245171568Sscottl     ar = Ar;
246171568Sscottl     if(key)
247171568Sscottl	  len = strlen(key);
248171568Sscottl     else
249171568Sscottl	  len = 0;
250171568Sscottl     state = 0;
251171568Sscottl     while((lp = getline(fd)) != NULL) {
252211095Sdes	  for(; isspace((unsigned char)*lp); lp++)
253171568Sscottl	       ;
254171568Sscottl	  switch(state) {
255171568Sscottl	  case 0:
256171568Sscottl	       if((p = strchr(lp, '{')) != NULL) {
257211095Sdes		    while((--p > lp) && *p && isspace((unsigned char)*p));
258171568Sscottl		    n = p - lp;
259171568Sscottl		    if(len && strncmp(lp, key, MAX(n, len)) == 0)
260171568Sscottl			 state = 2;
261171568Sscottl		    else
262171568Sscottl			 state = 1;
263171568Sscottl		    continue;
264171568Sscottl	       }
265171568Sscottl	       break;
266171568Sscottl
267171568Sscottl	  case 1:
268171568Sscottl	       if(*lp == '}')
269171568Sscottl		    state = 0;
270171568Sscottl	       continue;
271171568Sscottl
272171568Sscottl	  case 2:
273171568Sscottl	       if(*lp == '}')
274171568Sscottl		    goto done;
275171568Sscottl
276171568Sscottl	       break;
277171568Sscottl	  }
278171568Sscottl
279171568Sscottl
280211095Sdes	  for(p = &lp[strlen(lp)-1]; isspace((unsigned char)*p); p--)
281171568Sscottl	       *p = 0;
282171568Sscottl	  if((*nargs)-- > 0)
283171568Sscottl	       *ar++ = strdup(lp);
284171568Sscottl     }
285171568Sscottl
286171568Sscottl done:
287171568Sscottl     if(*nargs > 0)
288171568Sscottl	  *ar = 0;
289171568Sscottl     *nargs =  ar - Ar;
290171568Sscottl     return ar - Ar;
291171568Sscottl}
292171568Sscottl
293171568Sscottlstatic textkey_t *
294171568SscottlkeyLookup(char *key)
295171568Sscottl{
296171568Sscottl     textkey_t	*tk;
297171568Sscottl
298217859Scracauer     for(tk = keyMap; tk->name && strcmp(tk->name, "end"); tk++) {
299171568Sscottl	  if(strcasecmp(key, tk->name) == 0)
300171568Sscottl	       return tk;
301171568Sscottl     }
302171568Sscottl     return NULL;
303171568Sscottl}
304171568Sscottl
305171568Sscottlstatic void
306171568Sscottlpuke(isc_opt_t *op)
307171568Sscottl{
308171568Sscottl     printf("%24s = %d\n", "port", op->port);
309171568Sscottl     printf("%24s = %d\n", "tags", op->tags);
310171568Sscottl     printf("%24s = %d\n", "maxluns", op->maxluns);
311171568Sscottl     printf("%24s = %s\n", "iqn", op->iqn);
312171568Sscottl
313171568Sscottl     printf("%24s = %d\n", "maxConnections", op->maxConnections);
314171568Sscottl     printf("%24s = %d\n", "maxRecvDataSegmentLength", op->maxRecvDataSegmentLength);
315171568Sscottl     printf("%24s = %d\n", "maxXmitDataSegmentLength", op->maxRecvDataSegmentLength);
316171568Sscottl     printf("%24s = %d\n", "maxBurstLength", op->maxBurstLength);
317171568Sscottl     printf("%24s = %d\n", "firstBurstLength", op->firstBurstLength);
318171568Sscottl     printf("%24s = %d\n", "defaultTime2Wait", op->defaultTime2Wait);
319171568Sscottl     printf("%24s = %d\n", "defaultTime2Retain", op->defaultTime2Retain);
320171568Sscottl     printf("%24s = %d\n", "maxOutstandingR2T", op->maxOutstandingR2T);
321171568Sscottl     printf("%24s = %d\n", "errorRecoveryLevel", op->errorRecoveryLevel);
322171568Sscottl     printf("%24s = %d\n", "targetPortalGroupTag", op->targetPortalGroupTag);
323171568Sscottl
324171568Sscottl     printf("%24s = %s\n", "headerDigest", op->headerDigest);
325171568Sscottl     printf("%24s = %s\n", "dataDigest", op->dataDigest);
326171568Sscottl
327171568Sscottl     printf("%24s = %d\n", "initialR2T", op->initialR2T);
328171568Sscottl     printf("%24s = %d\n", "immediateData", op->immediateData);
329171568Sscottl     printf("%24s = %d\n", "dataPDUInOrder", op->dataPDUInOrder);
330171568Sscottl     printf("%24s = %d\n", "dataSequenceInOrder", op->dataSequenceInOrder);
331171568Sscottl
332171568Sscottl     printf("%24s = %s\n", "sessionType", op->sessionType);
333171568Sscottl     printf("%24s = %s\n", "targetAddress", op->targetAddress);
334171568Sscottl     printf("%24s = %s\n", "targetAlias", op->targetAlias);
335171568Sscottl     printf("%24s = %s\n", "targetName", op->targetName);
336171568Sscottl     printf("%24s = %s\n", "initiatorName", op->initiatorName);
337171568Sscottl     printf("%24s = %s\n", "initiatorAlias", op->initiatorAlias);
338171568Sscottl     printf("%24s = %s\n", "authMethod", op->authMethod);
339171568Sscottl     printf("%24s = %s\n", "chapSecret", op->chapSecret);
340171568Sscottl     printf("%24s = %s\n", "chapIName", op->chapIName);
341171568Sscottl     printf("%24s = %s\n", "tgtChapName", op->tgtChapName);
342171568Sscottl     printf("%24s = %s\n", "tgtChapSecret", op->tgtChapSecret);
343171568Sscottl     printf("%24s = %d\n", "tgttgtChallengeLen", op->tgtChallengeLen);
344171568Sscottl}
345171568Sscottl
346171568Sscottlvoid
347171568SscottlparseArgs(int nargs, char **args, isc_opt_t *op)
348171568Sscottl{
349171568Sscottl     char	**ar;
350171568Sscottl     char	*p, *v;
351171568Sscottl     textkey_t	*tk;
352171568Sscottl
353171568Sscottl     for(ar = args; nargs > 0; nargs--, ar++) {
354171568Sscottl	  p = strchr(*ar, '=');
355171568Sscottl	  if(p == NULL)
356171568Sscottl	       continue;
357171568Sscottl	  *p = 0;
358171568Sscottl	  v = p + 1;
359211095Sdes	  while(isspace((unsigned char)*--p))
360171568Sscottl	       *p = 0;
361211095Sdes	  while(isspace((unsigned char)*v))
362171568Sscottl	       v++;
363171568Sscottl	  if((tk = keyLookup(*ar)) == NULL)
364171568Sscottl	       continue;
365171568Sscottl	  setOption(op, tk->tokenID, v);
366171568Sscottl     }
367171568Sscottl}
368171568Sscottl
369171568Sscottlvoid
370171568SscottlparseConfig(FILE *fd, char *key, isc_opt_t *op)
371171568Sscottl{
372171568Sscottl     char	*Ar[256];
373171568Sscottl     int	cc;
374171568Sscottl
375171568Sscottl     cc = 256;
376171568Sscottl     if(getConfig(fd, key, Ar, &cc))
377171568Sscottl	  parseArgs(cc, Ar, op);
378171568Sscottl     if(vflag)
379171568Sscottl	  puke(op);
380171568Sscottl}
381