GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ifstated/parse.c Lines: 0 216 0.0 %
Date: 2017-11-07 Branches: 0 164 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 24 "parse.y"
13
#include <sys/types.h>
14
#include <sys/time.h>
15
#include <sys/socket.h>
16
#include <sys/stat.h>
17
#include <netinet/in.h>
18
#include <arpa/inet.h>
19
#include <net/if.h>
20
21
#include <ctype.h>
22
#include <unistd.h>
23
#include <err.h>
24
#include <errno.h>
25
#include <limits.h>
26
#include <stdarg.h>
27
#include <stdio.h>
28
#include <string.h>
29
#include <syslog.h>
30
#include <event.h>
31
32
#include "ifstated.h"
33
#include "log.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		 check_file_secrecy(int, const char *);
46
int		 yyparse(void);
47
int		 yylex(void);
48
int		 yyerror(const char *, ...)
49
    __attribute__((__format__ (printf, 1, 2)))
50
    __attribute__((__nonnull__ (1)));
51
int		 kw_cmp(const void *, const void *);
52
int		 lookup(char *);
53
int		 lgetc(int);
54
int		 lungetc(int);
55
int		 findeol(void);
56
57
TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
58
struct sym {
59
	TAILQ_ENTRY(sym)	 entry;
60
	int			 used;
61
	int			 persist;
62
	char			*nam;
63
	char			*val;
64
};
65
int		 symset(const char *, const char *, int);
66
char		*symget(const char *);
67
68
static struct ifsd_config	*conf;
69
char				*start_state;
70
71
struct ifsd_action		*curaction;
72
struct ifsd_state		*curstate;
73
74
void			 link_states(struct ifsd_action *);
75
void			 set_expression_depth(struct ifsd_expression *, int);
76
void			 init_state(struct ifsd_state *);
77
struct ifsd_ifstate	*new_ifstate(char *, int);
78
struct ifsd_external	*new_external(char *, u_int32_t);
79
80
typedef struct {
81
	union {
82
		int64_t		 number;
83
		char		*string;
84
		struct in_addr	 addr;
85
86
		struct ifsd_expression	*expression;
87
		struct ifsd_ifstate	*ifstate;
88
		struct ifsd_external	*external;
89
90
	} v;
91
	int lineno;
92
} YYSTYPE;
93
94
#line 95 "parse.c"
95
#define STATE 257
96
#define INITSTATE 258
97
#define LINK 259
98
#define UP 260
99
#define DOWN 261
100
#define UNKNOWN 262
101
#define IF 263
102
#define RUN 264
103
#define SETSTATE 265
104
#define EVERY 266
105
#define INIT 267
106
#define AND 268
107
#define OR 269
108
#define UNARY 270
109
#define ERROR 271
110
#define STRING 272
111
#define NUMBER 273
112
#define YYERRCODE 256
113
const short yylhs[] =
114
	{                                        -1,
115
    0,    0,    0,    0,    0,    0,    0,    1,    1,    8,
116
    7,    2,   11,   11,   12,    9,    9,   13,    9,   14,
117
   14,   15,   15,   17,   16,    3,    3,    3,    4,    6,
118
    6,    6,    5,    5,    5,    5,   18,   10,   19,   19,
119
   20,   20,
120
};
121
const short yylen[] =
122
	{                                         2,
123
    0,    2,    3,    3,    3,    3,    3,    2,    1,    3,
124
    2,    1,    2,    0,    2,    2,    2,    0,    4,    5,
125
    2,    3,    2,    0,    3,    5,    5,    5,    3,    1,
126
    1,    3,    2,    3,    3,    1,    0,    8,    2,    1,
127
    2,    2,
128
};
129
const short yydefred[] =
130
	{                                      1,
131
    0,    0,    0,    0,   18,    0,    0,    0,    2,    0,
132
    0,    0,    0,    7,    9,    0,   11,    0,   16,   17,
133
    0,    3,    4,    5,    6,    8,    0,    0,    0,    0,
134
    0,   30,   31,    0,   36,    0,    0,    0,    0,    0,
135
   33,    0,    0,    0,    0,   19,   13,    0,   29,   32,
136
    0,   34,   35,    0,   21,    0,    0,    0,   24,    0,
137
    0,    0,   40,   26,   27,   28,    0,    0,    0,    0,
138
   42,   41,   38,   39,   23,   20,    0,   25,   15,   22,
139
};
140
const short yydgoto[] =
141
	{                                       1,
142
   16,   31,   32,   33,   34,   35,   10,   11,   60,   13,
143
   45,   71,   18,   46,   68,   61,   69,   27,   62,   63,
144
};
145
const short yysindex[] =
146
	{                                      0,
147
  -10,    2, -259, -257,    0, -255, -254,  -40,    0,   13,
148
   23,   34,   42,    0,    0, -217,    0,  -31,    0,    0,
149
 -259,    0,    0,    0,    0,    0,   44, -210,  -31,  -31,
150
   11,    0,    0,   -9,    0, -217,   44,  -65, -214,  -38,
151
    0, -199,  -31,  -31, -104,    0,    0,   44,    0,    0,
152
   15,    0,    0,   44,    0, -235, -219, -218,    0,   52,
153
   52, -114,    0,    0,    0,    0,   52,  -98,   44,   44,
154
    0,    0,    0,    0,    0,    0,   52,    0,    0,    0,};
