GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/iscsictl/parse.c Lines: 0 204 0.0 %
Date: 2017-11-07 Branches: 0 160 0.0 %

Line Branch Exec Source
1
#include <stdlib.h>
2
#include <string.h>
3
#define YYBYACC 1
4
#define YYMAJOR 1
5
#define YYMINOR 9
6
#define YYLEX yylex()
7
#define YYEMPTY -1
8
#define yyclearin (yychar=(YYEMPTY))
9
#define yyerrok (yyerrflag=0)
10
#define YYRECOVERING() (yyerrflag!=0)
11
#define YYPREFIX "yy"
12
#line 26 "parse.y"
13
#include <sys/types.h>
14
#include <sys/queue.h>
15
#include <sys/socket.h>
16
#include <sys/stat.h>
17
#include <sys/uio.h>
18
#include <netinet/in.h>
19
#include <arpa/inet.h>
20
#include <ctype.h>
21
#include <err.h>
22
#include <errno.h>
23
#include <event.h>
24
#include <limits.h>
25
#include <netdb.h>
26
#include <stdarg.h>
27
#include <stdio.h>
28
#include <string.h>
29
#include <unistd.h>
30
31
#include <scsi/iscsi.h>
32
#include "iscsid.h"
33
#include "iscsictl.h"
34
35
TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
36
static struct file {
37
	TAILQ_ENTRY(file)	 entry;
38
	FILE			*stream;
39
	char			*name;
40
	int			 lineno;
41
	int			 errors;
42
} *file, *topfile;
43
struct file	*pushfile(const char *, int);
44
int		 popfile(void);
45
int		 yyparse(void);
46
int		 yylex(void);
47
int		 yyerror(const char *, ...)
48
    __attribute__((__format__ (printf, 1, 2)))
49
    __attribute__((__nonnull__ (1)));
50
int		 kw_cmp(const void *, const void *);
51
int		 lookup(char *);
52
int		 lgetc(int);
53
int		 lungetc(int);
54
int		 findeol(void);
55
56
void		 clear_config(struct iscsi_config *);
57
58
TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
59
struct sym {
60
	TAILQ_ENTRY(sym)	 entry;
61
	int			 used;
62
	int			 persist;
63
	char			*nam;
64
	char			*val;
65
};
66
int		 symset(const char *, const char *, int);
67
char		*symget(const char *);
68
69
static int			 errors;
70
static struct iscsi_config	*conf;
71
static struct session_config	*session;
72
73
struct addrinfo_opts {
74
	int	af;
75
	char	*port;
76
} addrinfo_opts;
77
78
typedef struct {
79
	union {
80
		int			 i;
81
		int64_t			 number;
82
		char			*string;
83
		struct addrinfo_opts	 addrinfo_opts;
84
		struct addrinfo		*addrinfo;
85
	} v;
86
	int lineno;
87
} YYSTYPE;
88
89
#line 90 "parse.c"
90
#define TARGET 257
91
#define TARGETNAME 258
92
#define TARGETADDR 259
93
#define INITIATORNAME 260
94
#define INITIATORADDR 261
95
#define ISID 262
96
#define ENABLED 263
97
#define DISABLED 264
98
#define NORMAL 265
99
#define DISCOVERY 266
100
#define ADDRESS 267
101
#define INET 268
102
#define INET6 269
103
#define PORT 270
104
#define INCLUDE 271
105
#define ERROR 272
106
#define STRING 273
107
#define NUMBER 274
108
#define YYERRCODE 256
109
const short yylhs[] =
110
	{                                        -1,
111
    0,    0,    0,    0,    0,    0,    0,   10,    9,    9,
112
   11,   14,   14,   15,   12,   16,   13,   17,   17,   18,
113
   18,   18,   18,   18,   18,    5,   19,    6,    6,    7,
114
    7,    8,    8,    4,    1,    1,    2,    2,    3,    3,
115
};
116
const short yylen[] =
117
	{                                         2,
118
    0,    2,    3,    3,    3,    3,    3,    2,    2,    1,
119
    3,    2,    0,    2,    4,    0,    7,    3,    2,    1,
120
    1,    2,    2,    2,    2,    2,    0,    2,    0,    2,
121
    1,    1,    1,    2,    1,    1,    1,    1,    1,    1,
122
};
123
const short yydefred[] =
124
	{                                      1,
125
    0,    0,    0,    0,    0,    0,    2,    0,    0,    0,
126
    0,    7,   16,    0,    8,    0,    3,    4,    5,    6,
127
    0,    0,   10,    0,    0,   15,    9,    0,    0,   12,
128
    0,    0,    0,    0,   37,   38,   39,   40,   20,   21,
129
    0,    0,   22,    0,   24,   23,   25,   17,    0,   19,
130
   26,    0,    0,   18,   35,   36,    0,   33,   32,    0,
131
   31,   14,   34,   30,
132
};
133
const short yydgoto[] =
134
	{                                       1,
135
   58,   39,   40,   59,   45,   51,   60,   61,   24,    8,
136
    9,   10,   11,   29,   54,   21,   41,   42,   52,
137
};
138
const short yysindex[] =
139
	{                                      0,
140
  -10,   -8, -266, -265, -263,  -52,    0,    1,    3,    4,
141
    5,    0,    0, -252,    0, -246,    0,    0,    0,    0,
142
  -89, -235,    0, -233,   31,    0,    0,   31, -240,    0,
143
 -231, -230, -229, -230,    0,    0,    0,    0,    0,    0,
144
 -124,   31,    0,    0,    0,    0,    0,    0,   35,    0,
145
    0, -264,   31,    0,    0,    0, -227,    0,    0, -264,
146
    0,    0,    0,    0,};
