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

Line Branch Exec Source
1
#include <stdlib.h>
2
#include <string.h>
3
#define YYBYACC 1
4
#define YYMAJOR 1
5
#define YYMINOR 9
6
#define YYLEX yylex()
7
#define YYEMPTY -1
8
#define yyclearin (yychar=(YYEMPTY))
9
#define yyerrok (yyerrflag=0)
10
#define YYRECOVERING() (yyerrflag!=0)
11
#define YYPREFIX "yy"
12
#line 26 "parse.y"
13
#include <sys/types.h>
14
#include <sys/socket.h>
15
#include <sys/stat.h>
16
#include <netinet/in.h>
17
#include <arpa/inet.h>
18
#include <ctype.h>
19
#include <err.h>
20
#include <errno.h>
21
#include <unistd.h>
22
#include <ifaddrs.h>
23
#include <limits.h>
24
#include <stdarg.h>
25
#include <stdio.h>
26
#include <string.h>
27
#include <syslog.h>
28
29
#include "ripd.h"
30
#include "rip.h"
31
#include "ripe.h"
32
#include "log.h"
33
34
TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
35
static struct file {
36
	TAILQ_ENTRY(file)	 entry;
37
	FILE			*stream;
38
	char			*name;
39
	int			 lineno;
40
	int			 errors;
41
} *file, *topfile;
42
struct file	*pushfile(const char *, int);
43
int		 popfile(void);
44
int		 yyparse(void);
45
int		 yylex(void);
46
int		 yyerror(const char *, ...)
47
    __attribute__((__format__ (printf, 1, 2)))
48
    __attribute__((__nonnull__ (1)));
49
int		 kw_cmp(const void *, const void *);
50
int		 lookup(char *);
51
int		 lgetc(int);
52
int		 lungetc(int);
53
int		 findeol(void);
54
55
TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
56
struct sym {
57
	TAILQ_ENTRY(sym)	 entry;
58
	int			 used;
59
	int			 persist;
60
	char			*nam;
61
	char			*val;
62
};
63
int		 symset(const char *, const char *, int);
64
char		*symget(const char *);
65
66
static struct {
67
	u_int8_t		 auth_key[MAX_SIMPLE_AUTH_LEN];
68
	struct auth_md_head	 md_list;
69
	enum auth_type		 auth_type;
70
	u_int8_t		 auth_keyid;
71
	u_int8_t		 cost;
72
} *defs, globaldefs, ifacedefs;
73
74
struct iface	*iface = NULL;
75
static struct ripd_conf	*conf;
76
static int		 errors = 0;
77
78
struct iface	*conf_get_if(struct kif *);
79
void		 clear_config(struct ripd_conf *);
80
int		 check_file_secrecy(int, const char *);
81
u_int32_t	 get_rtr_id(void);
82
int		 host(const char *, struct in_addr *, struct in_addr *);
83
84
typedef struct {
85
	union {
86
		int64_t		 number;
87
		char		*string;
88
	} v;
89
	int lineno;
90
} YYSTYPE;
91
92
#line 93 "parse.c"
93
#define SPLIT_HORIZON 257
94
#define TRIGGERED_UPDATES 258
95
#define FIBUPDATE 259
96
#define REDISTRIBUTE 260
97
#define RDOMAIN 261
98
#define AUTHKEY 262
99
#define AUTHTYPE 263
100
#define AUTHMD 264
101
#define AUTHMDKEYID 265
102
#define INTERFACE 266
103
#define RTLABEL 267
104
#define COST 268
105
#define PASSIVE 269
106
#define YES 270
107
#define NO 271
108
#define DEMOTE 272
109
#define ERROR 273
110
#define STRING 274
111
#define NUMBER 275
112
#define YYERRCODE 256
113
const short yylhs[] =
114
	{                                        -1,
115
    0,    0,    0,    0,    0,    0,    3,    3,    1,    1,
116
    2,    2,    5,    4,    4,    4,    4,    4,    4,    4,
117
    8,    9,   10,   11,    7,    7,    7,    7,    7,   12,
118
   12,   13,   15,    6,   14,   14,   16,   16,   17,   17,
119
   17,
120
};
121
const short yylen[] =
122
	{                                         2,
123
    0,    2,    3,    3,    3,    3,    2,    1,    1,    1,
124
    0,    1,    3,    2,    2,    2,    2,    3,    4,    1,
125
    3,    2,    2,    2,    2,    1,    1,    1,    1,    2,
126
    0,    2,    0,    4,    4,    3,    3,    2,    1,    2,
127
    1,
128
};
129
const short yydefred[] =
130
	{                                      1,
131
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
132
    0,    0,   12,    0,    2,    0,    0,    0,    0,   20,
133
   29,   28,   26,   27,    6,   14,    9,   10,   15,   17,
134
   16,   24,   23,    0,   22,   33,   25,    0,    0,    3,
135
    4,    5,   21,    0,    8,    0,    0,   18,    0,   34,
136
    7,   19,    0,    0,   30,   39,    0,   36,   41,    0,
137
    0,   40,   35,    0,   38,    0,   37,   32,
138
};
139
const short yydgoto[] =
140
	{                                       1,
141
   29,   16,   46,   17,   18,   19,   59,   21,   22,   23,
142
   24,   54,   67,   50,   44,   60,   61,
143
};
144
const short yysindex[] =
145
	{                                      0,
146
  -10,   -7, -267, -265, -265, -266, -261, -260, -259, -258,
147
 -256, -255,    0,  -53,    0, -241,   11,   12,   14,    0,
148
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
149
    0,    0,    0, -249,    0,    0,    0, -248, -263,    0,
150
    0,    0,    0,  -96,    0, -246, -245,    0,   20,    0,
151
    0,    0,   20, -124,    0,    0, -243,    0,    0, -113,
152
   20,    0,    0,   22,    0,   20,    0,    0,};
