xref: /openbsd-src/usr.sbin/ripd/parse.y (revision 08f6ba1906d01c4a24fa700d568400f71bcf9611)
1*08f6ba19Snaddy /*	$OpenBSD: parse.y,v 1.48 2021/10/15 15:01:28 naddy Exp $ */
2ddeeec14Snorby 
3ddeeec14Snorby /*
4ddeeec14Snorby  * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it>
5ddeeec14Snorby  * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
6ddeeec14Snorby  * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
7ddeeec14Snorby  * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
8ddeeec14Snorby  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
9ddeeec14Snorby  * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
10ddeeec14Snorby  * Copyright (c) 2001 Theo de Raadt.  All rights reserved.
11ddeeec14Snorby  *
12ddeeec14Snorby  * Permission to use, copy, modify, and distribute this software for any
13ddeeec14Snorby  * purpose with or without fee is hereby granted, provided that the above
14ddeeec14Snorby  * copyright notice and this permission notice appear in all copies.
15ddeeec14Snorby  *
16ddeeec14Snorby  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
17ddeeec14Snorby  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
18ddeeec14Snorby  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
19ddeeec14Snorby  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20ddeeec14Snorby  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21ddeeec14Snorby  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
22ddeeec14Snorby  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23ddeeec14Snorby  */
24ddeeec14Snorby 
25ddeeec14Snorby %{
26ddeeec14Snorby #include <sys/types.h>
27ddeeec14Snorby #include <sys/socket.h>
2820741916Sderaadt #include <sys/stat.h>
291acb5c27Sremi #include <net/route.h>
30ddeeec14Snorby #include <netinet/in.h>
31ddeeec14Snorby #include <arpa/inet.h>
32ddeeec14Snorby #include <ctype.h>
33ddeeec14Snorby #include <err.h>
34ddeeec14Snorby #include <errno.h>
3520741916Sderaadt #include <unistd.h>
36ddeeec14Snorby #include <limits.h>
37ddeeec14Snorby #include <stdarg.h>
38ddeeec14Snorby #include <stdio.h>
39ddeeec14Snorby #include <string.h>
404a1d3eaaSsthen #include <syslog.h>
41ddeeec14Snorby 
42ddeeec14Snorby #include "ripd.h"
43ddeeec14Snorby #include "rip.h"
44ddeeec14Snorby #include "ripe.h"
45ddeeec14Snorby #include "log.h"
46ddeeec14Snorby 
4720741916Sderaadt TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
4820741916Sderaadt static struct file {
4920741916Sderaadt 	TAILQ_ENTRY(file)	 entry;
5020741916Sderaadt 	FILE			*stream;
5120741916Sderaadt 	char			*name;
5220741916Sderaadt 	int			 lineno;
5320741916Sderaadt 	int			 errors;
54c6004ab9Smpf } *file, *topfile;
5520741916Sderaadt struct file	*pushfile(const char *, int);
5620741916Sderaadt int		 popfile(void);
57ddeeec14Snorby int		 yyparse(void);
5820741916Sderaadt int		 yylex(void);
597fe19e9cSdoug int		 yyerror(const char *, ...)
607fe19e9cSdoug     __attribute__((__format__ (printf, 1, 2)))
617fe19e9cSdoug     __attribute__((__nonnull__ (1)));
62ddeeec14Snorby int		 kw_cmp(const void *, const void *);
63ddeeec14Snorby int		 lookup(char *);
64d5d66eaeSderaadt int		 lgetc(int);
65ddeeec14Snorby int		 lungetc(int);
66ddeeec14Snorby int		 findeol(void);
6720741916Sderaadt 
6820741916Sderaadt TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
6920741916Sderaadt struct sym {
7020741916Sderaadt 	TAILQ_ENTRY(sym)	 entry;
7120741916Sderaadt 	int			 used;
7220741916Sderaadt 	int			 persist;
7320741916Sderaadt 	char			*nam;
7420741916Sderaadt 	char			*val;
7520741916Sderaadt };
7620741916Sderaadt int		 symset(const char *, const char *, int);
7720741916Sderaadt char		*symget(const char *);
78ddeeec14Snorby 
79ddeeec14Snorby static struct {
80d1c9c145Sclaudio 	u_int8_t		 auth_key[MAX_SIMPLE_AUTH_LEN];
81ddeeec14Snorby 	struct auth_md_head	 md_list;
82ddeeec14Snorby 	enum auth_type		 auth_type;
83ddeeec14Snorby 	u_int8_t		 auth_keyid;
84ddeeec14Snorby 	u_int8_t		 cost;
85ddeeec14Snorby } *defs, globaldefs, ifacedefs;
86ddeeec14Snorby 
8720741916Sderaadt struct iface	*iface = NULL;
8820741916Sderaadt static struct ripd_conf	*conf;
8920741916Sderaadt static int		 errors = 0;
90ddeeec14Snorby 
91ddeeec14Snorby struct iface	*conf_get_if(struct kif *);
9220741916Sderaadt void		 clear_config(struct ripd_conf *);
9320741916Sderaadt int		 check_file_secrecy(int, const char *);
9420741916Sderaadt u_int32_t	 get_rtr_id(void);
9520741916Sderaadt int		 host(const char *, struct in_addr *, struct in_addr *);
96ddeeec14Snorby 
97ddeeec14Snorby typedef struct {
98ddeeec14Snorby 	union {
9906f703ebSderaadt 		int64_t		 number;
100ddeeec14Snorby 		char		*string;
101ddeeec14Snorby 	} v;
102ddeeec14Snorby 	int lineno;
103ddeeec14Snorby } YYSTYPE;
104ddeeec14Snorby 
105ddeeec14Snorby %}
106ddeeec14Snorby 
1071acb5c27Sremi %token	SPLIT_HORIZON TRIGGERED_UPDATES FIBPRIORITY FIBUPDATE
1081acb5c27Sremi %token	REDISTRIBUTE RDOMAIN
109ddeeec14Snorby %token	AUTHKEY AUTHTYPE AUTHMD AUTHMDKEYID
1109bb9ec63Sclaudio %token	INTERFACE RTLABEL
111ddeeec14Snorby %token	COST PASSIVE
1129bb9ec63Sclaudio %token	YES NO
1134d8b14b6Smichele %token	DEMOTE
114ddeeec14Snorby %token	ERROR
115ddeeec14Snorby %token	<v.string>	STRING
11606f703ebSderaadt %token	<v.number>	NUMBER
11706f703ebSderaadt %type	<v.number>	yesno no
118ddeeec14Snorby %type	<v.string>	string
119ddeeec14Snorby 
120ddeeec14Snorby %%
121ddeeec14Snorby 
122ddeeec14Snorby grammar		: /* empty */
123ddeeec14Snorby 		| grammar '\n'
124ddeeec14Snorby 		| grammar conf_main '\n'
125ddeeec14Snorby 		| grammar varset '\n'
126ddeeec14Snorby 		| grammar interface '\n'
12720741916Sderaadt 		| grammar error '\n'		{ file->errors++; }
128ddeeec14Snorby 		;
129ddeeec14Snorby 
130ddeeec14Snorby string		: string STRING {
131ddeeec14Snorby 			if (asprintf(&$$, "%s %s", $1, $2) == -1) {
132ddeeec14Snorby 				free($1);
133ddeeec14Snorby 				free($2);
134ddeeec14Snorby 				yyerror("string: asprintf");
135ddeeec14Snorby 				YYERROR;
136ddeeec14Snorby 			}
137ddeeec14Snorby 			free($1);
138ddeeec14Snorby 			free($2);
139ddeeec14Snorby 		}
140ddeeec14Snorby 		| STRING
141ddeeec14Snorby 		;
142ddeeec14Snorby 
1439bb9ec63Sclaudio yesno		: YES	{ $$ = 1; }
1449bb9ec63Sclaudio 		| NO	{ $$ = 0; }
145ddeeec14Snorby 		;
146ddeeec14Snorby 
1479bb9ec63Sclaudio no		: /* empty */	{ $$ = 0; }
1489bb9ec63Sclaudio 		| NO		{ $$ = 1; }
1499bb9ec63Sclaudio 
150ddeeec14Snorby varset		: STRING '=' string {
1510c7b4ca6Sbenno 			char *s = $1;
152ddeeec14Snorby 			if (conf->opts & RIPD_OPT_VERBOSE)
153ddeeec14Snorby 				printf("%s = \"%s\"\n", $1, $3);
1540c7b4ca6Sbenno 			while (*s++) {
1550c7b4ca6Sbenno 				if (isspace((unsigned char)*s)) {
1560c7b4ca6Sbenno 					yyerror("macro name cannot contain "
1570c7b4ca6Sbenno 					    "whitespace");
15816a0a906Skrw 					free($1);
15916a0a906Skrw 					free($3);
1600c7b4ca6Sbenno 					YYERROR;
1610c7b4ca6Sbenno 				}
1620c7b4ca6Sbenno 			}
163ddeeec14Snorby 			if (symset($1, $3, 0) == -1)
164ddeeec14Snorby 				fatal("cannot store variable");
165ddeeec14Snorby 			free($1);
166ddeeec14Snorby 			free($3);
167ddeeec14Snorby 		}
168ddeeec14Snorby 		;
169ddeeec14Snorby 
170ddeeec14Snorby conf_main	: SPLIT_HORIZON STRING {
171ddeeec14Snorby 			/* clean flags first */
172ddeeec14Snorby 			conf->options &= ~(OPT_SPLIT_HORIZON |
173ddeeec14Snorby 			    OPT_SPLIT_POISONED);
174ddeeec14Snorby 			if (!strcmp($2, "none"))
175ddeeec14Snorby 				/* nothing */ ;
17646802160Smichele 			else if (!strcmp($2, "simple"))
177ddeeec14Snorby 				conf->options |= OPT_SPLIT_HORIZON;
178ddeeec14Snorby 			else if (!strcmp($2, "poisoned"))
179ddeeec14Snorby 				conf->options |= OPT_SPLIT_POISONED;
180ddeeec14Snorby 			else {
1818fb80d1cSmichele 				yyerror("unknown split horizon type");
182ddeeec14Snorby 				free($2);
183ddeeec14Snorby 				YYERROR;
184ddeeec14Snorby 			}
185ddeeec14Snorby 			free($2);
186ddeeec14Snorby 		}
187ddeeec14Snorby 		| TRIGGERED_UPDATES yesno {
188ddeeec14Snorby 			if ($2 == 1)
189ddeeec14Snorby 				conf->options |= OPT_TRIGGERED_UPDATES;
190ddeeec14Snorby 			else
191ddeeec14Snorby 				conf->options &= ~OPT_TRIGGERED_UPDATES;
192ddeeec14Snorby 		}
1930ab89b34Smichele 		| RDOMAIN NUMBER {
1940ab89b34Smichele 			if ($2 < 0 || $2 > RT_TABLEID_MAX) {
1950ab89b34Smichele 				yyerror("invalid rdomain");
1960ab89b34Smichele 				YYERROR;
1970ab89b34Smichele 			}
1980ab89b34Smichele 			conf->rdomain = $2;
1990ab89b34Smichele 		}
2001acb5c27Sremi 		| FIBPRIORITY NUMBER {
2011acb5c27Sremi 			if ($2 <= RTP_NONE || $2 > RTP_MAX) {
2021acb5c27Sremi 				yyerror("invalid fib-priority");
2031acb5c27Sremi 				YYERROR;
2041acb5c27Sremi 			}
2051acb5c27Sremi 			conf->fib_priority = $2;
2061acb5c27Sremi 		}
207ddeeec14Snorby 		| FIBUPDATE yesno {
208ddeeec14Snorby 			if ($2 == 0)
209ddeeec14Snorby 				conf->flags |= RIPD_FLAG_NO_FIB_UPDATE;
210ddeeec14Snorby 			else
211ddeeec14Snorby 				conf->flags &= ~RIPD_FLAG_NO_FIB_UPDATE;
212ddeeec14Snorby 		}
2139bb9ec63Sclaudio 		| no REDISTRIBUTE STRING {
2149bb9ec63Sclaudio 			struct redistribute	*r;
2159bb9ec63Sclaudio 
2169bb9ec63Sclaudio 			if ((r = calloc(1, sizeof(*r))) == NULL)
2179bb9ec63Sclaudio 				fatal(NULL);
2189bb9ec63Sclaudio 			if (!strcmp($3, "static"))
2199bb9ec63Sclaudio 				r->type = REDIST_STATIC;
2209bb9ec63Sclaudio 			else if (!strcmp($3, "connected"))
2219bb9ec63Sclaudio 				r->type = REDIST_CONNECTED;
22239c227bcSmichele 			else if (!strcmp($3, "default"))
22339c227bcSmichele 				r->type = REDIST_DEFAULT;
2249bb9ec63Sclaudio 			else if (host($3, &r->addr, &r->mask))
2259bb9ec63Sclaudio 				r->type = REDIST_ADDR;
226ddeeec14Snorby 			else {
227ddeeec14Snorby 				yyerror("unknown redistribute type");
2289bb9ec63Sclaudio 				free($3);
2299bb9ec63Sclaudio 				free(r);
230ddeeec14Snorby 				YYERROR;
231ddeeec14Snorby 			}
2329bb9ec63Sclaudio 
2339bb9ec63Sclaudio 			if ($1)
2349bb9ec63Sclaudio 				r->type |= REDIST_NO;
2359bb9ec63Sclaudio 
2369bb9ec63Sclaudio 			SIMPLEQ_INSERT_TAIL(&conf->redist_list, r,
2379bb9ec63Sclaudio 			    entry);
23839c227bcSmichele 
2399bb9ec63Sclaudio 			conf->redistribute |= REDISTRIBUTE_ON;
2409bb9ec63Sclaudio 			free($3);
2419bb9ec63Sclaudio 		}
2429bb9ec63Sclaudio 		| no REDISTRIBUTE RTLABEL STRING {
2439bb9ec63Sclaudio 			struct redistribute	*r;
2449bb9ec63Sclaudio 
2459bb9ec63Sclaudio 			if ((r = calloc(1, sizeof(*r))) == NULL)
2469bb9ec63Sclaudio 				fatal(NULL);
2479bb9ec63Sclaudio 			r->type = REDIST_LABEL;
2489bb9ec63Sclaudio 			r->label = rtlabel_name2id($4);
2499bb9ec63Sclaudio 			if ($1)
2509bb9ec63Sclaudio 				r->type |= REDIST_NO;
2519bb9ec63Sclaudio 			free($4);
2529bb9ec63Sclaudio 
2539bb9ec63Sclaudio 			SIMPLEQ_INSERT_TAIL(&conf->redist_list, r, entry);
2549bb9ec63Sclaudio 			conf->redistribute |= REDISTRIBUTE_ON;
255ddeeec14Snorby 		}
2560d0a18a3Smichele 		| defaults
257ddeeec14Snorby 		;
258ddeeec14Snorby 
25906f703ebSderaadt authmd		: AUTHMD NUMBER STRING {
260ddeeec14Snorby 			if ($2 < MIN_MD_ID || $2 > MAX_MD_ID) {
261ddeeec14Snorby 				yyerror("auth-md key-id out of range "
262ddeeec14Snorby 				    "(%d-%d)", MIN_MD_ID, MAX_MD_ID);
263ddeeec14Snorby 				free($3);
264ddeeec14Snorby 				YYERROR;
265ddeeec14Snorby 			}
266d1c9c145Sclaudio 			if (md_list_add(&defs->md_list, $2, $3) == -1) {
267ddeeec14Snorby 				yyerror("auth-md key length out of range "
268d1c9c145Sclaudio 				    "(max length %d)", MD5_DIGEST_LENGTH);
269ddeeec14Snorby 				free($3);
270ddeeec14Snorby 				YYERROR;
271ddeeec14Snorby 			}
272ddeeec14Snorby 			free($3);
273ddeeec14Snorby 		}
274ddeeec14Snorby 
27506f703ebSderaadt authmdkeyid	: AUTHMDKEYID NUMBER {
276ddeeec14Snorby 			if ($2 < MIN_MD_ID || $2 > MAX_MD_ID) {
277ddeeec14Snorby 				yyerror("auth-md-keyid out of range "
278ddeeec14Snorby 				    "(%d-%d)", MIN_MD_ID, MAX_MD_ID);
279ddeeec14Snorby 				YYERROR;
280ddeeec14Snorby 			}
281ddeeec14Snorby 			defs->auth_keyid = $2;
282ddeeec14Snorby 		}
283ddeeec14Snorby 
284ddeeec14Snorby authtype	: AUTHTYPE STRING {
285ddeeec14Snorby 			enum auth_type	type;
286ddeeec14Snorby 
287ddeeec14Snorby 			if (!strcmp($2, "none"))
288ddeeec14Snorby 				type = AUTH_NONE;
289ddeeec14Snorby 			else if (!strcmp($2, "simple"))
290ddeeec14Snorby 				type = AUTH_SIMPLE;
291ddeeec14Snorby 			else if (!strcmp($2, "crypt"))
292ddeeec14Snorby 				type = AUTH_CRYPT;
293ddeeec14Snorby 			else {
294ddeeec14Snorby 				yyerror("unknown auth-type");
295ddeeec14Snorby 				free($2);
296ddeeec14Snorby 				YYERROR;
297ddeeec14Snorby 			}
298ddeeec14Snorby 			free($2);
299ddeeec14Snorby 			defs->auth_type = type;
300ddeeec14Snorby 		}
301ddeeec14Snorby 		;
302ddeeec14Snorby 
303ddeeec14Snorby authkey		: AUTHKEY STRING {
304ddeeec14Snorby 			if (strlen($2) > MAX_SIMPLE_AUTH_LEN) {
305b8bbf4e7Sdavid 				yyerror("auth-key too long (max length %d)",
306ddeeec14Snorby 				    MAX_SIMPLE_AUTH_LEN);
307ddeeec14Snorby 				free($2);
308ddeeec14Snorby 				YYERROR;
309ddeeec14Snorby 			}
310d1c9c145Sclaudio 			bzero(defs->auth_key, MAX_SIMPLE_AUTH_LEN);
311d1c9c145Sclaudio 			memcpy(defs->auth_key, $2, strlen($2));
312ddeeec14Snorby 			free($2);
313ddeeec14Snorby 		}
314ddeeec14Snorby 		;
315ddeeec14Snorby 
31606f703ebSderaadt defaults	: COST NUMBER {
317ddeeec14Snorby 			if ($2 < 1 || $2 > INFINITY) {
318ddeeec14Snorby 				yyerror("cost out of range (%d-%d)", 1,
319ddeeec14Snorby 				    INFINITY);
320ddeeec14Snorby 				YYERROR;
321ddeeec14Snorby 			}
322ddeeec14Snorby 			defs->cost = $2;
323ddeeec14Snorby 		}
324ddeeec14Snorby 		| authtype
325ddeeec14Snorby 		| authkey
326ddeeec14Snorby 		| authmdkeyid
327ddeeec14Snorby 		| authmd
328ddeeec14Snorby 		;
329ddeeec14Snorby 
330ddeeec14Snorby optnl		: '\n' optnl
331ddeeec14Snorby 		|
332ddeeec14Snorby 		;
333ddeeec14Snorby 
334ddeeec14Snorby nl		: '\n' optnl
335ddeeec14Snorby 		;
336ddeeec14Snorby 
337ddeeec14Snorby interface	: INTERFACE STRING {
338ddeeec14Snorby 			struct kif *kif;
339ddeeec14Snorby 
340ddeeec14Snorby 			if ((kif = kif_findname($2)) == NULL) {
341ddeeec14Snorby 				yyerror("unknown interface %s", $2);
342ddeeec14Snorby 				free($2);
343ddeeec14Snorby 				YYERROR;
344ddeeec14Snorby 			}
345ddeeec14Snorby 			free($2);
346ddeeec14Snorby 			iface = conf_get_if(kif);
347ddeeec14Snorby 			if (iface == NULL)
348ddeeec14Snorby 				YYERROR;
349ddeeec14Snorby 			LIST_INSERT_HEAD(&conf->iface_list, iface, entry);
350ddeeec14Snorby 			memcpy(&ifacedefs, defs, sizeof(ifacedefs));
3510d0a18a3Smichele 			md_list_copy(&ifacedefs.md_list, &defs->md_list);
352ddeeec14Snorby 			defs = &ifacedefs;
353ddeeec14Snorby 		} interface_block {
354ddeeec14Snorby 			iface->cost = defs->cost;
355ddeeec14Snorby 			iface->auth_type = defs->auth_type;
356ddeeec14Snorby 			iface->auth_keyid = defs->auth_keyid;
357ddeeec14Snorby 			memcpy(iface->auth_key, defs->auth_key,
358ddeeec14Snorby 			    sizeof(iface->auth_key));
359ddeeec14Snorby 			md_list_copy(&iface->auth_md_list, &defs->md_list);
360ddeeec14Snorby 			md_list_clr(&defs->md_list);
361ddeeec14Snorby 			defs = &globaldefs;
362ddeeec14Snorby 		}
363ddeeec14Snorby 		;
364ddeeec14Snorby 
3657bc1b36bSremi interface_block	: /* empty */
3667bc1b36bSremi 		| '{' optnl interfaceopts_l '}'
367ddeeec14Snorby 		| '{' optnl '}'
368ddeeec14Snorby 		;
369ddeeec14Snorby 
3704d8b14b6Smichele interfaceopts_l	: interfaceopts_l interfaceoptsl nl
3714d8b14b6Smichele 		| interfaceoptsl optnl
372ddeeec14Snorby 		;
373ddeeec14Snorby 
3744d8b14b6Smichele interfaceoptsl	: PASSIVE		{ iface->passive = 1; }
3754d8b14b6Smichele 		| DEMOTE STRING		{
3764d8b14b6Smichele 			if (strlcpy(iface->demote_group, $2,
3774d8b14b6Smichele 			    sizeof(iface->demote_group)) >=
3784d8b14b6Smichele 			    sizeof(iface->demote_group)) {
3797fe19e9cSdoug 				yyerror("demote group name \"%s\" too long",
3807fe19e9cSdoug 				    $2);
3814d8b14b6Smichele 				free($2);
3824d8b14b6Smichele 				YYERROR;
3834d8b14b6Smichele 			}
3844d8b14b6Smichele 			free($2);
3854d8b14b6Smichele 			if (carp_demote_init(iface->demote_group,
3864d8b14b6Smichele 			    conf->opts & RIPD_OPT_FORCE_DEMOTE) == -1) {
3874d8b14b6Smichele 				yyerror("error initializing group \"%s\"",
3884d8b14b6Smichele 				    iface->demote_group);
3894d8b14b6Smichele 				YYERROR;
3904d8b14b6Smichele 			}
3914d8b14b6Smichele 		}
3924d8b14b6Smichele 		| defaults
393ddeeec14Snorby 		;
394ddeeec14Snorby %%
395ddeeec14Snorby 
396ddeeec14Snorby struct keywords {
397ddeeec14Snorby 	const char	*k_name;
398ddeeec14Snorby 	int		 k_val;
399ddeeec14Snorby };
400ddeeec14Snorby 
401ddeeec14Snorby int
yyerror(const char * fmt,...)402ddeeec14Snorby yyerror(const char *fmt, ...)
403ddeeec14Snorby {
404ddeeec14Snorby 	va_list		 ap;
405cd8337bcSbluhm 	char		*msg;
406ddeeec14Snorby 
40720741916Sderaadt 	file->errors++;
408ddeeec14Snorby 	va_start(ap, fmt);
409cd8337bcSbluhm 	if (vasprintf(&msg, fmt, ap) == -1)
410cd8337bcSbluhm 		fatalx("yyerror vasprintf");
411ddeeec14Snorby 	va_end(ap);
412cd8337bcSbluhm 	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
413cd8337bcSbluhm 	free(msg);
414ddeeec14Snorby 	return (0);
415ddeeec14Snorby }
416ddeeec14Snorby 
417ddeeec14Snorby int
kw_cmp(const void * k,const void * e)418ddeeec14Snorby kw_cmp(const void *k, const void *e)
419ddeeec14Snorby {
420ddeeec14Snorby 	return (strcmp(k, ((const struct keywords *)e)->k_name));
421ddeeec14Snorby }
422ddeeec14Snorby 
423ddeeec14Snorby int
lookup(char * s)424ddeeec14Snorby lookup(char *s)
425ddeeec14Snorby {
426ddeeec14Snorby 	/* this has to be sorted always */
427ddeeec14Snorby 	static const struct keywords keywords[] = {
428ddeeec14Snorby 	    {"auth-key",		AUTHKEY},
429ddeeec14Snorby 	    {"auth-md",			AUTHMD},
430ddeeec14Snorby 	    {"auth-md-keyid",		AUTHMDKEYID},
431ddeeec14Snorby 	    {"auth-type",		AUTHTYPE},
432ddeeec14Snorby 	    {"cost",			COST},
4334d8b14b6Smichele 	    {"demote",			DEMOTE},
4341acb5c27Sremi 	    {"fib-priority",		FIBPRIORITY},
435ddeeec14Snorby 	    {"fib-update",		FIBUPDATE},
436ddeeec14Snorby 	    {"interface",		INTERFACE},
4379bb9ec63Sclaudio 	    {"no",			NO},
438ddeeec14Snorby 	    {"passive",			PASSIVE},
4390ab89b34Smichele 	    {"rdomain",			RDOMAIN},
440ddeeec14Snorby 	    {"redistribute",		REDISTRIBUTE},
4419bb9ec63Sclaudio 	    {"rtlabel",			RTLABEL},
442ddeeec14Snorby 	    {"split-horizon",		SPLIT_HORIZON},
4439bb9ec63Sclaudio 	    {"triggered-updates",	TRIGGERED_UPDATES},
4449bb9ec63Sclaudio 	    {"yes",			YES}
445ddeeec14Snorby 	};
446ddeeec14Snorby 	const struct keywords	*p;
447ddeeec14Snorby 
448ddeeec14Snorby 	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
449ddeeec14Snorby 	    sizeof(keywords[0]), kw_cmp);
450ddeeec14Snorby 
451c186cac6Shenning 	if (p)
452ddeeec14Snorby 		return (p->k_val);
453c186cac6Shenning 	else
454ddeeec14Snorby 		return (STRING);
455ddeeec14Snorby }
456ddeeec14Snorby 
457ddeeec14Snorby #define MAXPUSHBACK	128
458ddeeec14Snorby 
459*08f6ba19Snaddy char	*parsebuf;
460ddeeec14Snorby int	 parseindex;
461*08f6ba19Snaddy char	 pushback_buffer[MAXPUSHBACK];
462ddeeec14Snorby int	 pushback_index = 0;
463ddeeec14Snorby 
464ddeeec14Snorby int
lgetc(int quotec)46520741916Sderaadt lgetc(int quotec)
466ddeeec14Snorby {
467ddeeec14Snorby 	int		c, next;
468ddeeec14Snorby 
469ddeeec14Snorby 	if (parsebuf) {
470ddeeec14Snorby 		/* Read character from the parsebuffer instead of input. */
471ddeeec14Snorby 		if (parseindex >= 0) {
472*08f6ba19Snaddy 			c = (unsigned char)parsebuf[parseindex++];
473ddeeec14Snorby 			if (c != '\0')
474ddeeec14Snorby 				return (c);
475ddeeec14Snorby 			parsebuf = NULL;
476ddeeec14Snorby 		} else
477ddeeec14Snorby 			parseindex++;
478ddeeec14Snorby 	}
479ddeeec14Snorby 
480ddeeec14Snorby 	if (pushback_index)
481*08f6ba19Snaddy 		return ((unsigned char)pushback_buffer[--pushback_index]);
482ddeeec14Snorby 
48320741916Sderaadt 	if (quotec) {
48420741916Sderaadt 		if ((c = getc(file->stream)) == EOF) {
485c6004ab9Smpf 			yyerror("reached end of file while parsing "
486c6004ab9Smpf 			    "quoted string");
487c6004ab9Smpf 			if (file == topfile || popfile() == EOF)
48820741916Sderaadt 				return (EOF);
48920741916Sderaadt 			return (quotec);
49020741916Sderaadt 		}
491d5d66eaeSderaadt 		return (c);
492d5d66eaeSderaadt 	}
493d5d66eaeSderaadt 
49420741916Sderaadt 	while ((c = getc(file->stream)) == '\\') {
49520741916Sderaadt 		next = getc(file->stream);
496ddeeec14Snorby 		if (next != '\n') {
497d5d66eaeSderaadt 			c = next;
498ddeeec14Snorby 			break;
499ddeeec14Snorby 		}
50020741916Sderaadt 		yylval.lineno = file->lineno;
50120741916Sderaadt 		file->lineno++;
502ddeeec14Snorby 	}
503ddeeec14Snorby 
50420741916Sderaadt 	while (c == EOF) {
505c6004ab9Smpf 		if (file == topfile || popfile() == EOF)
50620741916Sderaadt 			return (EOF);
50720741916Sderaadt 		c = getc(file->stream);
50820741916Sderaadt 	}
509ddeeec14Snorby 	return (c);
510ddeeec14Snorby }
511ddeeec14Snorby 
512ddeeec14Snorby int
lungetc(int c)513ddeeec14Snorby lungetc(int c)
514ddeeec14Snorby {
515ddeeec14Snorby 	if (c == EOF)
516ddeeec14Snorby 		return (EOF);
517ddeeec14Snorby 	if (parsebuf) {
518ddeeec14Snorby 		parseindex--;
519ddeeec14Snorby 		if (parseindex >= 0)
520ddeeec14Snorby 			return (c);
521ddeeec14Snorby 	}
522*08f6ba19Snaddy 	if (pushback_index + 1 >= MAXPUSHBACK)
523ddeeec14Snorby 		return (EOF);
524*08f6ba19Snaddy 	pushback_buffer[pushback_index++] = c;
525*08f6ba19Snaddy 	return (c);
526ddeeec14Snorby }
527ddeeec14Snorby 
528ddeeec14Snorby int
findeol(void)529ddeeec14Snorby findeol(void)
530ddeeec14Snorby {
531ddeeec14Snorby 	int	c;
532ddeeec14Snorby 
533ddeeec14Snorby 	parsebuf = NULL;
534ddeeec14Snorby 
535ddeeec14Snorby 	/* skip to either EOF or the first real EOL */
536ddeeec14Snorby 	while (1) {
5371a28f514Shenning 		if (pushback_index)
538*08f6ba19Snaddy 			c = (unsigned char)pushback_buffer[--pushback_index];
5391a28f514Shenning 		else
540d5d66eaeSderaadt 			c = lgetc(0);
541ddeeec14Snorby 		if (c == '\n') {
54220741916Sderaadt 			file->lineno++;
543ddeeec14Snorby 			break;
544ddeeec14Snorby 		}
545ddeeec14Snorby 		if (c == EOF)
546ddeeec14Snorby 			break;
547ddeeec14Snorby 	}
548ddeeec14Snorby 	return (ERROR);
549ddeeec14Snorby }
550ddeeec14Snorby 
551ddeeec14Snorby int
yylex(void)552ddeeec14Snorby yylex(void)
553ddeeec14Snorby {
554*08f6ba19Snaddy 	char	 buf[8096];
555*08f6ba19Snaddy 	char	*p, *val;
55620741916Sderaadt 	int	 quotec, next, c;
557ddeeec14Snorby 	int	 token;
558ddeeec14Snorby 
559ddeeec14Snorby top:
560ddeeec14Snorby 	p = buf;
5612053f12aSmpf 	while ((c = lgetc(0)) == ' ' || c == '\t')
562ddeeec14Snorby 		; /* nothing */
563ddeeec14Snorby 
56420741916Sderaadt 	yylval.lineno = file->lineno;
565ddeeec14Snorby 	if (c == '#')
566d5d66eaeSderaadt 		while ((c = lgetc(0)) != '\n' && c != EOF)
567ddeeec14Snorby 			; /* nothing */
568ddeeec14Snorby 	if (c == '$' && parsebuf == NULL) {
569ddeeec14Snorby 		while (1) {
570d5d66eaeSderaadt 			if ((c = lgetc(0)) == EOF)
571ddeeec14Snorby 				return (0);
572ddeeec14Snorby 
573ddeeec14Snorby 			if (p + 1 >= buf + sizeof(buf) - 1) {
574ddeeec14Snorby 				yyerror("string too long");
575ddeeec14Snorby 				return (findeol());
576ddeeec14Snorby 			}
577ddeeec14Snorby 			if (isalnum(c) || c == '_') {
578015d7b4dSbenno 				*p++ = c;
579ddeeec14Snorby 				continue;
580ddeeec14Snorby 			}
581ddeeec14Snorby 			*p = '\0';
582ddeeec14Snorby 			lungetc(c);
583ddeeec14Snorby 			break;
584ddeeec14Snorby 		}
585ddeeec14Snorby 		val = symget(buf);
586ddeeec14Snorby 		if (val == NULL) {
587ddeeec14Snorby 			yyerror("macro '%s' not defined", buf);
588ddeeec14Snorby 			return (findeol());
589ddeeec14Snorby 		}
590ddeeec14Snorby 		parsebuf = val;
591ddeeec14Snorby 		parseindex = 0;
592ddeeec14Snorby 		goto top;
593ddeeec14Snorby 	}
594ddeeec14Snorby 
595ddeeec14Snorby 	switch (c) {
596ddeeec14Snorby 	case '\'':
597ddeeec14Snorby 	case '"':
59820741916Sderaadt 		quotec = c;
599ddeeec14Snorby 		while (1) {
60020741916Sderaadt 			if ((c = lgetc(quotec)) == EOF)
601ddeeec14Snorby 				return (0);
602ddeeec14Snorby 			if (c == '\n') {
60320741916Sderaadt 				file->lineno++;
604ddeeec14Snorby 				continue;
605d5d66eaeSderaadt 			} else if (c == '\\') {
60620741916Sderaadt 				if ((next = lgetc(quotec)) == EOF)
607d5d66eaeSderaadt 					return (0);
608a1533359Ssashan 				if (next == quotec || next == ' ' ||
609a1533359Ssashan 				    next == '\t')
610d5d66eaeSderaadt 					c = next;
611daf24110Shenning 				else if (next == '\n') {
612daf24110Shenning 					file->lineno++;
613ea014f46Sderaadt 					continue;
614daf24110Shenning 				} else
615d5d66eaeSderaadt 					lungetc(next);
61620741916Sderaadt 			} else if (c == quotec) {
617d5d66eaeSderaadt 				*p = '\0';
618d5d66eaeSderaadt 				break;
61941eef22fSjsg 			} else if (c == '\0') {
62041eef22fSjsg 				yyerror("syntax error");
62141eef22fSjsg 				return (findeol());
622ddeeec14Snorby 			}
623ddeeec14Snorby 			if (p + 1 >= buf + sizeof(buf) - 1) {
624ddeeec14Snorby 				yyerror("string too long");
625ddeeec14Snorby 				return (findeol());
626ddeeec14Snorby 			}
627015d7b4dSbenno 			*p++ = c;
628ddeeec14Snorby 		}
629ddeeec14Snorby 		yylval.v.string = strdup(buf);
630ddeeec14Snorby 		if (yylval.v.string == NULL)
631a062aa9dSkrw 			err(1, "%s", __func__);
632ddeeec14Snorby 		return (STRING);
633ddeeec14Snorby 	}
634ddeeec14Snorby 
63506f703ebSderaadt #define allowed_to_end_number(x) \
6360cf2c9c3Smpf 	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
63706f703ebSderaadt 
63806f703ebSderaadt 	if (c == '-' || isdigit(c)) {
63906f703ebSderaadt 		do {
64006f703ebSderaadt 			*p++ = c;
641915c3f33Sderaadt 			if ((size_t)(p-buf) >= sizeof(buf)) {
64206f703ebSderaadt 				yyerror("string too long");
64306f703ebSderaadt 				return (findeol());
64406f703ebSderaadt 			}
645d5d66eaeSderaadt 		} while ((c = lgetc(0)) != EOF && isdigit(c));
64606f703ebSderaadt 		lungetc(c);
64706f703ebSderaadt 		if (p == buf + 1 && buf[0] == '-')
64806f703ebSderaadt 			goto nodigits;
64906f703ebSderaadt 		if (c == EOF || allowed_to_end_number(c)) {
65006f703ebSderaadt 			const char *errstr = NULL;
65106f703ebSderaadt 
65206f703ebSderaadt 			*p = '\0';
65306f703ebSderaadt 			yylval.v.number = strtonum(buf, LLONG_MIN,
65406f703ebSderaadt 			    LLONG_MAX, &errstr);
65506f703ebSderaadt 			if (errstr) {
65606f703ebSderaadt 				yyerror("\"%s\" invalid number: %s",
65706f703ebSderaadt 				    buf, errstr);
65806f703ebSderaadt 				return (findeol());
65906f703ebSderaadt 			}
66006f703ebSderaadt 			return (NUMBER);
66106f703ebSderaadt 		} else {
66206f703ebSderaadt nodigits:
66306f703ebSderaadt 			while (p > buf + 1)
664*08f6ba19Snaddy 				lungetc((unsigned char)*--p);
665*08f6ba19Snaddy 			c = (unsigned char)*--p;
66606f703ebSderaadt 			if (c == '-')
66706f703ebSderaadt 				return (c);
66806f703ebSderaadt 		}
66906f703ebSderaadt 	}
67006f703ebSderaadt 
671ddeeec14Snorby #define allowed_in_string(x) \
672ddeeec14Snorby 	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
673ddeeec14Snorby 	x != '{' && x != '}' && \
674ddeeec14Snorby 	x != '!' && x != '=' && x != '#' && \
675ddeeec14Snorby 	x != ','))
676ddeeec14Snorby 
677ddeeec14Snorby 	if (isalnum(c) || c == ':' || c == '_') {
678ddeeec14Snorby 		do {
679ddeeec14Snorby 			*p++ = c;
680915c3f33Sderaadt 			if ((size_t)(p-buf) >= sizeof(buf)) {
681ddeeec14Snorby 				yyerror("string too long");
682ddeeec14Snorby 				return (findeol());
683ddeeec14Snorby 			}
684d5d66eaeSderaadt 		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
685ddeeec14Snorby 		lungetc(c);
686ddeeec14Snorby 		*p = '\0';
687ddeeec14Snorby 		if ((token = lookup(buf)) == STRING)
688ddeeec14Snorby 			if ((yylval.v.string = strdup(buf)) == NULL)
689a062aa9dSkrw 				err(1, "%s", __func__);
690ddeeec14Snorby 		return (token);
691ddeeec14Snorby 	}
692ddeeec14Snorby 	if (c == '\n') {
69320741916Sderaadt 		yylval.lineno = file->lineno;
69420741916Sderaadt 		file->lineno++;
695ddeeec14Snorby 	}
696ddeeec14Snorby 	if (c == EOF)
697ddeeec14Snorby 		return (0);
698ddeeec14Snorby 	return (c);
699ddeeec14Snorby }
700ddeeec14Snorby 
70120741916Sderaadt int
check_file_secrecy(int fd,const char * fname)70220741916Sderaadt check_file_secrecy(int fd, const char *fname)
70320741916Sderaadt {
70420741916Sderaadt 	struct stat	st;
70520741916Sderaadt 
70620741916Sderaadt 	if (fstat(fd, &st)) {
70720741916Sderaadt 		log_warn("cannot stat %s", fname);
70820741916Sderaadt 		return (-1);
70920741916Sderaadt 	}
71020741916Sderaadt 	if (st.st_uid != 0 && st.st_uid != getuid()) {
71120741916Sderaadt 		log_warnx("%s: owner not root or current user", fname);
71220741916Sderaadt 		return (-1);
71320741916Sderaadt 	}
7147140c133Shenning 	if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
7157140c133Shenning 		log_warnx("%s: group writable or world read/writable", fname);
71620741916Sderaadt 		return (-1);
71720741916Sderaadt 	}
71820741916Sderaadt 	return (0);
71920741916Sderaadt }
72020741916Sderaadt 
72120741916Sderaadt struct file *
pushfile(const char * name,int secret)72220741916Sderaadt pushfile(const char *name, int secret)
72320741916Sderaadt {
72420741916Sderaadt 	struct file	*nfile;
72520741916Sderaadt 
7267fc93de0Stobias 	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
7276a3d55f9Skrw 		log_warn("%s", __func__);
72820741916Sderaadt 		return (NULL);
7296fa930c9Spyr 	}
7307fc93de0Stobias 	if ((nfile->name = strdup(name)) == NULL) {
7316a3d55f9Skrw 		log_warn("%s", __func__);
7327fc93de0Stobias 		free(nfile);
7337fc93de0Stobias 		return (NULL);
7347fc93de0Stobias 	}
73520741916Sderaadt 	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
7366a3d55f9Skrw 		log_warn("%s: %s", __func__, nfile->name);
73720741916Sderaadt 		free(nfile->name);
73820741916Sderaadt 		free(nfile);
73920741916Sderaadt 		return (NULL);
74020741916Sderaadt 	} else if (secret &&
74120741916Sderaadt 	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
74220741916Sderaadt 		fclose(nfile->stream);
74320741916Sderaadt 		free(nfile->name);
74420741916Sderaadt 		free(nfile);
74520741916Sderaadt 		return (NULL);
74620741916Sderaadt 	}
74720741916Sderaadt 	nfile->lineno = 1;
74820741916Sderaadt 	TAILQ_INSERT_TAIL(&files, nfile, entry);
74920741916Sderaadt 	return (nfile);
75020741916Sderaadt }
75120741916Sderaadt 
75220741916Sderaadt int
popfile(void)75320741916Sderaadt popfile(void)
75420741916Sderaadt {
75520741916Sderaadt 	struct file	*prev;
75620741916Sderaadt 
757c6004ab9Smpf 	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
75820741916Sderaadt 		prev->errors += file->errors;
759c6004ab9Smpf 
76020741916Sderaadt 	TAILQ_REMOVE(&files, file, entry);
76120741916Sderaadt 	fclose(file->stream);
76220741916Sderaadt 	free(file->name);
76320741916Sderaadt 	free(file);
76420741916Sderaadt 	file = prev;
765c6004ab9Smpf 	return (file ? 0 : EOF);
76620741916Sderaadt }
76720741916Sderaadt 
768ddeeec14Snorby struct ripd_conf *
parse_config(char * filename,int opts)769ddeeec14Snorby parse_config(char *filename, int opts)
770ddeeec14Snorby {
771ddeeec14Snorby 	struct sym	*sym, *next;
772ddeeec14Snorby 
773ddeeec14Snorby 	if ((conf = calloc(1, sizeof(struct ripd_conf))) == NULL)
774ddeeec14Snorby 		fatal("parse_config");
775ddeeec14Snorby 
776ddeeec14Snorby 	bzero(&globaldefs, sizeof(globaldefs));
777ddeeec14Snorby 	defs = &globaldefs;
778ddeeec14Snorby 	TAILQ_INIT(&defs->md_list);
7790d0a18a3Smichele 	defs->cost = DEFAULT_COST;
780ddeeec14Snorby 	defs->auth_type = AUTH_NONE;
781ddeeec14Snorby 	conf->opts = opts;
78246802160Smichele 	conf->options = OPT_SPLIT_POISONED;
7831acb5c27Sremi 	conf->fib_priority = RTP_RIP;
7849bb9ec63Sclaudio 	SIMPLEQ_INIT(&conf->redist_list);
785ddeeec14Snorby 
78620741916Sderaadt 	if ((file = pushfile(filename, !(conf->opts & RIPD_OPT_NOACTION))) == NULL) {
787ddeeec14Snorby 		free(conf);
788ddeeec14Snorby 		return (NULL);
789ddeeec14Snorby 	}
790d6fc1e53Smpf 	topfile = file;
791ddeeec14Snorby 
792ddeeec14Snorby 	yyparse();
79320741916Sderaadt 	errors = file->errors;
79420741916Sderaadt 	popfile();
795ddeeec14Snorby 
796ddeeec14Snorby 	/* Free macros and check which have not been used. */
79746bca67bSkrw 	TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
798ddeeec14Snorby 		if ((conf->opts & RIPD_OPT_VERBOSE2) && !sym->used)
799ddeeec14Snorby 			fprintf(stderr, "warning: macro '%s' not "
800ddeeec14Snorby 			    "used\n", sym->nam);
801ddeeec14Snorby 		if (!sym->persist) {
802ddeeec14Snorby 			free(sym->nam);
803ddeeec14Snorby 			free(sym->val);
80420741916Sderaadt 			TAILQ_REMOVE(&symhead, sym, entry);
805ddeeec14Snorby 			free(sym);
806ddeeec14Snorby 		}
807ddeeec14Snorby 	}
808ddeeec14Snorby 
809ddeeec14Snorby 	/* free global config defaults */
810ddeeec14Snorby 	md_list_clr(&globaldefs.md_list);
811ddeeec14Snorby 
812ddeeec14Snorby 	if (errors) {
813ddeeec14Snorby 		clear_config(conf);
814ddeeec14Snorby 		return (NULL);
815ddeeec14Snorby 	}
816ddeeec14Snorby 
817ddeeec14Snorby 	return (conf);
818ddeeec14Snorby }
819ddeeec14Snorby 
820ddeeec14Snorby int
symset(const char * nam,const char * val,int persist)821ddeeec14Snorby symset(const char *nam, const char *val, int persist)
822ddeeec14Snorby {
823ddeeec14Snorby 	struct sym	*sym;
824ddeeec14Snorby 
82554c95b7aSkrw 	TAILQ_FOREACH(sym, &symhead, entry) {
82654c95b7aSkrw 		if (strcmp(nam, sym->nam) == 0)
82754c95b7aSkrw 			break;
82854c95b7aSkrw 	}
829ddeeec14Snorby 
830ddeeec14Snorby 	if (sym != NULL) {
831ddeeec14Snorby 		if (sym->persist == 1)
832ddeeec14Snorby 			return (0);
833ddeeec14Snorby 		else {
834ddeeec14Snorby 			free(sym->nam);
835ddeeec14Snorby 			free(sym->val);
83620741916Sderaadt 			TAILQ_REMOVE(&symhead, sym, entry);
837ddeeec14Snorby 			free(sym);
838ddeeec14Snorby 		}
839ddeeec14Snorby 	}
840ddeeec14Snorby 	if ((sym = calloc(1, sizeof(*sym))) == NULL)
841ddeeec14Snorby 		return (-1);
842ddeeec14Snorby 
843ddeeec14Snorby 	sym->nam = strdup(nam);
844ddeeec14Snorby 	if (sym->nam == NULL) {
845ddeeec14Snorby 		free(sym);
846ddeeec14Snorby 		return (-1);
847ddeeec14Snorby 	}
848ddeeec14Snorby 	sym->val = strdup(val);
849ddeeec14Snorby 	if (sym->val == NULL) {
850ddeeec14Snorby 		free(sym->nam);
851ddeeec14Snorby 		free(sym);
852ddeeec14Snorby 		return (-1);
853ddeeec14Snorby 	}
854ddeeec14Snorby 	sym->used = 0;
855ddeeec14Snorby 	sym->persist = persist;
85620741916Sderaadt 	TAILQ_INSERT_TAIL(&symhead, sym, entry);
857ddeeec14Snorby 	return (0);
858ddeeec14Snorby }
859ddeeec14Snorby 
860ddeeec14Snorby int
cmdline_symset(char * s)861ddeeec14Snorby cmdline_symset(char *s)
862ddeeec14Snorby {
863ddeeec14Snorby 	char	*sym, *val;
864ddeeec14Snorby 	int	ret;
865ddeeec14Snorby 
866ddeeec14Snorby 	if ((val = strrchr(s, '=')) == NULL)
867ddeeec14Snorby 		return (-1);
868ed1b9eb8Smiko 	sym = strndup(s, val - s);
869ed1b9eb8Smiko 	if (sym == NULL)
870ed1b9eb8Smiko 		errx(1, "%s: strndup", __func__);
871ddeeec14Snorby 	ret = symset(sym, val + 1, 1);
872ddeeec14Snorby 	free(sym);
873ddeeec14Snorby 
874ddeeec14Snorby 	return (ret);
875ddeeec14Snorby }
876ddeeec14Snorby 
877ddeeec14Snorby char *
symget(const char * nam)878ddeeec14Snorby symget(const char *nam)
879ddeeec14Snorby {
880ddeeec14Snorby 	struct sym	*sym;
881ddeeec14Snorby 
88254c95b7aSkrw 	TAILQ_FOREACH(sym, &symhead, entry) {
883ddeeec14Snorby 		if (strcmp(nam, sym->nam) == 0) {
884ddeeec14Snorby 			sym->used = 1;
885ddeeec14Snorby 			return (sym->val);
886ddeeec14Snorby 		}
88754c95b7aSkrw 	}
888ddeeec14Snorby 	return (NULL);
889ddeeec14Snorby }
890ddeeec14Snorby 
891ddeeec14Snorby struct iface *
conf_get_if(struct kif * kif)892ddeeec14Snorby conf_get_if(struct kif *kif)
893ddeeec14Snorby {
894ddeeec14Snorby 	struct iface	*i;
895ddeeec14Snorby 
896ddeeec14Snorby 	LIST_FOREACH(i, &conf->iface_list, entry)
897ddeeec14Snorby 		if (i->ifindex == kif->ifindex) {
898ddeeec14Snorby 			yyerror("interface %s already configured",
899ddeeec14Snorby 			    kif->ifname);
900ddeeec14Snorby 			return (NULL);
901ddeeec14Snorby 		}
902ddeeec14Snorby 
903ddeeec14Snorby 	i = if_new(kif);
904ddeeec14Snorby 	i->auth_keyid = 1;
905ddeeec14Snorby 	i->passive = 0;
906ddeeec14Snorby 
907ddeeec14Snorby 	return (i);
908ddeeec14Snorby }
909ddeeec14Snorby 
910ddeeec14Snorby void
clear_config(struct ripd_conf * xconf)911ddeeec14Snorby clear_config(struct ripd_conf *xconf)
912ddeeec14Snorby {
913ddeeec14Snorby 	struct iface	*i;
914ddeeec14Snorby 
915ddeeec14Snorby 	while ((i = LIST_FIRST(&conf->iface_list)) != NULL) {
916ddeeec14Snorby 		LIST_REMOVE(i, entry);
917ddeeec14Snorby 		if_del(i);
918ddeeec14Snorby 	}
919ddeeec14Snorby 
920ddeeec14Snorby 	free(xconf);
921ddeeec14Snorby }
9229bb9ec63Sclaudio 
9239bb9ec63Sclaudio int
host(const char * s,struct in_addr * addr,struct in_addr * mask)9249bb9ec63Sclaudio host(const char *s, struct in_addr *addr, struct in_addr *mask)
9259bb9ec63Sclaudio {
9269bb9ec63Sclaudio 	struct in_addr		 ina;
9279bb9ec63Sclaudio 	int			 bits = 32;
9289bb9ec63Sclaudio 
9299bb9ec63Sclaudio 	bzero(&ina, sizeof(struct in_addr));
9309bb9ec63Sclaudio 	if (strrchr(s, '/') != NULL) {
9319bb9ec63Sclaudio 		if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)
9329bb9ec63Sclaudio 			return (0);
9339bb9ec63Sclaudio 	} else {
9349bb9ec63Sclaudio 		if (inet_pton(AF_INET, s, &ina) != 1)
9359bb9ec63Sclaudio 			return (0);
9369bb9ec63Sclaudio 	}
9379bb9ec63Sclaudio 
9389bb9ec63Sclaudio 	addr->s_addr = ina.s_addr;
9399bb9ec63Sclaudio 	mask->s_addr = prefixlen2mask(bits);
9409bb9ec63Sclaudio 
9419bb9ec63Sclaudio 	return (1);
9429bb9ec63Sclaudio }
943