1 /* $OpenBSD: parse.y,v 1.71 2019/02/13 22:57:08 deraadt 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 46 struct 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 }; 57 TAILQ_HEAD(files, file); 58 59 struct sym { 60 TAILQ_ENTRY(sym) entry; 61 int used; 62 int persist; 63 char *nam; 64 char *val; 65 }; 66 TAILQ_HEAD(symhead, sym); 67 68 struct 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 79 typedef 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 89 static int yyerror(const char *, ...) 90 __attribute__((__format__ (printf, 1, 2))) 91 __attribute__((__nonnull__ (1))); 92 static int kw_cmp(const void *, const void *); 93 static int lookup(char *); 94 static int igetc(void); 95 static int lgetc(int); 96 void lungetc(int); 97 static int findeol(void); 98 static int yylex(void); 99 static int check_file_secrecy(int, const char *); 100 static struct file *pushfile(const char *, int); 101 static int popfile(void); 102 static int yyparse(void); 103 static int symset(const char *, const char *, int); 104 static char *symget(const char *); 105 static struct iface *conf_get_if(struct kif *); 106 static struct tnbr *conf_get_tnbr(union ldpd_addr *); 107 static struct nbr_params *conf_get_nbrp(struct in_addr); 108 static struct l2vpn *conf_get_l2vpn(char *); 109 static struct l2vpn_if *conf_get_l2vpn_if(struct l2vpn *, struct kif *); 110 static struct l2vpn_pw *conf_get_l2vpn_pw(struct l2vpn *, struct kif *); 111 int conf_check_rdomain(unsigned int); 112 static void clear_config(struct ldpd_conf *xconf); 113 static uint32_t get_rtr_id(void); 114 static int get_address(const char *, union ldpd_addr *); 115 static int get_af_address(const char *, int *, union ldpd_addr *); 116 static int str2key(char *, const char *, int); 117 118 static struct file *file, *topfile; 119 static struct files files = TAILQ_HEAD_INITIALIZER(files); 120 static struct symhead symhead = TAILQ_HEAD_INITIALIZER(symhead); 121 static struct ldpd_conf *conf; 122 static int errors; 123 124 static int af; 125 static struct ldpd_af_conf *af_conf; 126 static struct iface *iface; 127 static struct iface_af *ia; 128 static struct tnbr *tnbr; 129 static struct nbr_params *nbrp; 130 static struct l2vpn *l2vpn; 131 static struct l2vpn_pw *pw; 132 133 static struct config_defaults globaldefs; 134 static struct config_defaults afdefs; 135 static struct config_defaults ifacedefs; 136 static struct config_defaults tnbrdefs; 137 static struct config_defaults pwdefs; 138 static 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 165 grammar : /* 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 176 include : 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 192 string : 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 205 routerid : 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 222 yesno : YES { $$ = 1; } 223 | NO { $$ = 0; } 224 ; 225 226 ldp_af : IPV4 { $$ = AF_INET; } 227 | IPV6 { $$ = AF_INET6; } 228 ; 229 230 l2vpn_type : VPLS { $$ = L2VPN_TYPE_VPLS; } 231 ; 232 233 pw_type : ETHERNET { $$ = PW_TYPE_ETHERNET; } 234 | ETHERNETTAGGED { $$ = PW_TYPE_ETHERNET_TAGGED; } 235 ; 236 237 varset : 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 257 conf_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 302 af : 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 330 af_block : '{' optnl afopts_l '}' 331 | '{' optnl '}' 332 | 333 ; 334 335 afopts_l : afopts_l afoptsl nl 336 | afoptsl optnl 337 ; 338 339 afoptsl : 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 368 af_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 390 iface_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 409 tnbr_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 428 tcpmd5 : 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 491 optnbrprefix : 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 512 auth : 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 525 nbr_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 554 pw_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 568 pwopts : 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 608 pseudowire : 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 673 pw_block : '{' optnl pwopts_l '}' 674 | '{' optnl '}' 675 | /* nothing */ 676 ; 677 678 pwopts_l : pwopts_l pwopts nl 679 | pwopts optnl 680 ; 681 682 l2vpnopts : 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 749 optnl : '\n' optnl 750 | 751 ; 752 753 nl : '\n' optnl /* one newline or more */ 754 ; 755 756 interface : 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 789 interface_block : '{' optnl interfaceopts_l '}' 790 | '{' optnl '}' 791 | /* nothing */ 792 ; 793 794 interfaceopts_l : interfaceopts_l iface_defaults nl 795 | iface_defaults optnl 796 ; 797 798 tneighbor : 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 833 tneighbor_block : '{' optnl tneighboropts_l '}' 834 | '{' optnl '}' 835 | /* nothing */ 836 ; 837 838 tneighboropts_l : tneighboropts_l tnbr_defaults nl 839 | tnbr_defaults optnl 840 ; 841 842 neighbor : NEIGHBOR routerid { 843 nbrp = conf_get_nbrp($2); 844 if (nbrp == NULL) 845 YYERROR; 846 } neighbor_block { 847 nbrp = NULL; 848 } 849 ; 850 851 neighbor_block : '{' optnl neighboropts_l '}' 852 | '{' optnl '}' 853 | /* nothing */ 854 ; 855 856 neighboropts_l : neighboropts_l nbr_opts nl 857 | nbr_opts optnl 858 ; 859 860 l2vpn : 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 870 l2vpn_block : '{' optnl l2vpnopts_l '}' 871 | '{' optnl '}' 872 | /* nothing */ 873 ; 874 875 l2vpnopts_l : l2vpnopts_l l2vpnopts nl 876 | l2vpnopts optnl 877 ; 878 879 %% 880 881 struct keywords { 882 const char *k_name; 883 int k_val; 884 }; 885 886 static int 887 yyerror(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 902 static int 903 kw_cmp(const void *k, const void *e) 904 { 905 return (strcmp(k, ((const struct keywords *)e)->k_name)); 906 } 907 908 static int 909 lookup(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 972 static int expanding; 973 974 int 975 igetc(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 995 static int 996 lgetc(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 1040 void 1041 lungetc(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 1056 static int 1057 findeol(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 1074 static int 1075 yylex(void) 1076 { 1077 unsigned char buf[8096]; 1078 unsigned 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(*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(*--p); 1193 c = *--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 1229 static int 1230 check_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 1249 static struct file * 1250 pushfile(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 1289 static int 1290 popfile(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 1306 struct ldpd_conf * 1307 parse_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 1367 static int 1368 symset(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 1407 int 1408 cmdline_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 1424 static char * 1425 symget(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 1438 static struct iface * 1439 conf_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 1469 static struct tnbr * 1470 conf_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 1487 static struct nbr_params * 1488 conf_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 1505 static struct l2vpn * 1506 conf_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 1520 static struct l2vpn_if * 1521 conf_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 1556 static struct l2vpn_pw * 1557 conf_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 1575 int 1576 conf_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 1592 static void 1593 clear_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 1633 static uint32_t 1634 get_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 1662 static int 1663 get_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 1681 static int 1682 get_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 1697 static int 1698 hexchar(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 1710 static int 1711 str2key(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