147
const short yyrindex[] =
148
	{                                      0,
149
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
150
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
151
    0,    0,    0,   37, -228,    0,    0, -113,    0,    0,
152
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
153
    0, -113,    0,    6,    0,    0,    0,    0,    0,    0,
154
    0,    0, -113,    0,    0,    0,    0,    0,    0,   19,
155
    0,    0,    0,    0,};
156
const short yygindex[] =
157
	{                                      0,
158
    0,    0,    0,    0,   14,    0,    0,  -11,    0,    0,
159
    0,    0,    0,  -25,    0,    0,    0,    9,    0,
160
};
161
#define YYTABLESIZE 285
162
const short yytable[] =
163
	{                                       7,
164
   48,   12,   30,   55,   56,   57,   13,   14,   16,   15,
165
   17,   13,   18,   19,   20,   29,   50,   31,   32,   33,
166
   34,   22,   35,   36,   37,   38,   23,   62,   28,   13,
167
   13,   13,   13,   25,   13,   13,   13,   13,   26,   27,
168
   28,   43,   44,   46,   53,   63,   11,   47,   64,   49,
169
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
170
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
171
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
172
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
173
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
174
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
175
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
176
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
177
   29,    0,    0,   31,   32,   33,   34,    0,   35,   36,
178
   37,   38,    0,   28,   13,   13,   13,   13,    0,   13,
179
   13,   13,   13,    0,    0,    0,    0,    0,    0,    0,
180
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
181
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
182
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
183
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
184
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
185
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
186
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
187
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
188
    0,    0,    0,    0,    0,    2,    3,    0,    0,    0,
189
    0,    4,    0,    0,    0,    0,    0,    0,    0,    0,
190
    5,    0,    6,   29,   29,   29,   29,    0,   29,   29,
191
   29,   29,    0,   27,   27,   27,   28,   28,   28,   28,
192
    0,   28,   28,   28,   28,
193
};
194
const short yycheck[] =
195
	{                                      10,
196
  125,   10,   28,  268,  269,  270,  273,  273,   61,  273,
197
   10,  125,   10,   10,   10,   10,   42,  258,  259,  260,
198
  261,  274,  263,  264,  265,  266,  273,   53,   10,  258,
199
  259,  260,  261,  123,  263,  264,  265,  266,  274,  273,
200
   10,  273,  273,  273,   10,  273,   10,   34,   60,   41,
201
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
202
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
203
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
204
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
205
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
206
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
207
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
208
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
209
  125,   -1,   -1,  258,  259,  260,  261,   -1,  263,  264,
210
  265,  266,   -1,  125,  258,  259,  260,  261,   -1,  263,
211
  264,  265,  266,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
212
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
213
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
214
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
215
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
216
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
217
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
218
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
219
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
220
   -1,   -1,   -1,   -1,   -1,  256,  257,   -1,   -1,   -1,
221
   -1,  262,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
222
  271,   -1,  273,  258,  259,  260,  261,   -1,  263,  264,
223
  265,  266,   -1,  268,  269,  270,  258,  259,  260,  261,
224
   -1,  263,  264,  265,  266,
225
};
226
#define YYFINAL 1
227
#ifndef YYDEBUG
228
#define YYDEBUG 0
229
#endif
230
#define YYMAXTOKEN 274
231
#if YYDEBUG
232
const char * const yyname[] =
233
	{
234
"end-of-file",0,0,0,0,0,0,0,0,0,"'\\n'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
235
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'='",0,0,0,0,0,0,0,
236
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
237
0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
238
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
239
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
240
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"TARGET",
241
"TARGETNAME","TARGETADDR","INITIATORNAME","INITIATORADDR","ISID","ENABLED",
242
"DISABLED","NORMAL","DISCOVERY","ADDRESS","INET","INET6","PORT","INCLUDE",
243
"ERROR","STRING","NUMBER",
244
};
245
const char * const yyrule[] =
246
	{"$accept : grammar",
247
"grammar :",
248
"grammar : grammar '\\n'",
249
"grammar : grammar include '\\n'",
250
"grammar : grammar varset '\\n'",
251
"grammar : grammar initiator '\\n'",
252
"grammar : grammar target '\\n'",
253
"grammar : grammar error '\\n'",
254
"include : INCLUDE STRING",
255
"string : string STRING",
256
"string : STRING",
257
"varset : STRING '=' string",
258
"optnl : '\\n' optnl",
259
"optnl :",
260
"nl : '\\n' optnl",
261
"initiator : ISID STRING NUMBER NUMBER",
262
"$$1 :",
263
"target : TARGET STRING $$1 '{' optnl targetopts_l '}'",
264
"targetopts_l : targetopts_l targetoptsl nl",
265
"targetopts_l : targetoptsl optnl",
266
"targetoptsl : state",
267
"targetoptsl : type",
268
"targetoptsl : TARGETNAME STRING",
269
"targetoptsl : INITIATORNAME STRING",
270
"targetoptsl : TARGETADDR addrinfo",
271
"targetoptsl : INITIATORADDR addrinfo",
272
"addrinfo : STRING addrinfo_opts",
273
"$$2 :",
274
"addrinfo_opts : $$2 addrinfo_opts_l",
275
"addrinfo_opts :",
276
"addrinfo_opts_l : addrinfo_opts_l addrinfo_opt",
277
"addrinfo_opts_l : addrinfo_opt",
278
"addrinfo_opt : port",
279
"addrinfo_opt : af",
280
"port : PORT STRING",
281
"af : INET",
282
"af : INET6",
283
"state : ENABLED",
284
"state : DISABLED",
285
"type : NORMAL",
286
"type : DISCOVERY",
287
};
288
#endif
289
#ifdef YYSTACKSIZE
290
#undef YYMAXDEPTH
291
#define YYMAXDEPTH YYSTACKSIZE
292
#else
293
#ifdef YYMAXDEPTH
294
#define YYSTACKSIZE YYMAXDEPTH
295
#else
296
#define YYSTACKSIZE 10000
297
#define YYMAXDEPTH 10000
298
#endif
299
#endif
300
#define YYINITSTACKSIZE 200
301
/* LINTUSED */
302
int yydebug;
303
int yynerrs;
304
int yyerrflag;
305
int yychar;
306
short *yyssp;
307
YYSTYPE *yyvsp;
308
YYSTYPE yyval;
309
YYSTYPE yylval;
310
short *yyss;
311
short *yysslim;
312
YYSTYPE *yyvs;
313
unsigned int yystacksize;
314
int yyparse(void);
315
#line 335 "parse.y"
316
317
struct keywords {
318
	const char	*k_name;
319
	int		 k_val;
320
};
321
322
int
323
yyerror(const char *fmt, ...)
324
{
325
	va_list	ap;
326
327
	file->errors++;
328
	va_start(ap, fmt);
329
	fprintf(stderr, "%s:%d: ", file->name, yylval.lineno);
330
	vfprintf(stderr, fmt, ap);
331
	fprintf(stderr, "\n");
332
	va_end(ap);
333
	return (0);
334
}
335
336
int
337
kw_cmp(const void *k, const void *e)
338
{
339
	return (strcmp(k, ((const struct keywords *)e)->k_name));
340
}
341
342
int
343
lookup(char *s)
344
{
345
	/* this has to be sorted always */
346
	static const struct keywords keywords[] = {
347
		{"address",		ADDRESS},
348
		{"disabled",		DISABLED},
349
		{"discovery",		DISCOVERY},
350
		{"enabled",		ENABLED},
351
		{"include",		INCLUDE},
352
		{"inet",		INET},
353
		{"inet4",		INET},
354
		{"inet6",		INET6},
355
		{"initiatoraddr",	INITIATORADDR},
356
		{"initiatorname",	INITIATORNAME},
357
		{"isid",		ISID},
358
		{"normal",		NORMAL},
359
		{"port",		PORT},
360
		{"target",		TARGET},
361
		{"targetaddr",		TARGETADDR},
362
		{"targetname",		TARGETNAME}
363
	};
364
	const struct keywords	*p;
365
366
	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
367
	    sizeof(keywords[0]), kw_cmp);
