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