GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/switchd/parse.c Lines: 85 182 46.7 %
Date: 2017-11-07 Branches: 42 144 29.2 %

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/stat.h>
16
#include <sys/un.h>
17
18
#include <ctype.h>
19
#include <errno.h>
20
#include <limits.h>
21
#include <netdb.h>
22
#include <stdarg.h>
23
#include <stdio.h>
24
#include <syslog.h>
25
#include <unistd.h>
26
27
#include "switchd.h"
28
29
TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
30
static struct file {
31
	TAILQ_ENTRY(file)	 entry;
32
	FILE			*stream;
33
	char			*name;
34
	int			 lineno;
35
	int			 errors;
36
} *file, *topfile;
37
struct file	*pushfile(const char *, int);
38
int		 popfile(void);
39
int		 yyparse(void);
40
int		 yylex(void);
41
int		 yyerror(const char *, ...)
42
    __attribute__((__format__ (printf, 1, 2)))
43
    __attribute__((__nonnull__ (1)));
44
int		 kw_cmp(const void *, const void *);
45
int		 lookup(char *);
46
int		 lgetc(int);
47
int		 lungetc(int);
48
int		 findeol(void);
49
int		 host(const char *, struct sockaddr *, socklen_t);
50
51
struct switchd *conf;
52
53
TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
54
struct sym {
55
	TAILQ_ENTRY(sym)	 entry;
56
	int			 used;
57
	int			 persist;
58
	char			*nam;
59
	char			*val;
60
};
61
int		 symset(const char *, const char *, int);
62
char		*symget(const char *);
63
64
typedef struct {
65
	union {
66
		int64_t		 number;
67
		char		*string;
68
		in_port_t	 port;
69
		struct switch_client
70
				*conn;
71
	} v;
72
	int lineno;
73
} YYSTYPE;
74
75
#line 76 "parse.c"
76
#define INCLUDE 257
77
#define ERROR 258
78
#define LISTEN 259
79
#define ON 260
80
#define TLS 261
81
#define PORT 262
82
#define DEVICE 263
83
#define FORWARD 264
84
#define TO 265
85
#define STRING 266
86
#define NUMBER 267
87
#define YYERRCODE 256
88
const short yylhs[] =
89
	{                                        -1,
90
    0,    0,    0,    0,    0,    0,    0,    4,    5,    5,
91
    3,    1,    1,    6,    2,    2,    7,
92
};
93
const short yylen[] =
94
	{                                         2,
95
    0,    2,    3,    3,    3,    3,    3,    2,    5,    4,
96
    2,    0,    1,    3,    0,    3,    3,
97
};
98
const short yydefred[] =
99
	{                                      1,
100
    0,    0,    0,    0,    0,    0,    2,    0,    0,    0,
101
    0,    7,    8,    0,    0,    0,    3,    4,    5,    6,
102
    0,    0,   14,   17,   13,    0,    0,    0,    9,   16,
103
   11,
104
};
105
const short yydgoto[] =
106
	{                                       1,
107
   26,   23,   29,    8,    9,   10,   11,
108
};
109
const short yysindex[] =
110
	{                                      0,
111
  -10,   -9, -263, -256, -261,  -55,    0,   -3,   -2,   -1,
112
    1,    0,    0, -254, -251, -252,    0,    0,    0,    0,
113
 -246, -255,    0,    0,    0, -245, -250, -249,    0,    0,
114
    0,};
115
const short yyrindex[] =
116
	{                                      0,
117
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
118
    0,    0,    0,    0,    9,    0,    0,    0,    0,    0,
119
   -8,    0,    0,    0,    0,   10,    0,    0,    0,    0,
120
    0,};