368
369
	if (p)
370
		return (p->k_val);
371
	else
372
		return (STRING);
373
}
374
375
#define MAXPUSHBACK	128
376
377
u_char	*parsebuf;
378
int	 parseindex;
379
u_char	 pushback_buffer[MAXPUSHBACK];
380
int	 pushback_index;
381
382
int
383
lgetc(int quotec)
384
{
385
	int		c, next;
386
387
	if (parsebuf) {
388
		/* Read character from the parsebuffer instead of input. */
389
		if (parseindex >= 0) {
390
			c = parsebuf[parseindex++];
391
			if (c != '\0')
392
				return (c);
393
			parsebuf = NULL;
394
		} else
395
			parseindex++;
396
	}
397
398
	if (pushback_index)
399
		return (pushback_buffer[--pushback_index]);
400
401
	if (quotec) {
402
		if ((c = getc(file->stream)) == EOF) {
403
			yyerror("reached end of file while parsing "
404
			    "quoted string");
405
			if (file == topfile || popfile() == EOF)
406
				return (EOF);
407
			return (quotec);
408
		}
409
		return (c);
410
	}
411
412
	while ((c = getc(file->stream)) == '\\') {
413
		next = getc(file->stream);
414
		if (next != '\n') {
415
			c = next;
416
			break;
417
		}
418
		yylval.lineno = file->lineno;
419
		file->lineno++;
420
	}
421
422
	while (c == EOF) {
423
		if (file == topfile || popfile() == EOF)
424
			return (EOF);
425
		c = getc(file->stream);
426
	}
427
	return (c);
428
}
429
430
int
431
lungetc(int c)
432
{
433
	if (c == EOF)
434
		return (EOF);
435
	if (parsebuf) {
436
		parseindex--;
437
		if (parseindex >= 0)
438
			return (c);
439
	}
440
	if (pushback_index < MAXPUSHBACK-1)
441
		return (pushback_buffer[pushback_index++] = c);
442
	else
443
		return (EOF);
444
}
445
446
int
447
findeol(void)
448
{
449
	int	c;
450
451
	parsebuf = NULL;
452
453
	/* skip to either EOF or the first real EOL */
454
	while (1) {
455
		if (pushback_index)
456
			c = pushback_buffer[--pushback_index];
457
		else
458
			c = lgetc(0);
459
		if (c == '\n') {
460
			file->lineno++;
461
			break;
462
		}
463
		if (c == EOF)
464
			break;
465
	}
466
	return (ERROR);
467
}
468
469
int
470
yylex(void)
471
{
472
	u_char	 buf[8096];
473
	u_char	*p, *val;
474
	int	 quotec, next, c;
475
	int	 token;
476
477
top:
478
	p = buf;
479
	while ((c = lgetc(0)) == ' ' || c == '\t')
480
		; /* nothing */
481
482
	yylval.lineno = file->lineno;
483
	if (c == '#')
484
		while ((c = lgetc(0)) != '\n' && c != EOF)
485
			; /* nothing */
486
	if (c == '$' && parsebuf == NULL) {
487
		while (1) {
488
			if ((c = lgetc(0)) == EOF)
489
				return (0);
490
491
			if (p + 1 >= buf + sizeof(buf) - 1) {
492
				yyerror("string too long");
493
				return (findeol());
494
			}
495
			if (isalnum(c) || c == '_') {
496
				*p++ = c;
497
				continue;
498
			}
499
			*p = '\0';
500
			lungetc(c);
501
			break;
502
		}
503
		val = symget(buf);
504
		if (val == NULL) {
505
			yyerror("macro '%s' not defined", buf);
506
			return (findeol());
507
		}
508
		parsebuf = val;
509
		parseindex = 0;
510
		goto top;
511
	}
512
513
	switch (c) {
514
	case '\'':
515
	case '"':
516
		quotec = c;
517
		while (1) {
518
			if ((c = lgetc(quotec)) == EOF)
519
				return (0);
520
			if (c == '\n') {
521
				file->lineno++;
522
				continue;
523
			} else if (c == '\\') {
524
				if ((next = lgetc(quotec)) == EOF)
525
					return (0);
526
				if (next == quotec || c == ' ' || c == '\t')
527
					c = next;
528
				else if (next == '\n') {
529
					file->lineno++;
530
					continue;
531
				} else
532
					lungetc(next);
533
			} else if (c == quotec) {
534
				*p = '\0';
535
				break;
536
			} else if (c == '\0') {
537
				yyerror("syntax error");
538
				return (findeol());
539
			}
540
			if (p + 1 >= buf + sizeof(buf) - 1) {
541
				yyerror("string too long");
542
				return (findeol());
543
			}
544
			*p++ = c;
545
		}
546
		yylval.v.string = strdup(buf);
547
		if (yylval.v.string == NULL)
548
			err(1, "yylex: strdup");
549
		return (STRING);
550
	}
551
552
#define allowed_to_end_number(x) \
553
	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
554
555
	if (c == '-' || isdigit(c)) {
556
		do {
557
			*p++ = c;
558
			if ((unsigned)(p-buf) >= sizeof(buf)) {
559
				yyerror("string too long");
560
				return (findeol());
561
			}
562
		} while ((c = lgetc(0)) != EOF && isdigit(c));
563
		lungetc(c);
564
		if (p == buf + 1 && buf[0] == '-')
565
			goto nodigits;
566
		if (c == EOF || allowed_to_end_number(c)) {
567
			const char *errstr = NULL;
568
569
			*p = '\0';
570
			yylval.v.number = strtonum(buf, LLONG_MIN,
571
			    LLONG_MAX, &errstr);
572
			if (errstr) {
573
				yyerror("\"%s\" invalid number: %s",
574
				    buf, errstr);
575
				return (findeol());
576
			}
577
			return (NUMBER);
578
		} else {
579
nodigits:
580
			while (p > buf + 1)
581
				lungetc(*--p);
582
			c = *--p;
583
			if (c == '-')
584
				return (c);
585
		}
586
	}
587
588
#define allowed_in_string(x) \
589
	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
590
	x != '{' && x != '}' && \
591
	x != '!' && x != '=' && x != '#' && \
592
	x != ','))
