GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ldpd/parse.y Lines: 0 391 0.0 %
Date: 2017-11-07 Branches: 0 316 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: parse.y,v 1.61 2017/03/03 23:41:27 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
42
struct file {
43
	TAILQ_ENTRY(file)	 entry;
44
	FILE			*stream;
45
	char			*name;
46
	int			 lineno;
47
	int			 errors;
48
};
49
TAILQ_HEAD(files, file);
50
51
struct sym {
52
	TAILQ_ENTRY(sym)	 entry;
53
	int			 used;
54
	int			 persist;
55
	char			*nam;
56
	char			*val;
57
};
58
TAILQ_HEAD(symhead, sym);
59
60
struct 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
71
typedef struct {
72
	union {
73
		int64_t		 number;
74
		char		*string;
75
	} v;
76
	int lineno;
77
} YYSTYPE;
78
79
#define MAXPUSHBACK	128
80
81
static int		 yyerror(const char *, ...)
82
    __attribute__((__format__ (printf, 1, 2)))
83
    __attribute__((__nonnull__ (1)));
84
static int		 kw_cmp(const void *, const void *);
85
static int		 lookup(char *);
86
static int		 lgetc(int);
87
static int		 lungetc(int);
88
static int		 findeol(void);
89
static int		 yylex(void);
90
static int		 check_file_secrecy(int, const char *);
91
static struct file	*pushfile(const char *, int);
92
static int		 popfile(void);
93
static int		 yyparse(void);
94
static int		 symset(const char *, const char *, int);
95
static char		*symget(const char *);
96
static struct iface	*conf_get_if(struct kif *);
97
static struct tnbr	*conf_get_tnbr(union ldpd_addr *);
98
static struct nbr_params *conf_get_nbrp(struct in_addr);
99
static struct l2vpn	*conf_get_l2vpn(char *);
100
static struct l2vpn_if	*conf_get_l2vpn_if(struct l2vpn *, struct kif *);
101
static struct l2vpn_pw	*conf_get_l2vpn_pw(struct l2vpn *, struct kif *);
102
int			 conf_check_rdomain(unsigned int);
103
static void		 clear_config(struct ldpd_conf *xconf);
104
static uint32_t		 get_rtr_id(void);
105
static int		 get_address(const char *, union ldpd_addr *);
106
static int		 get_af_address(const char *, int *, union ldpd_addr *);
107
108
static struct file		*file, *topfile;
109
static struct files		 files = TAILQ_HEAD_INITIALIZER(files);
110
static struct symhead		 symhead = TAILQ_HEAD_INITIALIZER(symhead);
111
static struct ldpd_conf		*conf;
112
static int			 errors;
113
114
static int			 af;
115
static struct ldpd_af_conf	*af_conf;
116
static struct iface		*iface;
117
static struct iface_af		*ia;
118
static struct tnbr		*tnbr;
119
static struct nbr_params	*nbrp;
120
static struct l2vpn		*l2vpn;
121
static struct l2vpn_pw		*pw;
122
123
static struct config_defaults	 globaldefs;
124
static struct config_defaults	 afdefs;
125
static struct config_defaults	 ifacedefs;
126
static struct config_defaults	 tnbrdefs;
127
static struct config_defaults	 pwdefs;
128
static struct config_defaults	*defs;
129
130
static unsigned char		*parsebuf;
131
static int			 parseindex;
132
static unsigned char		 pushback_buffer[MAXPUSHBACK];
133
static 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
157
grammar		: /* 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
168
include		: 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
183
string		: 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
196
yesno		: YES	{ $$ = 1; }
197
		| NO	{ $$ = 0; }
198
		;
199
200
ldp_af		: IPV4	{ $$ = AF_INET; }
201
		| IPV6	{ $$ = AF_INET6; }
202
		;
203
204
l2vpn_type	: VPLS	{ $$ = L2VPN_TYPE_VPLS; }
205
		;
206
207
pw_type		: ETHERNET		{ $$ = PW_TYPE_ETHERNET; }
208
		| ETHERNETTAGGED	{ $$ = PW_TYPE_ETHERNET_TAGGED; }
209
		;
210
211
varset		: 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
229
conf_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
280
af		: 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
308
af_block	: '{' optnl afopts_l '}'
309
		| '{' optnl '}'
310
		|
311
		;
312
313
afopts_l	: afopts_l afoptsl nl
314
		| afoptsl optnl
315
		;
316
317
afoptsl		:  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
346
af_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
368
iface_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
387
tnbr_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
406
nbr_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
442
pw_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
456
pwopts		: 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
509
pseudowire	: 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
573
pw_block	: '{' optnl pwopts_l '}'
574
		| '{' optnl '}'
575
		| /* nothing */