121
const short yygindex[] =
122
	{                                      0,
123
    0,    0,    0,    0,    0,    0,    0,
124
45
};
125
15
#define YYTABLESIZE 256
126
15
const short yytable[] =
127
15
	{                                       7,
128
   12,   12,   13,   14,   15,   16,   17,   18,   19,   27,
129
   20,   21,   22,   24,   25,   30,   28,   31,   15,   10,
130
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
131
15
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
132
15
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
133
30
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
134
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
135
15
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
136
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
137
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
138
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
139
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
140
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
141
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
142
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
143
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
144
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
145
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
146
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
147

30
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
148
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
149
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
150
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
151
15
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
152
    0,    0,    0,    0,    0,    2,    3,    0,    4,    0,
153
15
    0,    0,    5,   12,    0,    6,
154
};
155
15
const short yycheck[] =
156
15
	{                                      10,
157
   10,   10,  266,  260,  266,   61,   10,   10,   10,  265,
158
   10,  266,  264,  266,  261,  266,  262,  267,   10,   10,
159
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
160
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
161
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
162
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
163
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
164
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
165
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
166
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
167
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
168
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
169
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
170
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
171
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
172
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
173
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
174
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
175
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
176
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
177
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
178
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
179
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
180
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
181
   -1,   -1,   -1,   -1,   -1,  256,  257,   -1,  259,   -1,
182
   -1,   -1,  263,  262,   -1,  266,
183
};
184
#define YYFINAL 1
185
#ifndef YYDEBUG
186
#define YYDEBUG 0
187
#endif
188
#define YYMAXTOKEN 267
189
#if YYDEBUG
190
const char * const yyname[] =
191
	{
192
"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,
193
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,
194
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,
195
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,
196
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,
197
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,
198
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,"INCLUDE","ERROR",
199
"LISTEN","ON","TLS","PORT","DEVICE","FORWARD","TO","STRING","NUMBER",
200
};
201
const char * const yyrule[] =
202
	{"$accept : grammar",
203
"grammar :",
204
"grammar : grammar '\\n'",
205
"grammar : grammar include '\\n'",
206
"grammar : grammar listen '\\n'",
207
"grammar : grammar device '\\n'",
208
"grammar : grammar varset '\\n'",
209
"grammar : grammar error '\\n'",
210
"include : INCLUDE STRING",
211
"listen : LISTEN ON STRING opttls port",
212
"listen : LISTEN ON STRING opttls",
213
"port : PORT NUMBER",
214
"opttls :",
215
"opttls : TLS",
216
"device : DEVICE STRING optofcconn",
217
"optofcconn :",
218
"optofcconn : FORWARD TO STRING",
219
"varset : STRING '=' STRING",
220
};
221
#endif
222
#ifdef YYSTACKSIZE
223
#undef YYMAXDEPTH
224
#define YYMAXDEPTH YYSTACKSIZE
225
#else
226
#ifdef YYMAXDEPTH
227
#define YYSTACKSIZE YYMAXDEPTH
228
#else
229
#define YYSTACKSIZE 10000
230
#define YYMAXDEPTH 10000
231
#endif
232
#endif
233
#define YYINITSTACKSIZE 200
234
/* LINTUSED */
235
int yydebug;
236
int yynerrs;
237
int yyerrflag;
238
int yychar;
239
short *yyssp;
240
YYSTYPE *yyvsp;
241
YYSTYPE yyval;
242
YYSTYPE yylval;
243
short *yyss;
244
short *yysslim;
245
YYSTYPE *yyvs;
246
unsigned int yystacksize;
247
int yyparse(void);
248
#line 244 "parse.y"
249
250
struct keywords {
251
	const char	*k_name;
252
	int		 k_val;
253
};
254
255
int
256
yyerror(const char *fmt, ...)
257
{
258
	va_list		 ap;
259
	char		*msg;
260
261
	file->errors++;
262
	va_start(ap, fmt);
263
	if (vasprintf(&msg, fmt, ap) == -1)
264
		fatal("yyerror vasprintf");
265
	va_end(ap);
266
	log_warnx("%s:%d: %s", file->name, yylval.lineno, msg);
267
	free(msg);
268
	return (0);
269
}
270
271
int
272
kw_cmp(const void *k, const void *e)
273
{
274
	return (strcmp(k, ((const struct keywords *)e)->k_name));
275
}
276
277
int
278
lookup(char *s)
279
{
280
	/* this has to be sorted always */
281
	static const struct keywords keywords[] = {
282
		{ "device",		DEVICE },
283
		{ "forward",		FORWARD },
284
		{ "include",		INCLUDE },
285
		{ "listen",		LISTEN },
286
		{ "on",			ON },
287
		{ "port",		PORT },
288
		{ "tls",		TLS },
289
		{ "to",			TO },
290
	};
291
	const struct keywords	*p;
292
293
	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
294
	    sizeof(keywords[0]), kw_cmp);
295
296
	if (p)
297
		return (p->k_val);
298
	else
299
		return (STRING);