593
594
	if (isalnum(c) || c == ':' || c == '_') {
595
		do {
596
			*p++ = c;
597
			if ((unsigned)(p-buf) >= sizeof(buf)) {
598
				yyerror("string too long");
599
				return (findeol());
600
			}
601
		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
602
		lungetc(c);
603
		*p = '\0';
604
		if ((token = lookup(buf)) == STRING)
605
			if ((yylval.v.string = strdup(buf)) == NULL)
606
				err(1, "yylex: strdup");
607
		return (token);
608
	}
609
	if (c == '\n') {
610
		yylval.lineno = file->lineno;
611
		file->lineno++;
612
	}
613
	if (c == EOF)
614
		return (0);
615
	return (c);
616
}
617
618
struct file *
619
pushfile(const char *name, int secret)
620
{
621
	struct file	*nfile;
622
623
	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
624
		warn("malloc");
625
		return (NULL);
626
	}
627
	if ((nfile->name = strdup(name)) == NULL) {
628
		warn("malloc");
629
		free(nfile);
630
		return (NULL);
631
	}
632
	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
633
		warn("%s", nfile->name);
634
		free(nfile->name);
635
		free(nfile);
636
		return (NULL);
637
	}
638
	nfile->lineno = 1;
639
	TAILQ_INSERT_TAIL(&files, nfile, entry);
640
	return (nfile);