153
const short yyrindex[] =
154
	{                                      0,
155
 -227,    0,    0,    0,    0,    0,    0,    0,    0,    0,
156
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
157
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
158
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
159
    0,    0,    0,    0,    0,   24,    0,    0, -102,    0,
160
    0,    0, -102,    0,    0,    0,    0,    0,    0,    0,
161
 -102,    0,    0,    0,    0, -102,    0,    0,};
162
const short yygindex[] =
163
	{                                      0,
164
   30,    0,    0,    0,    0,    0,   35,    0,    0,    0,
165
    0,  -51,    0,    0,    0,    0,  -23,
166
};
167
#define YYTABLESIZE 264
168
const short yytable[] =
169
	{                                      15,
170
   58,   55,   25,   47,   27,   28,   26,   38,   31,   65,
171
   48,   63,   32,   33,   68,   34,   35,   36,   39,   37,
172
   40,   41,   31,   42,   43,   45,   49,   51,   52,   53,
173
   62,   66,   11,   13,   30,   20,   64,    0,    0,    0,
174
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
175
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
176
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
177
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
178
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
179
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
180
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
181
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
182
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
183
    0,    0,    0,    0,    0,    0,    0,    7,    8,    9,
184
   10,    0,    0,   12,   56,    0,    0,   57,    7,    8,
185
    9,   10,    0,    0,   12,   56,    0,    0,   57,   31,
186
   31,   31,   31,    0,    0,   31,   31,    0,    0,   31,
187
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
188
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
189
    0,    0,    0,    0,    0,    0,    0,    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,    2,    3,    4,    5,    0,
195
    6,    7,    8,    9,   10,   11,    0,   12,    0,    0,
196
   13,    0,    0,   14,
197
};
198
const short yycheck[] =
199
	{                                      10,
200
  125,   53,   10,  267,  270,  271,  274,   61,  275,   61,
201
  274,  125,  274,  274,   66,  275,  275,  274,  260,  275,
202
   10,   10,  125,   10,  274,  274,  123,  274,  274,   10,
203
  274,   10,  260,   10,    5,    1,   60,   -1,   -1,   -1,
204
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
205
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
206
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
207
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
208
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
209
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
210
   -1,   -1,   -1,   -1,   -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,  262,  263,  264,
214
  265,   -1,   -1,  268,  269,   -1,   -1,  272,  262,  263,
215
  264,  265,   -1,   -1,  268,  269,   -1,   -1,  272,  262,
216
  263,  264,  265,   -1,   -1,  268,  269,   -1,   -1,  272,
217
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
218
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
219
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
220
   -1,   -1,   -1,   -1,   -1,   -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,  256,  257,  258,  259,   -1,
225
  261,  262,  263,  264,  265,  266,   -1,  268,   -1,   -1,
226
  271,   -1,   -1,  274,
227
};
228
#define YYFINAL 1
229
#ifndef YYDEBUG
230
#define YYDEBUG 0
231
#endif
232
#define YYMAXTOKEN 275
233
#if YYDEBUG
234
const char * const yyname[] =
235
	{
236
"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,
237
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'='",0,0,0,0,0,0,0,
238
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
239
0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
240
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,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,"SPLIT_HORIZON",
243
"TRIGGERED_UPDATES","FIBUPDATE","REDISTRIBUTE","RDOMAIN","AUTHKEY","AUTHTYPE",
244
"AUTHMD","AUTHMDKEYID","INTERFACE","RTLABEL","COST","PASSIVE","YES","NO",
245
"DEMOTE","ERROR","STRING","NUMBER",
246
};
247
const char * const yyrule[] =
248
	{"$accept : grammar",
249
"grammar :",
250
"grammar : grammar '\\n'",
251
"grammar : grammar conf_main '\\n'",
252
"grammar : grammar varset '\\n'",
253
"grammar : grammar interface '\\n'",
254
"grammar : grammar error '\\n'",
255
"string : string STRING",
256
"string : STRING",
257
"yesno : YES",
258
"yesno : NO",
259
"no :",
260
"no : NO",
261
"varset : STRING '=' string",
262
"conf_main : SPLIT_HORIZON STRING",
263
"conf_main : TRIGGERED_UPDATES yesno",
264
"conf_main : RDOMAIN NUMBER",
265
"conf_main : FIBUPDATE yesno",
266
"conf_main : no REDISTRIBUTE STRING",
267
"conf_main : no REDISTRIBUTE RTLABEL STRING",
268
"conf_main : defaults",
269
"authmd : AUTHMD NUMBER STRING",
270
"authmdkeyid : AUTHMDKEYID NUMBER",
271
"authtype : AUTHTYPE STRING",
272
"authkey : AUTHKEY STRING",
273
"defaults : COST NUMBER",
274
"defaults : authtype",
275
"defaults : authkey",
276
"defaults : authmdkeyid",
277
"defaults : authmd",
278
"optnl : '\\n' optnl",
279
"optnl :",
280
"nl : '\\n' optnl",
281
"$$1 :",
282
"interface : INTERFACE STRING $$1 interface_block",
283
"interface_block : '{' optnl interfaceopts_l '}'",
284
"interface_block : '{' optnl '}'",
285
"interfaceopts_l : interfaceopts_l interfaceoptsl nl",
286
"interfaceopts_l : interfaceoptsl optnl",
287
"interfaceoptsl : PASSIVE",
288
"interfaceoptsl : DEMOTE STRING",
289
"interfaceoptsl : defaults",
290
};
291
#endif
292
#ifdef YYSTACKSIZE
293
#undef YYMAXDEPTH
294
#define YYMAXDEPTH YYSTACKSIZE
295
#else
296
#ifdef YYMAXDEPTH
297
#define YYSTACKSIZE YYMAXDEPTH
298
#else
299
#define YYSTACKSIZE 10000
300
#define YYMAXDEPTH 10000
301
#endif
302
#endif
303
#define YYINITSTACKSIZE 200
304
/* LINTUSED */
305
int yydebug;
306
int yynerrs;
307
int yyerrflag;
308
int yychar;
309
short *yyssp;
310
YYSTYPE *yyvsp;
311
YYSTYPE yyval;
312
YYSTYPE yylval;
313
short *yyss;
314
short *yysslim;
315
YYSTYPE *yyvs;
316
unsigned int yystacksize;
317
int yyparse(void);
318
#line 384 "parse.y"
319
320
struct keywords {
321
	const char	*k_name;
322
	int		 k_val;
323
};
324
325
int
326
yyerror(const char *fmt, ...)
327
{
328
	va_list		 ap;
329
	char		*msg;
330
331
	file->errors++;
332
	va_start(ap, fmt);
333
	if (vasprintf(&msg, fmt, ap) == -1)
334
		fatalx("yyerror vasprintf");
335
	va_end(ap);
336
	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
337
	free(msg);
338
	return (0);
339
}
340
341
int
342
kw_cmp(const void *k, const void *e)
343
{
344
	return (strcmp(k, ((const struct keywords *)e)->k_name));
345
}
346
347
int
348
lookup(char *s)
349
{
350
	/* this has to be sorted always */
351
	static const struct keywords keywords[] = {
352
	    {"auth-key",		AUTHKEY},
353
	    {"auth-md",			AUTHMD},
354
	    {"auth-md-keyid",		AUTHMDKEYID},
355
	    {"auth-type",		AUTHTYPE},
356
	    {"cost",			COST},
357
	    {"demote",			DEMOTE},
358
	    {"fib-update",		FIBUPDATE},
359
	    {"interface",		INTERFACE},
360
	    {"no",			NO},
361
	    {"passive",			PASSIVE},
362
	    {"rdomain",			RDOMAIN},
363
	    {"redistribute",		REDISTRIBUTE},
364
	    {"rtlabel",			RTLABEL},
365
	    {"split-horizon",		SPLIT_HORIZON},
366
	    {"triggered-updates",	TRIGGERED_UPDATES},
367
	    {"yes",			YES}
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 = 0;
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 != ','))
598
599
	if (isalnum(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
		log_warn("cannot stat %s", fname);
630
		return (-1);
631
	}
632
	if (st.st_uid != 0 && st.st_uid != getuid()) {
633
		log_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
		log_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
		log_warn("malloc");
650
		return (NULL);
651
	}
652
	if ((nfile->name = strdup(name)) == NULL) {
653
		log_warn("malloc");
654
		free(nfile);
655
		return (NULL);
656
	}
657
	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
658
		log_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 ripd_conf *
691
parse_config(char *filename, int opts)
692
{
693
	struct sym	*sym, *next;
694
695
	if ((conf = calloc(1, sizeof(struct ripd_conf))) == NULL)
696
		fatal("parse_config");
697
698
	bzero(&globaldefs, sizeof(globaldefs));
699
	defs = &globaldefs;
700
	TAILQ_INIT(&defs->md_list);
701
	defs->cost = DEFAULT_COST;
702
	defs->auth_type = AUTH_NONE;
703
	conf->opts = opts;
704
	conf->options = OPT_SPLIT_POISONED;
705
	SIMPLEQ_INIT(&conf->redist_list);
706
707
	if ((file = pushfile(filename, !(conf->opts & RIPD_OPT_NOACTION))) == NULL) {
708
		free(conf);
709
		return (NULL);
710
	}
711
	topfile = file;
712
713
	yyparse();
714
	errors = file->errors;
715
	popfile();
716
717
	/* Free macros and check which have not been used. */
718
	TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
719
		if ((conf->opts & RIPD_OPT_VERBOSE2) && !sym->used)
720
			fprintf(stderr, "warning: macro '%s' not "
721
			    "used\n", sym->nam);
722
		if (!sym->persist) {
723
			free(sym->nam);
724
			free(sym->val);
725
			TAILQ_REMOVE(&symhead, sym, entry);
726
			free(sym);
727
		}
728
	}
729
730
	/* free global config defaults */
731
	md_list_clr(&globaldefs.md_list);
732
733
	if (errors) {
734
		clear_config(conf);
735
		return (NULL);
736
	}
737
738
	return (conf);
739
}
740
741
int
742
symset(const char *nam, const char *val, int persist)
743
{
744
	struct sym	*sym;
745
746
	TAILQ_FOREACH(sym, &symhead, entry) {
747
		if (strcmp(nam, sym->nam) == 0)
748
			break;
749
	}
750
751
	if (sym != NULL) {
752
		if (sym->persist == 1)
753
			return (0);
754
		else {
755
			free(sym->nam);
756
			free(sym->val);
757
			TAILQ_REMOVE(&symhead, sym, entry);
758
			free(sym);
759
		}
760
	}
761
	if ((sym = calloc(1, sizeof(*sym))) == NULL)
762
		return (-1);
763
764
	sym->nam = strdup(nam);
765
	if (sym->nam == NULL) {
766
		free(sym);
767
		return (-1);
768
	}
769
	sym->val = strdup(val);
770
	if (sym->val == NULL) {
771
		free(sym->nam);
772
		free(sym);
773
		return (-1);
774
	}
775
	sym->used = 0;
776
	sym->persist = persist;
777
	TAILQ_INSERT_TAIL(&symhead, sym, entry);
778
	return (0);
779
}
780
781
int
782
cmdline_symset(char *s)
783
{
784
	char	*sym, *val;
785
	int	ret;
786
	size_t	len;
787
788
	if ((val = strrchr(s, '=')) == NULL)
789
		return (-1);
790
791
	len = strlen(s) - strlen(val) + 1;
792
	if ((sym = malloc(len)) == NULL)
793
		errx(1, "cmdline_symset: malloc");
794
795
	strlcpy(sym, s, len);
796
797
	ret = symset(sym, val + 1, 1);
798
	free(sym);
799
800
	return (ret);
801
}
802
803
char *
804
symget(const char *nam)
805
{
806
	struct sym	*sym;
807
808
	TAILQ_FOREACH(sym, &symhead, entry) {
809
		if (strcmp(nam, sym->nam) == 0) {
810
			sym->used = 1;
811
			return (sym->val);
812
		}
813
	}
814
	return (NULL);
815
}
816
817
struct iface *
818
conf_get_if(struct kif *kif)
819
{
820
	struct iface	*i;
821
822
	LIST_FOREACH(i, &conf->iface_list, entry)
823
		if (i->ifindex == kif->ifindex) {
824
			yyerror("interface %s already configured",
825
			    kif->ifname);
826
			return (NULL);
827
		}
828
829
	i = if_new(kif);
830
	i->auth_keyid = 1;
831
	i->passive = 0;
832
833
	return (i);
834
}
835
836
void
837
clear_config(struct ripd_conf *xconf)
838
{
839
	struct iface	*i;
840
841
	while ((i = LIST_FIRST(&conf->iface_list)) != NULL) {
842
		LIST_REMOVE(i, entry);
843
		if_del(i);
844
	}
845
846
	free(xconf);
847
}
848
849
int
850
host(const char *s, struct in_addr *addr, struct in_addr *mask)
851
{
852
	struct in_addr		 ina;
853
	int			 bits = 32;
854
855
	bzero(&ina, sizeof(struct in_addr));
856
	if (strrchr(s, '/') != NULL) {
857
		if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)
858
			return (0);
859
	} else {
860
		if (inet_pton(AF_INET, s, &ina) != 1)
861
			return (0);
862
	}