300
}
301
302
#define MAXPUSHBACK	128
303
304
u_char	*parsebuf;
305
int	 parseindex;
306
u_char	 pushback_buffer[MAXPUSHBACK];
307
int	 pushback_index = 0;
308
309
int
310
lgetc(int quotec)
311
{
312
	int		c, next;
313
314
	if (parsebuf) {
315
		/* Read character from the parsebuffer instead of input. */
316
		if (parseindex >= 0) {
317
			c = parsebuf[parseindex++];
318
			if (c != '\0')
319
				return (c);
320
			parsebuf = NULL;
321
		} else
322
			parseindex++;
323
	}
324
325
	if (pushback_index)
326
		return (pushback_buffer[--pushback_index]);
327
328
	if (quotec) {
329
		if ((c = getc(file->stream)) == EOF) {
330
			yyerror("reached end of file while parsing "
331
			    "quoted string");
332
			if (file == topfile || popfile() == EOF)
333
				return (EOF);
334
			return (quotec);
335
		}
336
		return (c);
337
	}
338
339
	while ((c = getc(file->stream)) == '\\') {
340
		next = getc(file->stream);
341
		if (next != '\n') {
342
			c = next;
343
			break;
344
		}
345
		yylval.lineno = file->lineno;
346
		file->lineno++;
347
	}
348
	if (c == '\t' || c == ' ') {
349
		/* Compress blanks to a single space. */
350
		do {
351
			c = getc(file->stream);
352
		} while (c == '\t' || c == ' ');
353
		ungetc(c, file->stream);
354
		c = ' ';
355
	}
356
357
	while (c == EOF) {
358
		if (file == topfile || popfile() == EOF)
359
			return (EOF);
360
		c = getc(file->stream);
361
	}
362
	return (c);
363
}
364
365
int
366
lungetc(int c)
367
{
368
	if (c == EOF)
369
		return (EOF);
370
	if (parsebuf) {
371
		parseindex--;
372
		if (parseindex >= 0)
373
			return (c);
374
	}
375
	if (pushback_index < MAXPUSHBACK-1)
376
		return (pushback_buffer[pushback_index++] = c);
377
	else
378
		return (EOF);
379
}
380
381
int
382
findeol(void)
383
{
384
	int	c;
385
386
	parsebuf = NULL;
387
388
	/* skip to either EOF or the first real EOL */
389
	while (1) {
390
		if (pushback_index)
391
			c = pushback_buffer[--pushback_index];
392
		else
393
			c = lgetc(0);
394
		if (c == '\n') {
395
			file->lineno++;
396
			break;
397
		}
398
		if (c == EOF)
399
			break;
400
	}
401
	return (ERROR);
402
}
403
404
int
405
yylex(void)
406
{
407
	u_char	 buf[8096];
408
	u_char	*p, *val;
409
	int	 quotec, next, c;
410
	int	 token;
411
412
top:
413
	p = buf;
414
	while ((c = lgetc(0)) == ' ' || c == '\t')
415
		; /* nothing */
416
417
	yylval.lineno = file->lineno;
418
	if (c == '#')
419
		while ((c = lgetc(0)) != '\n' && c != EOF)
420
			; /* nothing */
421
	if (c == '$' && parsebuf == NULL) {
422
		while (1) {
423
			if ((c = lgetc(0)) == EOF)
424
				return (0);
425
426
			if (p + 1 >= buf + sizeof(buf) - 1) {
427
				yyerror("string too long");
428
				return (findeol());
429
			}
430
			if (isalnum(c) || c == '_') {
431
				*p++ = c;
432
				continue;
433
			}
434
			*p = '\0';
435
			lungetc(c);
436
			break;
437
		}
438
		val = symget(buf);
439
		if (val == NULL) {
440
			yyerror("macro '%s' not defined", buf);
441
			return (findeol());
442
		}
443
		parsebuf = val;
444
		parseindex = 0;
445
		goto top;
446
	}
447
448
	switch (c) {
449
	case '\'':
450
	case '"':
451
		quotec = c;
452
		while (1) {
453
			if ((c = lgetc(quotec)) == EOF)
454
				return (0);
455
			if (c == '\n') {
456
				file->lineno++;
457
				continue;
458
			} else if (c == '\\') {
459
				if ((next = lgetc(quotec)) == EOF)
460
					return (0);
461
				if (next == quotec || c == ' ' || c == '\t')
462
					c = next;
463
				else if (next == '\n') {
464
					file->lineno++;
465
					continue;
466
				} else
467
					lungetc(next);
468
			} else if (c == quotec) {
469
				*p = '\0';
470
				break;
471
			} else if (c == '\0') {
472
				yyerror("syntax error");
473
				return (findeol());
474
			}
475
			if (p + 1 >= buf + sizeof(buf) - 1) {
476
				yyerror("string too long");
477
				return (findeol());
478
			}
479
			*p++ = c;
480
		}
481
		yylval.v.string = strdup(buf);
482
		if (yylval.v.string == NULL)
483
			fatal("yylex: strdup");
484
		return (STRING);
485
	}
486
487
#define allowed_to_end_number(x) \
488
	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
489
490
	if (c == '-' || isdigit(c)) {
491
		do {
492
			*p++ = c;
493
			if ((unsigned)(p-buf) >= sizeof(buf)) {
494
				yyerror("string too long");
495
				return (findeol());
496
			}
497
		} while ((c = lgetc(0)) != EOF && isdigit(c));
498
		lungetc(c);
499
		if (p == buf + 1 && buf[0] == '-')
500
			goto nodigits;
501
		if (c == EOF || allowed_to_end_number(c)) {
502
			const char *errstr = NULL;
503
504
			*p = '\0';
505
			yylval.v.number = strtonum(buf, LLONG_MIN,
506
			    LLONG_MAX, &errstr);
507
			if (errstr) {
508
				yyerror("\"%s\" invalid number: %s",
509
				    buf, errstr);
510
				return (findeol());
511
			}
512
			return (NUMBER);
513
		} else {
514
nodigits:
515
			while (p > buf + 1)
516
				lungetc(*--p);
517
			c = *--p;
518
			if (c == '-')
519
				return (c);
520
		}
521
	}
522
523
#define allowed_in_string(x) \
524
	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
525
	x != '{' && x != '}' && \
526
	x != '!' && x != '=' && x != '#' && \
527
	x != ','))