155
const short yyrindex[] =
156
	{                                      0,
157
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
158
    0,    0,    0,    0,    0,   -5,    0,    0,    0,    0,
159
    0,    0,    0,    0,    0,    0,  -60,   19,    0,    0,
160
    0,    0,    0, -101,    0,   56, -119,    0,    0,    0,
161
    0,    0,    0,    0,    0,    0,    0, -229,    0,    0,
162
    0,    0,    0, -215,    0,    0,    0,    0,    0,    0,
163
    0,    0,    0,    0,    0,    0,    0,    0, -101, -109,
164
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,};
165
const short yygindex[] =
166
	{                                      0,
167
   46,    0,    0,    0,   -4,    0,    0,    0,    6,    0,
168
  -17,  -53,    0,   -1,    0,    0,    0,    0,    0,    7,
169
};
170
#define YYTABLESIZE 262
171
const short yytable[] =
172
	{                                       9,
173
   37,   30,   50,   14,   37,   14,   12,   72,   29,   38,
174
   73,   14,   15,   75,   17,   14,   19,   20,   54,   47,
175
   21,   14,   22,   80,   40,   41,   76,    5,    6,    7,
176
   56,   59,   23,   14,   14,   14,   58,   14,   52,   53,
177
   64,   65,   66,   24,    5,    6,    7,   14,   14,   14,
178
   55,   25,   79,   37,   26,   39,   42,   48,   49,   51,
179
   57,   70,   14,   67,   12,   10,   36,   78,   74,    0,
180
    0,    0,    0,   77,    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,   37,    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,   14,   14,   14,    0,   14,    5,    6,
188
    7,    0,   59,   14,   14,   14,    0,   14,    5,    6,
189
    7,   14,   14,   14,    5,    6,    7,    0,    0,    0,
190
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
191
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
192
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
193
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
194
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
195
    0,    0,    0,    0,    0,    0,    0,    0,    0,   43,
196
   44,    0,    0,    0,    0,    0,    0,    0,    0,    0,
197
   28,    0,    0,    0,    0,    2,    3,    4,    0,    0,
198
    0,    0,    5,    6,    7,    0,    0,    0,   43,   44,
199
    0,    8,
200
};
201
const short yycheck[] =
202
	{                                      10,
203
   10,   33,   41,  123,   10,  125,    1,   61,   40,   27,
204
  125,   10,  272,   67,  272,  125,  272,  272,  123,   37,
205
   61,  123,   10,   77,   29,   30,  125,  263,  264,  265,
206
   48,  267,   10,  263,  264,  265,   54,  267,   43,   44,
207
  260,  261,  262,   10,  263,  264,  265,  263,  264,  265,
208
   45,   10,   70,   10,  272,  266,   46,  123,  273,  259,
209
   46,   10,  123,   58,   46,   10,   21,   69,   62,   -1,
210
   -1,   -1,   -1,   68,   -1,   -1,   -1,   -1,   -1,   -1,
211
   -1,   -1,   -1,   -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,  123,   -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,  263,  264,  265,   -1,  267,  263,  264,
218
  265,   -1,  267,  263,  264,  265,   -1,  267,  263,  264,
219
  265,  263,  264,  265,  263,  264,  265,   -1,   -1,   -1,
220
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
221
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
222
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
223
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
224
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
225
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  268,
226
  269,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
227
  272,   -1,   -1,   -1,   -1,  256,  257,  258,   -1,   -1,
228
   -1,   -1,  263,  264,  265,   -1,   -1,   -1,  268,  269,
229
   -1,  272,
230
};
231
#define YYFINAL 1
232
#ifndef YYDEBUG
233
#define YYDEBUG 0
234
#endif
235
#define YYMAXTOKEN 273
236
#if YYDEBUG
237
const char * const yyname[] =
238
	{
239
"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,
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,
241
"'='",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,
242
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,
243
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,
244
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,
245
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,
246
0,0,"STATE","INITSTATE","LINK","UP","DOWN","UNKNOWN","IF","RUN","SETSTATE",
247
"EVERY","INIT","AND","OR","UNARY","ERROR","STRING","NUMBER",
248
};
249
const char * const yyrule[] =
250
	{"$accept : grammar",
251
"grammar :",
252
"grammar : grammar '\\n'",
253
"grammar : grammar conf_main '\\n'",
254
"grammar : grammar varset '\\n'",
255
"grammar : grammar action '\\n'",
256
"grammar : grammar state '\\n'",
257
"grammar : grammar error '\\n'",
258
"string : string STRING",
259
"string : STRING",
260
"varset : STRING '=' string",
261
"conf_main : INITSTATE STRING",
262
"interface : STRING",
263
"optnl : '\\n' optnl",
264
"optnl :",
265
"nl : '\\n' optnl",
266
"action : RUN STRING",
267
"action : SETSTATE STRING",
268
"$$1 :",
269
"action : IF $$1 expr action_block",
270
"action_block : optnl '{' optnl action_l '}'",
271
"action_block : optnl action",
272
"action_l : action_l action nl",
273
"action_l : action nl",
274
"$$2 :",
275
"init : INIT $$2 action_block",
276
"if_test : interface '.' LINK '.' UP",
277
"if_test : interface '.' LINK '.' DOWN",
278
"if_test : interface '.' LINK '.' UNKNOWN",
279
"ext_test : STRING EVERY NUMBER",
280
"term : if_test",
281
"term : ext_test",
282
"term : '(' expr ')'",
283
"expr : '!' expr",
284
"expr : expr AND expr",
285
"expr : expr OR expr",
286
"expr : term",
287
"$$3 :",
288
"state : STATE string $$3 optnl '{' optnl stateopts_l '}'",
289
"stateopts_l : stateopts_l stateoptsl",
290
"stateopts_l : stateoptsl",
291
"stateoptsl : init nl",
292
"stateoptsl : action nl",
293
};
294
#endif
295
#ifdef YYSTACKSIZE
296
#undef YYMAXDEPTH
297
#define YYMAXDEPTH YYSTACKSIZE
298
#else
299
#ifdef YYMAXDEPTH
300
#define YYSTACKSIZE YYMAXDEPTH
301
#else
302
#define YYSTACKSIZE 10000
303
#define YYMAXDEPTH 10000
304
#endif
305
#endif
306
#define YYINITSTACKSIZE 200
307
/* LINTUSED */
308
int yydebug;
309
int yynerrs;
310
int yyerrflag;
311
int yychar;
312
short *yyssp;
313
YYSTYPE *yyvsp;
314
YYSTYPE yyval;
315
YYSTYPE yylval;
316
short *yyss;
317
short *yysslim;
318
YYSTYPE *yyvs;
319
unsigned int yystacksize;
320
int yyparse(void);
321
#line 356 "parse.y"
322
323
struct keywords {
324
	const char	*k_name;
325
	int		 k_val;
326
};
327
328
int
329
yyerror(const char *fmt, ...)
330
{
331
	va_list		 ap;
332
	char		*msg;
333
334
	file->errors++;
335
	va_start(ap, fmt);
336
	if (vasprintf(&msg, fmt, ap) == -1)
337
		fatalx("yyerror vasprintf");
338
	va_end(ap);
339
	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
340
	free(msg);
341
	return (0);
342
}
343
344
int
345
kw_cmp(const void *k, const void *e)
346
{
347
	return (strcmp(k, ((const struct keywords *)e)->k_name));
348
}
349
350
int
351
lookup(char *s)
352
{
353
	/* this has to be sorted always */
354
	static const struct keywords keywords[] = {
355
		{ "&&",			AND},
356
		{ "down",		DOWN},
357
		{ "every",		EVERY},
358
		{ "if",			IF},
359
		{ "init",		INIT},
360
		{ "init-state",		INITSTATE},
361
		{ "link",		LINK},
362
		{ "run",		RUN},
363
		{ "set-state",		SETSTATE},
364
		{ "state",		STATE},
365
		{ "unknown",		UNKNOWN},
366
		{ "up",			UP},
367
		{ "||",			OR}
368
	};
369
	const struct keywords	*p;
370
371
	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
372
	    sizeof(keywords[0]), kw_cmp);