576
		;
577
578
pwopts_l	: pwopts_l pwopts nl
579
		| pwopts optnl
580
		;
581
582
l2vpnopts	: 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
649
optnl		: '\n' optnl
650
		|
651
		;
652
653
nl		: '\n' optnl		/* one newline or more */
654
		;
655
656
interface	: 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
689
interface_block	: '{' optnl interfaceopts_l '}'
690
		| '{' optnl '}'
691
		| /* nothing */
692
		;
693
694
interfaceopts_l	: interfaceopts_l iface_defaults nl
695
		| iface_defaults optnl
696
		;
697
698
tneighbor	: 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
733
tneighbor_block	: '{' optnl tneighboropts_l '}'
734
		| '{' optnl '}'
735
		| /* nothing */
736
		;
737
738
tneighboropts_l	: tneighboropts_l tnbr_defaults nl
739
		| tnbr_defaults optnl
740
		;
741
742
neighbor	: 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
764
neighbor_block	: '{' optnl neighboropts_l '}'
765
		| '{' optnl '}'
766
		| /* nothing */
767
		;
768
769
neighboropts_l	: neighboropts_l nbr_opts nl
770
		| nbr_opts optnl
771
		;
772
773
l2vpn		: 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
783
l2vpn_block	: '{' optnl l2vpnopts_l '}'
784
		| '{' optnl '}'
785
		| /* nothing */
786
		;
787
788
l2vpnopts_l	: l2vpnopts_l l2vpnopts nl
789
		| l2vpnopts optnl
790
		;
791
792
%%
793
794
struct keywords {
795
	const char	*k_name;
796
	int		 k_val;
797
};
798
799
static int
800
yyerror(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
815
static int
816
kw_cmp(const void *k, const void *e)
817
{
818
	return (strcmp(k, ((const struct keywords *)e)->k_name));
819
}
820
821
static int
822
lookup(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
877
static int
878
lgetc(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
925
static int
926
lungetc(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
941
static int
942
findeol(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
964
static int
965
yylex(void)
966
{
967
	unsigned char	 buf[8096];
968
	unsigned char	*p, *val;
969
	int		 quotec, next, c;
970
	int		 token;
971
972
 top:
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 {
1074
 nodigits:
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
1113
static int
1114
check_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
1133
static struct file *
1134
pushfile(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
1164
static int
1165
popfile(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
1180
struct ldpd_conf *
1181
parse_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
1241
static int
1242
symset(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
1281
int
1282
cmdline_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
1303
static char *
1304
symget(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
1317
static struct iface *
1318
conf_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
1348
static struct tnbr *
1349
conf_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
1366
static struct nbr_params *
1367
conf_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
1384
static struct l2vpn *
1385
conf_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
1399
static struct l2vpn_if *
1400
conf_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
1435
static struct l2vpn_pw *
1436
conf_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
1454
int
1455
conf_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
1471
static void
1472
clear_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
1512
static uint32_t
1513
get_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
1541
static int
1542
get_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
1560
static int
1561
get_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
}