1 /* $KAME: parser.y,v 1.8 2000/11/08 03:03:34 jinmei Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $FreeBSD$ 32 */ 33 34 %{ 35 #include <sys/param.h> 36 #include <sys/ioctl.h> 37 #include <sys/socket.h> 38 #include <sys/uio.h> 39 #include <sys/queue.h> 40 41 #include <net/if.h> 42 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 43 #include <net/if_var.h> 44 #endif /* __FreeBSD__ >= 3 */ 45 46 #include <netinet/in.h> 47 #include <netinet/in_var.h> 48 #include <netinet/icmp6.h> 49 50 #include <limits.h> 51 #include <netdb.h> 52 #include <string.h> 53 #include <stdio.h> 54 55 #include "rrenumd.h" 56 57 struct config_is_set { 58 u_short cis_dest : 1; 59 } cis; 60 61 struct dst_list *dl_head; 62 struct payload_list *pl_head, ple_cur; 63 u_int retry; 64 char errbuf[LINE_MAX]; 65 66 extern int lineno; 67 extern void yyerror(const char *s); 68 extern int yylex(void); 69 static struct payload_list * pllist_lookup(int seqnum); 70 static void pllist_enqueue(struct payload_list *pl_entry); 71 72 #define MAX_RETRYNUM 10 /* upper limit of retry in this rrenumd program */ 73 #define MAX_SEQNUM 256 /* upper limit of seqnum in this rrenumd program */ 74 #define NOSPEC -1 75 76 %} 77 78 %union { 79 u_long num; 80 struct { 81 char *cp; 82 int len; 83 } cs; 84 struct in_addr addr4; 85 struct in6_addr addr6; 86 struct { 87 struct in6_addr addr; 88 u_char plen; 89 } prefix; 90 struct dst_list *dl; 91 struct payload_list *pl; 92 struct sockaddr *sa; 93 } 94 95 %token <num> ADD CHANGE SETGLOBAL 96 %token DEBUG_CMD DEST_CMD RETRY_CMD SEQNUM_CMD 97 %token MATCH_PREFIX_CMD MAXLEN_CMD MINLEN_CMD 98 %token USE_PREFIX_CMD KEEPLEN_CMD 99 %token VLTIME_CMD PLTIME_CMD 100 %token RAF_ONLINK_CMD RAF_AUTO_CMD RAF_DECRVALID_CMD RAF_DECRPREFD_CMD 101 %token <num> DAYS HOURS MINUTES SECONDS INFINITY 102 %token <num> ON OFF 103 %token BCL ECL EOS ERROR 104 %token <cs> NAME HOSTNAME QSTRING DECSTRING 105 %token <addr4> IPV4ADDR 106 %token <addr6> IPV6ADDR 107 %token <num> PREFIXLEN 108 109 %type <num> retrynum seqnum rrenum_cmd 110 %type <num> prefixlen maxlen minlen keeplen vltime pltime 111 %type <num> lifetime days hours minutes seconds 112 %type <num> decstring 113 %type <num> raf_onlink raf_auto raf_decrvalid raf_decrprefd flag 114 %type <dl> dest_addrs dest_addr sin sin6 115 %type <pl> rrenum_statement 116 %type <cs> ifname 117 %type <prefix> prefixval 118 119 %% 120 config: 121 /* empty */ 122 | statements 123 ; 124 125 statements: 126 statement 127 | statements statement 128 ; 129 130 statement: 131 debug_statement 132 | destination_statement 133 | rrenum_statement_without_seqnum 134 | rrenum_statement_with_seqnum 135 | error EOS 136 { 137 yyerrok; 138 } 139 | EOS 140 ; 141 142 debug_statement: 143 DEBUG_CMD flag EOS 144 { 145 #ifdef YYDEBUG 146 yydebug = $2; 147 #endif /* YYDEBUG */ 148 } 149 ; 150 151 destination_statement: 152 DEST_CMD dest_addrs retrynum EOS 153 { 154 dl_head = $2; 155 retry = $3; 156 } 157 ; 158 159 dest_addrs: 160 dest_addr 161 | dest_addrs dest_addr 162 { 163 $2->dl_next = $1; 164 $$ = $2; 165 } 166 ; 167 168 dest_addr : 169 sin 170 { 171 with_v4dest = 1; 172 } 173 | sin6 174 { 175 with_v6dest = 1; 176 } 177 | sin6 ifname 178 { 179 struct sockaddr_in6 *sin6; 180 181 sin6 = (struct sockaddr_in6 *)$1->dl_dst; 182 sin6->sin6_scope_id = if_nametoindex($2.cp); 183 with_v6dest = 1; 184 $$ = $1; 185 } 186 | HOSTNAME 187 { 188 struct sockaddr_storage *ss; 189 struct addrinfo hints, *res; 190 int error; 191 192 memset(&hints, 0, sizeof(hints)); 193 hints.ai_flags = AI_CANONNAME; 194 hints.ai_family = AF_UNSPEC; 195 hints.ai_socktype = SOCK_RAW; 196 hints.ai_protocol = 0; 197 error = getaddrinfo($1.cp, 0, &hints, &res); 198 if (error) { 199 snprintf(errbuf, sizeof(errbuf), 200 "name resolution failed for %s:%s", 201 $1.cp, gai_strerror(error)); 202 yyerror(errbuf); 203 } 204 ss = (struct sockaddr_storage *)malloc(sizeof(*ss)); 205 memset(ss, 0, sizeof(*ss)); 206 memcpy(ss, res->ai_addr, res->ai_addr->sa_len); 207 freeaddrinfo(res); 208 209 $$ = (struct dst_list *) 210 malloc(sizeof(struct dst_list)); 211 memset($$, 0, sizeof(struct dst_list)); 212 $$->dl_dst = (struct sockaddr *)ss; 213 } 214 ; 215 216 sin: 217 IPV4ADDR 218 { 219 struct sockaddr_in *sin; 220 221 sin = (struct sockaddr_in *)malloc(sizeof(*sin)); 222 memset(sin, 0, sizeof(*sin)); 223 sin->sin_len = sizeof(*sin); 224 sin->sin_family = AF_INET; 225 sin->sin_addr = $1; 226 227 $$ = (struct dst_list *) 228 malloc(sizeof(struct dst_list)); 229 memset($$, 0, sizeof(struct dst_list)); 230 $$->dl_dst = (struct sockaddr *)sin; 231 } 232 ; 233 234 sin6: 235 IPV6ADDR 236 { 237 struct sockaddr_in6 *sin6; 238 239 sin6 = (struct sockaddr_in6 *)malloc(sizeof(*sin6)); 240 memset(sin6, 0, sizeof(*sin6)); 241 sin6->sin6_len = sizeof(*sin6); 242 sin6->sin6_family = AF_INET6; 243 sin6->sin6_addr = $1; 244 245 $$ = (struct dst_list *) 246 malloc(sizeof(struct dst_list)); 247 memset($$, 0, sizeof(struct dst_list)); 248 $$->dl_dst = (struct sockaddr *)sin6; 249 } 250 251 ifname: 252 NAME 253 { 254 $$.cp = strdup($1.cp); 255 $$.len = $1.len; 256 } 257 | QSTRING 258 { 259 $1.cp[$1.len - 1] = 0; 260 $$.cp = strdup(&$1.cp[1]); 261 $$.len = $1.len - 2; 262 } 263 ; 264 265 retrynum: 266 /* empty */ 267 { 268 $$ = 2; 269 } 270 | RETRY_CMD decstring 271 { 272 if ($2 > MAX_RETRYNUM) 273 $2 = MAX_RETRYNUM; 274 $$ = $2; 275 } 276 ; 277 278 rrenum_statement_with_seqnum: 279 SEQNUM_CMD seqnum 280 { 281 if (pllist_lookup($2)) { 282 snprintf(errbuf, sizeof(errbuf), 283 "duplicate seqnum %ld specified at %d", 284 $2, lineno); 285 yyerror(errbuf); 286 } 287 } 288 BCL rrenum_statement EOS ECL EOS 289 { 290 $5->pl_irr.rr_seqnum = $2; 291 pllist_enqueue($5); 292 } 293 ; 294 295 seqnum: 296 /* empty */ 297 { 298 $$ = 0; 299 } 300 | decstring 301 { 302 if ($1 > MAX_SEQNUM) { 303 snprintf(errbuf, sizeof(errbuf), 304 "seqnum %ld is illegal for this program. " 305 "should be between 0 and %d", 306 $1, MAX_SEQNUM); 307 yyerror(errbuf); 308 } 309 $$ = $1; 310 } 311 ; 312 313 rrenum_statement_without_seqnum: 314 rrenum_statement EOS 315 { 316 if (pllist_lookup(0)) { 317 snprintf(errbuf, sizeof(errbuf), 318 "duplicate seqnum %d specified at %d", 319 0, lineno); 320 yyerror(errbuf); 321 } 322 $1->pl_irr.rr_seqnum = 0; 323 pllist_enqueue($1); 324 } 325 ; 326 327 rrenum_statement: 328 match_prefix_definition use_prefix_definition 329 { 330 $$ = (struct payload_list *) 331 malloc(sizeof(struct payload_list)); 332 memcpy($$, &ple_cur, sizeof(ple_cur)); 333 } 334 ; 335 336 match_prefix_definition: 337 rrenum_cmd MATCH_PREFIX_CMD prefixval maxlen minlen 338 { 339 struct icmp6_router_renum *irr; 340 struct rr_pco_match *rpm; 341 342 irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; 343 rpm = (struct rr_pco_match *)(irr + 1); 344 memset(rpm, 0, sizeof(*rpm)); 345 346 rpm->rpm_code = $1; 347 rpm->rpm_prefix = $3.addr; 348 rpm->rpm_matchlen = $3.plen; 349 rpm->rpm_maxlen = $4; 350 rpm->rpm_minlen = $5; 351 } 352 ; 353 354 rrenum_cmd: 355 /* empty */ 356 { 357 $$ = RPM_PCO_ADD; 358 } 359 | ADD 360 | CHANGE 361 | SETGLOBAL 362 ; 363 364 prefixval: 365 IPV6ADDR prefixlen 366 { 367 $$.addr = $1; 368 $$.plen = $2; 369 } 370 ; 371 372 prefixlen: 373 /* empty */ 374 { 375 $$ = 64; 376 } 377 | PREFIXLEN 378 ; 379 380 maxlen: 381 /* empty */ 382 { 383 $$ = 128; 384 } 385 | MAXLEN_CMD decstring 386 { 387 if ($2 > 128) 388 $2 = 128; 389 $$ = $2; 390 } 391 ; 392 393 minlen: 394 /* empty */ 395 { 396 $$ = 0; 397 } 398 | MINLEN_CMD decstring 399 { 400 if ($2 > 128) 401 $2 = 128; 402 $$ = $2; 403 } 404 ; 405 406 use_prefix_definition: 407 /* empty */ 408 { 409 struct icmp6_router_renum *irr; 410 struct rr_pco_match *rpm; 411 struct rr_pco_use *rpu; 412 413 irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; 414 rpm = (struct rr_pco_match *)(irr + 1); 415 rpu = (struct rr_pco_use *)(rpm + 1); 416 memset(rpu, 0, sizeof(*rpu)); 417 } 418 | USE_PREFIX_CMD prefixval keeplen use_prefix_values 419 { 420 struct icmp6_router_renum *irr; 421 struct rr_pco_match *rpm; 422 struct rr_pco_use *rpu; 423 424 irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; 425 rpm = (struct rr_pco_match *)(irr + 1); 426 rpu = (struct rr_pco_use *)(rpm + 1); 427 428 rpu->rpu_prefix = $2.addr; 429 rpu->rpu_uselen = $2.plen; 430 rpu->rpu_keeplen = $3; 431 } 432 ; 433 434 use_prefix_values: 435 /* empty */ 436 { 437 struct icmp6_router_renum *irr; 438 struct rr_pco_match *rpm; 439 struct rr_pco_use *rpu; 440 441 irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; 442 rpm = (struct rr_pco_match *)(irr + 1); 443 rpu = (struct rr_pco_use *)(rpm + 1); 444 memset(rpu, 0, sizeof(*rpu)); 445 446 rpu->rpu_vltime = htonl(DEF_VLTIME); 447 rpu->rpu_pltime = htonl(DEF_PLTIME); 448 rpu->rpu_ramask = 0; 449 rpu->rpu_flags = 0; 450 } 451 | BCL vltime pltime raf_onlink raf_auto raf_decrvalid raf_decrprefd ECL 452 { 453 struct icmp6_router_renum *irr; 454 struct rr_pco_match *rpm; 455 struct rr_pco_use *rpu; 456 457 irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; 458 rpm = (struct rr_pco_match *)(irr + 1); 459 rpu = (struct rr_pco_use *)(rpm + 1); 460 memset(rpu, 0, sizeof(*rpu)); 461 462 rpu->rpu_vltime = $2; 463 rpu->rpu_pltime = $3; 464 if ($4 == NOSPEC) { 465 rpu->rpu_ramask &= 466 ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; 467 } else { 468 rpu->rpu_ramask |= 469 ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; 470 if ($4 == ON) { 471 rpu->rpu_raflags |= 472 ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; 473 } else { 474 rpu->rpu_raflags &= 475 ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; 476 } 477 } 478 if ($5 == NOSPEC) { 479 rpu->rpu_ramask &= 480 ICMP6_RR_PCOUSE_RAFLAGS_AUTO; 481 } else { 482 rpu->rpu_ramask |= 483 ICMP6_RR_PCOUSE_RAFLAGS_AUTO; 484 if ($5 == ON) { 485 rpu->rpu_raflags |= 486 ICMP6_RR_PCOUSE_RAFLAGS_AUTO; 487 } else { 488 rpu->rpu_raflags &= 489 ~ICMP6_RR_PCOUSE_RAFLAGS_AUTO; 490 } 491 } 492 rpu->rpu_flags = 0; 493 if ($6 == ON) { 494 rpu->rpu_flags |= 495 ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME; 496 } 497 if ($7 == ON) { 498 rpu->rpu_flags |= 499 ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME; 500 } 501 } 502 ; 503 504 keeplen: 505 /* empty */ 506 { 507 $$ = 0; 508 } 509 | KEEPLEN_CMD decstring 510 { 511 if ($2 > 128) 512 $2 = 128; 513 $$ = $2; 514 } 515 ; 516 517 518 vltime: 519 /* empty */ 520 { 521 $$ = htonl(DEF_VLTIME); 522 } 523 | VLTIME_CMD lifetime 524 { 525 $$ = htonl($2); 526 } 527 ; 528 529 pltime: 530 /* empty */ 531 { 532 $$ = htonl(DEF_PLTIME); 533 } 534 | PLTIME_CMD lifetime 535 { 536 $$ = htonl($2); 537 } 538 539 raf_onlink: 540 /* empty */ 541 { 542 $$ = NOSPEC; 543 } 544 | RAF_ONLINK_CMD flag 545 { 546 $$ = $2; 547 } 548 ; 549 550 raf_auto: 551 /* empty */ 552 { 553 $$ = NOSPEC; 554 } 555 | RAF_AUTO_CMD flag 556 { 557 $$ = $2; 558 } 559 ; 560 561 raf_decrvalid: 562 /* empty */ 563 { 564 $$ = NOSPEC; 565 } 566 | RAF_DECRVALID_CMD flag 567 { 568 $$ = $2; 569 } 570 ; 571 572 raf_decrprefd: 573 /* empty */ 574 { 575 $$ = NOSPEC; 576 } 577 | RAF_DECRPREFD_CMD flag 578 { 579 $$ = $2; 580 } 581 ; 582 583 flag: 584 ON { $$ = ON; } 585 | OFF { $$ = OFF; } 586 ; 587 588 lifetime: 589 decstring 590 | INFINITY 591 { 592 $$ = 0xffffffff; 593 } 594 | days hours minutes seconds 595 { 596 int d, h, m, s; 597 598 d = $1 * 24 * 60 * 60; 599 h = $2 * 60 * 60; 600 m = $3 * 60; 601 s = $4; 602 $$ = d + h + m + s; 603 } 604 ; 605 606 days: 607 /* empty */ 608 { 609 $$ = 0; 610 } 611 | DAYS 612 ; 613 614 hours: 615 /* empty */ 616 { 617 $$ = 0; 618 } 619 | HOURS 620 ; 621 622 minutes: 623 /* empty */ 624 { 625 $$ = 0; 626 } 627 | MINUTES 628 ; 629 630 seconds: 631 /* empty */ 632 { 633 $$ = 0; 634 } 635 | SECONDS 636 ; 637 638 decstring: 639 DECSTRING 640 { 641 int dval; 642 643 dval = atoi($1.cp); 644 $$ = dval; 645 } 646 ; 647 648 %% 649 650 static struct payload_list * 651 pllist_lookup(int seqnum) 652 { 653 struct payload_list *pl; 654 for (pl = pl_head; pl && pl->pl_irr.rr_seqnum != seqnum; 655 pl = pl->pl_next) 656 continue; 657 return (pl); 658 } 659 660 static void 661 pllist_enqueue(struct payload_list *pl_entry) 662 { 663 struct payload_list *pl, *pl_last; 664 665 pl_last = NULL; 666 for (pl = pl_head; 667 pl && pl->pl_irr.rr_seqnum < pl_entry->pl_irr.rr_seqnum; 668 pl_last = pl, pl = pl->pl_next) 669 continue; 670 if (pl_last) 671 pl_last->pl_next = pl_entry; 672 else 673 pl_head = pl_entry; 674 675 return; 676 } 677