641
}
642
643
int
644
popfile(void)
645
{
646
	struct file	*prev;
647
648
	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
649
		prev->errors += file->errors;
650
651
	TAILQ_REMOVE(&files, file, entry);
652
	fclose(file->stream);
653
	free(file->name);
654
	free(file);
655
	file = prev;
656
	return (file ? 0 : EOF);
657
}
658
659
struct iscsi_config *
660
parse_config(char *filename)
661
{
662
	struct sym	*sym, *next;
663
664
	file = pushfile(filename, 1);
665
	if (file == NULL)
666
		return (NULL);
667
	topfile = file;
668
669
	conf = calloc(1, sizeof(struct iscsi_config));
670
	if (conf == NULL)
671
		return (NULL);
672
	SIMPLEQ_INIT(&conf->sessions);
673
674
	yyparse();
675
	errors = file->errors;
676
	popfile();
677
678
	/* Free macros and check which have not been used. */
679
	TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
680
		if (!sym->persist) {
681
			free(sym->nam);
682
			free(sym->val);
683
			TAILQ_REMOVE(&symhead, sym, entry);
684
			free(sym);
685
		}
686
	}
687
688
	if (errors) {
689
		clear_config(conf);
690
		return (NULL);
691
	}
692
693
	return (conf);
694
}
695
696
int
697
cmdline_symset(char *s)
698
{
699
	char	*sym, *val;
700
	int	ret;
701
	size_t	len;
702
703
	if ((val = strrchr(s, '=')) == NULL)
704
		return (-1);
705
706
	len = strlen(s) - strlen(val) + 1;
707
	if ((sym = malloc(len)) == NULL)
708
		errx(1, "cmdline_symset: malloc");
709
710
	strlcpy(sym, s, len);
711
712
	ret = symset(sym, val + 1, 1);
713
	free(sym);
714
715
	return (ret);
716
}
717
718
char *
719
symget(const char *nam)
720
{
721
	struct sym	*sym;
722
723
	TAILQ_FOREACH(sym, &symhead, entry) {
724
		if (strcmp(nam, sym->nam) == 0) {
725
			sym->used = 1;
726
			return (sym->val);
727
		}
728
	}
729
	return (NULL);
730
}
731
732
int
733
symset(const char *nam, const char *val, int persist)
734
{
735
	struct sym	*sym;
736
737
	TAILQ_FOREACH(sym, &symhead, entry) {
738
		if (strcmp(nam, sym->nam) == 0)
739
			break;
740
	}
741
742
	if (sym != NULL) {
743
		if (sym->persist == 1)
744
			return (0);
745
		else {
746
			free(sym->nam);
747
			free(sym->val);
748
			TAILQ_REMOVE(&symhead, sym, entry);
749
			free(sym);
750
		}
751
	}
752
	if ((sym = calloc(1, sizeof(*sym))) == NULL)
753
		return (-1);
754
755
	sym->nam = strdup(nam);
756
	if (sym->nam == NULL) {
757
		free(sym);
758
		return (-1);
759
	}
760
	sym->val = strdup(val);
761
	if (sym->val == NULL) {
762
		free(sym->nam);
763
		free(sym);
764
		return (-1);
765
	}
766
	sym->used = 0;
767
	sym->persist = persist;
768
	TAILQ_INSERT_TAIL(&symhead, sym, entry);
769
	return (0);
770
}
771
772
void
773
clear_config(struct iscsi_config *c)
774
{
775
	struct session_ctlcfg *s;
776
777
	while ((s = SIMPLEQ_FIRST(&c->sessions))) {
778
		SIMPLEQ_REMOVE_HEAD(&c->sessions, entry);
779
		free(s->session.TargetName);
780
		free(s->session.InitiatorName);
781
		free(s);
782
	}
783
784
	free(c);
785
}
786
#line 779 "parse.c"
787
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
788
static int yygrowstack(void)
789
{
790
    unsigned int newsize;
791
    long sslen;
792
    short *newss;
793
    YYSTYPE *newvs;
794
795
    if ((newsize = yystacksize) == 0)
796
        newsize = YYINITSTACKSIZE;
797
    else if (newsize >= YYMAXDEPTH)
798
        return -1;
799
    else if ((newsize *= 2) > YYMAXDEPTH)
800
        newsize = YYMAXDEPTH;
801
    sslen = yyssp - yyss;
802
#ifdef SIZE_MAX
803
#define YY_SIZE_MAX SIZE_MAX
804
#else
805
#define YY_SIZE_MAX 0xffffffffU
806
#endif
807
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newss)
808
        goto bail;
809
    newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
810
      (short *)malloc(newsize * sizeof *newss); /* overflow check above */
811
    if (newss == NULL)
812
        goto bail;
813
    yyss = newss;
814
    yyssp = newss + sslen;
815
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newvs)
816
        goto bail;
817
    newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
818
      (YYSTYPE *)malloc(newsize * sizeof *newvs); /* overflow check above */
819
    if (newvs == NULL)
820
        goto bail;
821
    yyvs = newvs;
822
    yyvsp = newvs + sslen;
823
    yystacksize = newsize;
824
    yysslim = yyss + newsize - 1;
825
    return 0;
826
bail:
827
    if (yyss)
828
            free(yyss);
829
    if (yyvs)
830
            free(yyvs);
831
    yyss = yyssp = NULL;