863
864
	addr->s_addr = ina.s_addr;
865
	mask->s_addr = prefixlen2mask(bits);
866
867
	return (1);
868
}
869
#line 862 "parse.c"
870
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
871
static int yygrowstack(void)
872
{
873
    unsigned int newsize;
874
    long sslen;
875
    short *newss;
876
    YYSTYPE *newvs;
877
878
    if ((newsize = yystacksize) == 0)
879
        newsize = YYINITSTACKSIZE;
880
    else if (newsize >= YYMAXDEPTH)
881
        return -1;
882
    else if ((newsize *= 2) > YYMAXDEPTH)
883
        newsize = YYMAXDEPTH;
884
    sslen = yyssp - yyss;
885
#ifdef SIZE_MAX
886
#define YY_SIZE_MAX SIZE_MAX
887
#else
888
#define YY_SIZE_MAX 0xffffffffU
889
#endif
890
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newss)
891
        goto bail;
892
    newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
893
      (short *)malloc(newsize * sizeof *newss); /* overflow check above */
894
    if (newss == NULL)
895
        goto bail;
896
    yyss = newss;
897
    yyssp = newss + sslen;
898
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newvs)
899
        goto bail;
900
    newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
901
      (YYSTYPE *)malloc(newsize * sizeof *newvs); /* overflow check above */
