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