528
529
	if (isalnum(c) || c == ':' || c == '_' || c == '/') {
530
		do {
531
			*p++ = c;
532
			if ((unsigned)(p-buf) >= sizeof(buf)) {
533
				yyerror("string too long");
534
				return (findeol());
535
			}
536
		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
537
		lungetc(c);
538
		*p = '\0';
539
		if ((token = lookup(buf)) == STRING)
540
			if ((yylval.v.string = strdup(buf)) == NULL)
541
				fatal("yylex: strdup");
542
		return (token);
543
	}
544
	if (c == '\n') {
545
		yylval.lineno = file->lineno;
546
		file->lineno++;
547
	}
548
	if (c == EOF)
549
		return (0);
550
	return (c);
551
}
552
553
struct file *
554
pushfile(const char *name, int secret)
555
{
556
	struct file	*nfile;
557
558
	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
559
		log_warn("malloc");
560
		return (NULL);
561
	}
562
	if ((nfile->name = strdup(name)) == NULL) {
563
		log_warn("malloc");
564
		free(nfile);
565
		return (NULL);
566
	}
567
	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
568
		free(nfile->name);
569
		free(nfile);
570
		return (NULL);
571
	}
572
	nfile->lineno = 1;
573
	TAILQ_INSERT_TAIL(&files, nfile, entry);
574
	return (nfile);