902
    if (newvs == NULL)
903
        goto bail;
904
    yyvs = newvs;
905
    yyvsp = newvs + sslen;
906
    yystacksize = newsize;
907
    yysslim = yyss + newsize - 1;
908
    return 0;
909
bail:
910
    if (yyss)
911
            free(yyss);
912
    if (yyvs)
913
            free(yyvs);
914
    yyss = yyssp = NULL;
915
    yyvs = yyvsp = NULL;
916
    yystacksize = 0;
917
    return -1;
918
}
919
920
#define YYABORT goto yyabort
921
#define YYREJECT goto yyabort
922
#define YYACCEPT goto yyaccept
923
#define YYERROR goto yyerrlab
924
int
925
yyparse(void)
926
{
927
    int yym, yyn, yystate;
928
#if YYDEBUG
929
    const char *yys;
930
931
    if ((yys = getenv("YYDEBUG")))
932
    {
933
        yyn = *yys;
934
        if (yyn >= '0' && yyn <= '9')
935
            yydebug = yyn - '0';
936
    }
937
#endif /* YYDEBUG */
938
939
    yynerrs = 0;
940
    yyerrflag = 0;
941
    yychar = (-1);
942
943
    if (yyss == NULL && yygrowstack()) goto yyoverflow;
944
    yyssp = yyss;
945
    yyvsp = yyvs;
946
    *yyssp = yystate = 0;
947
948
yyloop:
949
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
950
    if (yychar < 0)
951
    {
952
        if ((yychar = yylex()) < 0) yychar = 0;
953
#if YYDEBUG
954
        if (yydebug)
955
        {
956
            yys = 0;
957
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
958
            if (!yys) yys = "illegal-symbol";
959
            printf("%sdebug: state %d, reading %d (%s)\n",
960
                    YYPREFIX, yystate, yychar, yys);
961
        }
962
#endif
963
    }
964
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
965
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
966
    {
967
#if YYDEBUG
968
        if (yydebug)
969
            printf("%sdebug: state %d, shifting to state %d\n",
970
                    YYPREFIX, yystate, yytable[yyn]);
971
#endif
972
        if (yyssp >= yysslim && yygrowstack())
973
        {
974
            goto yyoverflow;
975
        }
976
        *++yyssp = yystate = yytable[yyn];
977
        *++yyvsp = yylval;
978
        yychar = (-1);
979
        if (yyerrflag > 0)  --yyerrflag;
980
        goto yyloop;
981
    }
982
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
983
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
984
    {
985
        yyn = yytable[yyn];
986
        goto yyreduce;
987
    }
988
    if (yyerrflag) goto yyinrecovery;
989
#if defined(__GNUC__)
990
    goto yynewerror;
991
#endif
992
yynewerror:
993
    yyerror("syntax error");
994
#if defined(__GNUC__)
995
    goto yyerrlab;
996
#endif
997
yyerrlab:
998
    ++yynerrs;
999
yyinrecovery:
1000
    if (yyerrflag < 3)
1001
    {
1002
        yyerrflag = 3;
1003
        for (;;)
1004
        {
1005
            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
1006
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1007
            {
1008
#if YYDEBUG
1009
                if (yydebug)
1010
                    printf("%sdebug: state %d, error recovery shifting\
1011
 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
1012
#endif
1013
                if (yyssp >= yysslim && yygrowstack())
1014
                {
1015
                    goto yyoverflow;
1016
                }
1017
                *++yyssp = yystate = yytable[yyn];
1018
                *++yyvsp = yylval;
1019
                goto yyloop;
1020
            }
1021
            else
1022
            {
1023
#if YYDEBUG
1024
                if (yydebug)
1025
                    printf("%sdebug: error recovery discarding state %d\n",
1026
                            YYPREFIX, *yyssp);
1027
#endif
1028
                if (yyssp <= yyss) goto yyabort;
1029
                --yyssp;
1030
                --yyvsp;
1031
            }
1032
        }
1033
    }
1034
    else
1035
    {
1036
        if (yychar == 0) goto yyabort;
1037
#if YYDEBUG
1038
        if (yydebug)
1039
        {
1040
            yys = 0;
1041
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1042
            if (!yys) yys = "illegal-symbol";
1043
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1044
                    YYPREFIX, yystate, yychar, yys);
1045
        }
1046
#endif
1047
        yychar = (-1);
1048
        goto yyloop;
1049
    }
1050
yyreduce:
1051
#if YYDEBUG
1052
    if (yydebug)
1053
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1054
                YYPREFIX, yystate, yyn, yyrule[yyn]);
