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