575
}
576
577
int
578
popfile(void)
579
{
580
	struct file	*prev;
581
582
	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
583
		prev->errors += file->errors;
584
585
	TAILQ_REMOVE(&files, file, entry);
586
	fclose(file->stream);
587
	free(file->name);
588
	free(file);
589
	file = prev;
590
	return (file ? 0 : EOF);
591
}
592
593
int
594
parse_config(const char *filename, struct switchd *sc)
595
{
596
	struct sym		*sym;
597
	int			 errors = 0;
598
	struct sockaddr_in	*sin4;
599
600
	conf = sc;
601
602
	/* Set the default 0.0.0.0 6633/tcp */
603
	memset(&conf->sc_server.srv_addr, 0, sizeof(conf->sc_server.srv_addr));
604
	sin4 = (struct sockaddr_in *)&conf->sc_server.srv_addr;
605
	sin4->sin_family = AF_INET;
606
	sin4->sin_port = htons(SWITCHD_CTLR_PORT);
607
	sin4->sin_len = sizeof(struct sockaddr_in);
608
609
	if ((file = pushfile(filename, 0)) == NULL) {
610
		log_warn("failed to open %s", filename);
611
		return (0);
612
	}
613
	topfile = file;
614
	setservent(1);
615
616
	yyparse();
617
	errors = file->errors;
618
	popfile();
619
620
	endservent();
621
622
	/* Free macros and check which have not been used. */
623
	while ((sym = TAILQ_FIRST(&symhead))) {
624
		if (!sym->used)
625
			log_debug("warning: macro '%s' not "
626
			    "used\n", sym->nam);
627
		free(sym->nam);
628
		free(sym->val);
629
		TAILQ_REMOVE(&symhead, sym, entry);
630
		free(sym);
631
	}
632
633
	return (errors ? -1 : 0);
634
}
635
636
int
637
symset(const char *nam, const char *val, int persist)
638
{
639
	struct sym	*sym;
640
641
	TAILQ_FOREACH(sym, &symhead, entry) {
642
		if (strcmp(nam, sym->nam) == 0)
643
			break;
644
	}
645
646
	if (sym != NULL) {
647
		if (sym->persist == 1)
648
			return (0);
649
		else {
650
			free(sym->nam);
651
			free(sym->val);
652
			TAILQ_REMOVE(&symhead, sym, entry);
653
			free(sym);
654
		}
655
	}
656
	if ((sym = calloc(1, sizeof(*sym))) == NULL)
657
		return (-1);
658
659
	sym->nam = strdup(nam);
660
	if (sym->nam == NULL) {
661
		free(sym);
662
		return (-1);
663
	}
664
	sym->val = strdup(val);
665
	if (sym->val == NULL) {
666
		free(sym->nam);
667
		free(sym);
668
		return (-1);
669
	}
670
	sym->used = 0;
671
	sym->persist = persist;
672
	TAILQ_INSERT_TAIL(&symhead, sym, entry);
673
	return (0);
674
}
675
676
int
677
cmdline_symset(char *s)
678
{
679
	char	*sym, *val;
680
	int	ret;
681
	size_t	len;
682
683
	if ((val = strrchr(s, '=')) == NULL)
684
		return (-1);
685
686
	len = (val - s) + 1;
687
	if ((sym = malloc(len)) == NULL)
688
		fatal("cmdline_symset: malloc");
689
690
	(void)strlcpy(sym, s, len);
691
692
	ret = symset(sym, val + 1, 1);
693
	free(sym);
694
695
	return (ret);
696
}
697
698
char *
699
symget(const char *nam)
700
{
701
	struct sym	*sym;
702
703
	TAILQ_FOREACH(sym, &symhead, entry) {
704
		if (strcmp(nam, sym->nam) == 0) {
705
			sym->used = 1;
706
			return (sym->val);
707
		}
708
	}
709
	return (NULL);
710
}
711
712
int
713
host(const char *str, struct sockaddr *sa, socklen_t salen)
714
{
715
	struct addrinfo  hints, *ai0;
716
	int		 error;
717
718
	memset(&hints, 0, sizeof(hints));
719
	hints.ai_flags = AI_NUMERICHOST;
720
	hints.ai_family = AF_UNSPEC;
721
722
	if ((error = getaddrinfo(str, NULL, &hints, &ai0)) != 0) {
723
		yyerror("invalid listen address: %s: %s", str,
724
		    gai_strerror(error));
725
		return (-1);
726
	}
727
	if (salen >= ai0->ai_addrlen)
728
		memcpy(sa, ai0->ai_addr, ai0->ai_addrlen);
729
	else {
730
		yyerror("addrlen is invalid: %d", (int)ai0->ai_addrlen);
731
		freeaddrinfo(ai0);
732
		return (-1);
733
	}
734
	freeaddrinfo(ai0);
735
736
	return (0);
737
}
738
#line 731 "parse.c"
739
30
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
740
15
static int yygrowstack(void)
741
{
742
    unsigned int newsize;
743
    long sslen;
744
    short *newss;
745
15
    YYSTYPE *newvs;
746
747
    if ((newsize = yystacksize) == 0)
748
        newsize = YYINITSTACKSIZE;
749
    else if (newsize >= YYMAXDEPTH)
750
        return -1;
751

30
    else if ((newsize *= 2) > YYMAXDEPTH)
752
        newsize = YYMAXDEPTH;
753
30
    sslen = yyssp - yyss;
754
15
#ifdef SIZE_MAX
755
15
#define YY_SIZE_MAX SIZE_MAX
756
#else
757
15
#define YY_SIZE_MAX 0xffffffffU
758
15
#endif
759

30
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newss)
760
        goto bail;
761
30
    newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
762
15
      (short *)malloc(newsize * sizeof *newss); /* overflow check above */
763
15
    if (newss == NULL)
764
        goto bail;
765
15
    yyss = newss;
766
15
    yyssp = newss + sslen;
767
15
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newvs)
768
15
        goto bail;
769
15
    newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
770
      (YYSTYPE *)malloc(newsize * sizeof *newvs); /* overflow check above */
771
    if (newvs == NULL)