373
374
	if (p)
375
		return (p->k_val);
376
	else
377
		return (STRING);
378
}
379
380
#define MAXPUSHBACK	128
381
382
u_char	*parsebuf;
383
int	 parseindex;
384
u_char	 pushback_buffer[MAXPUSHBACK];
385
int	 pushback_index;
386
387
int
388
lgetc(int quotec)
389
{
390
	int		c, next;
391
392
	if (parsebuf) {
393
		/* Read character from the parsebuffer instead of input. */
394
		if (parseindex >= 0) {
395
			c = parsebuf[parseindex++];
396
			if (c != '\0')
397
				return (c);
398
			parsebuf = NULL;
399
		} else
400
			parseindex++;
401
	}
402
403
	if (pushback_index)
404
		return (pushback_buffer[--pushback_index]);
405
406
	if (quotec) {
407
		if ((c = getc(file->stream)) == EOF) {
408
			yyerror("reached end of file while parsing "
409
			    "quoted string");
410
			if (file == topfile || popfile() == EOF)
411
				return (EOF);
412
			return (quotec);
413
		}
414
		return (c);
415
	}
416
417
	while ((c = getc(file->stream)) == '\\') {
418
		next = getc(file->stream);
419
		if (next != '\n') {
420
			c = next;
421
			break;
422
		}
423
		yylval.lineno = file->lineno;
424
		file->lineno++;
425
	}
426
427
	while (c == EOF) {
428
		if (file == topfile || popfile() == EOF)
429
			return (EOF);
430
		c = getc(file->stream);
431
	}
432
	return (c);
433
}
434
435
int
436
lungetc(int c)
437
{
438
	if (c == EOF)
439
		return (EOF);
440
	if (parsebuf) {
441
		parseindex--;
442
		if (parseindex >= 0)
443
			return (c);
444
	}
445
	if (pushback_index < MAXPUSHBACK-1)
446
		return (pushback_buffer[pushback_index++] = c);
447
	else
448
		return (EOF);
449
}
450
451
int
452
findeol(void)
453
{
454
	int	c;
455
456
	parsebuf = NULL;
457
458
	/* skip to either EOF or the first real EOL */
459
	while (1) {
460
		if (pushback_index)
461
			c = pushback_buffer[--pushback_index];
462
		else
463
			c = lgetc(0);
464
		if (c == '\n') {
465
			file->lineno++;
466
			break;
467
		}
468
		if (c == EOF)
469
			break;
470
	}
471
	return (ERROR);
472
}
473
474
int
475
yylex(void)
476
{
477
	u_char	 buf[8096];
478
	u_char	*p, *val;
479
	int	 quotec, next, c;
480
	int	 token;
481
482
top:
483
	p = buf;
484
	while ((c = lgetc(0)) == ' ' || c == '\t')
485
		; /* nothing */
486
487
	yylval.lineno = file->lineno;
488
	if (c == '#')
489
		while ((c = lgetc(0)) != '\n' && c != EOF)
490
			; /* nothing */
491
	if (c == '$' && parsebuf == NULL) {
492
		while (1) {
493
			if ((c = lgetc(0)) == EOF)
494
				return (0);
495
496
			if (p + 1 >= buf + sizeof(buf) - 1) {
497
				yyerror("string too long");
498
				return (findeol());
499
			}
500
			if (isalnum(c) || c == '_') {
501
				*p++ = c;
502
				continue;
503
			}
504
			*p = '\0';
505
			lungetc(c);
506
			break;
507
		}
508
		val = symget(buf);
509
		if (val == NULL) {
510
			yyerror("macro '%s' not defined", buf);
511
			return (findeol());
512
		}
513
		parsebuf = val;
514
		parseindex = 0;
515
		goto top;
516
	}
517
518
	switch (c) {
519
	case '\'':
520
	case '"':
521
		quotec = c;
522
		while (1) {
523
			if ((c = lgetc(quotec)) == EOF)
524
				return (0);
525
			if (c == '\n') {
526
				file->lineno++;
527
				continue;
528
			} else if (c == '\\') {
529
				if ((next = lgetc(quotec)) == EOF)
530
					return (0);
531
				if (next == quotec || c == ' ' || c == '\t')
532
					c = next;
533
				else if (next == '\n') {
534
					file->lineno++;
535
					continue;
536
				} else
537
					lungetc(next);
538
			} else if (c == quotec) {
539
				*p = '\0';
540
				break;
541
			} else if (c == '\0') {
542
				yyerror("syntax error");
543
				return (findeol());
544
			}
545
			if (p + 1 >= buf + sizeof(buf) - 1) {
546
				yyerror("string too long");
547
				return (findeol());
548
			}
549
			*p++ = c;
550
		}
551
		yylval.v.string = strdup(buf);
552
		if (yylval.v.string == NULL)
553
			err(1, "yylex: strdup");
554
		return (STRING);
555
	}
556
557
#define allowed_to_end_number(x) \
558
	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
559
560
	if (c == '-' || isdigit(c)) {
561
		do {
562
			*p++ = c;
563
			if ((unsigned)(p-buf) >= sizeof(buf)) {
564
				yyerror("string too long");
565
				return (findeol());
566
			}
567
		} while ((c = lgetc(0)) != EOF && isdigit(c));
568
		lungetc(c);
569
		if (p == buf + 1 && buf[0] == '-')
570
			goto nodigits;
571
		if (c == EOF || allowed_to_end_number(c)) {
572
			const char *errstr = NULL;
573
574
			*p = '\0';
575
			yylval.v.number = strtonum(buf, LLONG_MIN,
576
			    LLONG_MAX, &errstr);
577
			if (errstr) {
578
				yyerror("\"%s\" invalid number: %s",
579
				    buf, errstr);
580
				return (findeol());
581
			}
582
			return (NUMBER);
583
		} else {
584
nodigits:
585
			while (p > buf + 1)
586
				lungetc(*--p);
587
			c = *--p;
588
			if (c == '-')
589
				return (c);
590
		}
591
	}
592
593
#define allowed_in_string(x) \
594
	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
595
	x != '{' && x != '}' && \
596
	x != '!' && x != '=' && x != '#' && \
597
	x != ',' && x != '.'))
