1/*	$OpenBSD: parse.y,v 1.72 2021/10/15 15:01:28 naddy Exp $ */
2
3/*
4 * Copyright (c) 2013, 2015, 2016 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
6 * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
7 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
8 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
9 * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
10 * Copyright (c) 2001 Theo de Raadt.  All rights reserved.
11 *
12 * Permission to use, copy, modify, and distribute this software for any
13 * purpose with or without fee is hereby granted, provided that the above
14 * copyright notice and this permission notice appear in all copies.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
17 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
19 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
22 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 */
24
25%{
26#include <sys/stat.h>
27#include <sys/types.h>
28#include <sys/socket.h>
29#include <arpa/inet.h>
30#include <ctype.h>
31#include <err.h>
32#include <unistd.h>
33#include <ifaddrs.h>
34#include <net/if_types.h>
35#include <limits.h>
36#include <stdio.h>
37#include <syslog.h>
38#include <errno.h>
39#include <netdb.h>
40
41#include "ldpd.h"
42#include "ldpe.h"
43#include "lde.h"
44#include "log.h"
45
46struct file {
47	TAILQ_ENTRY(file)	 entry;
48	FILE			*stream;
49	char			*name;
50	size_t			 ungetpos;
51	size_t			 ungetsize;
52	u_char			*ungetbuf;
53	int			 eof_reached;
54	int			 lineno;
55	int			 errors;
56};
57TAILQ_HEAD(files, file);
58
59struct sym {
60	TAILQ_ENTRY(sym)	 entry;
61	int			 used;
62	int			 persist;
63	char			*nam;
64	char			*val;
65};
66TAILQ_HEAD(symhead, sym);
67
68struct config_defaults {
69	uint16_t	keepalive;
70	uint16_t	lhello_holdtime;
71	uint16_t	lhello_interval;
72	uint16_t	thello_holdtime;
73	uint16_t	thello_interval;
74	union ldpd_addr	trans_addr;
75	int		afflags;
76	uint8_t		pwflags;
77};
78
79typedef struct {
80	union {
81		int64_t		 number;
82		char		*string;
83		struct in_addr	 routerid;
84		struct ldp_auth	*auth;
85	} v;
86	int lineno;
87} YYSTYPE;
88
89static int		 yyerror(const char *, ...)
90    __attribute__((__format__ (printf, 1, 2)))
91    __attribute__((__nonnull__ (1)));
92static int		 kw_cmp(const void *, const void *);
93static int		 lookup(char *);
94static int		 igetc(void);
95static int		 lgetc(int);
96void			 lungetc(int);
97static int		 findeol(void);
98static int		 yylex(void);
99static int		 check_file_secrecy(int, const char *);
100static struct file	*pushfile(const char *, int);
101static int		 popfile(void);
102static int		 yyparse(void);
103static int		 symset(const char *, const char *, int);
104static char		*symget(const char *);
105static struct iface	*conf_get_if(struct kif *);
106static struct tnbr	*conf_get_tnbr(union ldpd_addr *);
107static struct nbr_params *conf_get_nbrp(struct in_addr);
108static struct l2vpn	*conf_get_l2vpn(char *);
109static struct l2vpn_if	*conf_get_l2vpn_if(struct l2vpn *, struct kif *);
110static struct l2vpn_pw	*conf_get_l2vpn_pw(struct l2vpn *, struct kif *);
111int			 conf_check_rdomain(unsigned int);
112static void		 clear_config(struct ldpd_conf *xconf);
113static uint32_t		 get_rtr_id(void);
114static int		 get_address(const char *, union ldpd_addr *);
115static int		 get_af_address(const char *, int *, union ldpd_addr *);
116static int		 str2key(char *, const char *, int);
117
118static struct file		*file, *topfile;
119static struct files		 files = TAILQ_HEAD_INITIALIZER(files);
120static struct symhead		 symhead = TAILQ_HEAD_INITIALIZER(symhead);
121static struct ldpd_conf		*conf;
122static int			 errors;
123
124static int			 af;
125static struct ldpd_af_conf	*af_conf;
126static struct iface		*iface;
127static struct iface_af		*ia;
128static struct tnbr		*tnbr;
129static struct nbr_params	*nbrp;
130static struct l2vpn		*l2vpn;
131static struct l2vpn_pw		*pw;
132
133static struct config_defaults	 globaldefs;
134static struct config_defaults	 afdefs;
135static struct config_defaults	 ifacedefs;
136static struct config_defaults	 tnbrdefs;
137static struct config_defaults	 pwdefs;
138static struct config_defaults	*defs;
139
140%}
141
142%token	INTERFACE TNEIGHBOR ROUTERID FIBUPDATE RDOMAIN EXPNULL
143%token	LHELLOHOLDTIME LHELLOINTERVAL
144%token	THELLOHOLDTIME THELLOINTERVAL
145%token	THELLOACCEPT AF IPV4 IPV6 INET INET6 GTSMENABLE GTSMHOPS
146%token	KEEPALIVE TRANSADDRESS TRANSPREFERENCE DSCISCOINTEROP
147%token	NEIGHBOR
148%token	TCP MD5SIG PASSWORD KEY
149%token	L2VPN TYPE VPLS PWTYPE MTU BRIDGE
150%token	ETHERNET ETHERNETTAGGED STATUSTLV CONTROLWORD
151%token	PSEUDOWIRE NEIGHBORID NEIGHBORADDR PWID
152%token	EXTTAG
153%token	YES NO
154%token	INCLUDE
155%token	ERROR
156%token	<v.string>	STRING
157%token	<v.number>	NUMBER
158%type	<v.number>	yesno ldp_af l2vpn_type pw_type
159%type	<v.string>	string
160%type	<v.routerid>	routerid
161%type	<v.auth>	auth tcpmd5 optnbrprefix
162
163%%
164
165grammar		: /* empty */
166		| grammar include '\n'
167		| grammar '\n'
168		| grammar conf_main '\n'
169		| grammar varset '\n'
170		| grammar af '\n'
171		| grammar neighbor '\n'
172		| grammar l2vpn '\n'
173		| grammar error '\n'		{ file->errors++; }
174		;
175
176include		: INCLUDE STRING		{
177			struct file	*nfile;
178
179			if ((nfile = pushfile($2,
180			    !(global.cmd_opts & LDPD_OPT_NOACTION))) == NULL) {
181				yyerror("failed to include file %s", $2);
182				free($2);
183				YYERROR;
184			}
185			free($2);
186
187			file = nfile;
188			lungetc('\n');
189		}
190		;
191
192string		: string STRING	{
193			if (asprintf(&$$, "%s %s", $1, $2) == -1) {
194				free($1);
195				free($2);
196				yyerror("string: asprintf");
197				YYERROR;
198			}
199			free($1);
200			free($2);
201		}
202		| STRING
203		;
204
205routerid	: STRING {
206			if (!inet_aton($1, &$$)) {
207				yyerror("%s: error parsing router id", $1);
208				free($1);
209				YYERROR;
210			}
211			if (bad_addr_v4($$)) {
212				yyerror("%s: invalid router id", $1);
213				free($1);
214				YYERROR;
215			}
216			free($1);
217
218			break;
219		}
220		;
221
222yesno		: YES	{ $$ = 1; }
223		| NO	{ $$ = 0; }
224		;
225
226ldp_af		: IPV4	{ $$ = AF_INET; }
227		| IPV6	{ $$ = AF_INET6; }
228		;
229
230l2vpn_type	: VPLS	{ $$ = L2VPN_TYPE_VPLS; }
231		;
232
233pw_type		: ETHERNET		{ $$ = PW_TYPE_ETHERNET; }
234		| ETHERNETTAGGED	{ $$ = PW_TYPE_ETHERNET_TAGGED; }
235		;
236
237varset		: STRING '=' string {
238			char *s = $1;
239			if (global.cmd_opts & LDPD_OPT_VERBOSE)
240				printf("%s = \"%s\"\n", $1, $3);
241			while (*s++) {
242				if (isspace((unsigned char)*s)) {
243					yyerror("macro name cannot contain "
244					    "whitespace");
245					free($1);
246					free($3);
247					YYERROR;
248				}
249			}
250			if (symset($1, $3, 0) == -1)
251				fatal("cannot store variable");
252			free($1);
253			free($3);
254		}
255		;
256
257conf_main	: ROUTERID routerid {
258			conf->rtr_id = $2;
259		}
260		| FIBUPDATE yesno {
261			if ($2 == 0)
262				conf->flags |= F_LDPD_NO_FIB_UPDATE;
263			else
264				conf->flags &= ~F_LDPD_NO_FIB_UPDATE;
265		}
266		| RDOMAIN NUMBER {
267			if ($2 < 0 || $2 > RT_TABLEID_MAX) {
268				yyerror("invalid rdomain");
269				YYERROR;
270			}
271			conf->rdomain = $2;
272		}
273		| TRANSPREFERENCE ldp_af {
274			conf->trans_pref = $2;
275
276			switch (conf->trans_pref) {
277			case AF_INET:
278				conf->trans_pref = DUAL_STACK_LDPOV4;
279				break;
280			case AF_INET6:
281				conf->trans_pref = DUAL_STACK_LDPOV6;
282				break;
283			default:
284				yyerror("invalid address-family");
285				YYERROR;
286			}
287		}
288		| DSCISCOINTEROP yesno {
289			if ($2 == 1)
290				conf->flags |= F_LDPD_DS_CISCO_INTEROP;
291			else
292				conf->flags &= ~F_LDPD_DS_CISCO_INTEROP;
293		}
294		| auth {
295			LIST_INSERT_HEAD(&conf->auth_list, $1, entry);
296		}
297		| af_defaults
298		| iface_defaults
299		| tnbr_defaults
300		;
301
302af		: AF ldp_af {
303			af = $2;
304			switch (af) {
305			case AF_INET:
306				af_conf = &conf->ipv4;
307				break;
308			case AF_INET6:
309				af_conf = &conf->ipv6;
310				break;
311			default:
312				yyerror("invalid address-family");
313				YYERROR;
314			}
315
316			afdefs = *defs;
317			defs = &afdefs;
318		} af_block {
319			af_conf->keepalive = defs->keepalive;
320			af_conf->thello_holdtime = defs->thello_holdtime;
321			af_conf->thello_interval = defs->thello_interval;
322			af_conf->flags = defs->afflags;
323			af_conf->flags |= F_LDPD_AF_ENABLED;
324			af_conf = NULL;
325			af = AF_UNSPEC;
326			defs = &globaldefs;
327		}
328		;
329
330af_block	: '{' optnl afopts_l '}'
331		| '{' optnl '}'
332		|
333		;
334
335afopts_l	: afopts_l afoptsl nl
336		| afoptsl optnl
337		;
338
339afoptsl		:  TRANSADDRESS STRING {
340			if (get_address($2, &af_conf->trans_addr) == -1) {
341				yyerror("error parsing transport-address");
342				free($2);
343				YYERROR;
344			}
345			free($2);
346			if (bad_addr(af, &af_conf->trans_addr)) {
347				yyerror("invalid transport-address");
348				YYERROR;
349			}
350			if (af == AF_INET6 &&
351			   IN6_IS_SCOPE_EMBED(&af_conf->trans_addr.v6)) {
352				yyerror("ipv6 transport-address can not be "
353				    "link-local");
354				YYERROR;
355			}
356		}
357		| GTSMENABLE yesno {
358			if ($2 == 0)
359				defs->afflags |= F_LDPD_AF_NO_GTSM;
360		}
361		| af_defaults
362		| iface_defaults
363		| tnbr_defaults
364		| interface
365		| tneighbor
366		;
367
368af_defaults	: THELLOACCEPT yesno {
369			if ($2 == 0)
370				defs->afflags &= ~F_LDPD_AF_THELLO_ACCEPT;
371			else
372				defs->afflags |= F_LDPD_AF_THELLO_ACCEPT;
373		}
374		| EXPNULL yesno {
375			if ($2 == 0)
376				defs->afflags &= ~F_LDPD_AF_EXPNULL;
377			else
378				defs->afflags |= F_LDPD_AF_EXPNULL;
379		}
380		| KEEPALIVE NUMBER {
381			if ($2 < MIN_KEEPALIVE || $2 > MAX_KEEPALIVE) {
382				yyerror("keepalive out of range (%d-%d)",
383				    MIN_KEEPALIVE, MAX_KEEPALIVE);
384				YYERROR;
385			}
386			defs->keepalive = $2;
387		}
388		;
389
390iface_defaults	: LHELLOHOLDTIME NUMBER {
391			if ($2 < MIN_HOLDTIME || $2 > MAX_HOLDTIME) {
392				yyerror("hello-holdtime out of range (%d-%d)",
393				    MIN_HOLDTIME, MAX_HOLDTIME);
394				YYERROR;
395			}
396			defs->lhello_holdtime = $2;
397		}
398		| LHELLOINTERVAL NUMBER {
399			if ($2 < MIN_HELLO_INTERVAL ||
400			    $2 > MAX_HELLO_INTERVAL) {
401				yyerror("hello-interval out of range (%d-%d)",
402				    MIN_HELLO_INTERVAL, MAX_HELLO_INTERVAL);
403				YYERROR;
404			}
405			defs->lhello_interval = $2;
406		}
407		;
408
409tnbr_defaults	: THELLOHOLDTIME NUMBER {
410			if ($2 < MIN_HOLDTIME || $2 > MAX_HOLDTIME) {
411				yyerror("hello-holdtime out of range (%d-%d)",
412				    MIN_HOLDTIME, MAX_HOLDTIME);
413				YYERROR;
414			}
415			defs->thello_holdtime = $2;
416		}
417		| THELLOINTERVAL NUMBER {
418			if ($2 < MIN_HELLO_INTERVAL ||
419			    $2 > MAX_HELLO_INTERVAL) {
420				yyerror("hello-interval out of range (%d-%d)",
421				    MIN_HELLO_INTERVAL, MAX_HELLO_INTERVAL);
422				YYERROR;
423			}
424			defs->thello_interval = $2;
425		}
426		;
427
428tcpmd5		: TCP MD5SIG PASSWORD STRING {
429			size_t len;
430
431			$$ = calloc(1, sizeof(*$$));
432			if ($$ == NULL) {
433				free($4);
434				yyerror("unable to allocate md5 key");
435				YYERROR;
436			}
437
438			len = strlen($4);
439			if (len > sizeof($$->md5key)) {
440				free($$);
441				free($4);
442				yyerror("tcp md5sig password too long: "
443				    "max %zu", sizeof($$->md5key));
444				YYERROR;
445			}
446
447			memcpy($$->md5key, $4, len);
448			$$->md5key_len = len;
449
450			free($4);
451		}
452		| TCP MD5SIG KEY STRING {
453			int len;
454
455			$$ = calloc(1, sizeof(*$$));
456			if ($$ == NULL) {
457				free($4);
458				yyerror("unable to allocate md5 key");
459				YYERROR;
460			}
461
462			len = str2key($$->md5key, $4, sizeof($$->md5key));
463			if (len == -1) {
464				free($$);
465				free($4);
466				yyerror("invalid hex string");
467				YYERROR;
468			}
469			if ((size_t)len > sizeof($$->md5key_len)) {
470				free($$);
471				free($4);
472				yyerror("tcp md5sig key too long: %d "
473				    "max %zu", len, sizeof($$->md5key));
474				YYERROR;
475			}
476
477			$$->md5key_len = len;
478
479			free($4);
480		}
481		| NO TCP MD5SIG {
482			$$ = calloc(1, sizeof(*$$));
483			if ($$ == NULL) {
484				yyerror("unable to allocate no md5 key");
485				YYERROR;
486			}
487			$$->md5key_len = 0;
488		}
489		;
490
491optnbrprefix	: STRING {
492			$$ = calloc(1, sizeof(*$$));
493			if ($$ == NULL) {
494				yyerror("unable to allocate auth");
495				free($1);
496				YYERROR;
497			}
498
499			$$->idlen = inet_net_pton(AF_INET, $1,
500			    &$$->id, sizeof($$->id));
501			if ($$->idlen == -1) {
502				yyerror("%s: %s", $1, strerror(errno));
503				free($1);
504				YYERROR;
505			}
506		}
507		| /* empty */ {
508			$$ = NULL;
509		}
510		;
511
512auth		: tcpmd5 optnbrprefix {
513			$$ = $1;
514			if ($2 != NULL) {
515				$$->id = $2->id;
516				$$->idlen = $2->idlen;
517				free($2);
518			} else {
519				$$->id.s_addr = 0;
520				$$->idlen = 0;
521			}
522		}
523		;
524
525nbr_opts	: KEEPALIVE NUMBER {
526			if ($2 < MIN_KEEPALIVE || $2 > MAX_KEEPALIVE) {
527				yyerror("keepalive out of range (%d-%d)",
528				    MIN_KEEPALIVE, MAX_KEEPALIVE);
529				YYERROR;
530			}
531			nbrp->keepalive = $2;
532			nbrp->flags |= F_NBRP_KEEPALIVE;
533		}
534		| tcpmd5 {
535			/* this is syntactic sugar... */
536			$1->id = nbrp->lsr_id;
537			$1->idlen = 32;
538			LIST_INSERT_HEAD(&conf->auth_list, $1, entry);
539		}
540		| GTSMENABLE yesno {
541			nbrp->flags |= F_NBRP_GTSM;
542			nbrp->gtsm_enabled = $2;
543		}
544		| GTSMHOPS NUMBER {
545			if ($2 < 1 || $2 > 255) {
546				yyerror("invalid number of hops %lld", $2);
547				YYERROR;
548			}
549			nbrp->gtsm_hops = $2;
550			nbrp->flags |= F_NBRP_GTSM_HOPS;
551		}
552		;
553
554pw_defaults	: STATUSTLV yesno {
555			if ($2 == 1)
556				defs->pwflags |= F_PW_STATUSTLV_CONF;
557			else
558				defs->pwflags &= ~F_PW_STATUSTLV_CONF;
559		}
560		| CONTROLWORD yesno {
561			if ($2 == 1)
562				defs->pwflags |= F_PW_CWORD_CONF;
563			else
564				defs->pwflags &= ~F_PW_CWORD_CONF;
565		}
566		;
567
568pwopts		: PWID NUMBER {
569			if ($2 < MIN_PWID_ID ||
570			    $2 > MAX_PWID_ID) {
571				yyerror("pw-id out of range (%d-%d)",
572				    MIN_PWID_ID, MAX_PWID_ID);
573				YYERROR;
574			}
575
576			pw->pwid = $2;
577		}
578		| NEIGHBORID routerid {
579			pw->lsr_id = $2;
580		}
581		| NEIGHBORADDR STRING {
582			int		 family;
583			union ldpd_addr	 addr;
584
585			if (get_af_address($2, &family, &addr) == -1) {
586				yyerror("error parsing neighbor address");
587				free($2);
588				YYERROR;
589			}
590			free($2);
591			if (bad_addr(family, &addr)) {
592				yyerror("invalid neighbor address");
593				YYERROR;
594			}
595			if (family == AF_INET6 &&
596			    IN6_IS_SCOPE_EMBED(&addr.v6)) {
597				yyerror("neighbor address can not be "
598				    "link-local");
599				YYERROR;
600			}
601
602			pw->af = family;
603			pw->addr = addr;
604		}
605		| pw_defaults
606		;
607
608pseudowire	: PSEUDOWIRE STRING {
609			struct kif	*kif;
610
611			if ((kif = kif_findname($2)) == NULL) {
612				yyerror("unknown interface %s", $2);
613				free($2);
614				YYERROR;
615			}
616			free($2);
617
618			if (kif->if_type != IFT_MPLSTUNNEL &&
619			    kmpw_find(kif->ifname) == -1) {
620				yyerror("unsupported interface type on "
621				    "interface %s", kif->ifname);
622				YYERROR;
623			}
624
625			pw = conf_get_l2vpn_pw(l2vpn, kif);
626			if (pw == NULL)
627				YYERROR;
628
629			pwdefs = *defs;
630			defs = &pwdefs;
631		} pw_block {
632			struct l2vpn	*l;
633			struct l2vpn_pw *p;
634
635			/* check for errors */
636			if (pw->pwid == 0) {
637				yyerror("missing pseudowire id");
638				YYERROR;
639			}
640			if (pw->lsr_id.s_addr == INADDR_ANY) {
641				yyerror("missing pseudowire neighbor-id");
642				YYERROR;
643			}
644			LIST_FOREACH(l, &conf->l2vpn_list, entry) {
645				LIST_FOREACH(p, &l->pw_list, entry) {
646					if (pw != p &&
647					    pw->pwid == p->pwid &&
648					    pw->af == p->af &&
649					    pw->lsr_id.s_addr ==
650					    p->lsr_id.s_addr) {
651						yyerror("pseudowire already "
652						    "configured");
653						YYERROR;
654					}
655				}
656			}
657
658			/*
659			 * If the neighbor address is not specified, use the
660			 * neighbor id.
661			 */
662			if (pw->af == AF_UNSPEC) {
663				pw->af = AF_INET;
664				pw->addr.v4 = pw->lsr_id;
665			}
666
667			pw->flags = defs->pwflags;
668			pw = NULL;
669			defs = &globaldefs;
670		}
671		;
672
673pw_block	: '{' optnl pwopts_l '}'
674		| '{' optnl '}'
675		| /* nothing */
676		;
677
678pwopts_l	: pwopts_l pwopts nl
679		| pwopts optnl
680		;
681
682l2vpnopts	: PWTYPE pw_type {
683			l2vpn->pw_type = $2;
684		}
685		| MTU NUMBER {
686			if ($2 < MIN_L2VPN_MTU ||
687			    $2 > MAX_L2VPN_MTU) {
688				yyerror("l2vpn mtu out of range (%d-%d)",
689				    MIN_L2VPN_MTU, MAX_L2VPN_MTU);
690				YYERROR;
691			}
692			l2vpn->mtu = $2;
693		}
694		| pw_defaults
695		| BRIDGE STRING {
696			struct l2vpn	 *l;
697			struct kif	 *kif;
698
699			if ((kif = kif_findname($2)) == NULL) {
700				yyerror("unknown interface %s", $2);
701				free($2);
702				YYERROR;
703			}
704			free($2);
705
706			if (l2vpn->br_ifindex != 0) {
707				yyerror("bridge interface cannot be "
708				    "redefined on l2vpn %s", l2vpn->name);
709				YYERROR;
710			}
711
712			if (kif->if_type != IFT_BRIDGE) {
713				yyerror("unsupported interface type on "
714				    "interface %s", kif->ifname);
715				YYERROR;
716			}
717
718			LIST_FOREACH(l, &conf->l2vpn_list, entry) {
719				if (l->br_ifindex == kif->ifindex) {
720					yyerror("bridge %s is already being "
721					    "used by l2vpn %s", kif->ifname,
722					    l->name);
723					YYERROR;
724				}
725			}
726
727			l2vpn->br_ifindex = kif->ifindex;
728			strlcpy(l2vpn->br_ifname, kif->ifname,
729			    sizeof(l2vpn->br_ifname));
730		}
731		| INTERFACE STRING {
732			struct kif	*kif;
733			struct l2vpn_if	*lif;
734
735			if ((kif = kif_findname($2)) == NULL) {
736				yyerror("unknown interface %s", $2);
737				free($2);
738				YYERROR;
739			}
740			free($2);
741
742			lif = conf_get_l2vpn_if(l2vpn, kif);
743			if (lif == NULL)
744				YYERROR;
745		}
746		| pseudowire
747		;
748
749optnl		: '\n' optnl
750		|
751		;
752
753nl		: '\n' optnl		/* one newline or more */
754		;
755
756interface	: INTERFACE STRING	{
757			struct kif	*kif;
758
759			if ((kif = kif_findname($2)) == NULL) {
760				yyerror("unknown interface %s", $2);
761				free($2);
762				YYERROR;
763			}
764			free($2);
765
766			iface = conf_get_if(kif);
767			if (iface == NULL)
768				YYERROR;
769
770			ia = iface_af_get(iface, af);
771			if (ia->enabled) {
772				yyerror("interface %s already configured for "
773				    "address-family %s", kif->ifname,
774				    af_name(af));
775				YYERROR;
776			}
777			ia->enabled = 1;
778
779			ifacedefs = *defs;
780			defs = &ifacedefs;
781		} interface_block {
782			ia->hello_holdtime = defs->lhello_holdtime;
783			ia->hello_interval = defs->lhello_interval;
784			iface = NULL;
785			defs = &afdefs;
786		}
787		;
788
789interface_block	: '{' optnl interfaceopts_l '}'
790		| '{' optnl '}'
791		| /* nothing */
792		;
793
794interfaceopts_l	: interfaceopts_l iface_defaults nl
795		| iface_defaults optnl
796		;
797
798tneighbor	: TNEIGHBOR STRING	{
799			union ldpd_addr	 addr;
800
801			if (get_address($2, &addr) == -1) {
802				yyerror("error parsing targeted-neighbor "
803				    "address");
804				free($2);
805				YYERROR;
806			}
807			free($2);
808			if (bad_addr(af, &addr)) {
809				yyerror("invalid targeted-neighbor address");
810				YYERROR;
811			}
812			if (af == AF_INET6 &&
813			   IN6_IS_SCOPE_EMBED(&addr.v6)) {
814				yyerror("targeted-neighbor address can not be "
815				    "link-local");
816				YYERROR;
817			}
818
819			tnbr = conf_get_tnbr(&addr);
820			if (tnbr == NULL)
821				YYERROR;
822
823			tnbrdefs = *defs;
824			defs = &tnbrdefs;
825		} tneighbor_block {
826			tnbr->hello_holdtime = defs->thello_holdtime;
827			tnbr->hello_interval = defs->thello_interval;
828			tnbr = NULL;
829			defs = &afdefs;
830		}
831		;
832
833tneighbor_block	: '{' optnl tneighboropts_l '}'
834		| '{' optnl '}'
835		| /* nothing */
836		;
837
838tneighboropts_l	: tneighboropts_l tnbr_defaults nl
839		| tnbr_defaults optnl
840		;
841
842neighbor	: NEIGHBOR routerid	{
843			nbrp = conf_get_nbrp($2);
844			if (nbrp == NULL)
845				YYERROR;
846		} neighbor_block {
847			nbrp = NULL;
848		}
849		;
850
851neighbor_block	: '{' optnl neighboropts_l '}'
852		| '{' optnl '}'
853		| /* nothing */
854		;
855
856neighboropts_l	: neighboropts_l nbr_opts nl
857		| nbr_opts optnl
858		;
859
860l2vpn		: L2VPN STRING TYPE l2vpn_type {
861			l2vpn = conf_get_l2vpn($2);
862			if (l2vpn == NULL)
863				YYERROR;
864			l2vpn->type = $4;
865		} l2vpn_block {
866			l2vpn = NULL;
867		}
868		;
869
870l2vpn_block	: '{' optnl l2vpnopts_l '}'
871		| '{' optnl '}'
872		| /* nothing */
873		;
874
875l2vpnopts_l	: l2vpnopts_l l2vpnopts nl
876		| l2vpnopts optnl
877		;
878
879%%
880
881struct keywords {
882	const char	*k_name;
883	int		 k_val;
884};
885
886static int
887yyerror(const char *fmt, ...)
888{
889	va_list		 ap;
890	char		*msg;
891
892	file->errors++;
893	va_start(ap, fmt);
894	if (vasprintf(&msg, fmt, ap) == -1)
895		fatalx("yyerror vasprintf");
896	va_end(ap);
897	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
898	free(msg);
899	return (0);
900}
901
902static int
903kw_cmp(const void *k, const void *e)
904{
905	return (strcmp(k, ((const struct keywords *)e)->k_name));
906}
907
908static int
909lookup(char *s)
910{
911	/* this has to be sorted always */
912	static const struct keywords keywords[] = {
913		{"address-family",		AF},
914		{"bridge",			BRIDGE},
915		{"control-word",		CONTROLWORD},
916		{"ds-cisco-interop",		DSCISCOINTEROP},
917		{"ethernet",			ETHERNET},
918		{"ethernet-tagged",		ETHERNETTAGGED},
919		{"explicit-null",		EXPNULL},
920		{"fib-update",			FIBUPDATE},
921		{"gtsm-enable",			GTSMENABLE},
922		{"gtsm-hops",			GTSMHOPS},
923		{"include",			INCLUDE},
924		{"inet",			INET},
925		{"inet6",			INET6},
926		{"interface",			INTERFACE},
927		{"ipv4",			IPV4},
928		{"ipv6",			IPV6},
929		{"keepalive",			KEEPALIVE},
930		{"key",				KEY},
931		{"l2vpn",			L2VPN},
932		{"link-hello-holdtime",		LHELLOHOLDTIME},
933		{"link-hello-interval",		LHELLOINTERVAL},
934		{"md5sig",			MD5SIG},
935		{"mtu",				MTU},
936		{"neighbor",			NEIGHBOR},
937		{"neighbor-addr",		NEIGHBORADDR},
938		{"neighbor-id",			NEIGHBORID},
939		{"no",				NO},
940		{"password",			PASSWORD},
941		{"pseudowire",			PSEUDOWIRE},
942		{"pw-id",			PWID},
943		{"pw-type",			PWTYPE},
944		{"rdomain",			RDOMAIN},
945		{"router-id",			ROUTERID},
946		{"status-tlv",			STATUSTLV},
947		{"targeted-hello-accept",	THELLOACCEPT},
948		{"targeted-hello-holdtime",	THELLOHOLDTIME},
949		{"targeted-hello-interval",	THELLOINTERVAL},
950		{"targeted-neighbor",		TNEIGHBOR},
951		{"tcp",				TCP},
952		{"transport-address",		TRANSADDRESS},
953		{"transport-preference",	TRANSPREFERENCE},
954		{"type",			TYPE},
955		{"vpls",			VPLS},
956		{"yes",				YES}
957	};
958	const struct keywords	*p;
959
960	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
961	    sizeof(keywords[0]), kw_cmp);
962
963	if (p)
964		return (p->k_val);
965	else
966		return (STRING);
967}
968
969#define START_EXPAND	1
970#define DONE_EXPAND	2
971
972static int	expanding;
973
974int
975igetc(void)
976{
977	int	c;
978
979	while (1) {
980		if (file->ungetpos > 0)
981			c = file->ungetbuf[--file->ungetpos];
982		else
983			c = getc(file->stream);
984
985		if (c == START_EXPAND)
986			expanding = 1;
987		else if (c == DONE_EXPAND)
988			expanding = 0;
989		else
990			break;
991	}
992	return (c);
993}
994
995static int
996lgetc(int quotec)
997{
998	int		c, next;
999
1000	if (quotec) {
1001		if ((c = igetc()) == EOF) {
1002			yyerror("reached end of file while parsing "
1003			    "quoted string");
1004			if (file == topfile || popfile() == EOF)
1005				return (EOF);
1006			return (quotec);
1007		}
1008		return (c);
1009	}
1010
1011	while ((c = igetc()) == '\\') {
1012		next = igetc();
1013		if (next != '\n') {
1014			c = next;
1015			break;
1016		}
1017		yylval.lineno = file->lineno;
1018		file->lineno++;
1019	}
1020
1021	if (c == EOF) {
1022		/*
1023		 * Fake EOL when hit EOF for the first time. This gets line
1024		 * count right if last line in included file is syntactically
1025		 * invalid and has no newline.
1026		 */
1027		if (file->eof_reached == 0) {
1028			file->eof_reached = 1;
1029			return ('\n');
1030		}
1031		while (c == EOF) {
1032			if (file == topfile || popfile() == EOF)
1033				return (EOF);
1034			c = igetc();
1035		}
1036	}
1037	return (c);
1038}
1039
1040void
1041lungetc(int c)
1042{
1043	if (c == EOF)
1044		return;
1045
1046	if (file->ungetpos >= file->ungetsize) {
1047		void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
1048		if (p == NULL)
1049			err(1, "%s", __func__);
1050		file->ungetbuf = p;
1051		file->ungetsize *= 2;
1052	}
1053	file->ungetbuf[file->ungetpos++] = c;
1054}
1055
1056static int
1057findeol(void)
1058{
1059	int	c;
1060
1061	/* skip to either EOF or the first real EOL */
1062	while (1) {
1063		c = lgetc(0);
1064		if (c == '\n') {
1065			file->lineno++;
1066			break;
1067		}
1068		if (c == EOF)
1069			break;
1070	}
1071	return (ERROR);
1072}
1073
1074static int
1075yylex(void)
1076{
1077	char	 buf[8096];
1078	char	*p, *val;
1079	int	 quotec, next, c;
1080	int	 token;
1081
1082 top:
1083	p = buf;
1084	while ((c = lgetc(0)) == ' ' || c == '\t')
1085		; /* nothing */
1086
1087	yylval.lineno = file->lineno;
1088	if (c == '#')
1089		while ((c = lgetc(0)) != '\n' && c != EOF)
1090			; /* nothing */
1091	if (c == '$' && !expanding) {
1092		while (1) {
1093			if ((c = lgetc(0)) == EOF)
1094				return (0);
1095
1096			if (p + 1 >= buf + sizeof(buf) - 1) {
1097				yyerror("string too long");
1098				return (findeol());
1099			}
1100			if (isalnum(c) || c == '_') {
1101				*p++ = c;
1102				continue;
1103			}
1104			*p = '\0';
1105			lungetc(c);
1106			break;
1107		}
1108		val = symget(buf);
1109		if (val == NULL) {
1110			yyerror("macro '%s' not defined", buf);
1111			return (findeol());
1112		}
1113		p = val + strlen(val) - 1;
1114		lungetc(DONE_EXPAND);
1115		while (p >= val) {
1116			lungetc((unsigned char)*p);
1117			p--;
1118		}
1119		lungetc(START_EXPAND);
1120		goto top;
1121	}
1122
1123	switch (c) {
1124	case '\'':
1125	case '"':
1126		quotec = c;
1127		while (1) {
1128			if ((c = lgetc(quotec)) == EOF)
1129				return (0);
1130			if (c == '\n') {
1131				file->lineno++;
1132				continue;
1133			} else if (c == '\\') {
1134				if ((next = lgetc(quotec)) == EOF)
1135					return (0);
1136				if (next == quotec || next == ' ' ||
1137				    next == '\t')
1138					c = next;
1139				else if (next == '\n') {
1140					file->lineno++;
1141					continue;
1142				} else
1143					lungetc(next);
1144			} else if (c == quotec) {
1145				*p = '\0';
1146				break;
1147			} else if (c == '\0') {
1148				yyerror("syntax error");
1149				return (findeol());
1150			}
1151			if (p + 1 >= buf + sizeof(buf) - 1) {
1152				yyerror("string too long");
1153				return (findeol());
1154			}
1155			*p++ = c;
1156		}
1157		yylval.v.string = strdup(buf);
1158		if (yylval.v.string == NULL)
1159			err(1, "%s", __func__);
1160		return (STRING);
1161	}
1162
1163#define allowed_to_end_number(x) \
1164	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
1165
1166	if (c == '-' || isdigit(c)) {
1167		do {
1168			*p++ = c;
1169			if ((size_t)(p-buf) >= sizeof(buf)) {
1170				yyerror("string too long");
1171				return (findeol());
1172			}
1173		} while ((c = lgetc(0)) != EOF && isdigit(c));
1174		lungetc(c);
1175		if (p == buf + 1 && buf[0] == '-')
1176			goto nodigits;
1177		if (c == EOF || allowed_to_end_number(c)) {
1178			const char *errstr = NULL;
1179
1180			*p = '\0';
1181			yylval.v.number = strtonum(buf, LLONG_MIN,
1182			    LLONG_MAX, &errstr);
1183			if (errstr) {
1184				yyerror("\"%s\" invalid number: %s",
1185				    buf, errstr);
1186				return (findeol());
1187			}
1188			return (NUMBER);
1189		} else {
1190 nodigits:
1191			while (p > buf + 1)
1192				lungetc((unsigned char)*--p);
1193			c = (unsigned char)*--p;
1194			if (c == '-')
1195				return (c);
1196		}
1197	}
1198
1199#define allowed_in_string(x) \
1200	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
1201	x != '{' && x != '}' && \
1202	x != '!' && x != '=' && x != '#' && \
1203	x != ','))
1204
1205	if (isalnum(c) || c == ':' || c == '_') {
1206		do {
1207			*p++ = c;
1208			if ((size_t)(p-buf) >= sizeof(buf)) {
1209				yyerror("string too long");
1210				return (findeol());
1211			}
1212		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
1213		lungetc(c);
1214		*p = '\0';
1215		if ((token = lookup(buf)) == STRING)
1216			if ((yylval.v.string = strdup(buf)) == NULL)
1217				err(1, "%s", __func__);
1218		return (token);
1219	}
1220	if (c == '\n') {
1221		yylval.lineno = file->lineno;
1222		file->lineno++;
1223	}
1224	if (c == EOF)
1225		return (0);
1226	return (c);
1227}
1228
1229static int
1230check_file_secrecy(int fd, const char *fname)
1231{
1232	struct stat	st;
1233
1234	if (fstat(fd, &st)) {
1235		log_warn("cannot stat %s", fname);
1236		return (-1);
1237	}
1238	if (st.st_uid != 0 && st.st_uid != getuid()) {
1239		log_warnx("%s: owner not root or current user", fname);
1240		return (-1);
1241	}
1242	if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
1243		log_warnx("%s: group writable or world read/writable", fname);
1244		return (-1);
1245	}
1246	return (0);
1247}
1248
1249static struct file *
1250pushfile(const char *name, int secret)
1251{
1252	struct file	*nfile;
1253
1254	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
1255		log_warn("%s", __func__);
1256		return (NULL);
1257	}
1258	if ((nfile->name = strdup(name)) == NULL) {
1259		log_warn("%s", __func__);
1260		free(nfile);
1261		return (NULL);
1262	}
1263	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
1264		log_warn("%s: %s", __func__, nfile->name);
1265		free(nfile->name);
1266		free(nfile);
1267		return (NULL);
1268	} else if (secret &&
1269	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
1270		fclose(nfile->stream);
1271		free(nfile->name);
1272		free(nfile);
1273		return (NULL);
1274	}
1275	nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
1276	nfile->ungetsize = 16;
1277	nfile->ungetbuf = malloc(nfile->ungetsize);
1278	if (nfile->ungetbuf == NULL) {
1279		log_warn("%s", __func__);
1280		fclose(nfile->stream);
1281		free(nfile->name);
1282		free(nfile);
1283		return (NULL);
1284	}
1285	TAILQ_INSERT_TAIL(&files, nfile, entry);
1286	return (nfile);
1287}
1288
1289static int
1290popfile(void)
1291{
1292	struct file	*prev;
1293
1294	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
1295		prev->errors += file->errors;
1296
1297	TAILQ_REMOVE(&files, file, entry);
1298	fclose(file->stream);
1299	free(file->name);
1300	free(file->ungetbuf);
1301	free(file);
1302	file = prev;
1303	return (file ? 0 : EOF);
1304}
1305
1306struct ldpd_conf *
1307parse_config(char *filename)
1308{
1309	struct sym	*sym, *next;
1310
1311	conf = config_new_empty();
1312	conf->rdomain = 0;
1313	conf->trans_pref = DUAL_STACK_LDPOV6;
1314
1315	defs = &globaldefs;
1316	defs->keepalive = DEFAULT_KEEPALIVE;
1317	defs->lhello_holdtime = LINK_DFLT_HOLDTIME;
1318	defs->lhello_interval = DEFAULT_HELLO_INTERVAL;
1319	defs->thello_holdtime = TARGETED_DFLT_HOLDTIME;
1320	defs->thello_interval = DEFAULT_HELLO_INTERVAL;
1321	defs->pwflags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF;
1322
1323	if ((file = pushfile(filename,
1324	    !(global.cmd_opts & LDPD_OPT_NOACTION))) == NULL) {
1325		free(conf);
1326		return (NULL);
1327	}
1328	topfile = file;
1329
1330	yyparse();
1331	errors = file->errors;
1332	popfile();
1333
1334	/* Free macros and check which have not been used. */
1335	TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
1336		if ((global.cmd_opts & LDPD_OPT_VERBOSE2) && !sym->used)
1337			fprintf(stderr, "warning: macro '%s' not "
1338			    "used\n", sym->nam);
1339		if (!sym->persist) {
1340			free(sym->nam);
1341			free(sym->val);
1342			TAILQ_REMOVE(&symhead, sym, entry);
1343			free(sym);
1344		}
1345	}
1346
1347	/* check that all interfaces belong to the configured rdomain */
1348	errors += conf_check_rdomain(conf->rdomain);
1349
1350	/* free global config defaults */
1351	if (errors) {
1352		clear_config(conf);
1353		return (NULL);
1354	}
1355
1356	if (conf->rtr_id.s_addr == INADDR_ANY)
1357		conf->rtr_id.s_addr = get_rtr_id();
1358
1359	/* if the ipv4 transport-address is not set, use the router-id */
1360	if ((conf->ipv4.flags & F_LDPD_AF_ENABLED) &&
1361	    conf->ipv4.trans_addr.v4.s_addr == INADDR_ANY)
1362		conf->ipv4.trans_addr.v4 = conf->rtr_id;
1363
1364	return (conf);
1365}
1366
1367static int
1368symset(const char *nam, const char *val, int persist)
1369{
1370	struct sym	*sym;
1371
1372	TAILQ_FOREACH(sym, &symhead, entry) {
1373		if (strcmp(nam, sym->nam) == 0)
1374			break;
1375	}
1376
1377	if (sym != NULL) {
1378		if (sym->persist == 1)
1379			return (0);
1380		else {
1381			free(sym->nam);
1382			free(sym->val);
1383			TAILQ_REMOVE(&symhead, sym, entry);
1384			free(sym);
1385		}
1386	}
1387	if ((sym = calloc(1, sizeof(*sym))) == NULL)
1388		return (-1);
1389
1390	sym->nam = strdup(nam);
1391	if (sym->nam == NULL) {
1392		free(sym);
1393		return (-1);
1394	}
1395	sym->val = strdup(val);
1396	if (sym->val == NULL) {
1397		free(sym->nam);
1398		free(sym);
1399		return (-1);
1400	}
1401	sym->used = 0;
1402	sym->persist = persist;
1403	TAILQ_INSERT_TAIL(&symhead, sym, entry);
1404	return (0);
1405}
1406
1407int
1408cmdline_symset(char *s)
1409{
1410	char	*sym, *val;
1411	int	ret;
1412
1413	if ((val = strrchr(s, '=')) == NULL)
1414		return (-1);
1415	sym = strndup(s, val - s);
1416	if (sym == NULL)
1417		errx(1, "%s: strndup", __func__);
1418	ret = symset(sym, val + 1, 1);
1419	free(sym);
1420
1421	return (ret);
1422}
1423
1424static char *
1425symget(const char *nam)
1426{
1427	struct sym	*sym;
1428
1429	TAILQ_FOREACH(sym, &symhead, entry) {
1430		if (strcmp(nam, sym->nam) == 0) {
1431			sym->used = 1;
1432			return (sym->val);
1433		}
1434	}
1435	return (NULL);
1436}
1437
1438static struct iface *
1439conf_get_if(struct kif *kif)
1440{
1441	struct iface	*i;
1442	struct l2vpn	*l;
1443
1444	if (kif->if_type == IFT_LOOP ||
1445	    kif->if_type == IFT_CARP ||
1446	    kif->if_type == IFT_BRIDGE ||
1447	    kif->if_type == IFT_MPLSTUNNEL) {
1448		yyerror("unsupported interface type on interface %s",
1449		    kif->ifname);
1450		return (NULL);
1451	}
1452
1453	LIST_FOREACH(l, &conf->l2vpn_list, entry)
1454		if (l2vpn_if_find(l, kif->ifindex)) {
1455			yyerror("interface %s already configured under "
1456			    "l2vpn %s", kif->ifname, l->name);
1457			return (NULL);
1458		}
1459
1460	LIST_FOREACH(i, &conf->iface_list, entry)
1461		if (i->ifindex == kif->ifindex)
1462			return (i);
1463
1464	i = if_new(kif);
1465	LIST_INSERT_HEAD(&conf->iface_list, i, entry);
1466	return (i);
1467}
1468
1469static struct tnbr *
1470conf_get_tnbr(union ldpd_addr *addr)
1471{
1472	struct tnbr	*t;
1473
1474	t = tnbr_find(conf, af, addr);
1475	if (t) {
1476		yyerror("targeted neighbor %s already configured",
1477		    log_addr(af, addr));
1478		return (NULL);
1479	}
1480
1481	t = tnbr_new(conf, af, addr);
1482	t->flags |= F_TNBR_CONFIGURED;
1483	LIST_INSERT_HEAD(&conf->tnbr_list, t, entry);
1484	return (t);
1485}
1486
1487static struct nbr_params *
1488conf_get_nbrp(struct in_addr lsr_id)
1489{
1490	struct nbr_params	*n;
1491
1492	LIST_FOREACH(n, &conf->nbrp_list, entry) {
1493		if (n->lsr_id.s_addr == lsr_id.s_addr) {
1494			yyerror("neighbor %s already configured",
1495			    inet_ntoa(lsr_id));
1496			return (NULL);
1497		}
1498	}
1499
1500	n = nbr_params_new(lsr_id);
1501	LIST_INSERT_HEAD(&conf->nbrp_list, n, entry);
1502	return (n);
1503}
1504
1505static struct l2vpn *
1506conf_get_l2vpn(char *name)
1507{
1508	struct l2vpn	 *l;
1509
1510	if (l2vpn_find(conf, name)) {
1511		yyerror("l2vpn %s already configured", name);
1512		return (NULL);
1513	}
1514
1515	l = l2vpn_new(name);
1516	LIST_INSERT_HEAD(&conf->l2vpn_list, l, entry);
1517	return (l);
1518}
1519
1520static struct l2vpn_if *
1521conf_get_l2vpn_if(struct l2vpn *l, struct kif *kif)
1522{
1523	struct iface	*i;
1524	struct l2vpn	*ltmp;
1525	struct l2vpn_if	*f;
1526
1527	if (kif->if_type == IFT_LOOP ||
1528	    kif->if_type == IFT_CARP ||
1529	    kif->if_type == IFT_BRIDGE ||
1530	    kif->if_type == IFT_MPLSTUNNEL) {
1531		yyerror("unsupported interface type on interface %s",
1532		    kif->ifname);
1533		return (NULL);
1534	}
1535
1536	LIST_FOREACH(ltmp, &conf->l2vpn_list, entry)
1537		if (l2vpn_if_find(ltmp, kif->ifindex)) {
1538			yyerror("interface %s already configured under "
1539			    "l2vpn %s", kif->ifname, ltmp->name);
1540			return (NULL);
1541		}
1542
1543	LIST_FOREACH(i, &conf->iface_list, entry) {
1544		if (i->ifindex == kif->ifindex) {
1545			yyerror("interface %s already configured",
1546			    kif->ifname);
1547			return (NULL);
1548		}
1549	}
1550
1551	f = l2vpn_if_new(l, kif);
1552	LIST_INSERT_HEAD(&l2vpn->if_list, f, entry);
1553	return (f);
1554}
1555
1556static struct l2vpn_pw *
1557conf_get_l2vpn_pw(struct l2vpn *l, struct kif *kif)
1558{
1559	struct l2vpn	*ltmp;
1560	struct l2vpn_pw	*p;
1561
1562	LIST_FOREACH(ltmp, &conf->l2vpn_list, entry) {
1563		if (l2vpn_pw_find(ltmp, kif->ifindex)) {
1564			yyerror("pseudowire %s is already being "
1565			    "used by l2vpn %s", kif->ifname, ltmp->name);
1566			return (NULL);
1567		}
1568	}
1569
1570	p = l2vpn_pw_new(l, kif);
1571	LIST_INSERT_HEAD(&l2vpn->pw_list, p, entry);
1572	return (p);
1573}
1574
1575int
1576conf_check_rdomain(unsigned int rdomain)
1577{
1578	struct iface	*i;
1579	int		 errs = 0;
1580
1581	LIST_FOREACH(i, &conf->iface_list, entry) {
1582		if (i->rdomain != rdomain) {
1583			logit(LOG_CRIT, "interface %s not in rdomain %u",
1584			    i->name, rdomain);
1585			errs++;
1586		}
1587	}
1588
1589	return (errs);
1590}
1591
1592static void
1593clear_config(struct ldpd_conf *xconf)
1594{
1595	struct iface		*i;
1596	struct tnbr		*t;
1597	struct nbr_params	*n;
1598	struct l2vpn		*l;
1599	struct l2vpn_if		*f;
1600	struct l2vpn_pw		*p;
1601
1602	while ((i = LIST_FIRST(&xconf->iface_list)) != NULL) {
1603		LIST_REMOVE(i, entry);
1604		free(i);
1605	}
1606
1607	while ((t = LIST_FIRST(&xconf->tnbr_list)) != NULL) {
1608		LIST_REMOVE(t, entry);
1609		free(t);
1610	}
1611
1612	while ((n = LIST_FIRST(&xconf->nbrp_list)) != NULL) {
1613		LIST_REMOVE(n, entry);
1614		free(n);
1615	}
1616
1617	while ((l = LIST_FIRST(&xconf->l2vpn_list)) != NULL) {
1618		while ((f = LIST_FIRST(&l->if_list)) != NULL) {
1619			LIST_REMOVE(f, entry);
1620			free(f);
1621		}
1622		while ((p = LIST_FIRST(&l->pw_list)) != NULL) {
1623			LIST_REMOVE(p, entry);
1624			free(p);
1625		}
1626		LIST_REMOVE(l, entry);
1627		free(l);
1628	}
1629
1630	free(xconf);
1631}
1632
1633static uint32_t
1634get_rtr_id(void)
1635{
1636	struct ifaddrs		*ifap, *ifa;
1637	uint32_t		 ip = 0, cur, localnet;
1638
1639	localnet = htonl(INADDR_LOOPBACK & IN_CLASSA_NET);
1640
1641	if (getifaddrs(&ifap) == -1) {
1642		log_warn("getifaddrs");
1643		return (0);
1644	}
1645
1646	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1647		if (strncmp(ifa->ifa_name, "carp", 4) == 0)
1648			continue;
1649		if (ifa->ifa_addr->sa_family != AF_INET)
1650			continue;
1651		cur = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
1652		if ((cur & localnet) == localnet)	/* skip 127/8 */
1653			continue;
1654		if (ntohl(cur) < ntohl(ip) || ip == 0)
1655			ip = cur;
1656	}
1657	freeifaddrs(ifap);
1658
1659	return (ip);
1660}
1661
1662static int
1663get_address(const char *s, union ldpd_addr *addr)
1664{
1665	switch (af) {
1666	case AF_INET:
1667		if (inet_pton(AF_INET, s, &addr->v4) != 1)
1668			return (-1);
1669		break;
1670	case AF_INET6:
1671		if (inet_pton(AF_INET6, s, &addr->v6) != 1)
1672			return (-1);
1673		break;
1674	default:
1675		return (-1);
1676	}
1677
1678	return (0);
1679}
1680
1681static int
1682get_af_address(const char *s, int *family, union ldpd_addr *addr)
1683{
1684	if (inet_pton(AF_INET, s, &addr->v4) == 1) {
1685		*family = AF_INET;
1686		return (0);
1687	}
1688
1689	if (inet_pton(AF_INET6, s, &addr->v6) == 1) {
1690		*family = AF_INET6;
1691		return (0);
1692	}
1693
1694	return (-1);
1695}
1696
1697static int
1698hexchar(int ch)
1699{
1700	if (ch >= '0' && ch <= '9')
1701		return (ch - '0');
1702	if (ch >= 'a' && ch <= 'f')
1703		return (ch - 'a');
1704	if (ch >= 'A' && ch <= 'F')
1705		return (ch - 'A');
1706
1707	return (-1);
1708}
1709
1710static int
1711str2key(char *dst, const char *src, int dstlen)
1712{
1713	int		i = 0;
1714	int		digit;
1715
1716	while (*src != '\0') {
1717		digit = hexchar(*src);
1718		if (digit == -1)
1719			return (-1);
1720
1721		if (i < dstlen)
1722			*dst = digit << 4;
1723
1724		src++;
1725		if (*src == '\0')
1726			return (-1);
1727		digit = hexchar(*src);
1728		if (digit == -1)
1729			return (-1);
1730
1731		if (i < dstlen)
1732			*dst |= digit;
1733
1734		src++;
1735		i++;
1736	}
1737
1738	return (i);
1739}
1740