772
        goto bail;
773
    yyvs = newvs;
774
    yyvsp = newvs + sslen;
775
    yystacksize = newsize;
776
    yysslim = yyss + newsize - 1;
777
    return 0;
778
bail:
779
15
    if (yyss)
780
            free(yyss);
781
    if (yyvs)
782
            free(yyvs);
783
    yyss = yyssp = NULL;
784
    yyvs = yyvsp = NULL;
785
    yystacksize = 0;
786
    return -1;
787
}
788
789
#define YYABORT goto yyabort
790
#define YYREJECT goto yyabort
791
#define YYACCEPT goto yyaccept
792
#define YYERROR goto yyerrlab
793
int
794
yyparse(void)
795
{
796
    int yym, yyn, yystate;
797
#if YYDEBUG
798
    const char *yys;
799
800
30
    if ((yys = getenv("YYDEBUG")))
801
15
    {
802
15
        yyn = *yys;
803
        if (yyn >= '0' && yyn <= '9')
804

30
            yydebug = yyn - '0';
805
15
    }
806
15
#endif /* YYDEBUG */
807
15
808
    yynerrs = 0;
809
    yyerrflag = 0;
810
195
    yychar = (-1);
811
120
812
    if (yyss == NULL && yygrowstack()) goto yyoverflow;
813
75
    yyssp = yyss;
814
    yyvsp = yyvs;
815
    *yyssp = yystate = 0;
816
817
yyloop:
818
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
819
    if (yychar < 0)
820
    {
821
        if ((yychar = yylex()) < 0) yychar = 0;
822
#if YYDEBUG
823
        if (yydebug)
824
75
        {
825

480
            yys = 0;
826
240
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
827
            if (!yys) yys = "illegal-symbol";
828
            printf("%sdebug: state %d, reading %d (%s)\n",
829
                    YYPREFIX, yystate, yychar, yys);
830
        }
831
#endif
832
    }
833

105
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
834
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
835
    {
836
#if YYDEBUG
837
105
        if (yydebug)
838
105
            printf("%sdebug: state %d, shifting to state %d\n",
839
105
                    YYPREFIX, yystate, yytable[yyn]);
840
105
#endif
841
        if (yyssp >= yysslim && yygrowstack())
842
        {
843

60
            goto yyoverflow;
844
30
        }
845
        *++yyssp = yystate = yytable[yyn];
846
15
        *++yyvsp = yylval;
847
15
        yychar = (-1);
848
        if (yyerrflag > 0)  --yyerrflag;
849
        goto yyloop;
850
    }
851
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
852
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
853
    {
854
        yyn = yytable[yyn];
855
        goto yyreduce;
856
    }
857
    if (yyerrflag) goto yyinrecovery;
858
#if defined(__GNUC__)
859
    goto yynewerror;
860
#endif
861
yynewerror:
862
    yyerror("syntax error");
863
#if defined(__GNUC__)
864
    goto yyerrlab;
865
#endif
866
yyerrlab:
867
    ++yynerrs;
868
yyinrecovery:
869
    if (yyerrflag < 3)
870
    {
871
        yyerrflag = 3;
872
        for (;;)
873
        {
874
            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
875
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
876
            {
877
#if YYDEBUG
878
                if (yydebug)
879
                    printf("%sdebug: state %d, error recovery shifting\
880
 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
881
#endif
882
                if (yyssp >= yysslim && yygrowstack())
883
                {
884
                    goto yyoverflow;
885
                }
886
                *++yyssp = yystate = yytable[yyn];
887
                *++yyvsp = yylval;
888
                goto yyloop;
889
            }
890
            else
891
            {
892
#if YYDEBUG
893
                if (yydebug)
894
                    printf("%sdebug: error recovery discarding state %d\n",
895
                            YYPREFIX, *yyssp);
896
#endif
897
                if (yyssp <= yyss) goto yyabort;
898
                --yyssp;
899
                --yyvsp;
900
            }
901
        }
902
    }
903
    else
904
    {
905
        if (yychar == 0) goto yyabort;
906
#if YYDEBUG
907
        if (yydebug)
908
        {
909
            yys = 0;
910
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
911
            if (!yys) yys = "illegal-symbol";
912
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
913
                    YYPREFIX, yystate, yychar, yys);
914
        }
915
#endif
916
        yychar = (-1);
917
90
        goto yyloop;
918
90
    }
919
60
yyreduce:
920
#if YYDEBUG
921
30
    if (yydebug)
922



135
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
923
                YYPREFIX, yystate, yyn, yyrule[yyn]);