598
599
	if (isalnum(c) || c == ':' || c == '_' || c == '&' || c == '|') {
600
		do {
601
			*p++ = c;
602
			if ((unsigned)(p-buf) >= sizeof(buf)) {
603
				yyerror("string too long");
604
				return (findeol());
605
			}
606
		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
607
		lungetc(c);
608
		*p = '\0';
609
		if ((token = lookup(buf)) == STRING)
610
			if ((yylval.v.string = strdup(buf)) == NULL)
611
				err(1, "yylex: strdup");
612
		return (token);
613
	}
614
	if (c == '\n') {
615
		yylval.lineno = file->lineno;
616
		file->lineno++;
617
	}
618
	if (c == EOF)
619
		return (0);
620
	return (c);
621
}
622
623
int
624
check_file_secrecy(int fd, const char *fname)
625
{
626
	struct stat	st;
627
628
	if (fstat(fd, &st)) {
629
		warn("cannot stat %s", fname);
630
		return (-1);
631
	}
632
	if (st.st_uid != 0 && st.st_uid != getuid()) {
633
		warnx("%s: owner not root or current user", fname);
634
		return (-1);
635
	}
636
	if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
637
		warnx("%s: group writable or world read/writable", fname);
638
		return (-1);
639
	}
640
	return (0);
641
}
642
643
struct file *
644
pushfile(const char *name, int secret)
645
{
646
	struct file	*nfile;
647
648
	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
649
		warn("malloc");
650
		return (NULL);
651
	}
652
	if ((nfile->name = strdup(name)) == NULL) {
653
		warn("strdup");
654
		free(nfile);
655
		return (NULL);
656
	}
657
	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
658
		warn("%s", nfile->name);
659
		free(nfile->name);
660
		free(nfile);
661
		return (NULL);
662
	} else if (secret &&
663
	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
664
		fclose(nfile->stream);
665
		free(nfile->name);
666
		free(nfile);
667
		return (NULL);
668
	}
669
	nfile->lineno = 1;
670
	TAILQ_INSERT_TAIL(&files, nfile, entry);
671
	return (nfile);
672
}
673
674
int
675
popfile(void)
676
{
677
	struct file	*prev;
678
679
	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
680
		prev->errors += file->errors;
681
682
	TAILQ_REMOVE(&files, file, entry);
683
	fclose(file->stream);
684
	free(file->name);
685
	free(file);
686
	file = prev;
687
	return (file ? 0 : EOF);
688
}
689
690
struct ifsd_config *
691
parse_config(char *filename, int opts)
692
{
693
	int		 errors = 0;
694
	struct sym	*sym, *next;
695
	struct ifsd_state *state;
696
697
	if ((conf = calloc(1, sizeof(struct ifsd_config))) == NULL) {
698
		err(1, NULL);
699
		return (NULL);
700
	}
701
702
	if ((file = pushfile(filename, 0)) == NULL) {
703
		free(conf);
704
		return (NULL);
705
	}
706
	topfile = file;
707
708
	TAILQ_INIT(&conf->states);
709
710
	init_state(&conf->initstate);
711
	curaction = conf->initstate.body;
712
	conf->opts = opts;
713
714
	yyparse();
715
716
	/* Link states */
717
	TAILQ_FOREACH(state, &conf->states, entries) {
718
		link_states(state->init);
719
		link_states(state->body);
720
	}
721
722
	errors = file->errors;
723
	popfile();
724
725
	if (start_state != NULL) {
726
		TAILQ_FOREACH(state, &conf->states, entries) {
727
			if (strcmp(start_state, state->name) == 0) {
728
				conf->curstate = state;
729
				break;
730
			}
731
		}
732
		if (conf->curstate == NULL)
733
			errx(1, "invalid start state %s", start_state);
734
	} else {
735
		conf->curstate = TAILQ_FIRST(&conf->states);
736
	}
737
738
	/* Free macros and check which have not been used. */
739
	TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
740
		if ((conf->opts & IFSD_OPT_VERBOSE2) && !sym->used)
741
			fprintf(stderr, "warning: macro '%s' not "
742
			    "used\n", sym->nam);
743
		if (!sym->persist) {
744
			free(sym->nam);
745
			free(sym->val);
746
			TAILQ_REMOVE(&symhead, sym, entry);
747
			free(sym);
748
		}
749
	}
750
751
	if (errors) {
752
		clear_config(conf);
753
		errors = 0;
754
		return (NULL);
755
	}
756
757
	return (conf);