1055
#endif
1056
    yym = yylen[yyn];
1057
    if (yym)
1058
        yyval = yyvsp[1-yym];
1059
    else
1060
        memset(&yyval, 0, sizeof yyval);
1061
    switch (yyn)
1062
    {
1063
case 6:
1064
#line 126 "parse.y"
1065
{ file->errors++; }
1066
break;
1067
case 7:
1068
#line 129 "parse.y"
1069
{
1070
			if (asprintf(&yyval.v.string, "%s %s", yyvsp[-1].v.string, yyvsp[0].v.string) == -1) {
1071
				free(yyvsp[-1].v.string);
1072
				free(yyvsp[0].v.string);
1073
				yyerror("string: asprintf");
1074
				YYERROR;
1075
			}
1076
			free(yyvsp[-1].v.string);
1077
			free(yyvsp[0].v.string);
1078
		}
1079
break;
1080
case 9:
1081
#line 142 "parse.y"
1082
{ yyval.v.number = 1; }
1083
break;
1084
case 10:
1085
#line 143 "parse.y"
1086
{ yyval.v.number = 0; }
1087
break;
1088
case 11:
1089
#line 146 "parse.y"
1090
{ yyval.v.number = 0; }
1091
break;
1092
case 12:
1093
#line 147 "parse.y"
1094
{ yyval.v.number = 1; }
1095
break;
1096
case 13:
1097
#line 149 "parse.y"
1098
{
1099
			char *s = yyvsp[-2].v.string;
1100
			if (conf->opts & RIPD_OPT_VERBOSE)
1101
				printf("%s = \"%s\"\n", yyvsp[-2].v.string, yyvsp[0].v.string);
1102
			while (*s++) {
1103
				if (isspace((unsigned char)*s)) {
1104
					yyerror("macro name cannot contain "
1105
					    "whitespace");
1106
					YYERROR;
1107
				}
1108
			}
1109
			if (symset(yyvsp[-2].v.string, yyvsp[0].v.string, 0) == -1)
1110
				fatal("cannot store variable");
1111
			free(yyvsp[-2].v.string);
1112
			free(yyvsp[0].v.string);
1113
		}
1114
break;
1115
case 14:
1116
#line 167 "parse.y"
1117
{
1118
			/* clean flags first */
1119
			conf->options &= ~(OPT_SPLIT_HORIZON |
1120
			    OPT_SPLIT_POISONED);
1121
			if (!strcmp(yyvsp[0].v.string, "none"))
1122
				/* nothing */ ;
1123
			else if (!strcmp(yyvsp[0].v.string, "simple"))
1124
				conf->options |= OPT_SPLIT_HORIZON;
1125
			else if (!strcmp(yyvsp[0].v.string, "poisoned"))
1126
				conf->options |= OPT_SPLIT_POISONED;
1127
			else {
1128
				yyerror("unknown split horizon type");
1129
				free(yyvsp[0].v.string);
1130
				YYERROR;
1131
			}
1132
			free(yyvsp[0].v.string);
1133
		}
1134
break;
1135
case 15:
1136
#line 184 "parse.y"
1137
{
1138
			if (yyvsp[0].v.number == 1)
1139
				conf->options |= OPT_TRIGGERED_UPDATES;
1140
			else
1141
				conf->options &= ~OPT_TRIGGERED_UPDATES;
1142
		}
1143
break;
1144
case 16:
1145
#line 190 "parse.y"
1146
{
1147
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > RT_TABLEID_MAX) {
1148
				yyerror("invalid rdomain");
1149
				YYERROR;
1150
			}
1151
			conf->rdomain = yyvsp[0].v.number;
1152
		}