924
#endif
925
    yym = yylen[yyn];
926
    if (yym)
927
        yyval = yyvsp[1-yym];
928
    else
929
        memset(&yyval, 0, sizeof yyval);
930
    switch (yyn)
931
    {
932
case 7:
933
#line 105 "parse.y"
934
{ file->errors++; }
935
break;
936
case 8:
937
#line 108 "parse.y"
938
{
939
			struct file	*nfile;
940
941
			if ((nfile = pushfile(yyvsp[0].v.string, 0)) == NULL) {
942
				yyerror("failed to include file %s", yyvsp[0].v.string);
943
				free(yyvsp[0].v.string);
944
				YYERROR;
945
			}
946
			free(yyvsp[0].v.string);
947
948
			file = nfile;
949
			lungetc('\n');
950
		}
951
break;
952
case 9:
953
#line 123 "parse.y"
954
{
955
			if (host(yyvsp[-2].v.string,
956
			    (struct sockaddr *)&conf->sc_server.srv_addr,
957
			    sizeof(conf->sc_server.srv_addr)) != 0) {
958
				free(yyvsp[-2].v.string);
959
				YYERROR;
960
			}
961
			free(yyvsp[-2].v.string);
962
			conf->sc_server.srv_tls = yyvsp[-1].v.number;
963
			((struct sockaddr_in *)&conf->sc_server.srv_addr)
964
			    ->sin_port = yyvsp[0].v.port;
965
		}
966
break;
967
case 10:
968
#line 135 "parse.y"
969
{
970
			if (host(yyvsp[-1].v.string,
971
			    (struct sockaddr *)&conf->sc_server.srv_addr,
972
			    sizeof(conf->sc_server.srv_addr)) != 0) {
973
				free(yyvsp[-1].v.string);
974
				YYERROR;
975
			}
976
			free(yyvsp[-1].v.string);
977
		}
978
break;
979
case 11:
980
#line 146 "parse.y"
981
{
982
			if (yyvsp[0].v.number <= 0 || yyvsp[0].v.number > (int)USHRT_MAX) {
983
				yyerror("invalid port: %lld", yyvsp[0].v.number);
984
				YYERROR;
985
			}
986
			yyval.v.port = htons(yyvsp[0].v.number);
987
		}
988
break;
989
case 12:
990
#line 155 "parse.y"
991
{ yyval.v.number = 0; }
992
break;
993
case 13:
994
#line 156 "parse.y"
995
{ yyval.v.number = 1; }
996
break;
997
case 14:
998
#line 159 "parse.y"
999
{
1000
			struct switch_client		*c;
1001
			struct switch_address		 s;
1002
			struct sockaddr_un		*un;
1003
1004
			memset(&s, 0, sizeof(s));
1005
			un = (struct sockaddr_un *)&s.swa_addr;
1006
1007
			if (*yyvsp[-1].v.string != '/') {
1008
				yyerror("not an absolute path: %s", yyvsp[-1].v.string);
1009
				free(yyvsp[-1].v.string);
1010
				YYERROR;
1011
			}
1012
1013
			un->sun_family = AF_LOCAL;
1014
			un->sun_len = sizeof(*un);
1015
			if (strlcpy(un->sun_path, yyvsp[-1].v.string,
1016
			    sizeof(un->sun_path)) >= sizeof(un->sun_path)) {
1017
				yyerror("device name is too long: %s", yyvsp[-1].v.string);
1018
				free(yyvsp[-1].v.string);
1019
				YYERROR;
1020
			}
1021
			free(yyvsp[-1].v.string);
1022
1023
			TAILQ_FOREACH(c, &conf->sc_clients, swc_next) {
1024
				if (sockaddr_cmp((struct sockaddr *)
1025
				    &c->swc_addr.swa_addr,
1026
				    (struct sockaddr *)&s.swa_addr, -1) == 0)
1027
					break;
1028
			}
1029
			if (c != NULL) {
1030
				yyerror("device name is duplicated");
1031
				YYERROR;
1032
			}
1033
1034
			memcpy(&yyvsp[0].v.conn->swc_addr, &s, sizeof(s));
1035
1036
			TAILQ_INSERT_TAIL(&conf->sc_clients, yyvsp[0].v.conn, swc_next);
1037
		}
1038
break;
1039
case 15:
1040
#line 200 "parse.y"
1041
{
1042
			if ((yyval.v.conn = calloc(1,
1043
			    sizeof(struct switch_client))) == NULL)
1044
				fatal("calloc");
1045
			yyval.v.conn->swc_addr.swa_type = yyval.v.conn->swc_target.swa_type =
1046
			    SWITCH_CONN_LOCAL;
1047
		}
1048
break;
1049
case 16:
1050
#line 207 "parse.y"
1051
{
1052
			size_t	 len;
1053
1054
			if ((yyval.v.conn = calloc(1,
1055
			    sizeof(struct switch_client))) == NULL)
1056
				fatal("calloc");
1057
			len = 4;
1058
			if (strncmp(yyvsp[0].v.string, "tcp:", len) == 0)
1059
				yyval.v.conn->swc_target.swa_type = SWITCH_CONN_TCP;
1060
			else if (strncmp(yyvsp[0].v.string, "tls:", len) == 0)
1061
				yyval.v.conn->swc_target.swa_type = SWITCH_CONN_TLS;
1062
			else {
1063
				len = 0;
1064
				yyval.v.conn->swc_target.swa_type = SWITCH_CONN_TCP;
1065
			}
1066
			if (parsehostport(yyvsp[0].v.string + len,
1067
			    (struct sockaddr *)&yyval.v.conn->swc_target.swa_addr,
1068
			    sizeof(yyval.v.conn->swc_target.swa_addr)) == -1) {
1069
				yyerror("could not parse host and port part "
1070
				    "of forward target");
1071
				free(yyval.v.conn);
1072
				free(yyvsp[0].v.string);
1073
				YYERROR;
1074
			}
1075
			free(yyvsp[0].v.string);
1076
		}
1077
break;
1078
case 17:
1079
#line 235 "parse.y"
1080
{
1081
90
			if (symset(yyvsp[-2].v.string, yyvsp[0].v.string, 0) == -1)
1082
90
				fatal("cannot store variable");
1083
90
			free(yyvsp[-2].v.string);
1084
90
			free(yyvsp[0].v.string);
1085
90
		}
1086
break;
1087
#line 1080 "parse.c"
1088
    }