832
    yyvs = yyvsp = NULL;
833
    yystacksize = 0;
834
    return -1;
835
}
836
837
#define YYABORT goto yyabort
838
#define YYREJECT goto yyabort
839
#define YYACCEPT goto yyaccept
840
#define YYERROR goto yyerrlab
841
int
842
yyparse(void)
843
{
844
    int yym, yyn, yystate;
845
#if YYDEBUG
846
    const char *yys;
847
848
    if ((yys = getenv("YYDEBUG")))
849
    {
850
        yyn = *yys;
851
        if (yyn >= '0' && yyn <= '9')
852
            yydebug = yyn - '0';
853
    }
854
#endif /* YYDEBUG */
855
856
    yynerrs = 0;
857
    yyerrflag = 0;
858
    yychar = (-1);
859
860
    if (yyss == NULL && yygrowstack()) goto yyoverflow;
861
    yyssp = yyss;
862
    yyvsp = yyvs;
863
    *yyssp = yystate = 0;
864
865
yyloop:
866
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
867
    if (yychar < 0)
868
    {
869
        if ((yychar = yylex()) < 0) yychar = 0;
870
#if YYDEBUG
871
        if (yydebug)
872
        {
873
            yys = 0;
874
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
875
            if (!yys) yys = "illegal-symbol";
876
            printf("%sdebug: state %d, reading %d (%s)\n",
877
                    YYPREFIX, yystate, yychar, yys);
878
        }
879
#endif
880
    }
881
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
882
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
883
    {
884
#if YYDEBUG
885
        if (yydebug)
886
            printf("%sdebug: state %d, shifting to state %d\n",
887
                    YYPREFIX, yystate, yytable[yyn]);
888
#endif
889
        if (yyssp >= yysslim && yygrowstack())
890
        {
891
            goto yyoverflow;
892
        }
893
        *++yyssp = yystate = yytable[yyn];
894
        *++yyvsp = yylval;
895
        yychar = (-1);
896
        if (yyerrflag > 0)  --yyerrflag;
897
        goto yyloop;
898
    }
899
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
900
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
901
    {
902
        yyn = yytable[yyn];
903
        goto yyreduce;
904
    }
905
    if (yyerrflag) goto yyinrecovery;
906
#if defined(__GNUC__)
907
    goto yynewerror;
908
#endif
909
yynewerror:
910
    yyerror("syntax error");
911
#if defined(__GNUC__)
912
    goto yyerrlab;
913
#endif
914
yyerrlab:
915
    ++yynerrs;
916
yyinrecovery:
917
    if (yyerrflag < 3)
918
    {
919
        yyerrflag = 3;
920
        for (;;)
921
        {
922
            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
923
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
924
            {
925
#if YYDEBUG
926
                if (yydebug)
927
                    printf("%sdebug: state %d, error recovery shifting\
928
 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
929
#endif
930
                if (yyssp >= yysslim && yygrowstack())
931
                {
932
                    goto yyoverflow;
933
                }
934
                *++yyssp = yystate = yytable[yyn];
935
                *++yyvsp = yylval;
936
                goto yyloop;
937
            }
938
            else
939
            {
940
#if YYDEBUG
941
                if (yydebug)
942
                    printf("%sdebug: error recovery discarding state %d\n",
943
                            YYPREFIX, *yyssp);
944
#endif
945
                if (yyssp <= yyss) goto yyabort;
946
                --yyssp;
947
                --yyvsp;
948
            }
949
        }
950
    }
951
    else
952
    {
953
        if (yychar == 0) goto yyabort;
954
#if YYDEBUG
955
        if (yydebug)
956
        {
957
            yys = 0;
958
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
959
            if (!yys) yys = "illegal-symbol";
960
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
961
                    YYPREFIX, yystate, yychar, yys);
962
        }
963
#endif
964
        yychar = (-1);
965
        goto yyloop;
966
    }
967
yyreduce:
968
#if YYDEBUG
969
    if (yydebug)
970
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
971
                YYPREFIX, yystate, yyn, yyrule[yyn]);
972
#endif
973
    yym = yylen[yyn];
974
    if (yym)
975
        yyval = yyvsp[1-yym];
976
    else
977
        memset(&yyval, 0, sizeof yyval);
978
    switch (yyn)