1153
break;
1154
case 17:
1155
#line 197 "parse.y"
1156
{
1157
			if (yyvsp[0].v.number == 0)
1158
				conf->flags |= RIPD_FLAG_NO_FIB_UPDATE;
1159
			else
1160
				conf->flags &= ~RIPD_FLAG_NO_FIB_UPDATE;
1161
		}
1162
break;
1163
case 18:
1164
#line 203 "parse.y"
1165
{
1166
			struct redistribute	*r;
1167
1168
			if ((r = calloc(1, sizeof(*r))) == NULL)
1169
				fatal(NULL);
1170
			if (!strcmp(yyvsp[0].v.string, "static"))
1171
				r->type = REDIST_STATIC;
1172
			else if (!strcmp(yyvsp[0].v.string, "connected"))
1173
				r->type = REDIST_CONNECTED;
1174
			else if (!strcmp(yyvsp[0].v.string, "default"))
1175
				r->type = REDIST_DEFAULT;
1176
			else if (host(yyvsp[0].v.string, &r->addr, &r->mask))
1177
				r->type = REDIST_ADDR;
1178
			else {
1179
				yyerror("unknown redistribute type");
1180
				free(yyvsp[0].v.string);
1181
				free(r);
1182
				YYERROR;
1183
			}
1184
1185
			if (yyvsp[-2].v.number)
1186
				r->type |= REDIST_NO;
1187
1188
			SIMPLEQ_INSERT_TAIL(&conf->redist_list, r,
1189
			    entry);
1190
1191
			conf->redistribute |= REDISTRIBUTE_ON;
1192
			free(yyvsp[0].v.string);
1193
		}