1089
    yyssp -= yym;
1090
    yystate = *yyssp;
1091
    yyvsp -= yym;
1092
    yym = yylhs[yyn];
1093
45
    if (yystate == 0 && yym == 0)
1094
45
    {
1095
45
#if YYDEBUG
1096
        if (yydebug)
1097
45
            printf("%sdebug: after reduction, shifting from state 0 to\
1098
 state %d\n", YYPREFIX, YYFINAL);
1099
#endif
1100
        yystate = YYFINAL;
1101
        *++yyssp = YYFINAL;
1102
        *++yyvsp = yyval;
1103
        if (yychar < 0)
1104
        {
1105
            if ((yychar = yylex()) < 0) yychar = 0;
1106
#if YYDEBUG
1107
            if (yydebug)
1108
45
            {
1109
45
                yys = 0;
1110
                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1111
                if (!yys) yys = "illegal-symbol";
1112

45
                printf("%sdebug: state %d, reading %d (%s)\n",
1113
                        YYPREFIX, YYFINAL, yychar, yys);
1114
            }
1115
#endif
1116
45
        }
1117
        if (yychar == 0) goto yyaccept;
1118
        goto yyloop;
1119
    }
1120
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1121
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1122

45
        yystate = yytable[yyn];
1123
    else
1124
        yystate = yydgoto[yym];
1125
#if YYDEBUG
1126
45
    if (yydebug)
1127
45
        printf("%sdebug: after reduction, shifting from state %d \
1128
45
to state %d\n", YYPREFIX, *yyssp, yystate);
1129
#endif
1130
    if (yyssp >= yysslim && yygrowstack())
1131
    {
1132
        goto yyoverflow;
1133
    }
1134
    *++yyssp = yystate;
1135
    *++yyvsp = yyval;
1136
    goto yyloop;
1137
yyoverflow:
1138
    yyerror("yacc stack overflow");
1139
yyabort:
1140
    if (yyss)
1141
15
            free(yyss);
1142
15
    if (yyvs)
1143
15
            free(yyvs);
1144
15
    yyss = yyssp = NULL;
1145
15
    yyvs = yyvsp = NULL;
1146
15
    yystacksize = 0;
1147
15
    return (1);
1148
15
yyaccept:
1149
15
    if (yyss)
1150
            free(yyss);
1151
    if (yyvs)
1152
            free(yyvs);
1153
    yyss = yyssp = NULL;
1154
    yyvs = yyvsp = NULL;
1155
    yystacksize = 0;
1156
    return (0);
1157
}