979
    {
980
case 7:
981
#line 126 "parse.y"
982
{ file->errors++; }
983
break;
984
case 8:
985
#line 129 "parse.y"
986
{
987
			struct file	*nfile;
988
989
			if ((nfile = pushfile(yyvsp[0].v.string, 1)) == NULL) {
990
				yyerror("failed to include file %s", yyvsp[0].v.string);
991
				free(yyvsp[0].v.string);
992
				YYERROR;
993
			}
994
			free(yyvsp[0].v.string);
995
996
			file = nfile;
997
			lungetc('\n');
998
		}
999
break;
1000
case 9:
1001
#line 144 "parse.y"
1002
{
1003
			if (asprintf(&yyval.v.string, "%s %s", yyvsp[-1].v.string, yyvsp[0].v.string) == -1) {
1004
				free(yyvsp[-1].v.string);
1005
				free(yyvsp[0].v.string);
1006
				yyerror("string: asprintf");
1007
				YYERROR;
1008
			}
1009
			free(yyvsp[-1].v.string);
1010
			free(yyvsp[0].v.string);
1011
		}
1012
break;
1013
case 11:
1014
#line 157 "parse.y"
1015
{
1016
			char *s = yyvsp[-2].v.string;
1017
			while (*s++) {
1018
				if (isspace((unsigned char)*s)) {
1019
					yyerror("macro name cannot contain "
1020
					    "whitespace");
1021
					YYERROR;
1022
				}
1023
			}
1024
			if (symset(yyvsp[-2].v.string, yyvsp[0].v.string, 0) == -1)
1025
				err(1, "cannot store variable");
1026
			free(yyvsp[-2].v.string);
1027
			free(yyvsp[0].v.string);
1028
		}
1029
break;
1030
case 15:
1031
#line 180 "parse.y"
1032
{
1033
			u_int32_t mask1, mask2;
1034
1035
			if (!strcasecmp(yyvsp[-2].v.string, "oui")) {
1036
				conf->initiator.isid_base = ISCSI_ISID_OUI;
1037
				mask1 = 0x3fffff00;
1038
				mask2 = 0x000000ff;
1039
			} else if (!strcasecmp(yyvsp[-2].v.string, "en")) {
1040
				conf->initiator.isid_base = ISCSI_ISID_EN;
1041
				mask1 = 0x00ffffff;
1042
				mask2 = 0;
1043
			} else if (!strcasecmp(yyvsp[-2].v.string, "rand")) {
1044
				conf->initiator.isid_base = ISCSI_ISID_RAND;
1045
				mask1 = 0x00ffffff;
1046
				mask2 = 0;
1047
			} else {
1048
				yyerror("isid type %s unknown", yyvsp[-2].v.string);
1049
				free(yyvsp[-2].v.string);
1050
				YYERROR;
1051
			}
1052
			free(yyvsp[-2].v.string);
1053
			conf->initiator.isid_base |= yyvsp[-1].v.number & mask1;
1054
			conf->initiator.isid_base |= (yyvsp[0].v.number >> 16) & mask2;
1055
			conf->initiator.isid_qual = yyvsp[0].v.number;
1056
		}
1057
break;
1058
case 16:
1059
#line 207 "parse.y"
1060
{
1061
			struct session_ctlcfg *scelm;
1062
1063
			scelm = calloc(1, sizeof(*scelm));
1064
			session = &scelm->session;
1065
			if (strlcpy(session->SessionName, yyvsp[0].v.string,
1066
			    sizeof(session->SessionName)) >=
1067
			    sizeof(session->SessionName)) {
1068
				yyerror("target name \"%s\" too long", yyvsp[0].v.string);
1069
				free(yyvsp[0].v.string);
1070
				free(scelm);
1071
				YYERROR;
1072
			}
1073
			free(yyvsp[0].v.string);
1074
			SIMPLEQ_INSERT_TAIL(&conf->sessions, scelm, entry);
1075
		}
1076
break;
1077
case 20:
1078
#line 229 "parse.y"
1079
{ session->disabled = yyvsp[0].v.i; }
1080
break;
1081
case 21:
1082
#line 230 "parse.y"
1083
{ session->SessionType = yyvsp[0].v.i; }
1084
break;
1085
case 22:
1086
#line 231 "parse.y"
1087
{ session->TargetName = yyvsp[0].v.string; }
1088
break;
1089
case 23:
1090
#line 232 "parse.y"
1091
{ session->InitiatorName = yyvsp[0].v.string; }
1092
break;
1093
case 24:
1094
#line 233 "parse.y"
1095
{
1096
			bcopy(yyvsp[0].v.addrinfo->ai_addr, &session->connection.TargetAddr,
1097
			    yyvsp[0].v.addrinfo->ai_addr->sa_len);
1098
			freeaddrinfo(yyvsp[0].v.addrinfo);
1099
		}
1100
break;
1101
case 25:
1102
#line 238 "parse.y"
1103
{
1104
			((struct sockaddr_in *)yyvsp[0].v.addrinfo->ai_addr)->sin_port = 0;
1105
			bcopy(yyvsp[0].v.addrinfo->ai_addr, &session->connection.LocalAddr,
1106
			    yyvsp[0].v.addrinfo->ai_addr->sa_len);
1107
			freeaddrinfo(yyvsp[0].v.addrinfo);
1108
		}
1109
break;
1110
case 26:
1111
#line 246 "parse.y"
1112
{
1113
			struct addrinfo hints;
1114
			char *hostname;
1115
			int error;
1116
1117
			yyval.v.addrinfo = NULL;
1118
1119
			if (yyvsp[0].v.addrinfo_opts.port == NULL) {
1120
				if ((yyvsp[0].v.addrinfo_opts.port = strdup("iscsi")) == NULL) {
1121
					free(yyvsp[-1].v.string);
1122
					yyerror("port strdup");
1123
					YYERROR;
1124
				}
1125
			}
1126
1127
			memset(&hints, 0, sizeof(hints));
1128
			hints.ai_family = yyvsp[0].v.addrinfo_opts.af;
1129
			hints.ai_socktype = SOCK_STREAM;
1130
			hints.ai_protocol = IPPROTO_TCP;
1131
1132
			if (strcmp(yyvsp[-1].v.string, "*") == 0) {
1133
				hostname = NULL;
1134
				hints.ai_flags = AI_PASSIVE;
1135
			} else
1136
				hostname = yyvsp[-1].v.string;
1137
1138
			error = getaddrinfo(hostname, yyvsp[0].v.addrinfo_opts.port, &hints, &yyval.v.addrinfo);
1139
			if (error) {
1140
				yyerror("%s (%s %s)", gai_strerror(error),
1141
				    yyvsp[-1].v.string, yyvsp[0].v.addrinfo_opts.port);
1142
				free(yyvsp[-1].v.string);
1143
				free(yyvsp[0].v.addrinfo_opts.port);
1144
				YYERROR;
1145
			}
1146
1147
			free(yyvsp[-1].v.string);
1148
			free(yyvsp[0].v.addrinfo_opts.port);
1149
		}
1150
break;
1151
case 27:
1152
#line 286 "parse.y"
1153
{
1154
			addrinfo_opts.port = NULL;
1155
			addrinfo_opts.af = PF_UNSPEC;
1156
		}
1157
break;
1158
case 28:
1159
#line 290 "parse.y"
1160
{ yyval.v.addrinfo_opts = addrinfo_opts; }
1161
break;
1162
case 29:
1163
#line 291 "parse.y"
1164
{
1165
			addrinfo_opts.port = NULL;
1166
			addrinfo_opts.af = PF_UNSPEC;
1167
			yyval.v.addrinfo_opts = addrinfo_opts;
1168
		}
1169
break;
1170
case 32:
1171
#line 302 "parse.y"
1172
{
1173
			if (addrinfo_opts.port != NULL) {
1174
				yyerror("port cannot be redefined");
1175
				YYERROR;
1176
			}
1177
			addrinfo_opts.port = yyvsp[0].v.string;
1178
		}
1179
break;
1180
case 33:
1181
#line 309 "parse.y"
1182
{
1183
			if (addrinfo_opts.af != PF_UNSPEC) {
1184
				yyerror("address family cannot be redefined");
1185
				YYERROR;
1186
			}
1187
			addrinfo_opts.af = yyvsp[0].v.i;
1188
		}
1189
break;
1190
case 34:
1191
#line 318 "parse.y"
1192
{ yyval.v.string = yyvsp[0].v.string; }
1193
break;
1194
case 35:
1195
#line 321 "parse.y"
1196
{ yyval.v.i = PF_INET; }
1197
break;
1198
case 36:
1199
#line 322 "parse.y"
1200
{ yyval.v.i = PF_INET6; }
1201
break;
1202
case 37:
1203
#line 325 "parse.y"
1204
{ yyval.v.i = 0; }
1205
break;
1206
case 38:
1207
#line 326 "parse.y"
1208
{ yyval.v.i = 1; }
1209
break;
1210
case 39:
1211
#line 329 "parse.y"
1212
{ yyval.v.i = SESSION_TYPE_NORMAL; }
1213
break;
1214
case 40:
1215
#line 330 "parse.y"
1216
{ yyval.v.i = SESSION_TYPE_DISCOVERY; }
1217
break;
1218
#line 1211 "parse.c"
1219
    }