758
}
759
760
void
761
link_states(struct ifsd_action *action)
762
{
763
	struct ifsd_action *subaction;
764
765
	switch (action->type) {
766
	default:
767
	case IFSD_ACTION_COMMAND:
768
		break;
769
	case IFSD_ACTION_CHANGESTATE: {
770
		struct ifsd_state *state;
771
772
		TAILQ_FOREACH(state, &conf->states, entries) {
773
			if (strcmp(action->act.statename,
774
			    state->name) == 0) {
775
				action->act.nextstate = state;
776
				break;
777
			}
778
		}
779
		if (state == NULL) {
780
			fprintf(stderr, "error: state '%s' not declared\n",
781
			    action->act.statename);
782
			file->errors++;
783
		}
784
		break;
785
	}
786
	case IFSD_ACTION_CONDITION:
787
		TAILQ_FOREACH(subaction, &action->act.c.actions, entries)
788
			link_states(subaction);
789
		break;
790
	}
791
}
792
793
int
794
symset(const char *nam, const char *val, int persist)
795
{
796
	struct sym	*sym;
797
798
	TAILQ_FOREACH(sym, &symhead, entry) {
799
		if (strcmp(nam, sym->nam) == 0)
800
			break;
801
	}
802
803
	if (sym != NULL) {
804
		if (sym->persist == 1)
805
			return (0);
806
		else {
807
			free(sym->nam);
808
			free(sym->val);
809
			TAILQ_REMOVE(&symhead, sym, entry);
810
			free(sym);
811
		}
812
	}
813
	if ((sym = calloc(1, sizeof(*sym))) == NULL)
814
		return (-1);
815
816
	sym->nam = strdup(nam);
817
	if (sym->nam == NULL) {
818
		free(sym);
819
		return (-1);
820
	}
821
	sym->val = strdup(val);
822
	if (sym->val == NULL) {
823
		free(sym->nam);
824
		free(sym);
825
		return (-1);
826
	}
827
	sym->used = 0;
828
	sym->persist = persist;
829
	TAILQ_INSERT_TAIL(&symhead, sym, entry);
830
	return (0);
831
}
832
833
int
834
cmdline_symset(char *s)
835
{
836
	char	*sym, *val;
837
	int	ret;
838
	size_t	len;
839
840
	if ((val = strrchr(s, '=')) == NULL)
841
		return (-1);
842
843
	len = strlen(s) - strlen(val) + 1;
844
	if ((sym = malloc(len)) == NULL)
845
		err(1, NULL);
846
847
	strlcpy(sym, s, len);
848
849
	ret = symset(sym, val + 1, 1);
850
	free(sym);
851
852
	return (ret);
853
}
854
855
char *
856
symget(const char *nam)
857
{
858
	struct sym	*sym;
859
860
	TAILQ_FOREACH(sym, &symhead, entry) {
861
		if (strcmp(nam, sym->nam) == 0) {
862
			sym->used = 1;
863
			return (sym->val);
864
		}
865
	}
866
	return (NULL);
867
}
868
869
void
870
set_expression_depth(struct ifsd_expression *expression, int depth)
871
{
872
	expression->depth = depth;
873
	if (conf->maxdepth < depth)
874
		conf->maxdepth = depth;
875
	if (expression->left != NULL)
876
		set_expression_depth(expression->left, depth + 1);
877
	if (expression->right != NULL)
878
		set_expression_depth(expression->right, depth + 1);
879
}
880
881
void
882
init_state(struct ifsd_state *state)
883
{
884
	TAILQ_INIT(&state->interface_states);
885
	TAILQ_INIT(&state->external_tests);
886
887
	if ((state->init = calloc(1, sizeof(*state->init))) == NULL)
888
		err(1, "init_state: calloc");
889
	state->init->type = IFSD_ACTION_CONDITION;
890
	TAILQ_INIT(&state->init->act.c.actions);
891
892
	if ((state->body = calloc(1, sizeof(*state->body))) == NULL)
893
		err(1, "init_state: calloc");
894
	state->body->type = IFSD_ACTION_CONDITION;
895
	TAILQ_INIT(&state->body->act.c.actions);
896
}
897
898
struct ifsd_ifstate *
899
new_ifstate(char *ifname, int s)
900
{
901
	struct ifsd_ifstate *ifstate = NULL;
902
	struct ifsd_state *state;
903
904
	if (curstate != NULL)
905
		state = curstate;
906
	else
907
		state = &conf->initstate;
908
909
	TAILQ_FOREACH(ifstate, &state->interface_states, entries)
910
		if (strcmp(ifstate->ifname, ifname) == 0 &&
911
		    ifstate->ifstate == s)
912
			break;
913
	if (ifstate == NULL) {
914
		if ((ifstate = calloc(1, sizeof(*ifstate))) == NULL)
915
			err(1, NULL);
916
		if (strlcpy(ifstate->ifname, ifname,
917
		    sizeof(ifstate->ifname)) >= sizeof(ifstate->ifname))
918
			errx(1, "ifname strlcpy truncation");
919
		free(ifname);
920
		ifstate->ifstate = s;
921
		TAILQ_INIT(&ifstate->expressions);
922
		TAILQ_INSERT_TAIL(&state->interface_states, ifstate, entries);
923
	}
924
	ifstate->prevstate = -1;
925
	ifstate->refcount++;
926
	return (ifstate);
927
}
928
929
struct ifsd_external *
930
new_external(char *command, u_int32_t frequency)
931
{
932
	struct ifsd_external *external = NULL;
933
	struct ifsd_state *state;
934
935
	if (curstate != NULL)
936
		state = curstate;
937
	else
938
		state = &conf->initstate;
939
940
	TAILQ_FOREACH(external, &state->external_tests, entries)
941
		if (strcmp(external->command, command) == 0 &&
942
		    external->frequency == frequency)
943
			break;
944
	if (external == NULL) {
945
		if ((external = calloc(1, sizeof(*external))) == NULL)
946
			err(1, NULL);
947
		if ((external->command = strdup(command)) == NULL)
948
			err(1, NULL);
949
		external->frequency = frequency;
950
		TAILQ_INIT(&external->expressions);
951
		TAILQ_INSERT_TAIL(&state->external_tests, external, entries);
952
	}
953
	external->prevstatus = -1;
954
	external->refcount++;
955
	return (external);
956
}
957
#line 950 "parse.c"
958
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
959
static int yygrowstack(void)
960
{
961
    unsigned int newsize;
962
    long sslen;
963
    short *newss;
964
    YYSTYPE *newvs;
965
966
    if ((newsize = yystacksize) == 0)
967
        newsize = YYINITSTACKSIZE;
968
    else if (newsize >= YYMAXDEPTH)
969
        return -1;
970
    else if ((newsize *= 2) > YYMAXDEPTH)
971
        newsize = YYMAXDEPTH;
972
    sslen = yyssp - yyss;
973
#ifdef SIZE_MAX
974
#define YY_SIZE_MAX SIZE_MAX
975
#else
976
#define YY_SIZE_MAX 0xffffffffU
977
#endif
978
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newss)
979
        goto bail;