1194
break;
1195
case 19:
1196
#line 232 "parse.y"
1197
{
1198
			struct redistribute	*r;
1199
1200
			if ((r = calloc(1, sizeof(*r))) == NULL)
1201
				fatal(NULL);
1202
			r->type = REDIST_LABEL;
1203
			r->label = rtlabel_name2id(yyvsp[0].v.string);
1204
			if (yyvsp[-3].v.number)
1205
				r->type |= REDIST_NO;
1206
			free(yyvsp[0].v.string);
1207
1208
			SIMPLEQ_INSERT_TAIL(&conf->redist_list, r, entry);
1209
			conf->redistribute |= REDISTRIBUTE_ON;
1210
		}
1211
break;
1212
case 21:
1213
#line 249 "parse.y"
1214
{
1215
			if (yyvsp[-1].v.number < MIN_MD_ID || yyvsp[-1].v.number > MAX_MD_ID) {
1216
				yyerror("auth-md key-id out of range "
1217
				    "(%d-%d)", MIN_MD_ID, MAX_MD_ID);
1218
				free(yyvsp[0].v.string);
1219
				YYERROR;
1220
			}
1221
			if (md_list_add(&defs->md_list, yyvsp[-1].v.number, yyvsp[0].v.string) == -1) {
1222
				yyerror("auth-md key length out of range "
1223
				    "(max length %d)", MD5_DIGEST_LENGTH);
1224
				free(yyvsp[0].v.string);
1225
				YYERROR;
1226
			}
1227
			free(yyvsp[0].v.string);
1228
		}
1229
break;
1230
case 22:
1231
#line 265 "parse.y"
1232
{
1233
			if (yyvsp[0].v.number < MIN_MD_ID || yyvsp[0].v.number > MAX_MD_ID) {
1234
				yyerror("auth-md-keyid out of range "
1235
				    "(%d-%d)", MIN_MD_ID, MAX_MD_ID);
1236
				YYERROR;
1237
			}
1238
			defs->auth_keyid = yyvsp[0].v.number;
1239
		}
1240
break;
1241
case 23:
1242
#line 274 "parse.y"
1243
{
1244
			enum auth_type	type;
1245
1246
			if (!strcmp(yyvsp[0].v.string, "none"))
1247
				type = AUTH_NONE;
1248
			else if (!strcmp(yyvsp[0].v.string, "simple"))
1249
				type = AUTH_SIMPLE;
1250
			else if (!strcmp(yyvsp[0].v.string, "crypt"))
1251
				type = AUTH_CRYPT;
1252
			else {
1253
				yyerror("unknown auth-type");
1254
				free(yyvsp[0].v.string);
1255
				YYERROR;
1256
			}
1257
			free(yyvsp[0].v.string);
1258
			defs->auth_type = type;
1259
		}
1260
break;
1261
case 24:
1262
#line 293 "parse.y"
1263
{
1264
			if (strlen(yyvsp[0].v.string) > MAX_SIMPLE_AUTH_LEN) {
1265
				yyerror("auth-key too long (max length %d)",
1266
				    MAX_SIMPLE_AUTH_LEN);
1267
				free(yyvsp[0].v.string);
1268
				YYERROR;
1269
			}
1270
			bzero(defs->auth_key, MAX_SIMPLE_AUTH_LEN);
1271
			memcpy(defs->auth_key, yyvsp[0].v.string, strlen(yyvsp[0].v.string));
1272
			free(yyvsp[0].v.string);
1273
		}
1274
break;
1275
case 25:
1276
#line 306 "parse.y"
1277
{
1278
			if (yyvsp[0].v.number < 1 || yyvsp[0].v.number > INFINITY) {
1279
				yyerror("cost out of range (%d-%d)", 1,
1280
				    INFINITY);
1281
				YYERROR;
1282
			}
1283
			defs->cost = yyvsp[0].v.number;
1284
		}
