parse.y revision 1.35
1/* $OpenBSD: parse.y,v 1.35 2016/05/23 15:41:04 renato Exp $ */ 2 3/* 4 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org> 5 * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org> 6 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> 7 * Copyright (c) 2001 Markus Friedl. All rights reserved. 8 * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. 9 * Copyright (c) 2001 Theo de Raadt. All rights reserved. 10 * 11 * Permission to use, copy, modify, and distribute this software for any 12 * purpose with or without fee is hereby granted, provided that the above 13 * copyright notice and this permission notice appear in all copies. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24%{ 25#include <sys/types.h> 26#include <sys/socket.h> 27#include <sys/stat.h> 28#include <netinet/in.h> 29#include <arpa/inet.h> 30#include <ctype.h> 31#include <err.h> 32#include <errno.h> 33#include <unistd.h> 34#include <ifaddrs.h> 35#include <net/if_types.h> 36#include <limits.h> 37#include <stdarg.h> 38#include <stdio.h> 39#include <string.h> 40#include <syslog.h> 41 42#include "ldp.h" 43#include "ldpd.h" 44#include "lde.h" 45#include "ldpe.h" 46#include "log.h" 47 48TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); 49static struct file { 50 TAILQ_ENTRY(file) entry; 51 FILE *stream; 52 char *name; 53 int lineno; 54 int errors; 55} *file, *topfile; 56struct file *pushfile(const char *, int); 57int popfile(void); 58int check_file_secrecy(int, const char *); 59int yyparse(void); 60int yylex(void); 61int yyerror(const char *, ...) 62 __attribute__((__format__ (printf, 1, 2))) 63 __attribute__((__nonnull__ (1))); 64int kw_cmp(const void *, const void *); 65int lookup(char *); 66int lgetc(int); 67int lungetc(int); 68int findeol(void); 69 70TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 71struct sym { 72 TAILQ_ENTRY(sym) entry; 73 int used; 74 int persist; 75 char *nam; 76 char *val; 77}; 78 79int symset(const char *, const char *, int); 80char *symget(const char *); 81 82void clear_config(struct ldpd_conf *xconf); 83u_int32_t get_rtr_id(void); 84int host(const char *, struct in_addr *, struct in_addr *); 85 86static struct ldpd_conf *conf; 87static int errors = 0; 88 89struct iface *iface = NULL; 90struct tnbr *tnbr = NULL; 91struct nbr_params *nbrp = NULL; 92struct l2vpn *l2vpn = NULL; 93struct l2vpn_pw *pw = NULL; 94 95struct config_defaults { 96 u_int16_t lhello_holdtime; 97 u_int16_t lhello_interval; 98 u_int16_t thello_holdtime; 99 u_int16_t thello_interval; 100 u_int8_t pwflags; 101}; 102 103struct config_defaults globaldefs; 104struct config_defaults ifacedefs; 105struct config_defaults tnbrdefs; 106struct config_defaults pwdefs; 107struct config_defaults *defs; 108 109int bad_ip_addr(struct in_addr); 110 111struct iface *conf_get_if(struct kif *); 112struct tnbr *conf_get_tnbr(struct in_addr); 113struct nbr_params *conf_get_nbrp(struct in_addr); 114struct l2vpn *conf_get_l2vpn(char *); 115struct l2vpn_if *conf_get_l2vpn_if(struct l2vpn *, struct kif *); 116struct l2vpn_pw *conf_get_l2vpn_pw(struct l2vpn *, struct kif *); 117 118typedef struct { 119 union { 120 int64_t number; 121 char *string; 122 } v; 123 int lineno; 124} YYSTYPE; 125 126%} 127 128%token INTERFACE TNEIGHBOR ROUTERID FIBUPDATE 129%token LHELLOHOLDTIME LHELLOINTERVAL 130%token THELLOHOLDTIME THELLOINTERVAL 131%token THELLOACCEPT 132%token KEEPALIVE 133%token NEIGHBOR PASSWORD 134%token L2VPN TYPE VPLS PWTYPE MTU BRIDGE 135%token ETHERNET ETHERNETTAGGED STATUSTLV CONTROLWORD 136%token PSEUDOWIRE NEIGHBOR PWID 137%token EXTTAG 138%token YES NO 139%token INCLUDE 140%token ERROR 141%token <v.string> STRING 142%token <v.number> NUMBER 143%type <v.number> yesno 144%type <v.number> l2vpn_type 145%type <v.number> pw_type 146%type <v.string> string 147 148%% 149 150grammar : /* empty */ 151 | grammar include '\n' 152 | grammar '\n' 153 | grammar conf_main '\n' 154 | grammar varset '\n' 155 | grammar interface '\n' 156 | grammar tneighbor '\n' 157 | grammar neighbor '\n' 158 | grammar l2vpn '\n' 159 | grammar error '\n' { file->errors++; } 160 ; 161 162include : INCLUDE STRING { 163 struct file *nfile; 164 165 if ((nfile = pushfile($2, 1)) == NULL) { 166 yyerror("failed to include file %s", $2); 167 free($2); 168 YYERROR; 169 } 170 free($2); 171 172 file = nfile; 173 lungetc('\n'); 174 } 175 ; 176 177string : string STRING { 178 if (asprintf(&$$, "%s %s", $1, $2) == -1) { 179 free($1); 180 free($2); 181 yyerror("string: asprintf"); 182 YYERROR; 183 } 184 free($1); 185 free($2); 186 } 187 | STRING 188 ; 189 190yesno : YES { $$ = 1; } 191 | NO { $$ = 0; } 192 ; 193 194l2vpn_type : VPLS { $$ = L2VPN_TYPE_VPLS; } 195 ; 196 197pw_type : ETHERNET { $$ = PW_TYPE_ETHERNET; } 198 | ETHERNETTAGGED { $$ = PW_TYPE_ETHERNET_TAGGED; } 199 ; 200 201varset : STRING '=' string { 202 if (conf->opts & LDPD_OPT_VERBOSE) 203 printf("%s = \"%s\"\n", $1, $3); 204 if (symset($1, $3, 0) == -1) 205 fatal("cannot store variable"); 206 free($1); 207 free($3); 208 } 209 ; 210 211conf_main : ROUTERID STRING { 212 if (!inet_aton($2, &conf->rtr_id)) { 213 yyerror("error parsing router-id"); 214 free($2); 215 YYERROR; 216 } 217 free($2); 218 if (bad_ip_addr(conf->rtr_id)) { 219 yyerror("invalid router-id"); 220 YYERROR; 221 } 222 } 223 | FIBUPDATE yesno { 224 if ($2 == 0) 225 conf->flags |= LDPD_FLAG_NO_FIB_UPDATE; 226 else 227 conf->flags &= ~LDPD_FLAG_NO_FIB_UPDATE; 228 } 229 | THELLOACCEPT yesno { 230 if ($2 == 0) 231 conf->flags &= ~LDPD_FLAG_TH_ACCEPT; 232 else 233 conf->flags |= LDPD_FLAG_TH_ACCEPT; 234 } 235 | KEEPALIVE NUMBER { 236 if ($2 < MIN_KEEPALIVE || $2 > MAX_KEEPALIVE) { 237 yyerror("keepalive out of range (%d-%d)", 238 MIN_KEEPALIVE, MAX_KEEPALIVE); 239 YYERROR; 240 } 241 conf->keepalive = $2; 242 } 243 | iface_defaults 244 | tnbr_defaults 245 ; 246 247iface_defaults : LHELLOHOLDTIME NUMBER { 248 if ($2 < MIN_HOLDTIME || 249 $2 > MAX_HOLDTIME) { 250 yyerror("hello holdtime out of range (%d-%d)", 251 MIN_HOLDTIME, MAX_HOLDTIME); 252 YYERROR; 253 } 254 defs->lhello_holdtime = $2; 255 } 256 | LHELLOINTERVAL NUMBER { 257 if ($2 < MIN_HELLO_INTERVAL || 258 $2 > MAX_HELLO_INTERVAL) { 259 yyerror("hello-interval out of range (%d-%d)", 260 MIN_HELLO_INTERVAL, MAX_HELLO_INTERVAL); 261 YYERROR; 262 } 263 defs->lhello_interval = $2; 264 } 265 ; 266 267tnbr_defaults : THELLOHOLDTIME NUMBER { 268 if ($2 < MIN_HOLDTIME || 269 $2 > MAX_HOLDTIME) { 270 yyerror("hello holdtime out of range (%d-%d)", 271 MIN_HOLDTIME, MAX_HOLDTIME); 272 YYERROR; 273 } 274 conf->thello_holdtime = $2; 275 defs->thello_holdtime = $2; 276 } 277 | THELLOINTERVAL NUMBER { 278 if ($2 < MIN_HELLO_INTERVAL || 279 $2 > MAX_HELLO_INTERVAL) { 280 yyerror("hello-interval out of range (%d-%d)", 281 MIN_HELLO_INTERVAL, MAX_HELLO_INTERVAL); 282 YYERROR; 283 } 284 conf->thello_interval = $2; 285 defs->thello_interval = $2; 286 } 287 ; 288 289nbr_opts : KEEPALIVE NUMBER { 290 if ($2 < MIN_KEEPALIVE || $2 > MAX_KEEPALIVE) { 291 yyerror("keepalive out of range (%d-%d)", 292 MIN_KEEPALIVE, MAX_KEEPALIVE); 293 YYERROR; 294 } 295 nbrp->keepalive = $2; 296 nbrp->flags |= F_NBRP_KEEPALIVE; 297 } 298 | PASSWORD STRING { 299 if (strlcpy(nbrp->auth.md5key, $2, 300 sizeof(nbrp->auth.md5key)) >= 301 sizeof(nbrp->auth.md5key)) { 302 yyerror("tcp md5sig password too long: max %zu", 303 sizeof(nbrp->auth.md5key) - 1); 304 free($2); 305 YYERROR; 306 } 307 nbrp->auth.md5key_len = strlen($2); 308 nbrp->auth.method = AUTH_MD5SIG; 309 free($2); 310 } 311 ; 312 313pw_defaults : STATUSTLV yesno { 314 if ($2 == 1) { 315 defs->pwflags |= F_PW_STATUSTLV_CONF; 316 defs->pwflags |= F_PW_STATUSTLV; 317 } else { 318 defs->pwflags &= ~F_PW_STATUSTLV_CONF; 319 defs->pwflags &= ~F_PW_STATUSTLV; 320 } 321 } 322 | CONTROLWORD yesno { 323 if ($2 == 1) { 324 defs->pwflags |= F_PW_CONTROLWORD_CONF; 325 defs->pwflags |= F_PW_CONTROLWORD; 326 } else { 327 defs->pwflags &= ~F_PW_CONTROLWORD_CONF; 328 defs->pwflags &= ~F_PW_CONTROLWORD; 329 } 330 } 331 ; 332 333pwopts : PWID NUMBER { 334 if ($2 < MIN_PWID_ID || 335 $2 > MAX_PWID_ID) { 336 yyerror("pw-id out of range (%d-%d)", 337 MIN_PWID_ID, MAX_PWID_ID); 338 YYERROR; 339 } 340 341 pw->pwid = $2; 342 } 343 | NEIGHBOR STRING { 344 struct in_addr addr; 345 struct tnbr *t; 346 347 if (inet_aton($2, &addr) == 0) { 348 yyerror( 349 "error parsing neighbor address"); 350 free($2); 351 YYERROR; 352 } 353 free($2); 354 355 pw->addr.s_addr = addr.s_addr; 356 357 t = tnbr_find(conf, addr); 358 if (t == NULL) { 359 t = tnbr_new(conf, addr); 360 LIST_INSERT_HEAD(&conf->tnbr_list, t, entry); 361 } 362 363 t->pw_count++; 364 } 365 | pw_defaults 366 ; 367 368pseudowire : PSEUDOWIRE STRING { 369 struct kif *kif; 370 371 if ((kif = kif_findname($2)) == NULL) { 372 yyerror("unknown interface %s", $2); 373 free($2); 374 YYERROR; 375 } 376 free($2); 377 378 if (kif->if_type != IFT_MPLSTUNNEL) { 379 yyerror("unsupported interface type on " 380 "interface %s", kif->ifname); 381 YYERROR; 382 } 383 384 pw = conf_get_l2vpn_pw(l2vpn, kif); 385 if (pw == NULL) 386 YYERROR; 387 LIST_INSERT_HEAD(&l2vpn->pw_list, pw, entry); 388 389 memcpy(&pwdefs, defs, sizeof(pwdefs)); 390 defs = &pwdefs; 391 } pw_block { 392 struct l2vpn *l; 393 struct l2vpn_pw *p; 394 395 LIST_FOREACH(l, &conf->l2vpn_list, entry) 396 LIST_FOREACH(p, &l->pw_list, entry) 397 if (pw != p && 398 pw->pwid == p->pwid && 399 pw->addr.s_addr == p->addr.s_addr) { 400 yyerror("pseudowire already " 401 "configured"); 402 YYERROR; 403 } 404 405 pw->flags = defs->pwflags; 406 defs = &globaldefs; 407 pw = NULL; 408 } 409 ; 410 411pw_block : '{' optnl pwopts_l '}' 412 | '{' optnl '}' 413 | /* nothing */ 414 ; 415 416pwopts_l : pwopts_l pwopts nl 417 | pwopts optnl 418 ; 419 420l2vpnopts : PWTYPE pw_type { 421 l2vpn->pw_type = $2; 422 } 423 | MTU NUMBER { 424 if ($2 < MIN_L2VPN_MTU || 425 $2 > MAX_L2VPN_MTU) { 426 yyerror("l2vpn mtu out of range (%d-%d)", 427 MIN_L2VPN_MTU, MAX_L2VPN_MTU); 428 YYERROR; 429 } 430 l2vpn->mtu = $2; 431 } 432 | pw_defaults 433 | BRIDGE STRING { 434 struct l2vpn *l; 435 struct kif *kif; 436 437 if ((kif = kif_findname($2)) == NULL) { 438 yyerror("unknown interface %s", $2); 439 free($2); 440 YYERROR; 441 } 442 free($2); 443 444 if (l2vpn->br_ifindex != 0) { 445 yyerror("bridge interface cannot be " 446 "redefined on l2vpn %s", l2vpn->name); 447 YYERROR; 448 } 449 450 if (kif->if_type != IFT_BRIDGE) { 451 yyerror("unsupported interface type on " 452 "interface %s", kif->ifname); 453 YYERROR; 454 } 455 456 LIST_FOREACH(l, &conf->l2vpn_list, entry) { 457 if (l->br_ifindex == kif->ifindex) { 458 yyerror("bridge %s is already being " 459 "used by l2vpn %s", kif->ifname, 460 l->name); 461 YYERROR; 462 } 463 } 464 465 l2vpn->br_ifindex = kif->ifindex; 466 strlcpy(l2vpn->br_ifname, kif->ifname, 467 sizeof(l2vpn->br_ifname)); 468 } 469 | INTERFACE STRING { 470 struct kif *kif; 471 struct l2vpn_if *lif; 472 473 if ((kif = kif_findname($2)) == NULL) { 474 yyerror("unknown interface %s", $2); 475 free($2); 476 YYERROR; 477 } 478 free($2); 479 480 if (kif->if_type == IFT_BRIDGE 481 || kif->if_type == IFT_LOOP 482 || kif->if_type == IFT_CARP) { 483 yyerror("unsupported interface type on " 484 "interface %s", kif->ifname); 485 YYERROR; 486 } 487 488 lif = conf_get_l2vpn_if(l2vpn, kif); 489 if (lif == NULL) 490 YYERROR; 491 LIST_INSERT_HEAD(&l2vpn->if_list, lif, entry); 492 } 493 | pseudowire 494 ; 495 496optnl : '\n' optnl 497 | 498 ; 499 500nl : '\n' optnl /* one newline or more */ 501 ; 502 503interface : INTERFACE STRING { 504 struct kif *kif; 505 506 if ((kif = kif_findname($2)) == NULL) { 507 yyerror("unknown interface %s", $2); 508 free($2); 509 YYERROR; 510 } 511 free($2); 512 iface = conf_get_if(kif); 513 if (iface == NULL) 514 YYERROR; 515 if (iface->if_type == IFT_LOOP || 516 iface->if_type == IFT_CARP || 517 iface->if_type == IFT_MPLSTUNNEL) { 518 yyerror("unsupported interface type on " 519 "interface %s", iface->name); 520 YYERROR; 521 } 522 LIST_INSERT_HEAD(&conf->iface_list, iface, entry); 523 524 memcpy(&ifacedefs, defs, sizeof(ifacedefs)); 525 defs = &ifacedefs; 526 } interface_block { 527 iface->hello_holdtime = defs->lhello_holdtime; 528 iface->hello_interval = defs->lhello_interval; 529 iface = NULL; 530 531 defs = &globaldefs; 532 } 533 ; 534 535interface_block : '{' optnl interfaceopts_l '}' 536 | '{' optnl '}' 537 | /* nothing */ 538 ; 539 540interfaceopts_l : interfaceopts_l iface_defaults nl 541 | iface_defaults optnl 542 ; 543 544tneighbor : TNEIGHBOR STRING { 545 struct in_addr addr; 546 547 if (inet_aton($2, &addr) == 0) { 548 yyerror( 549 "error parsing neighbor address"); 550 free($2); 551 YYERROR; 552 } 553 free($2); 554 if (bad_ip_addr(addr)) { 555 yyerror("invalid neighbor address"); 556 YYERROR; 557 } 558 559 tnbr = conf_get_tnbr(addr); 560 if (tnbr == NULL) 561 YYERROR; 562 563 tnbr->flags |= F_TNBR_CONFIGURED; 564 LIST_INSERT_HEAD(&conf->tnbr_list, tnbr, entry); 565 566 memcpy(&tnbrdefs, defs, sizeof(tnbrdefs)); 567 defs = &tnbrdefs; 568 } tneighbor_block { 569 tnbr->hello_holdtime = defs->thello_holdtime; 570 tnbr->hello_interval = defs->thello_interval; 571 tnbr = NULL; 572 573 defs = &globaldefs; 574 } 575 ; 576 577tneighbor_block : '{' optnl tneighboropts_l '}' 578 | '{' optnl '}' 579 | /* nothing */ 580 ; 581 582tneighboropts_l : tneighboropts_l tnbr_defaults nl 583 | tnbr_defaults optnl 584 ; 585 586neighbor : NEIGHBOR STRING { 587 struct in_addr addr; 588 589 if (inet_aton($2, &addr) == 0) { 590 yyerror( 591 "error parsing neighbor address"); 592 free($2); 593 YYERROR; 594 } 595 free($2); 596 if (bad_ip_addr(addr)) { 597 yyerror("invalid neighbor address"); 598 YYERROR; 599 } 600 601 nbrp = conf_get_nbrp(addr); 602 if (nbrp == NULL) 603 YYERROR; 604 LIST_INSERT_HEAD(&conf->nbrp_list, nbrp, entry); 605 } neighbor_block { 606 nbrp = NULL; 607 } 608 ; 609 610neighbor_block : '{' optnl neighboropts_l '}' 611 | '{' optnl '}' 612 | /* nothing */ 613 ; 614 615neighboropts_l : neighboropts_l nbr_opts nl 616 | nbr_opts optnl 617 ; 618 619l2vpn : L2VPN STRING TYPE l2vpn_type { 620 l2vpn = conf_get_l2vpn($2); 621 if (l2vpn == NULL) 622 YYERROR; 623 l2vpn->type = $4; 624 LIST_INSERT_HEAD(&conf->l2vpn_list, l2vpn, entry); 625 } l2vpn_block { 626 l2vpn = NULL; 627 } 628 ; 629 630l2vpn_block : '{' optnl l2vpnopts_l '}' 631 | '{' optnl '}' 632 | /* nothing */ 633 ; 634 635l2vpnopts_l : l2vpnopts_l l2vpnopts nl 636 | l2vpnopts optnl 637 ; 638 639%% 640 641struct keywords { 642 const char *k_name; 643 int k_val; 644}; 645 646int 647yyerror(const char *fmt, ...) 648{ 649 va_list ap; 650 char *msg; 651 652 file->errors++; 653 va_start(ap, fmt); 654 if (vasprintf(&msg, fmt, ap) == -1) 655 fatalx("yyerror vasprintf"); 656 va_end(ap); 657 logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg); 658 free(msg); 659 return (0); 660} 661 662int 663kw_cmp(const void *k, const void *e) 664{ 665 return (strcmp(k, ((const struct keywords *)e)->k_name)); 666} 667 668int 669lookup(char *s) 670{ 671 /* this has to be sorted always */ 672 static const struct keywords keywords[] = { 673 {"bridge", BRIDGE}, 674 {"control-word", CONTROLWORD}, 675 {"ethernet", ETHERNET}, 676 {"ethernet-tagged", ETHERNETTAGGED}, 677 {"fib-update", FIBUPDATE}, 678 {"include", INCLUDE}, 679 {"interface", INTERFACE}, 680 {"keepalive", KEEPALIVE}, 681 {"l2vpn", L2VPN}, 682 {"link-hello-holdtime", LHELLOHOLDTIME}, 683 {"link-hello-interval", LHELLOINTERVAL}, 684 {"mtu", MTU}, 685 {"neighbor", NEIGHBOR}, 686 {"no", NO}, 687 {"password", PASSWORD}, 688 {"pseudowire", PSEUDOWIRE}, 689 {"pw-id", PWID}, 690 {"pw-type", PWTYPE}, 691 {"router-id", ROUTERID}, 692 {"status-tlv", STATUSTLV}, 693 {"targeted-hello-accept", THELLOACCEPT}, 694 {"targeted-hello-holdtime", THELLOHOLDTIME}, 695 {"targeted-hello-interval", THELLOINTERVAL}, 696 {"targeted-neighbor", TNEIGHBOR}, 697 {"type", TYPE}, 698 {"vpls", VPLS}, 699 {"yes", YES} 700 }; 701 const struct keywords *p; 702 703 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 704 sizeof(keywords[0]), kw_cmp); 705 706 if (p) 707 return (p->k_val); 708 else 709 return (STRING); 710} 711 712#define MAXPUSHBACK 128 713 714u_char *parsebuf; 715int parseindex; 716u_char pushback_buffer[MAXPUSHBACK]; 717int pushback_index = 0; 718 719int 720lgetc(int quotec) 721{ 722 int c, next; 723 724 if (parsebuf) { 725 /* Read character from the parsebuffer instead of input. */ 726 if (parseindex >= 0) { 727 c = parsebuf[parseindex++]; 728 if (c != '\0') 729 return (c); 730 parsebuf = NULL; 731 } else 732 parseindex++; 733 } 734 735 if (pushback_index) 736 return (pushback_buffer[--pushback_index]); 737 738 if (quotec) { 739 if ((c = getc(file->stream)) == EOF) { 740 yyerror("reached end of file while parsing " 741 "quoted string"); 742 if (file == topfile || popfile() == EOF) 743 return (EOF); 744 return (quotec); 745 } 746 return (c); 747 } 748 749 while ((c = getc(file->stream)) == '\\') { 750 next = getc(file->stream); 751 if (next != '\n') { 752 c = next; 753 break; 754 } 755 yylval.lineno = file->lineno; 756 file->lineno++; 757 } 758 759 while (c == EOF) { 760 if (file == topfile || popfile() == EOF) 761 return (EOF); 762 c = getc(file->stream); 763 } 764 return (c); 765} 766 767int 768lungetc(int c) 769{ 770 if (c == EOF) 771 return (EOF); 772 if (parsebuf) { 773 parseindex--; 774 if (parseindex >= 0) 775 return (c); 776 } 777 if (pushback_index < MAXPUSHBACK-1) 778 return (pushback_buffer[pushback_index++] = c); 779 else 780 return (EOF); 781} 782 783int 784findeol(void) 785{ 786 int c; 787 788 parsebuf = NULL; 789 790 /* skip to either EOF or the first real EOL */ 791 while (1) { 792 if (pushback_index) 793 c = pushback_buffer[--pushback_index]; 794 else 795 c = lgetc(0); 796 if (c == '\n') { 797 file->lineno++; 798 break; 799 } 800 if (c == EOF) 801 break; 802 } 803 return (ERROR); 804} 805 806int 807yylex(void) 808{ 809 u_char buf[8096]; 810 u_char *p, *val; 811 int quotec, next, c; 812 int token; 813 814top: 815 p = buf; 816 while ((c = lgetc(0)) == ' ' || c == '\t') 817 ; /* nothing */ 818 819 yylval.lineno = file->lineno; 820 if (c == '#') 821 while ((c = lgetc(0)) != '\n' && c != EOF) 822 ; /* nothing */ 823 if (c == '$' && parsebuf == NULL) { 824 while (1) { 825 if ((c = lgetc(0)) == EOF) 826 return (0); 827 828 if (p + 1 >= buf + sizeof(buf) - 1) { 829 yyerror("string too long"); 830 return (findeol()); 831 } 832 if (isalnum(c) || c == '_') { 833 *p++ = c; 834 continue; 835 } 836 *p = '\0'; 837 lungetc(c); 838 break; 839 } 840 val = symget(buf); 841 if (val == NULL) { 842 yyerror("macro '%s' not defined", buf); 843 return (findeol()); 844 } 845 parsebuf = val; 846 parseindex = 0; 847 goto top; 848 } 849 850 switch (c) { 851 case '\'': 852 case '"': 853 quotec = c; 854 while (1) { 855 if ((c = lgetc(quotec)) == EOF) 856 return (0); 857 if (c == '\n') { 858 file->lineno++; 859 continue; 860 } else if (c == '\\') { 861 if ((next = lgetc(quotec)) == EOF) 862 return (0); 863 if (next == quotec || c == ' ' || c == '\t') 864 c = next; 865 else if (next == '\n') { 866 file->lineno++; 867 continue; 868 } else 869 lungetc(next); 870 } else if (c == quotec) { 871 *p = '\0'; 872 break; 873 } else if (c == '\0') { 874 yyerror("syntax error"); 875 return (findeol()); 876 } 877 if (p + 1 >= buf + sizeof(buf) - 1) { 878 yyerror("string too long"); 879 return (findeol()); 880 } 881 *p++ = c; 882 } 883 yylval.v.string = strdup(buf); 884 if (yylval.v.string == NULL) 885 err(1, "yylex: strdup"); 886 return (STRING); 887 } 888 889#define allowed_to_end_number(x) \ 890 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') 891 892 if (c == '-' || isdigit(c)) { 893 do { 894 *p++ = c; 895 if ((unsigned)(p-buf) >= sizeof(buf)) { 896 yyerror("string too long"); 897 return (findeol()); 898 } 899 } while ((c = lgetc(0)) != EOF && isdigit(c)); 900 lungetc(c); 901 if (p == buf + 1 && buf[0] == '-') 902 goto nodigits; 903 if (c == EOF || allowed_to_end_number(c)) { 904 const char *errstr = NULL; 905 906 *p = '\0'; 907 yylval.v.number = strtonum(buf, LLONG_MIN, 908 LLONG_MAX, &errstr); 909 if (errstr) { 910 yyerror("\"%s\" invalid number: %s", 911 buf, errstr); 912 return (findeol()); 913 } 914 return (NUMBER); 915 } else { 916nodigits: 917 while (p > buf + 1) 918 lungetc(*--p); 919 c = *--p; 920 if (c == '-') 921 return (c); 922 } 923 } 924 925#define allowed_in_string(x) \ 926 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 927 x != '{' && x != '}' && \ 928 x != '!' && x != '=' && x != '#' && \ 929 x != ',')) 930 931 if (isalnum(c) || c == ':' || c == '_') { 932 do { 933 *p++ = c; 934 if ((unsigned)(p-buf) >= sizeof(buf)) { 935 yyerror("string too long"); 936 return (findeol()); 937 } 938 } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); 939 lungetc(c); 940 *p = '\0'; 941 if ((token = lookup(buf)) == STRING) 942 if ((yylval.v.string = strdup(buf)) == NULL) 943 err(1, "yylex: strdup"); 944 return (token); 945 } 946 if (c == '\n') { 947 yylval.lineno = file->lineno; 948 file->lineno++; 949 } 950 if (c == EOF) 951 return (0); 952 return (c); 953} 954 955int 956check_file_secrecy(int fd, const char *fname) 957{ 958 struct stat st; 959 960 if (fstat(fd, &st)) { 961 log_warn("cannot stat %s", fname); 962 return (-1); 963 } 964 if (st.st_uid != 0 && st.st_uid != getuid()) { 965 log_warnx("%s: owner not root or current user", fname); 966 return (-1); 967 } 968 if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) { 969 log_warnx("%s: group writable or world read/writable", fname); 970 return (-1); 971 } 972 return (0); 973} 974 975struct file * 976pushfile(const char *name, int secret) 977{ 978 struct file *nfile; 979 980 if ((nfile = calloc(1, sizeof(struct file))) == NULL) { 981 log_warn("malloc"); 982 return (NULL); 983 } 984 if ((nfile->name = strdup(name)) == NULL) { 985 log_warn("strdup"); 986 free(nfile); 987 return (NULL); 988 } 989 if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { 990 log_warn("%s", nfile->name); 991 free(nfile->name); 992 free(nfile); 993 return (NULL); 994 } else if (secret && 995 check_file_secrecy(fileno(nfile->stream), nfile->name)) { 996 fclose(nfile->stream); 997 free(nfile->name); 998 free(nfile); 999 return (NULL); 1000 } 1001 nfile->lineno = 1; 1002 TAILQ_INSERT_TAIL(&files, nfile, entry); 1003 return (nfile); 1004} 1005 1006int 1007popfile(void) 1008{ 1009 struct file *prev; 1010 1011 if ((prev = TAILQ_PREV(file, files, entry)) != NULL) 1012 prev->errors += file->errors; 1013 1014 TAILQ_REMOVE(&files, file, entry); 1015 fclose(file->stream); 1016 free(file->name); 1017 free(file); 1018 file = prev; 1019 return (file ? 0 : EOF); 1020} 1021 1022struct ldpd_conf * 1023parse_config(char *filename, int opts) 1024{ 1025 struct sym *sym, *next; 1026 1027 if ((conf = calloc(1, sizeof(struct ldpd_conf))) == NULL) 1028 fatal("parse_config"); 1029 conf->opts = opts; 1030 conf->keepalive = DEFAULT_KEEPALIVE; 1031 1032 bzero(&globaldefs, sizeof(globaldefs)); 1033 defs = &globaldefs; 1034 defs->lhello_holdtime = LINK_DFLT_HOLDTIME; 1035 defs->lhello_interval = DEFAULT_HELLO_INTERVAL; 1036 defs->thello_holdtime = TARGETED_DFLT_HOLDTIME; 1037 defs->thello_interval = DEFAULT_HELLO_INTERVAL; 1038 conf->thello_holdtime = TARGETED_DFLT_HOLDTIME; 1039 conf->thello_interval = DEFAULT_HELLO_INTERVAL; 1040 defs->pwflags |= F_PW_STATUSTLV_CONF; 1041 defs->pwflags |= F_PW_STATUSTLV; 1042 defs->pwflags |= F_PW_CONTROLWORD_CONF; 1043 defs->pwflags |= F_PW_CONTROLWORD; 1044 1045 if ((file = pushfile(filename, !(conf->opts & LDPD_OPT_NOACTION))) == NULL) { 1046 free(conf); 1047 return (NULL); 1048 } 1049 topfile = file; 1050 1051 LIST_INIT(&conf->iface_list); 1052 LIST_INIT(&conf->addr_list); 1053 LIST_INIT(&conf->tnbr_list); 1054 LIST_INIT(&conf->nbrp_list); 1055 LIST_INIT(&conf->l2vpn_list); 1056 1057 yyparse(); 1058 errors = file->errors; 1059 popfile(); 1060 1061 /* Free macros and check which have not been used. */ 1062 for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) { 1063 next = TAILQ_NEXT(sym, entry); 1064 if ((conf->opts & LDPD_OPT_VERBOSE2) && !sym->used) 1065 fprintf(stderr, "warning: macro '%s' not " 1066 "used\n", sym->nam); 1067 if (!sym->persist) { 1068 free(sym->nam); 1069 free(sym->val); 1070 TAILQ_REMOVE(&symhead, sym, entry); 1071 free(sym); 1072 } 1073 } 1074 1075 /* free global config defaults */ 1076 if (errors) { 1077 clear_config(conf); 1078 return (NULL); 1079 } 1080 1081 if (conf->rtr_id.s_addr == 0) 1082 conf->rtr_id.s_addr = get_rtr_id(); 1083 1084 return (conf); 1085} 1086 1087int 1088symset(const char *nam, const char *val, int persist) 1089{ 1090 struct sym *sym; 1091 1092 for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam); 1093 sym = TAILQ_NEXT(sym, entry)) 1094 ; /* nothing */ 1095 1096 if (sym != NULL) { 1097 if (sym->persist == 1) 1098 return (0); 1099 else { 1100 free(sym->nam); 1101 free(sym->val); 1102 TAILQ_REMOVE(&symhead, sym, entry); 1103 free(sym); 1104 } 1105 } 1106 if ((sym = calloc(1, sizeof(*sym))) == NULL) 1107 return (-1); 1108 1109 sym->nam = strdup(nam); 1110 if (sym->nam == NULL) { 1111 free(sym); 1112 return (-1); 1113 } 1114 sym->val = strdup(val); 1115 if (sym->val == NULL) { 1116 free(sym->nam); 1117 free(sym); 1118 return (-1); 1119 } 1120 sym->used = 0; 1121 sym->persist = persist; 1122 TAILQ_INSERT_TAIL(&symhead, sym, entry); 1123 return (0); 1124} 1125 1126int 1127cmdline_symset(char *s) 1128{ 1129 char *sym, *val; 1130 int ret; 1131 size_t len; 1132 1133 if ((val = strrchr(s, '=')) == NULL) 1134 return (-1); 1135 1136 len = strlen(s) - strlen(val) + 1; 1137 if ((sym = malloc(len)) == NULL) 1138 errx(1, "cmdline_symset: malloc"); 1139 1140 strlcpy(sym, s, len); 1141 1142 ret = symset(sym, val + 1, 1); 1143 free(sym); 1144 1145 return (ret); 1146} 1147 1148char * 1149symget(const char *nam) 1150{ 1151 struct sym *sym; 1152 1153 TAILQ_FOREACH(sym, &symhead, entry) 1154 if (strcmp(nam, sym->nam) == 0) { 1155 sym->used = 1; 1156 return (sym->val); 1157 } 1158 return (NULL); 1159} 1160 1161int 1162bad_ip_addr(struct in_addr addr) 1163{ 1164 u_int32_t a = ntohl(addr.s_addr); 1165 1166 return (((a >> IN_CLASSA_NSHIFT) == 0) 1167 || ((a >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 1168 || IN_MULTICAST(a) || IN_BADCLASS(a)); 1169} 1170 1171struct iface * 1172conf_get_if(struct kif *kif) 1173{ 1174 struct iface *i; 1175 1176 LIST_FOREACH(i, &conf->iface_list, entry) { 1177 if (i->ifindex == kif->ifindex) { 1178 yyerror("interface %s already configured", 1179 kif->ifname); 1180 return (NULL); 1181 } 1182 } 1183 1184 i = if_new(kif); 1185 1186 return (i); 1187} 1188 1189struct tnbr * 1190conf_get_tnbr(struct in_addr addr) 1191{ 1192 struct tnbr *t; 1193 1194 t = tnbr_find(conf, addr); 1195 if (t && (t->flags & F_TNBR_CONFIGURED)) { 1196 yyerror("targeted neighbor %s already configured", 1197 inet_ntoa(addr)); 1198 return (NULL); 1199 } 1200 1201 t = tnbr_new(conf, addr); 1202 1203 return (t); 1204} 1205 1206struct nbr_params * 1207conf_get_nbrp(struct in_addr addr) 1208{ 1209 struct nbr_params *n; 1210 1211 LIST_FOREACH(n, &conf->nbrp_list, entry) { 1212 if (n->addr.s_addr == addr.s_addr) { 1213 yyerror("neighbor %s already configured", 1214 inet_ntoa(addr)); 1215 return (NULL); 1216 } 1217 } 1218 1219 n = nbr_params_new(addr); 1220 1221 return (n); 1222} 1223 1224struct l2vpn * 1225conf_get_l2vpn(char *name) 1226{ 1227 struct l2vpn *l; 1228 1229 if (l2vpn_find(conf, name)) { 1230 yyerror("l2vpn %s already configured", name); 1231 return (NULL); 1232 } 1233 1234 l = l2vpn_new(name); 1235 1236 return (l); 1237} 1238 1239struct l2vpn_if * 1240conf_get_l2vpn_if(struct l2vpn *l, struct kif *kif) 1241{ 1242 struct iface *i; 1243 struct l2vpn *ltmp; 1244 1245 LIST_FOREACH(i, &conf->iface_list, entry) { 1246 if (i->ifindex == kif->ifindex) { 1247 yyerror("interface %s already configured", 1248 kif->ifname); 1249 return (NULL); 1250 } 1251 } 1252 1253 LIST_FOREACH(ltmp, &conf->l2vpn_list, entry) 1254 if (l2vpn_if_find(ltmp, kif->ifindex)) { 1255 yyerror("interface %s is already being " 1256 "used by l2vpn %s", kif->ifname, ltmp->name); 1257 return (NULL); 1258 } 1259 1260 return (l2vpn_if_new(l, kif)); 1261} 1262 1263struct l2vpn_pw * 1264conf_get_l2vpn_pw(struct l2vpn *l, struct kif *kif) 1265{ 1266 struct l2vpn *ltmp; 1267 1268 LIST_FOREACH(ltmp, &conf->l2vpn_list, entry) { 1269 if (l2vpn_pw_find(ltmp, kif->ifindex)) { 1270 yyerror("pseudowire %s is already being " 1271 "used by l2vpn %s", kif->ifname, ltmp->name); 1272 return (NULL); 1273 } 1274 } 1275 1276 return (l2vpn_pw_new(l, kif)); 1277} 1278 1279void 1280clear_config(struct ldpd_conf *xconf) 1281{ 1282 struct iface *i; 1283 struct tnbr *t; 1284 struct nbr_params *n; 1285 struct l2vpn *l; 1286 struct l2vpn_if *f; 1287 struct l2vpn_pw *p; 1288 1289 while ((i = LIST_FIRST(&xconf->iface_list)) != NULL) { 1290 LIST_REMOVE(i, entry); 1291 if_del(i); 1292 } 1293 1294 while ((t = LIST_FIRST(&xconf->tnbr_list)) != NULL) { 1295 LIST_REMOVE(t, entry); 1296 tnbr_del(t); 1297 } 1298 1299 while ((n = LIST_FIRST(&xconf->nbrp_list)) != NULL) { 1300 LIST_REMOVE(n, entry); 1301 free(n); 1302 } 1303 1304 while ((l = LIST_FIRST(&xconf->l2vpn_list)) != NULL) { 1305 while ((f = LIST_FIRST(&l->if_list)) != NULL) { 1306 LIST_REMOVE(f, entry); 1307 free(f); 1308 } 1309 while ((p = LIST_FIRST(&l->pw_list)) != NULL) { 1310 LIST_REMOVE(p, entry); 1311 free(p); 1312 } 1313 LIST_REMOVE(l, entry); 1314 free(l); 1315 } 1316 1317 free(xconf); 1318} 1319 1320u_int32_t 1321get_rtr_id(void) 1322{ 1323 struct ifaddrs *ifap, *ifa; 1324 u_int32_t ip = 0, cur, localnet; 1325 1326 localnet = htonl(INADDR_LOOPBACK & IN_CLASSA_NET); 1327 1328 if (getifaddrs(&ifap) == -1) 1329 fatal("getifaddrs"); 1330 1331 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 1332 if (strncmp(ifa->ifa_name, "carp", 4) == 0) 1333 continue; 1334 if (ifa->ifa_addr->sa_family != AF_INET) 1335 continue; 1336 cur = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; 1337 if ((cur & localnet) == localnet) /* skip 127/8 */ 1338 continue; 1339 if (ntohl(cur) < ntohl(ip) || ip == 0) 1340 ip = cur; 1341 } 1342 freeifaddrs(ifap); 1343 1344 if (ip == 0) 1345 fatal("router-id is 0.0.0.0"); 1346 1347 return (ip); 1348} 1349 1350int 1351host(const char *s, struct in_addr *addr, struct in_addr *mask) 1352{ 1353 struct in_addr ina; 1354 int bits = 32; 1355 1356 bzero(&ina, sizeof(struct in_addr)); 1357 if (strrchr(s, '/') != NULL) { 1358 if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) 1359 return (0); 1360 } else { 1361 if (inet_pton(AF_INET, s, &ina) != 1) 1362 return (0); 1363 } 1364 1365 addr->s_addr = ina.s_addr; 1366 mask->s_addr = prefixlen2mask(bits); 1367 1368 return (1); 1369} 1370