980
    newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
981
      (short *)malloc(newsize * sizeof *newss); /* overflow check above */
982
    if (newss == NULL)
983
        goto bail;
984
    yyss = newss;
985
    yyssp = newss + sslen;
986
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newvs)
987
        goto bail;
988
    newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
989
      (YYSTYPE *)malloc(newsize * sizeof *newvs); /* overflow check above */
990
    if (newvs == NULL)
991
        goto bail;
992
    yyvs = newvs;
993
    yyvsp = newvs + sslen;
994
    yystacksize = newsize;
995
    yysslim = yyss + newsize - 1;
996
    return 0;
997
bail:
998
    if (yyss)
999
            free(yyss);
1000
    if (yyvs)
1001
            free(yyvs);
1002
    yyss = yyssp = NULL;
1003
    yyvs = yyvsp = NULL;
1004
    yystacksize = 0;
1005
    return -1;
1006
}
1007
1008
#define YYABORT goto yyabort
1009
#define YYREJECT goto yyabort
1010
#define YYACCEPT goto yyaccept
1011
#define YYERROR goto yyerrlab
1012
int
1013
yyparse(void)
1014
{
1015
    int yym, yyn, yystate;
1016
#if YYDEBUG
1017
    const char *yys;
1018
1019
    if ((yys = getenv("YYDEBUG")))
1020
    {
1021
        yyn = *yys;
1022
        if (yyn >= '0' && yyn <= '9')
1023
            yydebug = yyn - '0';
1024
    }
1025
#endif /* YYDEBUG */
1026
1027
    yynerrs = 0;
1028
    yyerrflag = 0;
1029
    yychar = (-1);
1030
1031
    if (yyss == NULL && yygrowstack()) goto yyoverflow;
1032
    yyssp = yyss;
1033
    yyvsp = yyvs;
1034
    *yyssp = yystate = 0;
1035
1036
yyloop:
1037
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1038
    if (yychar < 0)
1039
    {
1040
        if ((yychar = yylex()) < 0) yychar = 0;
1041
#if YYDEBUG
1042
        if (yydebug)
1043
        {
1044
            yys = 0;
1045
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1046
            if (!yys) yys = "illegal-symbol";
1047
            printf("%sdebug: state %d, reading %d (%s)\n",
1048
                    YYPREFIX, yystate, yychar, yys);
1049
        }
1050
#endif
1051
    }
1052
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1053
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1054
    {
1055
#if YYDEBUG
1056
        if (yydebug)
1057
            printf("%sdebug: state %d, shifting to state %d\n",
1058
                    YYPREFIX, yystate, yytable[yyn]);
1059
#endif
1060
        if (yyssp >= yysslim && yygrowstack())
1061
        {
1062
            goto yyoverflow;
1063
        }
1064
        *++yyssp = yystate = yytable[yyn];
1065
        *++yyvsp = yylval;
1066
        yychar = (-1);
1067
        if (yyerrflag > 0)  --yyerrflag;
1068
        goto yyloop;
1069
    }
1070
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1071
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1072
    {
1073
        yyn = yytable[yyn];
1074
        goto yyreduce;
1075
    }
1076
    if (yyerrflag) goto yyinrecovery;
1077
#if defined(__GNUC__)
1078
    goto yynewerror;
1079
#endif
1080
yynewerror:
1081
    yyerror("syntax error");
1082
#if defined(__GNUC__)
1083
    goto yyerrlab;
1084
#endif
1085
yyerrlab:
1086
    ++yynerrs;
1087
yyinrecovery:
1088
    if (yyerrflag < 3)
1089
    {
1090
        yyerrflag = 3;
1091
        for (;;)
1092
        {
1093
            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
1094
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1095
            {
1096
#if YYDEBUG
1097
                if (yydebug)
1098
                    printf("%sdebug: state %d, error recovery shifting\
1099
 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
1100
#endif
1101
                if (yyssp >= yysslim && yygrowstack())
1102
                {
1103
                    goto yyoverflow;
1104
                }
1105
                *++yyssp = yystate = yytable[yyn];
1106
                *++yyvsp = yylval;
1107
                goto yyloop;
1108
            }
1109
            else
1110
            {
1111
#if YYDEBUG
1112
                if (yydebug)
1113
                    printf("%sdebug: error recovery discarding state %d\n",
1114
                            YYPREFIX, *yyssp);
1115
#endif
1116
                if (yyssp <= yyss) goto yyabort;
1117
                --yyssp;
1118
                --yyvsp;
1119
            }
1120
        }
1121
    }
1122
    else
1123
    {
1124
        if (yychar == 0) goto yyabort;
1125
#if YYDEBUG
1126
        if (yydebug)
1127
        {
1128
            yys = 0;
1129
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1130
            if (!yys) yys = "illegal-symbol";
1131
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1132
                    YYPREFIX, yystate, yychar, yys);
1133
        }
1134
#endif
1135
        yychar = (-1);
1136
        goto yyloop;
1137
    }
1138
yyreduce:
1139
#if YYDEBUG
1140
    if (yydebug)
1141
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1142
                YYPREFIX, yystate, yyn, yyrule[yyn]);
1143
#endif
1144
    yym = yylen[yyn];
1145
    if (yym)
1146
        yyval = yyvsp[1-yym];
1147
    else
1148
        memset(&yyval, 0, sizeof yyval);
1149
    switch (yyn)