1285
break;
1286
case 33:
1287
#line 327 "parse.y"
1288
{
1289
			struct kif *kif;
1290
1291
			if ((kif = kif_findname(yyvsp[0].v.string)) == NULL) {
1292
				yyerror("unknown interface %s", yyvsp[0].v.string);
1293
				free(yyvsp[0].v.string);
1294
				YYERROR;
1295
			}
1296
			free(yyvsp[0].v.string);
1297
			iface = conf_get_if(kif);
1298
			if (iface == NULL)
1299
				YYERROR;
1300
			LIST_INSERT_HEAD(&conf->iface_list, iface, entry);
1301
			memcpy(&ifacedefs, defs, sizeof(ifacedefs));
1302
			md_list_copy(&ifacedefs.md_list, &defs->md_list);
1303
			defs = &ifacedefs;
1304
		}
1305
break;
1306
case 34:
1307
#line 343 "parse.y"
1308
{
1309
			iface->cost = defs->cost;
1310
			iface->auth_type = defs->auth_type;
1311
			iface->auth_keyid = defs->auth_keyid;
1312
			memcpy(iface->auth_key, defs->auth_key,
1313
			    sizeof(iface->auth_key));
1314
			md_list_copy(&iface->auth_md_list, &defs->md_list);
1315
			md_list_clr(&defs->md_list);
1316
			defs = &globaldefs;
1317
		}
1318
break;
1319
case 39:
1320
#line 363 "parse.y"
1321
{ iface->passive = 1; }
1322
break;
1323
case 40:
1324
#line 364 "parse.y"
1325
{
1326
			if (strlcpy(iface->demote_group, yyvsp[0].v.string,
1327
			    sizeof(iface->demote_group)) >=
1328
			    sizeof(iface->demote_group)) {
1329
				yyerror("demote group name \"%s\" too long",
1330
				    yyvsp[0].v.string);
1331
				free(yyvsp[0].v.string);
1332
				YYERROR;
1333
			}
1334
			free(yyvsp[0].v.string);
1335
			if (carp_demote_init(iface->demote_group,
1336
			    conf->opts & RIPD_OPT_FORCE_DEMOTE) == -1) {
1337
				yyerror("error initializing group \"%s\"",
1338
				    iface->demote_group);
1339
				YYERROR;
1340
			}
1341
		}
1342
break;
1343
#line 1336 "parse.c"
1344
    }
1345
    yyssp -= yym;
1346
    yystate = *yyssp;
1347
    yyvsp -= yym;
1348
    yym = yylhs[yyn];
1349
    if (yystate == 0 && yym == 0)
1350
    {
1351
#if YYDEBUG
1352
        if (yydebug)
1353
            printf("%sdebug: after reduction, shifting from state 0 to\
1354
 state %d\n", YYPREFIX, YYFINAL);
1355
#endif
1356
        yystate = YYFINAL;
1357
        *++yyssp = YYFINAL;
1358
        *++yyvsp = yyval;
1359
        if (yychar < 0)
1360
        {
1361
            if ((yychar = yylex()) < 0) yychar = 0;
1362
#if YYDEBUG
1363
            if (yydebug)
1364
            {
1365
                yys = 0;
1366
                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1367
                if (!yys) yys = "illegal-symbol";
1368
                printf("%sdebug: state %d, reading %d (%s)\n",
1369
                        YYPREFIX, YYFINAL, yychar, yys);
1370
            }
1371
#endif
1372
        }
1373
        if (yychar == 0) goto yyaccept;
1374
        goto yyloop;
1375
    }
1376
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1377
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1378
        yystate = yytable[yyn];
1379
    else
1380
        yystate = yydgoto[yym];
1381
#if YYDEBUG
1382
    if (yydebug)
1383
        printf("%sdebug: after reduction, shifting from state %d \
1384
to state %d\n", YYPREFIX, *yyssp, yystate);
1385
#endif
1386
    if (yyssp >= yysslim && yygrowstack())
1387
    {
1388
        goto yyoverflow;
1389
    }
1390
    *++yyssp = yystate;
1391
    *++yyvsp = yyval;
1392
    goto yyloop;
1393
yyoverflow:
1394
    yyerror("yacc stack overflow");
1395
yyabort:
1396
    if (yyss)
1397
            free(yyss);
1398
    if (yyvs)
1399
            free(yyvs);
1400
    yyss = yyssp = NULL;
1401
    yyvs = yyvsp = NULL;
1402
    yystacksize = 0;
1403
    return (1);
1404
yyaccept:
1405
    if (yyss)
1406
            free(yyss);
1407
    if (yyvs)
1408
            free(yyvs);
1409
    yyss = yyssp = NULL;
1410
    yyvs = yyvsp = NULL;
1411
    yystacksize = 0;
1412
    return (0);
1413
}