1220
    yyssp -= yym;
1221
    yystate = *yyssp;
1222
    yyvsp -= yym;
1223
    yym = yylhs[yyn];
1224
    if (yystate == 0 && yym == 0)
1225
    {
1226
#if YYDEBUG
1227
        if (yydebug)
1228
            printf("%sdebug: after reduction, shifting from state 0 to\
1229
 state %d\n", YYPREFIX, YYFINAL);
1230
#endif
1231
        yystate = YYFINAL;
1232
        *++yyssp = YYFINAL;
1233
        *++yyvsp = yyval;
1234
        if (yychar < 0)
1235
        {
1236
            if ((yychar = yylex()) < 0) yychar = 0;
1237
#if YYDEBUG
1238
            if (yydebug)
1239
            {
1240
                yys = 0;
1241
                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1242
                if (!yys) yys = "illegal-symbol";
1243
                printf("%sdebug: state %d, reading %d (%s)\n",
1244
                        YYPREFIX, YYFINAL, yychar, yys);
1245
            }
1246
#endif
1247
        }
1248
        if (yychar == 0) goto yyaccept;
1249
        goto yyloop;
1250
    }
1251
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1252
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1253
        yystate = yytable[yyn];
1254
    else
1255
        yystate = yydgoto[yym];
1256
#if YYDEBUG
1257
    if (yydebug)
1258
        printf("%sdebug: after reduction, shifting from state %d \
1259
to state %d\n", YYPREFIX, *yyssp, yystate);
1260
#endif
1261
    if (yyssp >= yysslim && yygrowstack())
1262
    {
1263
        goto yyoverflow;
1264
    }
1265
    *++yyssp = yystate;
1266
    *++yyvsp = yyval;
1267
    goto yyloop;
1268
yyoverflow:
1269
    yyerror("yacc stack overflow");
1270
yyabort:
1271
    if (yyss)
1272
            free(yyss);
1273
    if (yyvs)
1274
            free(yyvs);
1275
    yyss = yyssp = NULL;
1276
    yyvs = yyvsp = NULL;
1277
    yystacksize = 0;
1278
    return (1);
1279
yyaccept:
1280
    if (yyss)
1281
            free(yyss);
1282
    if (yyvs)
1283
            free(yyvs);
1284
    yyss = yyssp = NULL;
1285
    yyvs = yyvsp = NULL;
1286
    yystacksize = 0;
1287
    return (0);
1288
}