Bug Summary

File:src/usr.sbin/ifstated/obj/parse.c
Warning:line 995, column 13
Attempt to free released memory

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name parse.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/ifstated/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/ifstated -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/ifstated/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c parse.c
1#include <stdlib.h>
2#include <string.h>
3#define YYBYACC1 1
4#define YYMAJOR1 1
5#define YYMINOR9 9
6#define YYLEXyylex() yylex()
7#define YYEMPTY-1 -1
8#define yyclearin(yychar=(-1)) (yychar=(YYEMPTY-1))
9#define yyerrok(yyerrflag=0) (yyerrflag=0)
10#define YYRECOVERING()(yyerrflag!=0) (yyerrflag!=0)
11#define YYPREFIX"yy" "yy"
12#line 24 "/usr/src/usr.sbin/ifstated/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(*__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
35TAILQ_HEAD(files, file)struct files { struct file *tqh_first; struct file **tqh_last
; }
files = TAILQ_HEAD_INITIALIZER(files){ ((void *)0), &(files).tqh_first };
36static struct file {
37 TAILQ_ENTRY(file)struct { struct file *tqe_next; struct file **tqe_prev; } entry;
38 FILE *stream;
39 char *name;
40 int lineno;
41 int errors;
42} *file, *topfile;
43struct file *pushfile(const char *, int);
44int popfile(void);
45int check_file_secrecy(int, const char *);
46int yyparse(void);
47int yylex(void);
48int yyerror(const char *, ...)
49 __attribute__((__format__ (printf, 1, 2)))
50 __attribute__((__nonnull__ (1)));
51int kw_cmp(const void *, const void *);
52int lookup(char *);
53int lgetc(int);
54int lungetc(int);
55int findeol(void);
56
57TAILQ_HEAD(symhead, sym)struct symhead { struct sym *tqh_first; struct sym **tqh_last
; }
symhead = TAILQ_HEAD_INITIALIZER(symhead){ ((void *)0), &(symhead).tqh_first };
58struct sym {
59 TAILQ_ENTRY(sym)struct { struct sym *tqe_next; struct sym **tqe_prev; } entry;
60 int used;
61 int persist;
62 char *nam;
63 char *val;
64};
65int symset(const char *, const char *, int);
66char *symget(const char *);
67
68static struct ifsd_config *conf;
69char *start_state;
70
71struct ifsd_action *curaction;
72struct ifsd_state *curstate;
73
74void link_states(struct ifsd_action *);
75void set_expression_depth(struct ifsd_expression *, int);
76void init_state(struct ifsd_state *);
77struct ifsd_ifstate *new_ifstate(char *, int);
78struct ifsd_external *new_external(char *, u_int32_t);
79
80typedef 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 STATE257 257
96#define INITSTATE258 258
97#define LINK259 259
98#define UP260 260
99#define DOWN261 261
100#define UNKNOWN262 262
101#define IF263 263
102#define RUN264 264
103#define SETSTATE265 265
104#define EVERY266 266
105#define INIT267 267
106#define AND268 268
107#define OR269 269
108#define UNARY270 270
109#define ERROR271 271
110#define STRING272 272
111#define NUMBER273 273
112#define YYERRCODE256 256
113const 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};
121const 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};
129const 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};
140const 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};
145const 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,};
155const 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,};
165const 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 YYTABLESIZE262 262
171const 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};
201const 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 YYFINAL1 1
232#ifndef YYDEBUG0
233#define YYDEBUG0 0
234#endif
235#define YYMAXTOKEN273 273
236#if YYDEBUG0
237const 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,
2400,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,
2420,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,
2430,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,
2440,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,
2450,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,
2460,0,"STATE","INITSTATE","LINK","UP","DOWN","UNKNOWN","IF","RUN","SETSTATE",
247"EVERY","INIT","AND","OR","UNARY","ERROR","STRING","NUMBER",
248};
249const 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 YYSTACKSIZE10000
296#undef YYMAXDEPTH10000
297#define YYMAXDEPTH10000 YYSTACKSIZE10000
298#else
299#ifdef YYMAXDEPTH10000
300#define YYSTACKSIZE10000 YYMAXDEPTH10000
301#else
302#define YYSTACKSIZE10000 10000
303#define YYMAXDEPTH10000 10000
304#endif
305#endif
306#define YYINITSTACKSIZE200 200
307/* LINTUSED */
308int yydebug;
309int yynerrs;
310int yyerrflag;
311int yychar;
312short *yyssp;
313YYSTYPE *yyvsp;
314YYSTYPE yyval;
315YYSTYPE yylval;
316short *yyss;
317short *yysslim;
318YYSTYPE *yyvs;
319unsigned int yystacksize;
320int yyparse(void);
321#line 358 "/usr/src/usr.sbin/ifstated/parse.y"
322
323struct keywords {
324 const char *k_name;
325 int k_val;
326};
327
328int
329yyerror(const char *fmt, ...)
330{
331 va_list ap;
332 char *msg;
333
334 file->errors++;
335 va_start(ap, fmt)__builtin_va_start(ap, fmt);
336 if (vasprintf(&msg, fmt, ap) == -1)
337 fatalx("yyerror vasprintf");
338 va_end(ap)__builtin_va_end(ap);
339 logit(LOG_CRIT2, "%s:%d: %s", file->name, yylval.lineno, msg);
340 free(msg);
341 return (0);
342}
343
344int
345kw_cmp(const void *k, const void *e)
346{
347 return (strcmp(k, ((const struct keywords *)e)->k_name));
348}
349
350int
351lookup(char *s)
352{
353 /* this has to be sorted always */
354 static const struct keywords keywords[] = {
355 { "&&", AND268},
356 { "down", DOWN261},
357 { "every", EVERY266},
358 { "if", IF263},
359 { "init", INIT267},
360 { "init-state", INITSTATE258},
361 { "link", LINK259},
362 { "run", RUN264},
363 { "set-state", SETSTATE265},
364 { "state", STATE257},
365 { "unknown", UNKNOWN262},
366 { "up", UP260},
367 { "||", OR269}
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 (STRING272);
378}
379
380#define MAXPUSHBACK128 128
381
382char *parsebuf;
383int parseindex;
384char pushback_buffer[MAXPUSHBACK128];
385int pushback_index = 0;
386
387int
388lgetc(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 = (unsigned char)parsebuf[parseindex++];
396 if (c != '\0')
397 return (c);
398 parsebuf = NULL((void *)0);
399 } else
400 parseindex++;
401 }
402
403 if (pushback_index)
404 return ((unsigned char)pushback_buffer[--pushback_index]);
405
406 if (quotec) {
407 if ((c = getc(file->stream)(!__isthreaded ? (--(file->stream)->_r < 0 ? __srget
(file->stream) : (int)(*(file->stream)->_p++)) : (getc
)(file->stream))
) == EOF(-1)) {
408 yyerror("reached end of file while parsing "
409 "quoted string");
410 if (file == topfile || popfile() == EOF(-1))
411 return (EOF(-1));
412 return (quotec);
413 }
414 return (c);
415 }
416
417 while ((c = getc(file->stream)(!__isthreaded ? (--(file->stream)->_r < 0 ? __srget
(file->stream) : (int)(*(file->stream)->_p++)) : (getc
)(file->stream))
) == '\\') {
418 next = getc(file->stream)(!__isthreaded ? (--(file->stream)->_r < 0 ? __srget
(file->stream) : (int)(*(file->stream)->_p++)) : (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(-1)) {
428 if (file == topfile || popfile() == EOF(-1))
429 return (EOF(-1));
430 c = getc(file->stream)(!__isthreaded ? (--(file->stream)->_r < 0 ? __srget
(file->stream) : (int)(*(file->stream)->_p++)) : (getc
)(file->stream))
;
431 }
432 return (c);
433}
434
435int
436lungetc(int c)
437{
438 if (c == EOF(-1))
439 return (EOF(-1));
440 if (parsebuf) {
441 parseindex--;
442 if (parseindex >= 0)
443 return (c);
444 }
445 if (pushback_index + 1 >= MAXPUSHBACK128)
446 return (EOF(-1));
447 pushback_buffer[pushback_index++] = c;
448 return (c);
449}
450
451int
452findeol(void)
453{
454 int c;
455
456 parsebuf = NULL((void *)0);
457
458 /* skip to either EOF or the first real EOL */
459 while (1) {
460 if (pushback_index)
461 c = (unsigned char)pushback_buffer[--pushback_index];
462 else
463 c = lgetc(0);
464 if (c == '\n') {
465 file->lineno++;
466 break;
467 }
468 if (c == EOF(-1))
469 break;
470 }
471 return (ERROR271);
472}
473
474int
475yylex(void)
476{
477 char buf[8096];
478 char *p, *val;
479 int quotec, next, c;
480 int token;
481
482top:
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(-1))
490 ; /* nothing */
491 if (c == '$' && parsebuf == NULL((void *)0)) {
492 while (1) {
493 if ((c = lgetc(0)) == EOF(-1))
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((void *)0)) {
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(-1))
524 return (0);
525 if (c == '\n') {
526 file->lineno++;
527 continue;
528 } else if (c == '\\') {
529 if ((next = lgetc(quotec)) == EOF(-1))
530 return (0);
531 if (next == quotec || next == ' ' ||
532 next == '\t')
533 c = next;
534 else if (next == '\n') {
535 file->lineno++;
536 continue;
537 } else
538 lungetc(next);
539 } else if (c == quotec) {
540 *p = '\0';
541 break;
542 } else if (c == '\0') {
543 yyerror("syntax error");
544 return (findeol());
545 }
546 if (p + 1 >= buf + sizeof(buf) - 1) {
547 yyerror("string too long");
548 return (findeol());
549 }
550 *p++ = c;
551 }
552 yylval.v.string = strdup(buf);
553 if (yylval.v.string == NULL((void *)0))
554 err(1, "%s", __func__);
555 return (STRING272);
556 }
557
558#define allowed_to_end_number(x)(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' ||
x == '=')
\
559 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
560
561 if (c == '-' || isdigit(c)) {
562 do {
563 *p++ = c;
564 if ((size_t)(p-buf) >= sizeof(buf)) {
565 yyerror("string too long");
566 return (findeol());
567 }
568 } while ((c = lgetc(0)) != EOF(-1) && isdigit(c));
569 lungetc(c);
570 if (p == buf + 1 && buf[0] == '-')
571 goto nodigits;
572 if (c == EOF(-1) || allowed_to_end_number(c)(isspace(c) || c == ')' || c ==',' || c == '/' || c == '}' ||
c == '=')
) {
573 const char *errstr = NULL((void *)0);
574
575 *p = '\0';
576 yylval.v.number = strtonum(buf, LLONG_MIN(-9223372036854775807LL -1LL),
577 LLONG_MAX9223372036854775807LL, &errstr);
578 if (errstr) {
579 yyerror("\"%s\" invalid number: %s",
580 buf, errstr);
581 return (findeol());
582 }
583 return (NUMBER273);
584 } else {
585nodigits:
586 while (p > buf + 1)
587 lungetc((unsigned char)*--p);
588 c = (unsigned char)*--p;
589 if (c == '-')
590 return (c);
591 }
592 }
593
594#define allowed_in_string(x)(isalnum(x) || (ispunct(x) && x != '(' && x !=
')' && x != '{' && x != '}' && x != '!'
&& x != '=' && x != '#' && x != ',' &&
x != '.'))
\
595 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
596 x != '{' && x != '}' && \
597 x != '!' && x != '=' && x != '#' && \
598 x != ',' && x != '.'))
599
600 if (isalnum(c) || c == ':' || c == '_' || c == '&' || c == '|') {
601 do {
602 *p++ = c;
603 if ((size_t)(p-buf) >= sizeof(buf)) {
604 yyerror("string too long");
605 return (findeol());
606 }
607 } while ((c = lgetc(0)) != EOF(-1) && (allowed_in_string(c)(isalnum(c) || (ispunct(c) && c != '(' && c !=
')' && c != '{' && c != '}' && c != '!'
&& c != '=' && c != '#' && c != ',' &&
c != '.'))
));
608 lungetc(c);
609 *p = '\0';
610 if ((token = lookup(buf)) == STRING272)
611 if ((yylval.v.string = strdup(buf)) == NULL((void *)0))
612 err(1, "%s", __func__);
613 return (token);
614 }
615 if (c == '\n') {
616 yylval.lineno = file->lineno;
617 file->lineno++;
618 }
619 if (c == EOF(-1))
620 return (0);
621 return (c);
622}
623
624int
625check_file_secrecy(int fd, const char *fname)
626{
627 struct stat st;
628
629 if (fstat(fd, &st)) {
630 warn("cannot stat %s", fname);
631 return (-1);
632 }
633 if (st.st_uid != 0 && st.st_uid != getuid()) {
634 warnx("%s: owner not root or current user", fname);
635 return (-1);
636 }
637 if (st.st_mode & (S_IWGRP0000020 | S_IXGRP0000010 | S_IRWXO0000007)) {
638 warnx("%s: group writable or world read/writable", fname);
639 return (-1);
640 }
641 return (0);
642}
643
644struct file *
645pushfile(const char *name, int secret)
646{
647 struct file *nfile;
648
649 if ((nfile = calloc(1, sizeof(struct file))) == NULL((void *)0)) {
650 warn("%s", __func__);
651 return (NULL((void *)0));
652 }
653 if ((nfile->name = strdup(name)) == NULL((void *)0)) {
654 warn("%s", __func__);
655 free(nfile);
656 return (NULL((void *)0));
657 }
658 if ((nfile->stream = fopen(nfile->name, "r")) == NULL((void *)0)) {
659 warn("%s: %s", __func__, nfile->name);
660 free(nfile->name);
661 free(nfile);
662 return (NULL((void *)0));
663 } else if (secret &&
664 check_file_secrecy(fileno(nfile->stream)(!__isthreaded ? ((nfile->stream)->_file) : (fileno)(nfile
->stream))
, nfile->name)) {
665 fclose(nfile->stream);
666 free(nfile->name);
667 free(nfile);
668 return (NULL((void *)0));
669 }
670 nfile->lineno = 1;
671 TAILQ_INSERT_TAIL(&files, nfile, entry)do { (nfile)->entry.tqe_next = ((void *)0); (nfile)->entry
.tqe_prev = (&files)->tqh_last; *(&files)->tqh_last
= (nfile); (&files)->tqh_last = &(nfile)->entry
.tqe_next; } while (0)
;
672 return (nfile);
673}
674
675int
676popfile(void)
677{
678 struct file *prev;
679
680 if ((prev = TAILQ_PREV(file, files, entry)(*(((struct files *)((file)->entry.tqe_prev))->tqh_last
))
) != NULL((void *)0))
681 prev->errors += file->errors;
682
683 TAILQ_REMOVE(&files, file, entry)do { if (((file)->entry.tqe_next) != ((void *)0)) (file)->
entry.tqe_next->entry.tqe_prev = (file)->entry.tqe_prev
; else (&files)->tqh_last = (file)->entry.tqe_prev;
*(file)->entry.tqe_prev = (file)->entry.tqe_next; ; ; }
while (0)
;
684 fclose(file->stream);
685 free(file->name);
686 free(file);
687 file = prev;
688 return (file ? 0 : EOF(-1));
689}
690
691struct ifsd_config *
692parse_config(char *filename, int opts)
693{
694 int errors = 0;
695 struct sym *sym, *next;
696 struct ifsd_state *state;
697
698 if ((conf = calloc(1, sizeof(struct ifsd_config))) == NULL((void *)0)) {
699 err(1, "%s", __func__);
700 return (NULL((void *)0));
701 }
702
703 if ((file = pushfile(filename, 0)) == NULL((void *)0)) {
704 free(conf);
705 return (NULL((void *)0));
706 }
707 topfile = file;
708
709 TAILQ_INIT(&conf->states)do { (&conf->states)->tqh_first = ((void *)0); (&
conf->states)->tqh_last = &(&conf->states)->
tqh_first; } while (0)
;
710
711 init_state(&conf->initstate);
712 curaction = conf->initstate.body;
713 conf->opts = opts;
714
715 yyparse();
716
717 /* Link states */
718 TAILQ_FOREACH(state, &conf->states, entries)for((state) = ((&conf->states)->tqh_first); (state)
!= ((void *)0); (state) = ((state)->entries.tqe_next))
{
719 link_states(state->init);
720 link_states(state->body);
721 }
722
723 errors = file->errors;
724 popfile();
725
726 if (start_state != NULL((void *)0)) {
727 TAILQ_FOREACH(state, &conf->states, entries)for((state) = ((&conf->states)->tqh_first); (state)
!= ((void *)0); (state) = ((state)->entries.tqe_next))
{
728 if (strcmp(start_state, state->name) == 0) {
729 conf->curstate = state;
730 break;
731 }
732 }
733 if (conf->curstate == NULL((void *)0))
734 errx(1, "invalid start state %s", start_state);
735 } else {
736 conf->curstate = TAILQ_FIRST(&conf->states)((&conf->states)->tqh_first);
737 }
738
739 /* Free macros and check which have not been used. */
740 TAILQ_FOREACH_SAFE(sym, &symhead, entry, next)for ((sym) = ((&symhead)->tqh_first); (sym) != ((void *
)0) && ((next) = ((sym)->entry.tqe_next), 1); (sym
) = (next))
{
741 if ((conf->opts & IFSD_OPT_VERBOSE20x00000002) && !sym->used)
742 fprintf(stderr(&__sF[2]), "warning: macro '%s' not "
743 "used\n", sym->nam);
744 if (!sym->persist) {
745 free(sym->nam);
746 free(sym->val);
747 TAILQ_REMOVE(&symhead, sym, entry)do { if (((sym)->entry.tqe_next) != ((void *)0)) (sym)->
entry.tqe_next->entry.tqe_prev = (sym)->entry.tqe_prev;
else (&symhead)->tqh_last = (sym)->entry.tqe_prev;
*(sym)->entry.tqe_prev = (sym)->entry.tqe_next; ; ; } while
(0)
;
748 free(sym);
749 }
750 }
751
752 if (errors) {
753 clear_config(conf);
754 errors = 0;
755 return (NULL((void *)0));
756 }
757
758 return (conf);
759}
760
761void
762link_states(struct ifsd_action *action)
763{
764 struct ifsd_action *subaction;
765
766 switch (action->type) {
767 default:
768 case IFSD_ACTION_COMMAND1:
769 break;
770 case IFSD_ACTION_CHANGESTATE2: {
771 struct ifsd_state *state;
772
773 TAILQ_FOREACH(state, &conf->states, entries)for((state) = ((&conf->states)->tqh_first); (state)
!= ((void *)0); (state) = ((state)->entries.tqe_next))
{
774 if (strcmp(action->act.statename,
775 state->name) == 0) {
776 action->act.nextstate = state;
777 break;
778 }
779 }
780 if (state == NULL((void *)0)) {
781 fprintf(stderr(&__sF[2]), "error: state '%s' not declared\n",
782 action->act.statename);
783 file->errors++;
784 }
785 break;
786 }
787 case IFSD_ACTION_CONDITION3:
788 TAILQ_FOREACH(subaction, &action->act.c.actions, entries)for((subaction) = ((&action->act.c.actions)->tqh_first
); (subaction) != ((void *)0); (subaction) = ((subaction)->
entries.tqe_next))
789 link_states(subaction);
790 break;
791 }
792}
793
794int
795symset(const char *nam, const char *val, int persist)
796{
797 struct sym *sym;
798
799 TAILQ_FOREACH(sym, &symhead, entry)for((sym) = ((&symhead)->tqh_first); (sym) != ((void *
)0); (sym) = ((sym)->entry.tqe_next))
{
800 if (strcmp(nam, sym->nam) == 0)
801 break;
802 }
803
804 if (sym != NULL((void *)0)) {
805 if (sym->persist == 1)
806 return (0);
807 else {
808 free(sym->nam);
809 free(sym->val);
810 TAILQ_REMOVE(&symhead, sym, entry)do { if (((sym)->entry.tqe_next) != ((void *)0)) (sym)->
entry.tqe_next->entry.tqe_prev = (sym)->entry.tqe_prev;
else (&symhead)->tqh_last = (sym)->entry.tqe_prev;
*(sym)->entry.tqe_prev = (sym)->entry.tqe_next; ; ; } while
(0)
;
811 free(sym);
812 }
813 }
814 if ((sym = calloc(1, sizeof(*sym))) == NULL((void *)0))
815 return (-1);
816
817 sym->nam = strdup(nam);
818 if (sym->nam == NULL((void *)0)) {
819 free(sym);
820 return (-1);
821 }
822 sym->val = strdup(val);
823 if (sym->val == NULL((void *)0)) {
824 free(sym->nam);
825 free(sym);
826 return (-1);
827 }
828 sym->used = 0;
829 sym->persist = persist;
830 TAILQ_INSERT_TAIL(&symhead, sym, entry)do { (sym)->entry.tqe_next = ((void *)0); (sym)->entry.
tqe_prev = (&symhead)->tqh_last; *(&symhead)->tqh_last
= (sym); (&symhead)->tqh_last = &(sym)->entry.
tqe_next; } while (0)
;
831 return (0);
832}
833
834int
835cmdline_symset(char *s)
836{
837 char *sym, *val;
838 int ret;
839
840 if ((val = strrchr(s, '=')) == NULL((void *)0))
841 return (-1);
842 sym = strndup(s, val - s);
843 if (sym == NULL((void *)0))
844 err(1, "%s", __func__);
845 ret = symset(sym, val + 1, 1);
846 free(sym);
847
848 return (ret);
849}
850
851char *
852symget(const char *nam)
853{
854 struct sym *sym;
855
856 TAILQ_FOREACH(sym, &symhead, entry)for((sym) = ((&symhead)->tqh_first); (sym) != ((void *
)0); (sym) = ((sym)->entry.tqe_next))
{
857 if (strcmp(nam, sym->nam) == 0) {
858 sym->used = 1;
859 return (sym->val);
860 }
861 }
862 return (NULL((void *)0));
863}
864
865void
866set_expression_depth(struct ifsd_expression *expression, int depth)
867{
868 expression->depth = depth;
869 if (conf->maxdepth < depth)
870 conf->maxdepth = depth;
871 if (expression->left != NULL((void *)0))
872 set_expression_depth(expression->left, depth + 1);
873 if (expression->right != NULL((void *)0))
874 set_expression_depth(expression->right, depth + 1);
875}
876
877void
878init_state(struct ifsd_state *state)
879{
880 TAILQ_INIT(&state->interface_states)do { (&state->interface_states)->tqh_first = ((void
*)0); (&state->interface_states)->tqh_last = &
(&state->interface_states)->tqh_first; } while (0)
;
881 TAILQ_INIT(&state->external_tests)do { (&state->external_tests)->tqh_first = ((void *
)0); (&state->external_tests)->tqh_last = &(&
state->external_tests)->tqh_first; } while (0)
;
882
883 if ((state->init = calloc(1, sizeof(*state->init))) == NULL((void *)0))
884 err(1, "%s", __func__);
885 state->init->type = IFSD_ACTION_CONDITION3;
886 TAILQ_INIT(&state->init->act.c.actions)do { (&state->init->act.c.actions)->tqh_first = (
(void *)0); (&state->init->act.c.actions)->tqh_last
= &(&state->init->act.c.actions)->tqh_first
; } while (0)
;
887
888 if ((state->body = calloc(1, sizeof(*state->body))) == NULL((void *)0))
889 err(1, "%s", __func__);
890 state->body->type = IFSD_ACTION_CONDITION3;
891 TAILQ_INIT(&state->body->act.c.actions)do { (&state->body->act.c.actions)->tqh_first = (
(void *)0); (&state->body->act.c.actions)->tqh_last
= &(&state->body->act.c.actions)->tqh_first
; } while (0)
;
892}
893
894struct ifsd_ifstate *
895new_ifstate(char *ifname, int s)
896{
897 struct ifsd_ifstate *ifstate = NULL((void *)0);
898 struct ifsd_state *state;
899
900 if (curstate != NULL((void *)0))
901 state = curstate;
902 else
903 state = &conf->initstate;
904
905 TAILQ_FOREACH(ifstate, &state->interface_states, entries)for((ifstate) = ((&state->interface_states)->tqh_first
); (ifstate) != ((void *)0); (ifstate) = ((ifstate)->entries
.tqe_next))
906 if (strcmp(ifstate->ifname, ifname) == 0 &&
907 ifstate->ifstate == s)
908 break;
909 if (ifstate == NULL((void *)0)) {
910 if ((ifstate = calloc(1, sizeof(*ifstate))) == NULL((void *)0))
911 err(1, "%s", __func__);
912 if (strlcpy(ifstate->ifname, ifname,
913 sizeof(ifstate->ifname)) >= sizeof(ifstate->ifname))
914 errx(1, "ifname strlcpy truncation");
915 free(ifname);
916 ifstate->ifstate = s;
917 TAILQ_INIT(&ifstate->expressions)do { (&ifstate->expressions)->tqh_first = ((void *)
0); (&ifstate->expressions)->tqh_last = &(&
ifstate->expressions)->tqh_first; } while (0)
;
918 TAILQ_INSERT_TAIL(&state->interface_states, ifstate, entries)do { (ifstate)->entries.tqe_next = ((void *)0); (ifstate)->
entries.tqe_prev = (&state->interface_states)->tqh_last
; *(&state->interface_states)->tqh_last = (ifstate)
; (&state->interface_states)->tqh_last = &(ifstate
)->entries.tqe_next; } while (0)
;
919 }
920 ifstate->prevstate = -1;
921 ifstate->refcount++;
922 return (ifstate);
923}
924
925struct ifsd_external *
926new_external(char *command, u_int32_t frequency)
927{
928 struct ifsd_external *external = NULL((void *)0);
929 struct ifsd_state *state;
930
931 if (curstate != NULL((void *)0))
932 state = curstate;
933 else
934 state = &conf->initstate;
935
936 TAILQ_FOREACH(external, &state->external_tests, entries)for((external) = ((&state->external_tests)->tqh_first
); (external) != ((void *)0); (external) = ((external)->entries
.tqe_next))
937 if (strcmp(external->command, command) == 0 &&
938 external->frequency == frequency)
939 break;
940 if (external == NULL((void *)0)) {
941 if ((external = calloc(1, sizeof(*external))) == NULL((void *)0))
942 err(1, "%s", __func__);
943 if ((external->command = strdup(command)) == NULL((void *)0))
944 err(1, "%s", __func__);
945 external->frequency = frequency;
946 TAILQ_INIT(&external->expressions)do { (&external->expressions)->tqh_first = ((void *
)0); (&external->expressions)->tqh_last = &(&
external->expressions)->tqh_first; } while (0)
;
947 TAILQ_INSERT_TAIL(&state->external_tests, external, entries)do { (external)->entries.tqe_next = ((void *)0); (external
)->entries.tqe_prev = (&state->external_tests)->
tqh_last; *(&state->external_tests)->tqh_last = (external
); (&state->external_tests)->tqh_last = &(external
)->entries.tqe_next; } while (0)
;
948 }
949 external->prevstatus = -1;
950 external->refcount++;
951 return (external);
952}
953#line 946 "parse.c"
954/* allocate initial stack or double stack size, up to YYMAXDEPTH */
955static int yygrowstack(void)
956{
957 unsigned int newsize;
958 long sslen;
959 short *newss;
960 YYSTYPE *newvs;
961
962 if ((newsize = yystacksize) == 0)
3
Assuming the condition is false
4
Taking false branch
963 newsize = YYINITSTACKSIZE200;
964 else if (newsize >= YYMAXDEPTH10000)
5
Assuming 'newsize' is < YYMAXDEPTH
6
Taking false branch
965 return -1;
966 else if ((newsize *= 2) > YYMAXDEPTH10000)
7
Assuming the condition is false
8
Taking false branch
967 newsize = YYMAXDEPTH10000;
968 sslen = yyssp - yyss;
969#ifdef SIZE_MAX0xffffffffffffffffUL
970#define YY_SIZE_MAX0xffffffffffffffffUL SIZE_MAX0xffffffffffffffffUL
971#else
972#define YY_SIZE_MAX0xffffffffffffffffUL 0xffffffffU
973#endif
974 if (newsize && YY_SIZE_MAX0xffffffffffffffffUL / newsize < sizeof *newss)
9
Assuming 'newsize' is 0
975 goto bail;
976 newss = (short *)realloc(yyss, newsize * sizeof *newss);
977 if (newss == NULL((void *)0))
10
Assuming 'newss' is not equal to NULL
11
Taking false branch
978 goto bail;
979 yyss = newss;
980 yyssp = newss + sslen;
981 if (newsize
11.1
'newsize' is 0
&& YY_SIZE_MAX0xffffffffffffffffUL / newsize < sizeof *newvs)
982 goto bail;
983 newvs = (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs);
12
Memory is released
984 if (newvs == NULL((void *)0))
13
Assuming 'newvs' is equal to NULL
14
Taking true branch
985 goto bail;
15
Control jumps to line 992
986 yyvs = newvs;
987 yyvsp = newvs + sslen;
988 yystacksize = newsize;
989 yysslim = yyss + newsize - 1;
990 return 0;
991bail:
992 if (yyss
15.1
'yyss' is non-null
)
16
Taking true branch
993 free(yyss);
994 if (yyvs)
17
Assuming 'yyvs' is non-null
18
Taking true branch
995 free(yyvs);
19
Attempt to free released memory
996 yyss = yyssp = NULL((void *)0);
997 yyvs = yyvsp = NULL((void *)0);
998 yystacksize = 0;
999 return -1;
1000}
1001
1002#define YYABORTgoto yyabort goto yyabort
1003#define YYREJECTgoto yyabort goto yyabort
1004#define YYACCEPTgoto yyaccept goto yyaccept
1005#define YYERRORgoto yyerrlab goto yyerrlab
1006int
1007yyparse(void)
1008{
1009 int yym, yyn, yystate;
1010#if YYDEBUG0
1011 const char *yys;
1012
1013 if ((yys = getenv("YYDEBUG")))
1014 {
1015 yyn = *yys;
1016 if (yyn >= '0' && yyn <= '9')
1017 yydebug = yyn - '0';
1018 }
1019#endif /* YYDEBUG */
1020
1021 yynerrs = 0;
1022 yyerrflag = 0;
1023 yychar = (-1);
1024
1025 if (yyss == NULL((void *)0) && yygrowstack()) goto yyoverflow;
1
Assuming 'yyss' is equal to NULL
2
Calling 'yygrowstack'
1026 yyssp = yyss;
1027 yyvsp = yyvs;
1028 *yyssp = yystate = 0;
1029
1030yyloop:
1031 if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1032 if (yychar < 0)
1033 {
1034 if ((yychar = yylex()) < 0) yychar = 0;
1035#if YYDEBUG0
1036 if (yydebug)
1037 {
1038 yys = 0;
1039 if (yychar <= YYMAXTOKEN273) yys = yyname[yychar];
1040 if (!yys) yys = "illegal-symbol";
1041 printf("%sdebug: state %d, reading %d (%s)\n",
1042 YYPREFIX"yy", yystate, yychar, yys);
1043 }
1044#endif
1045 }
1046 if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1047 yyn <= YYTABLESIZE262 && yycheck[yyn] == yychar)
1048 {
1049#if YYDEBUG0
1050 if (yydebug)
1051 printf("%sdebug: state %d, shifting to state %d\n",
1052 YYPREFIX"yy", yystate, yytable[yyn]);
1053#endif
1054 if (yyssp >= yysslim && yygrowstack())
1055 {
1056 goto yyoverflow;
1057 }
1058 *++yyssp = yystate = yytable[yyn];
1059 *++yyvsp = yylval;
1060 yychar = (-1);
1061 if (yyerrflag > 0) --yyerrflag;
1062 goto yyloop;
1063 }
1064 if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1065 yyn <= YYTABLESIZE262 && yycheck[yyn] == yychar)
1066 {
1067 yyn = yytable[yyn];
1068 goto yyreduce;
1069 }
1070 if (yyerrflag) goto yyinrecovery;
1071#if defined(__GNUC__4)
1072 goto yynewerror;
1073#endif
1074yynewerror:
1075 yyerror("syntax error");
1076#if defined(__GNUC__4)
1077 goto yyerrlab;
1078#endif
1079yyerrlab:
1080 ++yynerrs;
1081yyinrecovery:
1082 if (yyerrflag < 3)
1083 {
1084 yyerrflag = 3;
1085 for (;;)
1086 {
1087 if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE256) >= 0 &&
1088 yyn <= YYTABLESIZE262 && yycheck[yyn] == YYERRCODE256)
1089 {
1090#if YYDEBUG0
1091 if (yydebug)
1092 printf("%sdebug: state %d, error recovery shifting\
1093 to state %d\n", YYPREFIX"yy", *yyssp, yytable[yyn]);
1094#endif
1095 if (yyssp >= yysslim && yygrowstack())
1096 {
1097 goto yyoverflow;
1098 }
1099 *++yyssp = yystate = yytable[yyn];
1100 *++yyvsp = yylval;
1101 goto yyloop;
1102 }
1103 else
1104 {
1105#if YYDEBUG0
1106 if (yydebug)
1107 printf("%sdebug: error recovery discarding state %d\n",
1108 YYPREFIX"yy", *yyssp);
1109#endif
1110 if (yyssp <= yyss) goto yyabort;
1111 --yyssp;
1112 --yyvsp;
1113 }
1114 }
1115 }
1116 else
1117 {
1118 if (yychar == 0) goto yyabort;
1119#if YYDEBUG0
1120 if (yydebug)
1121 {
1122 yys = 0;
1123 if (yychar <= YYMAXTOKEN273) yys = yyname[yychar];
1124 if (!yys) yys = "illegal-symbol";
1125 printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1126 YYPREFIX"yy", yystate, yychar, yys);
1127 }
1128#endif
1129 yychar = (-1);
1130 goto yyloop;
1131 }
1132yyreduce:
1133#if YYDEBUG0
1134 if (yydebug)
1135 printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1136 YYPREFIX"yy", yystate, yyn, yyrule[yyn]);
1137#endif
1138 yym = yylen[yyn];
1139 if (yym)
1140 yyval = yyvsp[1-yym];
1141 else
1142 memset(&yyval, 0, sizeof yyval);
1143 switch (yyn)
1144 {
1145case 7:
1146#line 128 "/usr/src/usr.sbin/ifstated/parse.y"
1147{ file->errors++; }
1148break;
1149case 8:
1150#line 131 "/usr/src/usr.sbin/ifstated/parse.y"
1151{
1152 if (asprintf(&yyval.v.string, "%s %s", yyvsp[-1].v.string, yyvsp[0].v.string) == -1) {
1153 free(yyvsp[-1].v.string);
1154 free(yyvsp[0].v.string);
1155 yyerror("string: asprintf");
1156 YYERRORgoto yyerrlab;
1157 }
1158 free(yyvsp[-1].v.string);
1159 free(yyvsp[0].v.string);
1160 }
1161break;
1162case 10:
1163#line 144 "/usr/src/usr.sbin/ifstated/parse.y"
1164{
1165 char *s = yyvsp[-2].v.string;
1166 if (conf->opts & IFSD_OPT_VERBOSE0x00000001)
1167 printf("%s = \"%s\"\n", yyvsp[-2].v.string, yyvsp[0].v.string);
1168 while (*s++) {
1169 if (isspace((unsigned char)*s)) {
1170 yyerror("macro name cannot contain "
1171 "whitespace");
1172 free(yyvsp[-2].v.string);
1173 free(yyvsp[0].v.string);
1174 YYERRORgoto yyerrlab;
1175 }
1176 }
1177 if (symset(yyvsp[-2].v.string, yyvsp[0].v.string, 0) == -1) {
1178 free(yyvsp[-2].v.string);
1179 free(yyvsp[0].v.string);
1180 yyerror("cannot store variable");
1181 YYERRORgoto yyerrlab;
1182 }
1183 free(yyvsp[-2].v.string);
1184 free(yyvsp[0].v.string);
1185 }
1186break;
1187case 11:
1188#line 168 "/usr/src/usr.sbin/ifstated/parse.y"
1189{
1190 start_state = yyvsp[0].v.string;
1191 }
1192break;
1193case 12:
1194#line 173 "/usr/src/usr.sbin/ifstated/parse.y"
1195{
1196 if (if_nametoindex(yyvsp[0].v.string) == 0) {
1197 yyerror("unknown interface %s", yyvsp[0].v.string);
1198 free(yyvsp[0].v.string);
1199 YYERRORgoto yyerrlab;
1200 }
1201 yyval.v.string = yyvsp[0].v.string;
1202 }
1203break;
1204case 16:
1205#line 190 "/usr/src/usr.sbin/ifstated/parse.y"
1206{
1207 struct ifsd_action *action;
1208
1209 if ((action = calloc(1, sizeof(*action))) == NULL((void *)0))
1210 err(1, "action: calloc");
1211 action->type = IFSD_ACTION_COMMAND1;
1212 action->act.command = yyvsp[0].v.string;
1213 TAILQ_INSERT_TAIL(&curaction->act.c.actions,do { (action)->entries.tqe_next = ((void *)0); (action)->
entries.tqe_prev = (&curaction->act.c.actions)->tqh_last
; *(&curaction->act.c.actions)->tqh_last = (action)
; (&curaction->act.c.actions)->tqh_last = &(action
)->entries.tqe_next; } while (0)
1214 action, entries)do { (action)->entries.tqe_next = ((void *)0); (action)->
entries.tqe_prev = (&curaction->act.c.actions)->tqh_last
; *(&curaction->act.c.actions)->tqh_last = (action)
; (&curaction->act.c.actions)->tqh_last = &(action
)->entries.tqe_next; } while (0)
;
1215 }
1216break;
1217case 17:
1218#line 200 "/usr/src/usr.sbin/ifstated/parse.y"
1219{
1220 struct ifsd_action *action;
1221
1222 if (curstate == NULL((void *)0)) {
1223 free(yyvsp[0].v.string);
1224 yyerror("set-state must be used inside 'if'");
1225 YYERRORgoto yyerrlab;
1226 }
1227 if ((action = calloc(1, sizeof(*action))) == NULL((void *)0))
1228 err(1, "action: calloc");
1229 action->type = IFSD_ACTION_CHANGESTATE2;
1230 action->act.statename = yyvsp[0].v.string;
1231 TAILQ_INSERT_TAIL(&curaction->act.c.actions,do { (action)->entries.tqe_next = ((void *)0); (action)->
entries.tqe_prev = (&curaction->act.c.actions)->tqh_last
; *(&curaction->act.c.actions)->tqh_last = (action)
; (&curaction->act.c.actions)->tqh_last = &(action
)->entries.tqe_next; } while (0)
1232 action, entries)do { (action)->entries.tqe_next = ((void *)0); (action)->
entries.tqe_prev = (&curaction->act.c.actions)->tqh_last
; *(&curaction->act.c.actions)->tqh_last = (action)
; (&curaction->act.c.actions)->tqh_last = &(action
)->entries.tqe_next; } while (0)
;
1233 }
1234break;
1235case 18:
1236#line 215 "/usr/src/usr.sbin/ifstated/parse.y"
1237{
1238 struct ifsd_action *action;
1239
1240 if ((action = calloc(1, sizeof(*action))) == NULL((void *)0))
1241 err(1, "action: calloc");
1242 action->type = IFSD_ACTION_CONDITION3;
1243 TAILQ_INIT(&action->act.c.actions)do { (&action->act.c.actions)->tqh_first = ((void *
)0); (&action->act.c.actions)->tqh_last = &(&
action->act.c.actions)->tqh_first; } while (0)
;
1244 TAILQ_INSERT_TAIL(&curaction->act.c.actions,do { (action)->entries.tqe_next = ((void *)0); (action)->
entries.tqe_prev = (&curaction->act.c.actions)->tqh_last
; *(&curaction->act.c.actions)->tqh_last = (action)
; (&curaction->act.c.actions)->tqh_last = &(action
)->entries.tqe_next; } while (0)
1245 action, entries)do { (action)->entries.tqe_next = ((void *)0); (action)->
entries.tqe_prev = (&curaction->act.c.actions)->tqh_last
; *(&curaction->act.c.actions)->tqh_last = (action)
; (&curaction->act.c.actions)->tqh_last = &(action
)->entries.tqe_next; } while (0)
;
1246 action->parent = curaction;
1247 curaction = action;
1248 }
1249break;
1250case 19:
1251#line 226 "/usr/src/usr.sbin/ifstated/parse.y"
1252{
1253 set_expression_depth(curaction->act.c.expression, 0);
1254 curaction = curaction->parent;
1255 }
1256break;
1257case 24:
1258#line 240 "/usr/src/usr.sbin/ifstated/parse.y"
1259{
1260 if (curstate != NULL((void *)0))
1261 curaction = curstate->init;
1262 else
1263 curaction = conf->initstate.init;
1264 }
1265break;
1266case 25:
1267#line 245 "/usr/src/usr.sbin/ifstated/parse.y"
1268{
1269 if (curstate != NULL((void *)0))
1270 curaction = curstate->body;
1271 else
1272 curaction = conf->initstate.body;
1273 }
1274break;
1275case 26:
1276#line 253 "/usr/src/usr.sbin/ifstated/parse.y"
1277{
1278 yyval.v.ifstate = new_ifstate(yyvsp[-4].v.string, IFSD_LINKUP2);
1279 }
1280break;
1281case 27:
1282#line 256 "/usr/src/usr.sbin/ifstated/parse.y"
1283{
1284 yyval.v.ifstate = new_ifstate(yyvsp[-4].v.string, IFSD_LINKDOWN1);
1285 }
1286break;
1287case 28:
1288#line 259 "/usr/src/usr.sbin/ifstated/parse.y"
1289{
1290 yyval.v.ifstate = new_ifstate(yyvsp[-4].v.string, IFSD_LINKUNKNOWN0);
1291 }
1292break;
1293case 29:
1294#line 264 "/usr/src/usr.sbin/ifstated/parse.y"
1295{
1296 if (yyvsp[0].v.number <= 0 || yyvsp[0].v.number > UINT_MAX(2147483647 *2U +1U)) {
1297 yyerror("invalid interval: %lld", yyvsp[0].v.number);
1298 free(yyvsp[-2].v.string);
1299 YYERRORgoto yyerrlab;
1300 }
1301 yyval.v.external = new_external(yyvsp[-2].v.string, yyvsp[0].v.number);
1302 free(yyvsp[-2].v.string);
1303 }
1304break;
1305case 30:
1306#line 275 "/usr/src/usr.sbin/ifstated/parse.y"
1307{
1308 if ((yyval.v.expression = calloc(1, sizeof(*yyval.v.expression))) == NULL((void *)0))
1309 err(1, NULL((void *)0));
1310 curaction->act.c.expression = yyval.v.expression;
1311 yyval.v.expression->type = IFSD_OPER_IFSTATE5;
1312 yyval.v.expression->u.ifstate = yyvsp[0].v.ifstate;
1313 TAILQ_INSERT_TAIL(&yyvsp[0].v.ifstate->expressions, yyval.v.expression, entries)do { (yyval.v.expression)->entries.tqe_next = ((void *)0);
(yyval.v.expression)->entries.tqe_prev = (&yyvsp[0].v
.ifstate->expressions)->tqh_last; *(&yyvsp[0].v.ifstate
->expressions)->tqh_last = (yyval.v.expression); (&
yyvsp[0].v.ifstate->expressions)->tqh_last = &(yyval
.v.expression)->entries.tqe_next; } while (0)
;
1314 }
1315break;
1316case 31:
1317#line 283 "/usr/src/usr.sbin/ifstated/parse.y"
1318{
1319 if ((yyval.v.expression = calloc(1, sizeof(*yyval.v.expression))) == NULL((void *)0))
1320 err(1, NULL((void *)0));
1321 curaction->act.c.expression = yyval.v.expression;
1322 yyval.v.expression->type = IFSD_OPER_EXTERNAL4;
1323 yyval.v.expression->u.external = yyvsp[0].v.external;
1324 TAILQ_INSERT_TAIL(&yyvsp[0].v.external->expressions, yyval.v.expression, entries)do { (yyval.v.expression)->entries.tqe_next = ((void *)0);
(yyval.v.expression)->entries.tqe_prev = (&yyvsp[0].v
.external->expressions)->tqh_last; *(&yyvsp[0].v.external
->expressions)->tqh_last = (yyval.v.expression); (&
yyvsp[0].v.external->expressions)->tqh_last = &(yyval
.v.expression)->entries.tqe_next; } while (0)
;
1325 }
1326break;
1327case 32:
1328#line 291 "/usr/src/usr.sbin/ifstated/parse.y"
1329{
1330 yyval.v.expression = yyvsp[-1].v.expression;
1331 }
1332break;
1333case 33:
1334#line 296 "/usr/src/usr.sbin/ifstated/parse.y"
1335{
1336 if ((yyval.v.expression = calloc(1, sizeof(*yyval.v.expression))) == NULL((void *)0))
1337 err(1, NULL((void *)0));
1338 curaction->act.c.expression = yyval.v.expression;
1339 yyval.v.expression->type = IFSD_OPER_NOT3;
1340 yyvsp[0].v.expression->parent = yyval.v.expression;
1341 yyval.v.expression->right = yyvsp[0].v.expression;
1342 }
1343break;
1344case 34:
1345#line 304 "/usr/src/usr.sbin/ifstated/parse.y"
1346{
1347 if ((yyval.v.expression = calloc(1, sizeof(*yyval.v.expression))) == NULL((void *)0))
1348 err(1, NULL((void *)0));
1349 curaction->act.c.expression = yyval.v.expression;
1350 yyval.v.expression->type = IFSD_OPER_AND1;
1351 yyvsp[-2].v.expression->parent = yyval.v.expression;
1352 yyvsp[0].v.expression->parent = yyval.v.expression;
1353 yyval.v.expression->left = yyvsp[-2].v.expression;
1354 yyval.v.expression->right = yyvsp[0].v.expression;
1355 }
1356break;
1357case 35:
1358#line 314 "/usr/src/usr.sbin/ifstated/parse.y"
1359{
1360 if ((yyval.v.expression = calloc(1, sizeof(*yyval.v.expression))) == NULL((void *)0))
1361 err(1, NULL((void *)0));
1362 curaction->act.c.expression = yyval.v.expression;
1363 yyval.v.expression->type = IFSD_OPER_OR2;
1364 yyvsp[-2].v.expression->parent = yyval.v.expression;
1365 yyvsp[0].v.expression->parent = yyval.v.expression;
1366 yyval.v.expression->left = yyvsp[-2].v.expression;
1367 yyval.v.expression->right = yyvsp[0].v.expression;
1368 }
1369break;
1370case 37:
1371#line 327 "/usr/src/usr.sbin/ifstated/parse.y"
1372{
1373 struct ifsd_state *state = NULL((void *)0);
1374
1375 TAILQ_FOREACH(state, &conf->states, entries)for((state) = ((&conf->states)->tqh_first); (state)
!= ((void *)0); (state) = ((state)->entries.tqe_next))
1376 if (!strcmp(state->name, yyvsp[0].v.string)) {
1377 yyerror("state %s already exists", yyvsp[0].v.string);
1378 free(yyvsp[0].v.string);
1379 YYERRORgoto yyerrlab;
1380 }
1381 if ((state = calloc(1, sizeof(*curstate))) == NULL((void *)0))
1382 err(1, NULL((void *)0));
1383 init_state(state);
1384 state->name = yyvsp[0].v.string;
1385 curstate = state;
1386 curaction = state->body;
1387 }
1388break;
1389case 38:
1390#line 342 "/usr/src/usr.sbin/ifstated/parse.y"
1391{
1392 TAILQ_INSERT_TAIL(&conf->states, curstate, entries)do { (curstate)->entries.tqe_next = ((void *)0); (curstate
)->entries.tqe_prev = (&conf->states)->tqh_last;
*(&conf->states)->tqh_last = (curstate); (&conf
->states)->tqh_last = &(curstate)->entries.tqe_next
; } while (0)
;
1393 curstate = NULL((void *)0);
1394 curaction = conf->initstate.body;
1395 }
1396break;
1397#line 1390 "parse.c"
1398 }
1399 yyssp -= yym;
1400 yystate = *yyssp;
1401 yyvsp -= yym;
1402 yym = yylhs[yyn];
1403 if (yystate == 0 && yym == 0)
1404 {
1405#if YYDEBUG0
1406 if (yydebug)
1407 printf("%sdebug: after reduction, shifting from state 0 to\
1408 state %d\n", YYPREFIX"yy", YYFINAL1);
1409#endif
1410 yystate = YYFINAL1;
1411 *++yyssp = YYFINAL1;
1412 *++yyvsp = yyval;
1413 if (yychar < 0)
1414 {
1415 if ((yychar = yylex()) < 0) yychar = 0;
1416#if YYDEBUG0
1417 if (yydebug)
1418 {
1419 yys = 0;
1420 if (yychar <= YYMAXTOKEN273) yys = yyname[yychar];
1421 if (!yys) yys = "illegal-symbol";
1422 printf("%sdebug: state %d, reading %d (%s)\n",
1423 YYPREFIX"yy", YYFINAL1, yychar, yys);
1424 }
1425#endif
1426 }
1427 if (yychar == 0) goto yyaccept;
1428 goto yyloop;
1429 }
1430 if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1431 yyn <= YYTABLESIZE262 && yycheck[yyn] == yystate)
1432 yystate = yytable[yyn];
1433 else
1434 yystate = yydgoto[yym];
1435#if YYDEBUG0
1436 if (yydebug)
1437 printf("%sdebug: after reduction, shifting from state %d \
1438to state %d\n", YYPREFIX"yy", *yyssp, yystate);
1439#endif
1440 if (yyssp >= yysslim && yygrowstack())
1441 {
1442 goto yyoverflow;
1443 }
1444 *++yyssp = yystate;
1445 *++yyvsp = yyval;
1446 goto yyloop;
1447yyoverflow:
1448 yyerror("yacc stack overflow");
1449yyabort:
1450 if (yyss)
1451 free(yyss);
1452 if (yyvs)
1453 free(yyvs);
1454 yyss = yyssp = NULL((void *)0);
1455 yyvs = yyvsp = NULL((void *)0);
1456 yystacksize = 0;
1457 return (1);
1458yyaccept:
1459 if (yyss)
1460 free(yyss);
1461 if (yyvs)
1462 free(yyvs);
1463 yyss = yyssp = NULL((void *)0);
1464 yyvs = yyvsp = NULL((void *)0);
1465 yystacksize = 0;
1466 return (0);
1467}