1150
    {
1151
case 7:
1152
#line 128 "parse.y"
1153
{ file->errors++; }
1154
break;
1155
case 8:
1156
#line 131 "parse.y"
1157
{
1158
			if (asprintf(&yyval.v.string, "%s %s", yyvsp[-1].v.string, yyvsp[0].v.string) == -1) {
1159
				free(yyvsp[-1].v.string);
1160
				free(yyvsp[0].v.string);
1161
				yyerror("string: asprintf");
1162
				YYERROR;
1163
			}
1164
			free(yyvsp[-1].v.string);
1165
			free(yyvsp[0].v.string);
1166
		}
1167
break;
1168
case 10:
1169
#line 144 "parse.y"
1170
{
1171
			char *s = yyvsp[-2].v.string;
1172
			if (conf->opts & IFSD_OPT_VERBOSE)
1173
				printf("%s = \"%s\"\n", yyvsp[-2].v.string, yyvsp[0].v.string);
1174
			while (*s++) {
1175
				if (isspace((unsigned char)*s)) {
1176
					yyerror("macro name cannot contain "
1177
					    "whitespace");
1178
					YYERROR;
1179
				}
1180
			}
1181
			if (symset(yyvsp[-2].v.string, yyvsp[0].v.string, 0) == -1) {
1182
				free(yyvsp[-2].v.string);
1183
				free(yyvsp[0].v.string);
1184
				yyerror("cannot store variable");
1185
				YYERROR;
1186
			}
1187
			free(yyvsp[-2].v.string);
1188
			free(yyvsp[0].v.string);
1189
		}
1190
break;
1191
case 11:
1192
#line 166 "parse.y"
1193
{
1194
			start_state = yyvsp[0].v.string;
1195
		}
1196
break;
1197
case 12:
1198
#line 171 "parse.y"
1199
{
1200
			if (if_nametoindex(yyvsp[0].v.string) == 0) {
1201
				yyerror("unknown interface %s", yyvsp[0].v.string);
1202
				free(yyvsp[0].v.string);
1203
				YYERROR;
1204
			}
1205
			yyval.v.string = yyvsp[0].v.string;
1206
		}
1207
break;
1208
case 16:
1209
#line 188 "parse.y"
1210
{
1211
			struct ifsd_action *action;
1212
1213
			if ((action = calloc(1, sizeof(*action))) == NULL)
1214
				err(1, "action: calloc");
1215
			action->type = IFSD_ACTION_COMMAND;
1216
			action->act.command = yyvsp[0].v.string;
1217
			TAILQ_INSERT_TAIL(&curaction->act.c.actions,
1218
			    action, entries);
1219
		}
1220
break;
1221
case 17:
1222
#line 198 "parse.y"
1223
{
1224
			struct ifsd_action *action;
1225
1226
			if (curstate == NULL) {
1227
				free(yyvsp[0].v.string);
1228
				yyerror("set-state must be used inside 'if'");
1229
				YYERROR;
1230
			}
1231
			if ((action = calloc(1, sizeof(*action))) == NULL)
1232
				err(1, "action: calloc");
1233
			action->type = IFSD_ACTION_CHANGESTATE;
1234
			action->act.statename = yyvsp[0].v.string;
1235
			TAILQ_INSERT_TAIL(&curaction->act.c.actions,
1236
			    action, entries);
1237
		}
1238
break;
1239
case 18:
1240
#line 213 "parse.y"
1241
{
1242
			struct ifsd_action *action;
1243
1244
			if ((action = calloc(1, sizeof(*action))) == NULL)
1245
				err(1, "action: calloc");
1246
			action->type = IFSD_ACTION_CONDITION;
1247
			TAILQ_INIT(&action->act.c.actions);
1248
			TAILQ_INSERT_TAIL(&curaction->act.c.actions,
1249
			    action, entries);
1250
			action->parent = curaction;
1251
			curaction = action;
1252
		}
1253
break;
1254
case 19:
1255
#line 224 "parse.y"
1256
{
1257
			set_expression_depth(curaction->act.c.expression, 0);
1258
			curaction = curaction->parent;
1259
		}
1260
break;
1261
case 24:
1262
#line 238 "parse.y"
1263
{
1264
			if (curstate != NULL)
1265
				curaction = curstate->init;
1266
			else
1267
				curaction = conf->initstate.init;
1268
		}
1269
break;
1270
case 25:
1271
#line 243 "parse.y"
1272
{
1273
			if (curstate != NULL)
1274
				curaction = curstate->body;
1275
			else
1276
				curaction = conf->initstate.body;
1277
		}
1278
break;
1279
case 26:
1280
#line 251 "parse.y"
1281
{
1282
			yyval.v.ifstate = new_ifstate(yyvsp[-4].v.string, IFSD_LINKUP);
1283
		}
1284
break;
1285
case 27:
1286
#line 254 "parse.y"
1287
{
1288
			yyval.v.ifstate = new_ifstate(yyvsp[-4].v.string, IFSD_LINKDOWN);
1289
		}
1290
break;
1291
case 28:
1292
#line 257 "parse.y"
1293
{
1294
			yyval.v.ifstate = new_ifstate(yyvsp[-4].v.string, IFSD_LINKUNKNOWN);
1295
		}
1296
break;
1297
case 29:
1298
#line 262 "parse.y"
1299
{
1300
			if (yyvsp[0].v.number <= 0 || yyvsp[0].v.number > UINT_MAX) {
1301
				yyerror("invalid interval: %lld", yyvsp[0].v.number);
1302
				free(yyvsp[-2].v.string);
1303
				YYERROR;
1304
			}
1305
			yyval.v.external = new_external(yyvsp[-2].v.string, yyvsp[0].v.number);
1306
			free(yyvsp[-2].v.string);
1307
		}
1308
break;
1309
case 30:
1310
#line 273 "parse.y"
1311
{
1312
			if ((yyval.v.expression = calloc(1, sizeof(*yyval.v.expression))) == NULL)
1313
				err(1, NULL);
1314
			curaction->act.c.expression = yyval.v.expression;
1315
			yyval.v.expression->type = IFSD_OPER_IFSTATE;
1316
			yyval.v.expression->u.ifstate = yyvsp[0].v.ifstate;
1317
			TAILQ_INSERT_TAIL(&yyvsp[0].v.ifstate->expressions, yyval.v.expression, entries);
1318
		}
1319
break;
1320
case 31:
1321
#line 281 "parse.y"
1322
{
1323
			if ((yyval.v.expression = calloc(1, sizeof(*yyval.v.expression))) == NULL)
1324
				err(1, NULL);
1325
			curaction->act.c.expression = yyval.v.expression;
1326
			yyval.v.expression->type = IFSD_OPER_EXTERNAL;
1327
			yyval.v.expression->u.external = yyvsp[0].v.external;
1328
			TAILQ_INSERT_TAIL(&yyvsp[0].v.external->expressions, yyval.v.expression, entries);
1329
		}
1330
break;
1331
case 32:
1332
#line 289 "parse.y"
1333
{
1334
			yyval.v.expression = yyvsp[-1].v.expression;
1335
		}
1336
break;
1337
case 33:
1338
#line 294 "parse.y"
1339
{
1340
			if ((yyval.v.expression = calloc(1, sizeof(*yyval.v.expression))) == NULL)
1341
				err(1, NULL);
1342
			curaction->act.c.expression = yyval.v.expression;
1343
			yyval.v.expression->type = IFSD_OPER_NOT;
1344
			yyvsp[0].v.expression->parent = yyval.v.expression;
1345
			yyval.v.expression->right = yyvsp[0].v.expression;
1346
		}
1347
break;
1348
case 34:
1349
#line 302 "parse.y"
1350
{
1351
			if ((yyval.v.expression = calloc(1, sizeof(*yyval.v.expression))) == NULL)
1352
				err(1, NULL);
1353
			curaction->act.c.expression = yyval.v.expression;
1354
			yyval.v.expression->type = IFSD_OPER_AND;
1355
			yyvsp[-2].v.expression->parent = yyval.v.expression;
1356
			yyvsp[0].v.expression->parent = yyval.v.expression;
1357
			yyval.v.expression->left = yyvsp[-2].v.expression;
1358
			yyval.v.expression->right = yyvsp[0].v.expression;
1359
		}
1360
break;
1361
case 35:
1362
#line 312 "parse.y"
1363
{
1364
			if ((yyval.v.expression = calloc(1, sizeof(*yyval.v.expression))) == NULL)
1365
				err(1, NULL);
1366
			curaction->act.c.expression = yyval.v.expression;
1367
			yyval.v.expression->type = IFSD_OPER_OR;
1368
			yyvsp[-2].v.expression->parent = yyval.v.expression;
1369
			yyvsp[0].v.expression->parent = yyval.v.expression;
1370
			yyval.v.expression->left = yyvsp[-2].v.expression;
1371
			yyval.v.expression->right = yyvsp[0].v.expression;
1372
		}
1373
break;
1374
case 37:
1375
#line 325 "parse.y"
1376
{
1377
			struct ifsd_state *state = NULL;
1378
1379
			TAILQ_FOREACH(state, &conf->states, entries)
1380
				if (!strcmp(state->name, yyvsp[0].v.string)) {
1381
					yyerror("state %s already exists", yyvsp[0].v.string);
1382
					free(yyvsp[0].v.string);
1383
					YYERROR;
1384
				}
1385
			if ((state = calloc(1, sizeof(*curstate))) == NULL)
1386
				err(1, NULL);
1387
			init_state(state);
1388
			state->name = yyvsp[0].v.string;
1389
			curstate = state;
1390
			curaction = state->body;
1391
		}
1392
break;
1393
case 38:
1394
#line 340 "parse.y"
1395
{
1396
			TAILQ_INSERT_TAIL(&conf->states, curstate, entries);
1397
			curstate = NULL;
1398
			curaction = conf->initstate.body;
1399
		}
1400
break;
1401
#line 1394 "parse.c"
1402
    }
