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