1/* 2 * $Id: gram.y,v 1.21 2009/06/19 07:34:07 psavola Exp $ 3 * 4 * Authors: 5 * Pedro Roque <roque@di.fc.ul.pt> 6 * Lars Fenneberg <lf@elemental.net> 7 * 8 * This software is Copyright 1996-2000 by the above mentioned author(s), 9 * All Rights Reserved. 10 * 11 * The license which is distributed with this software in the file COPYRIGHT 12 * applies to this software. If your distribution is missing this file, you 13 * may request it from <pekkas@netcore.fi>. 14 * 15 */ 16%{ 17#include <config.h> 18#include <includes.h> 19#include <radvd.h> 20#include <defaults.h> 21 22extern struct Interface *IfaceList; 23struct Interface *iface = NULL; 24struct AdvPrefix *prefix = NULL; 25struct AdvRoute *route = NULL; 26struct AdvRDNSS *rdnss = NULL; 27 28extern char *conf_file; 29extern int num_lines; 30extern char *yytext; 31extern int sock; 32 33static void cleanup(void); 34static void yyerror(char *msg); 35 36#if 0 /* no longer necessary? */ 37#ifndef HAVE_IN6_ADDR_S6_ADDR 38# ifdef __FreeBSD__ 39# define s6_addr32 __u6_addr.__u6_addr32 40# define s6_addr16 __u6_addr.__u6_addr16 41# endif 42#endif 43#endif 44 45#define ABORT do { cleanup(); YYABORT; } while (0); 46 47%} 48 49%token T_INTERFACE 50%token T_PREFIX 51%token T_ROUTE 52%token T_RDNSS 53%token T_CLIENTS 54 55%token <str> STRING 56%token <num> NUMBER 57%token <snum> SIGNEDNUMBER 58%token <dec> DECIMAL 59%token <num> SWITCH 60%token <addr> IPV6ADDR 61%token INFINITY 62 63%token T_IgnoreIfMissing 64%token T_AdvSendAdvert 65%token T_MaxRtrAdvInterval 66%token T_MinRtrAdvInterval 67%token T_MinDelayBetweenRAs 68%token T_AdvManagedFlag 69%token T_AdvOtherConfigFlag 70%token T_AdvLinkMTU 71%token T_AdvReachableTime 72%token T_AdvRetransTimer 73%token T_AdvCurHopLimit 74%token T_AdvDefaultLifetime 75%token T_AdvDefaultPreference 76%token T_AdvSourceLLAddress 77 78%token T_AdvOnLink 79%token T_AdvAutonomous 80%token T_AdvValidLifetime 81%token T_AdvPreferredLifetime 82 83%token T_AdvRouterAddr 84%token T_AdvHomeAgentFlag 85%token T_AdvIntervalOpt 86%token T_AdvHomeAgentInfo 87 88%token T_Base6to4Interface 89%token T_UnicastOnly 90 91%token T_HomeAgentPreference 92%token T_HomeAgentLifetime 93 94%token T_AdvRoutePreference 95%token T_AdvRouteLifetime 96 97%token T_AdvRDNSSPreference 98%token T_AdvRDNSSOpenFlag 99%token T_AdvRDNSSLifetime 100 101%token T_AdvMobRtrSupportFlag 102 103%token T_BAD_TOKEN 104 105%type <str> name 106%type <pinfo> optional_prefixlist prefixdef prefixlist 107%type <ainfo> optional_clientslist clientslist v6addrlist 108%type <rinfo> optional_routelist routedef routelist 109%type <rdnssinfo> optional_rdnsslist rdnssdef rdnsslist 110%type <num> number_or_infinity 111 112%union { 113 unsigned int num; 114 int snum; 115 double dec; 116 struct in6_addr *addr; 117 char *str; 118 struct AdvPrefix *pinfo; 119 struct AdvRoute *rinfo; 120 struct AdvRDNSS *rdnssinfo; 121 struct Clients *ainfo; 122}; 123 124%% 125 126grammar : grammar ifacedef 127 | ifacedef 128 ; 129 130ifacedef : ifacehead '{' ifaceparams '}' ';' 131 { 132 struct Interface *iface2; 133 134 iface2 = IfaceList; 135 while (iface2) 136 { 137 if (!strcmp(iface2->Name, iface->Name)) 138 { 139 flog(LOG_ERR, "duplicate interface " 140 "definition for %s", iface->Name); 141 ABORT; 142 } 143 iface2 = iface2->next; 144 } 145 146 if (check_device(sock, iface) < 0) { 147 if (iface->IgnoreIfMissing) { 148 dlog(LOG_DEBUG, 4, "interface %s did not exist, ignoring the interface", iface->Name); 149 goto skip_interface; 150 } 151 else { 152 flog(LOG_ERR, "interface %s does not exist", iface->Name); 153 ABORT; 154 } 155 } 156 if (setup_deviceinfo(sock, iface) < 0) 157 ABORT; 158 if (check_iface(iface) < 0) 159 ABORT; 160 if (setup_linklocal_addr(sock, iface) < 0) 161 ABORT; 162 if (setup_allrouters_membership(sock, iface) < 0) 163 ABORT; 164 165 iface->next = IfaceList; 166 IfaceList = iface; 167 168 dlog(LOG_DEBUG, 4, "interface definition for %s is ok", iface->Name); 169 170skip_interface: 171 iface = NULL; 172 }; 173 174ifacehead : T_INTERFACE name 175 { 176 iface = malloc(sizeof(struct Interface)); 177 178 if (iface == NULL) { 179 flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); 180 ABORT; 181 } 182 183 iface_init_defaults(iface); 184 strncpy(iface->Name, $2, IFNAMSIZ-1); 185 iface->Name[IFNAMSIZ-1] = '\0'; 186 } 187 ; 188 189name : STRING 190 { 191 /* check vality */ 192 $$ = $1; 193 } 194 ; 195 196ifaceparams : optional_ifacevlist optional_prefixlist optional_clientslist optional_routelist optional_rdnsslist 197 { 198 iface->AdvPrefixList = $2; 199 iface->ClientList = $3; 200 iface->AdvRouteList = $4; 201 iface->AdvRDNSSList = $5; 202 } 203 ; 204 205optional_ifacevlist: /* empty */ 206 | ifacevlist 207 ; 208 209optional_prefixlist: /* empty */ 210 { 211 $$ = NULL; 212 } 213 | prefixlist 214 ; 215 216optional_clientslist: /* empty */ 217 { 218 $$ = NULL; 219 } 220 | clientslist 221 ; 222 223optional_routelist: /* empty */ 224 { 225 $$ = NULL; 226 } 227 | routelist 228 ; 229 230optional_rdnsslist: /* empty */ 231 { 232 $$ = NULL; 233 } 234 | rdnsslist 235 ; 236 237ifacevlist : ifacevlist ifaceval 238 | ifaceval 239 ; 240 241ifaceval : T_MinRtrAdvInterval NUMBER ';' 242 { 243 iface->MinRtrAdvInterval = $2; 244 } 245 | T_MaxRtrAdvInterval NUMBER ';' 246 { 247 iface->MaxRtrAdvInterval = $2; 248 } 249 | T_MinDelayBetweenRAs NUMBER ';' 250 { 251 iface->MinDelayBetweenRAs = $2; 252 } 253 | T_MinRtrAdvInterval DECIMAL ';' 254 { 255 iface->MinRtrAdvInterval = $2; 256 } 257 | T_MaxRtrAdvInterval DECIMAL ';' 258 { 259 iface->MaxRtrAdvInterval = $2; 260 } 261 | T_MinDelayBetweenRAs DECIMAL ';' 262 { 263 iface->MinDelayBetweenRAs = $2; 264 } 265 | T_IgnoreIfMissing SWITCH ';' 266 { 267 iface->IgnoreIfMissing = $2; 268 } 269 | T_AdvSendAdvert SWITCH ';' 270 { 271 iface->AdvSendAdvert = $2; 272 } 273 | T_AdvManagedFlag SWITCH ';' 274 { 275 iface->AdvManagedFlag = $2; 276 } 277 | T_AdvOtherConfigFlag SWITCH ';' 278 { 279 iface->AdvOtherConfigFlag = $2; 280 } 281 | T_AdvLinkMTU NUMBER ';' 282 { 283 iface->AdvLinkMTU = $2; 284 } 285 | T_AdvReachableTime NUMBER ';' 286 { 287 iface->AdvReachableTime = $2; 288 } 289 | T_AdvRetransTimer NUMBER ';' 290 { 291 iface->AdvRetransTimer = $2; 292 } 293 | T_AdvDefaultLifetime NUMBER ';' 294 { 295 iface->AdvDefaultLifetime = $2; 296 } 297 | T_AdvDefaultPreference SIGNEDNUMBER ';' 298 { 299 iface->AdvDefaultPreference = $2; 300 } 301 | T_AdvCurHopLimit NUMBER ';' 302 { 303 iface->AdvCurHopLimit = $2; 304 } 305 | T_AdvSourceLLAddress SWITCH ';' 306 { 307 iface->AdvSourceLLAddress = $2; 308 } 309 | T_AdvIntervalOpt SWITCH ';' 310 { 311 iface->AdvIntervalOpt = $2; 312 } 313 | T_AdvHomeAgentInfo SWITCH ';' 314 { 315 iface->AdvHomeAgentInfo = $2; 316 } 317 | T_AdvHomeAgentFlag SWITCH ';' 318 { 319 iface->AdvHomeAgentFlag = $2; 320 } 321 | T_HomeAgentPreference NUMBER ';' 322 { 323 iface->HomeAgentPreference = $2; 324 } 325 | T_HomeAgentLifetime NUMBER ';' 326 { 327 iface->HomeAgentLifetime = $2; 328 } 329 | T_UnicastOnly SWITCH ';' 330 { 331 iface->UnicastOnly = $2; 332 } 333 | T_AdvMobRtrSupportFlag SWITCH ';' 334 { 335 iface->AdvMobRtrSupportFlag = $2; 336 } 337 ; 338 339clientslist : T_CLIENTS '{' v6addrlist '}' ';' 340 { 341 $$ = $3; 342 } 343 ; 344 345v6addrlist : IPV6ADDR ';' 346 { 347 struct Clients *new = calloc(1, sizeof(struct Clients)); 348 if (new == NULL) { 349 flog(LOG_CRIT, "calloc failed: %s", strerror(errno)); 350 ABORT; 351 } 352 353 memcpy(&(new->Address), $1, sizeof(struct in6_addr)); 354 $$ = new; 355 } 356 | v6addrlist IPV6ADDR ';' 357 { 358 struct Clients *new = calloc(1, sizeof(struct Clients)); 359 if (new == NULL) { 360 flog(LOG_CRIT, "calloc failed: %s", strerror(errno)); 361 ABORT; 362 } 363 364 memcpy(&(new->Address), $2, sizeof(struct in6_addr)); 365 new->next = $1; 366 $$ = new; 367 } 368 ; 369 370 371prefixlist : prefixdef optional_prefixlist 372 { 373 $1->next = $2; 374 $$ = $1; 375 } 376 ; 377 378prefixdef : prefixhead '{' optional_prefixplist '}' ';' 379 { 380 unsigned int dst; 381 382 if (prefix->AdvPreferredLifetime > 383 prefix->AdvValidLifetime) 384 { 385 flog(LOG_ERR, "AdvValidLifeTime must be " 386 "greater than AdvPreferredLifetime in %s, line %d", 387 conf_file, num_lines); 388 ABORT; 389 } 390 391 if( prefix->if6to4[0] ) 392 { 393 if (get_v4addr(prefix->if6to4, &dst) < 0) 394 { 395 flog(LOG_ERR, "interface %s has no IPv4 addresses, disabling 6to4 prefix", prefix->if6to4 ); 396 prefix->enabled = 0; 397 } else 398 { 399 *((uint16_t *)(prefix->Prefix.s6_addr)) = htons(0x2002); 400 memcpy( prefix->Prefix.s6_addr + 2, &dst, sizeof( dst ) ); 401 } 402 } 403 404 $$ = prefix; 405 prefix = NULL; 406 } 407 ; 408 409prefixhead : T_PREFIX IPV6ADDR '/' NUMBER 410 { 411 struct in6_addr zeroaddr; 412 prefix = malloc(sizeof(struct AdvPrefix)); 413 414 if (prefix == NULL) { 415 flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); 416 ABORT; 417 } 418 419 prefix_init_defaults(prefix); 420 421 if ($4 > MAX_PrefixLen) 422 { 423 flog(LOG_ERR, "invalid prefix length in %s, line %d", conf_file, num_lines); 424 ABORT; 425 } 426 427 prefix->PrefixLen = $4; 428 429 memcpy(&prefix->Prefix, $2, sizeof(struct in6_addr)); 430 431 memset(&zeroaddr, 0, sizeof(zeroaddr)); 432 if (!memcmp($2, &zeroaddr, sizeof(struct in6_addr))) { 433#ifndef HAVE_IFADDRS_H 434 flog(LOG_ERR, "invalid all-zeros prefix in %s, line %d", conf_file, num_lines); 435 ABORT; 436#else 437 dlog(LOG_DEBUG, 5, "all-zeros prefix in %s, line %d, parsing..", conf_file, num_lines); 438 struct ifaddrs *ifap, *ifa; 439 if (getifaddrs(&ifap) != 0) 440 flog(LOG_ERR, "getifaddrs failed: %s", strerror(errno)); 441 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 442 struct sockaddr_in6 *s6; 443 char buf[INET6_ADDRSTRLEN]; 444 if (strncmp(ifa->ifa_name, iface->Name, IFNAMSIZ)) 445 continue; 446 if (ifa->ifa_addr->sa_family != AF_INET6) 447 continue; 448 s6 = (struct sockaddr_in6 *)(ifa->ifa_addr); 449 if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) 450 continue; 451 if (inet_ntop(ifa->ifa_addr->sa_family, (void *)&(s6->sin6_addr), buf, sizeof(buf)) == NULL) { 452 flog(LOG_ERR, "%s: inet_ntop failed in %s, line %d!", ifa->ifa_name, conf_file, num_lines); 453 } 454 else { 455 dlog(LOG_DEBUG, 5, "auto-selected prefix %s on interface %s", buf, ifa->ifa_name); 456 memcpy(&prefix->Prefix, &s6->sin6_addr, sizeof(struct in6_addr)); 457 prefix->AdvRouterAddr=1; 458 prefix->AutoSelected=1; 459 } 460 } 461 if (!memcmp(&prefix->Prefix, &zeroaddr, sizeof(struct in6_addr))) { 462 prefix->enabled = 0; 463 flog(LOG_WARNING, "no auto-selected prefix on interface %s, disabling advertisements", iface->Name); 464 } 465 freeifaddrs(ifap); 466 freeifaddrs(ifa); 467#endif /* ifndef HAVE_IFADDRS_H */ 468 } 469 } 470 ; 471 472optional_prefixplist: /* empty */ 473 | prefixplist 474 ; 475 476prefixplist : prefixplist prefixparms 477 | prefixparms 478 ; 479 480prefixparms : T_AdvOnLink SWITCH ';' 481 { 482 prefix->AdvOnLinkFlag = $2; 483 } 484 | T_AdvAutonomous SWITCH ';' 485 { 486 prefix->AdvAutonomousFlag = $2; 487 } 488 | T_AdvRouterAddr SWITCH ';' 489 { 490 if (prefix->AutoSelected && $2 == 0) 491 flog(LOG_WARNING, "prefix automatically selected, AdvRouterAddr always enabled, ignoring config line %d", num_lines); 492 else 493 prefix->AdvRouterAddr = $2; 494 } 495 | T_AdvValidLifetime number_or_infinity ';' 496 { 497 prefix->AdvValidLifetime = $2; 498 } 499 | T_AdvPreferredLifetime number_or_infinity ';' 500 { 501 prefix->AdvPreferredLifetime = $2; 502 } 503 | T_Base6to4Interface name ';' 504 { 505 if (prefix->AutoSelected) { 506 flog(LOG_ERR, "automatically selecting the prefix and Base6to4Interface are mutually exclusive"); 507 ABORT; 508 } /* fallthrough */ 509 dlog(LOG_DEBUG, 4, "using interface %s for 6to4", $2); 510 strncpy(prefix->if6to4, $2, IFNAMSIZ-1); 511 prefix->if6to4[IFNAMSIZ-1] = '\0'; 512 } 513 ; 514 515routelist : routedef optional_routelist 516 { 517 $1->next = $2; 518 $$ = $1; 519 } 520 ; 521 522routedef : routehead '{' optional_routeplist '}' ';' 523 { 524 $$ = route; 525 route = NULL; 526 } 527 ; 528 529 530routehead : T_ROUTE IPV6ADDR '/' NUMBER 531 { 532 route = malloc(sizeof(struct AdvRoute)); 533 534 if (route == NULL) { 535 flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); 536 ABORT; 537 } 538 539 route_init_defaults(route, iface); 540 541 if ($4 > MAX_PrefixLen) 542 { 543 flog(LOG_ERR, "invalid route prefix length in %s, line %d", conf_file, num_lines); 544 ABORT; 545 } 546 547 route->PrefixLen = $4; 548 549 memcpy(&route->Prefix, $2, sizeof(struct in6_addr)); 550 } 551 ; 552 553 554optional_routeplist: /* empty */ 555 | routeplist 556 ; 557 558routeplist : routeplist routeparms 559 | routeparms 560 ; 561 562 563routeparms : T_AdvRoutePreference SIGNEDNUMBER ';' 564 { 565 route->AdvRoutePreference = $2; 566 } 567 | T_AdvRouteLifetime number_or_infinity ';' 568 { 569 route->AdvRouteLifetime = $2; 570 } 571 ; 572 573rdnsslist : rdnssdef optional_rdnsslist 574 { 575 $1->next = $2; 576 $$ = $1; 577 } 578 ; 579 580rdnssdef : rdnsshead '{' optional_rdnssplist '}' ';' 581 { 582 $$ = rdnss; 583 rdnss = NULL; 584 } 585 ; 586 587rdnssaddrs : rdnssaddrs rdnssaddr 588 | rdnssaddr 589 ; 590 591rdnssaddr : IPV6ADDR 592 { 593 if (!rdnss) { 594 /* first IP found */ 595 rdnss = malloc(sizeof(struct AdvRDNSS)); 596 597 if (rdnss == NULL) { 598 flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); 599 ABORT; 600 } 601 602 rdnss_init_defaults(rdnss, iface); 603 } 604 605 switch (rdnss->AdvRDNSSNumber) { 606 case 0: 607 memcpy(&rdnss->AdvRDNSSAddr1, $1, sizeof(struct in6_addr)); 608 rdnss->AdvRDNSSNumber++; 609 break; 610 case 1: 611 memcpy(&rdnss->AdvRDNSSAddr2, $1, sizeof(struct in6_addr)); 612 rdnss->AdvRDNSSNumber++; 613 break; 614 case 2: 615 memcpy(&rdnss->AdvRDNSSAddr3, $1, sizeof(struct in6_addr)); 616 rdnss->AdvRDNSSNumber++; 617 break; 618 default: 619 flog(LOG_CRIT, "Too many addresses in RDNSS section"); 620 ABORT; 621 } 622 623 } 624 ; 625 626rdnsshead : T_RDNSS rdnssaddrs 627 { 628 if (!rdnss) { 629 flog(LOG_CRIT, "No address specified in RDNSS section"); 630 ABORT; 631 } 632 } 633 ; 634 635optional_rdnssplist: /* empty */ 636 | rdnssplist 637 ; 638 639rdnssplist : rdnssplist rdnssparms 640 | rdnssparms 641 ; 642 643 644rdnssparms : T_AdvRDNSSPreference NUMBER ';' 645 { 646 rdnss->AdvRDNSSPreference = $2; 647 } 648 | T_AdvRDNSSOpenFlag SWITCH ';' 649 { 650 rdnss->AdvRDNSSOpenFlag = $2; 651 } 652 | T_AdvRDNSSLifetime number_or_infinity ';' 653 { 654 if ($2 < iface->MaxRtrAdvInterval && $2 != 0) { 655 flog(LOG_ERR, "AdvRDNSSLifetime must be at least MaxRtrAdvInterval"); 656 ABORT; 657 } 658 if ($2 > 2*(iface->MaxRtrAdvInterval)) 659 flog(LOG_WARNING, "Warning: AdvRDNSSLifetime <= 2*MaxRtrAdvInterval would allow stale DNS servers to be deleted faster"); 660 661 rdnss->AdvRDNSSLifetime = $2; 662 } 663 ; 664 665number_or_infinity : NUMBER 666 { 667 $$ = $1; 668 } 669 | INFINITY 670 { 671 $$ = (uint32_t)~0; 672 } 673 ; 674 675%% 676 677static 678void cleanup(void) 679{ 680 if (iface) 681 free(iface); 682 683 if (prefix) 684 free(prefix); 685 686 if (route) 687 free(route); 688 689 if (rdnss) 690 free(rdnss); 691} 692 693static void 694yyerror(char *msg) 695{ 696 cleanup(); 697 flog(LOG_ERR, "%s in %s, line %d: %s", msg, conf_file, num_lines, yytext); 698} 699