1403
    yyssp -= yym;
1404
    yystate = *yyssp;
1405
    yyvsp -= yym;
1406
    yym = yylhs[yyn];
1407
    if (yystate == 0 && yym == 0)
1408
    {
1409
#if YYDEBUG
1410
        if (yydebug)
1411
            printf("%sdebug: after reduction, shifting from state 0 to\
1412
 state %d\n", YYPREFIX, YYFINAL);
1413
#endif
1414
        yystate = YYFINAL;
1415
        *++yyssp = YYFINAL;
1416
        *++yyvsp = yyval;
1417
        if (yychar < 0)
1418
        {
1419
            if ((yychar = yylex()) < 0) yychar = 0;
1420
#if YYDEBUG
1421
            if (yydebug)
1422
            {
1423
                yys = 0;
1424
                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1425
                if (!yys) yys = "illegal-symbol";
1426
                printf("%sdebug: state %d, reading %d (%s)\n",
1427
                        YYPREFIX, YYFINAL, yychar, yys);
1428
            }
1429
#endif
1430
        }
1431
        if (yychar == 0) goto yyaccept;
1432
        goto yyloop;
1433
    }
1434
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1435
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1436
        yystate = yytable[yyn];
1437
    else
1438
        yystate = yydgoto[yym];
1439
#if YYDEBUG
1440
    if (yydebug)
1441
        printf("%sdebug: after reduction, shifting from state %d \
1442
to state %d\n", YYPREFIX, *yyssp, yystate);
1443
#endif
1444
    if (yyssp >= yysslim && yygrowstack())
1445
    {
1446
        goto yyoverflow;
1447
    }
1448
    *++yyssp = yystate;
1449
    *++yyvsp = yyval;
1450
    goto yyloop;
1451
yyoverflow:
1452
    yyerror("yacc stack overflow");
1453
yyabort:
1454
    if (yyss)
1455
            free(yyss);
1456
    if (yyvs)
1457
            free(yyvs);
1458
    yyss = yyssp = NULL;
1459
    yyvs = yyvsp = NULL;
1460
    yystacksize = 0;
1461
    return (1);
1462
yyaccept:
1463
    if (yyss)
1464
            free(yyss);
1465
    if (yyvs)
1466
            free(yyvs);
1467
    yyss = yyssp = NULL;
1468
    yyvs = yyvsp = NULL;
1469
    yystacksize = 0;
1470
    return (0);
1471
}