xref: /freebsd-13.1/sbin/iscontrol/config.c (revision 1de7b4b8)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2005-2009 Daniel Braniss <[email protected]>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29 /*
30  | $Id: config.c,v 2.1 2006/11/12 08:06:51 danny Exp danny $
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <time.h>
43 #include <ctype.h>
44 #include <camlib.h>
45 
46 #include <dev/iscsi_initiator/iscsi.h>
47 #include "iscontrol.h"
48 
49 /*
50  | ints
51  */
52 #define OPT_port			1
53 #define OPT_tags			2
54 
55 #define OPT_maxConnections		3
56 #define OPT_maxRecvDataSegmentLength	4
57 #define OPT_maxXmitDataSegmentLength	5
58 #define OPT_maxBurstLength		6
59 #define OPT_firstBurstLength		7
60 #define OPT_defaultTime2Wait		8
61 #define OPT_defaultTime2Retain		9
62 #define OPT_maxOutstandingR2T		10
63 #define OPT_errorRecoveryLevel		11
64 #define OPT_targetPortalGroupTag	12
65 #define OPT_headerDigest		13
66 #define OPT_dataDigest			14
67 /*
68  | Booleans
69  */
70 #define OPT_initialR2T			16
71 #define OPT_immediateData		17
72 #define OPT_dataPDUInOrder		18
73 #define OPT_dataSequenceInOrder		19
74 /*
75  | strings
76  */
77 #define OPT_sessionType			15
78 
79 #define OPT_targetAddress		21
80 #define OPT_targetAlias			22
81 #define OPT_targetName			23
82 #define OPT_initiatorName		24
83 #define OPT_initiatorAlias		25
84 #define OPT_authMethod			26
85 
86 #define OPT_chapSecret			27
87 #define OPT_chapIName			28
88 #define OPT_chapDigest			29
89 #define OPT_tgtChapName			30
90 #define OPT_tgtChapSecret		31
91 #define OPT_tgtChallengeLen		32
92 /*
93  | private
94  */
95 #define OPT_maxluns			33
96 #define OPT_iqn				34
97 #define OPT_sockbufsize			35
98 
99 /*
100  | sentinel
101  */
102 #define OPT_end				0
103 
104 #define _OFF(v)	((int)&((isc_opt_t *)NULL)->v)
105 #define _E(u, s, v) {.usage=u, .scope=s, .name=#v, .tokenID=OPT_##v}
106 
107 textkey_t keyMap[] = {
108      _E(U_PR, S_PR, port),
109      _E(U_PR, S_PR, tags),
110      _E(U_PR, S_PR, maxluns),
111      _E(U_PR, S_PR, sockbufsize),
112 
113      _E(U_PR, S_PR, iqn),
114      _E(U_PR, S_PR, chapSecret),
115      _E(U_PR, S_PR, chapIName),
116      _E(U_PR, S_PR, chapDigest),
117      _E(U_PR, S_PR, tgtChapName),
118      _E(U_PR, S_PR, tgtChapSecret),
119      _E(U_PR, S_PR, tgtChallengeLen),
120 
121      _E(U_IO, S_CO, headerDigest),
122      _E(U_IO, S_CO, dataDigest),
123 
124      _E(U_IO, S_CO, authMethod),
125 
126      _E(U_LO, S_SW, maxConnections),
127      _E(U_IO, S_SW, targetName),
128 
129      _E(U_IO, S_SW, initiatorName),
130      _E(U_ALL,S_SW, targetAlias),
131      _E(U_ALL,S_SW, initiatorAlias),
132      _E(U_ALL,S_SW, targetAddress),
133 
134      _E(U_ALL,S_SW, targetPortalGroupTag),
135 
136      _E(U_LO, S_SW, initialR2T),
137      _E(U_LO, S_SW, immediateData),
138 
139      _E(U_ALL,S_CO, maxRecvDataSegmentLength),
140      _E(U_ALL,S_CO, maxXmitDataSegmentLength),
141 
142      _E(U_LO, S_SW, maxBurstLength),
143      _E(U_LO, S_SW, firstBurstLength),
144      _E(U_LO, S_SW, defaultTime2Wait),
145      _E(U_LO, S_SW, defaultTime2Retain),
146 
147      _E(U_LO, S_SW, maxOutstandingR2T),
148      _E(U_LO, S_SW, dataPDUInOrder),
149      _E(U_LO, S_SW, dataSequenceInOrder),
150 
151      _E(U_LO, S_SW, errorRecoveryLevel),
152 
153      _E(U_LO, S_SW, sessionType),
154 
155      _E(0, 0, end)
156 };
157 
158 #define _OPT_INT(w)	strtol((char *)w, NULL, 0)
159 #define _OPT_STR(w)	(char *)(w)
160 
161 static __inline  int
_OPT_BOOL(char * w)162 _OPT_BOOL(char *w)
163 {
164      if(isalpha((unsigned char)*w))
165 	  return strcasecmp(w, "TRUE") == 0;
166      else
167 	  return _OPT_INT(w);
168 }
169 
170 #define _CASE(k, v)	case OPT_##k: op->k = v; break
171 static void
setOption(isc_opt_t * op,int which,void * rval)172 setOption(isc_opt_t *op, int which, void *rval)
173 {
174      switch(which) {
175 	  _CASE(port, _OPT_INT(rval));
176 	  _CASE(tags, _OPT_INT(rval));
177 	  _CASE(maxluns, _OPT_INT(rval));
178 	  _CASE(iqn, _OPT_STR(rval));
179 	  _CASE(sockbufsize, _OPT_INT(rval));
180 
181 	  _CASE(maxConnections, _OPT_INT(rval));
182 	  _CASE(maxRecvDataSegmentLength, _OPT_INT(rval));
183 	  _CASE(maxXmitDataSegmentLength, _OPT_INT(rval));
184 	  _CASE(maxBurstLength, _OPT_INT(rval));
185 	  _CASE(firstBurstLength, _OPT_INT(rval));
186 	  _CASE(defaultTime2Wait, _OPT_INT(rval));
187 	  _CASE(defaultTime2Retain, _OPT_INT(rval));
188 	  _CASE(maxOutstandingR2T, _OPT_INT(rval));
189 	  _CASE(errorRecoveryLevel, _OPT_INT(rval));
190 	  _CASE(targetPortalGroupTag, _OPT_INT(rval));
191 	  _CASE(headerDigest, _OPT_STR(rval));
192 	  _CASE(dataDigest, _OPT_STR(rval));
193 
194 	  _CASE(targetAddress, _OPT_STR(rval));
195 	  _CASE(targetAlias, _OPT_STR(rval));
196 	  _CASE(targetName, _OPT_STR(rval));
197 	  _CASE(initiatorName, _OPT_STR(rval));
198 	  _CASE(initiatorAlias, _OPT_STR(rval));
199 	  _CASE(authMethod, _OPT_STR(rval));
200 	  _CASE(chapSecret, _OPT_STR(rval));
201 	  _CASE(chapIName, _OPT_STR(rval));
202 	  _CASE(chapDigest, _OPT_STR(rval));
203 
204 	  _CASE(tgtChapName, _OPT_STR(rval));
205 	  _CASE(tgtChapSecret, _OPT_STR(rval));
206 
207 	  _CASE(initialR2T, _OPT_BOOL(rval));
208 	  _CASE(immediateData, _OPT_BOOL(rval));
209 	  _CASE(dataPDUInOrder, _OPT_BOOL(rval));
210 	  _CASE(dataSequenceInOrder, _OPT_BOOL(rval));
211      }
212 }
213 
214 static char *
get_line(FILE * fd)215 get_line(FILE *fd)
216 {
217      static char	*sp, line[BUFSIZ];
218      char		*lp, *p;
219 
220      do {
221 	  if(sp == NULL)
222 	       sp = fgets(line, sizeof line, fd);
223 
224 	  if((lp = sp) == NULL)
225 	       break;
226 	  if((p = strchr(lp, '\n')) != NULL)
227 	       *p = 0;
228 	  if((p = strchr(lp, '#')) != NULL)
229 	       *p = 0;
230 	  if((p = strchr(lp, ';')) != NULL) {
231 	       *p++ = 0;
232 	       sp = p;
233 	  } else
234 	       sp = NULL;
235 	  if(*lp)
236 	       return lp;
237      } while (feof(fd) == 0);
238      return NULL;
239 }
240 
241 static int
getConfig(FILE * fd,char * key,char ** Ar,int * nargs)242 getConfig(FILE *fd, char *key, char **Ar, int *nargs)
243 {
244      char	*lp, *p, **ar;
245      int	state, len, n;
246 
247      ar = Ar;
248      if(key)
249 	  len = strlen(key);
250      else
251 	  len = 0;
252      state = 0;
253      while((lp = get_line(fd)) != NULL) {
254 	  for(; isspace((unsigned char)*lp); lp++)
255 	       ;
256 	  switch(state) {
257 	  case 0:
258 	       if((p = strchr(lp, '{')) != NULL) {
259 		    while((--p > lp) && *p && isspace((unsigned char)*p));
260 		    n = p - lp;
261 		    if(len && strncmp(lp, key, MAX(n, len)) == 0)
262 			 state = 2;
263 		    else
264 			 state = 1;
265 		    continue;
266 	       }
267 	       break;
268 
269 	  case 1:
270 	       if(*lp == '}')
271 		    state = 0;
272 	       continue;
273 
274 	  case 2:
275 	       if(*lp == '}')
276 		    goto done;
277 
278 	       break;
279 	  }
280 
281 
282 	  for(p = &lp[strlen(lp)-1]; isspace((unsigned char)*p); p--)
283 	       *p = 0;
284 	  if((*nargs)-- > 0)
285 	       *ar++ = strdup(lp);
286      }
287 
288  done:
289      if(*nargs > 0)
290 	  *ar = 0;
291      *nargs =  ar - Ar;
292      return ar - Ar;
293 }
294 
295 static textkey_t *
keyLookup(char * key)296 keyLookup(char *key)
297 {
298      textkey_t	*tk;
299 
300      for(tk = keyMap; tk->name && strcmp(tk->name, "end"); tk++) {
301 	  if(strcasecmp(key, tk->name) == 0)
302 	       return tk;
303      }
304      return NULL;
305 }
306 
307 static void
puke(isc_opt_t * op)308 puke(isc_opt_t *op)
309 {
310      printf("%24s = %d\n", "port", op->port);
311      printf("%24s = %d\n", "tags", op->tags);
312      printf("%24s = %d\n", "maxluns", op->maxluns);
313      printf("%24s = %s\n", "iqn", op->iqn);
314 
315      printf("%24s = %d\n", "maxConnections", op->maxConnections);
316      printf("%24s = %d\n", "maxRecvDataSegmentLength", op->maxRecvDataSegmentLength);
317      printf("%24s = %d\n", "maxXmitDataSegmentLength", op->maxRecvDataSegmentLength);
318      printf("%24s = %d\n", "maxBurstLength", op->maxBurstLength);
319      printf("%24s = %d\n", "firstBurstLength", op->firstBurstLength);
320      printf("%24s = %d\n", "defaultTime2Wait", op->defaultTime2Wait);
321      printf("%24s = %d\n", "defaultTime2Retain", op->defaultTime2Retain);
322      printf("%24s = %d\n", "maxOutstandingR2T", op->maxOutstandingR2T);
323      printf("%24s = %d\n", "errorRecoveryLevel", op->errorRecoveryLevel);
324      printf("%24s = %d\n", "targetPortalGroupTag", op->targetPortalGroupTag);
325 
326      printf("%24s = %s\n", "headerDigest", op->headerDigest);
327      printf("%24s = %s\n", "dataDigest", op->dataDigest);
328 
329      printf("%24s = %d\n", "initialR2T", op->initialR2T);
330      printf("%24s = %d\n", "immediateData", op->immediateData);
331      printf("%24s = %d\n", "dataPDUInOrder", op->dataPDUInOrder);
332      printf("%24s = %d\n", "dataSequenceInOrder", op->dataSequenceInOrder);
333 
334      printf("%24s = %s\n", "sessionType", op->sessionType);
335      printf("%24s = %s\n", "targetAddress", op->targetAddress);
336      printf("%24s = %s\n", "targetAlias", op->targetAlias);
337      printf("%24s = %s\n", "targetName", op->targetName);
338      printf("%24s = %s\n", "initiatorName", op->initiatorName);
339      printf("%24s = %s\n", "initiatorAlias", op->initiatorAlias);
340      printf("%24s = %s\n", "authMethod", op->authMethod);
341      printf("%24s = %s\n", "chapSecret", op->chapSecret);
342      printf("%24s = %s\n", "chapIName", op->chapIName);
343      printf("%24s = %s\n", "tgtChapName", op->tgtChapName);
344      printf("%24s = %s\n", "tgtChapSecret", op->tgtChapSecret);
345      printf("%24s = %d\n", "tgttgtChallengeLen", op->tgtChallengeLen);
346 }
347 
348 void
parseArgs(int nargs,char ** args,isc_opt_t * op)349 parseArgs(int nargs, char **args, isc_opt_t *op)
350 {
351      char	**ar;
352      char	*p, *v;
353      textkey_t	*tk;
354 
355      for(ar = args; nargs > 0; nargs--, ar++) {
356 	  p = strchr(*ar, '=');
357 	  if(p == NULL)
358 	       continue;
359 	  *p = 0;
360 	  v = p + 1;
361 	  while(isspace((unsigned char)*--p))
362 	       *p = 0;
363 	  while(isspace((unsigned char)*v))
364 	       v++;
365 	  if((tk = keyLookup(*ar)) == NULL)
366 	       continue;
367 	  setOption(op, tk->tokenID, v);
368      }
369 }
370 
371 void
parseConfig(FILE * fd,char * key,isc_opt_t * op)372 parseConfig(FILE *fd, char *key, isc_opt_t *op)
373 {
374      char	*Ar[256];
375      int	cc;
376 
377      cc = 256;
378      if(getConfig(fd, key, Ar, &cc))
379 	  parseArgs(cc, Ar, op);
380      if(vflag)
381 	  puke(op);
382 }
383