1 /* $KAME: parser.y,v 1.8 2000/11/08 03:03:34 jinmei Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the project nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 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 #if 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 rr_pco_match *rpm; 337 338 rpm = &ple_cur.pl_rpm; 339 memset(rpm, 0, sizeof(*rpm)); 340 341 rpm->rpm_code = $1; 342 rpm->rpm_prefix = $3.addr; 343 rpm->rpm_matchlen = $3.plen; 344 rpm->rpm_maxlen = $4; 345 rpm->rpm_minlen = $5; 346 } 347 ; 348 349 rrenum_cmd: 350 /* empty */ 351 { 352 $$ = RPM_PCO_ADD; 353 } 354 | ADD 355 | CHANGE 356 | SETGLOBAL 357 ; 358 359 prefixval: 360 IPV6ADDR prefixlen 361 { 362 $$.addr = $1; 363 $$.plen = $2; 364 } 365 ; 366 367 prefixlen: 368 /* empty */ 369 { 370 $$ = 64; 371 } 372 | PREFIXLEN 373 ; 374 375 maxlen: 376 /* empty */ 377 { 378 $$ = 128; 379 } 380 | MAXLEN_CMD decstring 381 { 382 if ($2 > 128) 383 $2 = 128; 384 $$ = $2; 385 } 386 ; 387 388 minlen: 389 /* empty */ 390 { 391 $$ = 0; 392 } 393 | MINLEN_CMD decstring 394 { 395 if ($2 > 128) 396 $2 = 128; 397 $$ = $2; 398 } 399 ; 400 401 use_prefix_definition: 402 /* empty */ 403 { 404 struct icmp6_router_renum *irr; 405 struct rr_pco_match *rpm; 406 struct rr_pco_use *rpu; 407 408 irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; 409 rpm = (struct rr_pco_match *)(irr + 1); 410 rpu = (struct rr_pco_use *)(rpm + 1); 411 memset(rpu, 0, sizeof(*rpu)); 412 } 413 | USE_PREFIX_CMD prefixval keeplen use_prefix_values 414 { 415 struct icmp6_router_renum *irr; 416 struct rr_pco_match *rpm; 417 struct rr_pco_use *rpu; 418 419 irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; 420 rpm = (struct rr_pco_match *)(irr + 1); 421 rpu = (struct rr_pco_use *)(rpm + 1); 422 423 rpu->rpu_prefix = $2.addr; 424 rpu->rpu_uselen = $2.plen; 425 rpu->rpu_keeplen = $3; 426 } 427 ; 428 429 use_prefix_values: 430 /* empty */ 431 { 432 struct icmp6_router_renum *irr; 433 struct rr_pco_match *rpm; 434 struct rr_pco_use *rpu; 435 436 irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; 437 rpm = (struct rr_pco_match *)(irr + 1); 438 rpu = (struct rr_pco_use *)(rpm + 1); 439 memset(rpu, 0, sizeof(*rpu)); 440 441 rpu->rpu_vltime = htonl(DEF_VLTIME); 442 rpu->rpu_pltime = htonl(DEF_PLTIME); 443 rpu->rpu_ramask = 0; 444 rpu->rpu_flags = 0; 445 } 446 | BCL vltime pltime raf_onlink raf_auto raf_decrvalid raf_decrprefd ECL 447 { 448 struct icmp6_router_renum *irr; 449 struct rr_pco_match *rpm; 450 struct rr_pco_use *rpu; 451 452 irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; 453 rpm = (struct rr_pco_match *)(irr + 1); 454 rpu = (struct rr_pco_use *)(rpm + 1); 455 memset(rpu, 0, sizeof(*rpu)); 456 457 rpu->rpu_vltime = $2; 458 rpu->rpu_pltime = $3; 459 if ($4 == NOSPEC) { 460 rpu->rpu_ramask &= 461 ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; 462 } else { 463 rpu->rpu_ramask |= 464 ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; 465 if ($4 == ON) { 466 rpu->rpu_raflags |= 467 ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; 468 } else { 469 rpu->rpu_raflags &= 470 ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; 471 } 472 } 473 if ($5 == NOSPEC) { 474 rpu->rpu_ramask &= 475 ICMP6_RR_PCOUSE_RAFLAGS_AUTO; 476 } else { 477 rpu->rpu_ramask |= 478 ICMP6_RR_PCOUSE_RAFLAGS_AUTO; 479 if ($5 == ON) { 480 rpu->rpu_raflags |= 481 ICMP6_RR_PCOUSE_RAFLAGS_AUTO; 482 } else { 483 rpu->rpu_raflags &= 484 ~ICMP6_RR_PCOUSE_RAFLAGS_AUTO; 485 } 486 } 487 rpu->rpu_flags = 0; 488 if ($6 == ON) { 489 rpu->rpu_flags |= 490 ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME; 491 } 492 if ($7 == ON) { 493 rpu->rpu_flags |= 494 ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME; 495 } 496 } 497 ; 498 499 keeplen: 500 /* empty */ 501 { 502 $$ = 0; 503 } 504 | KEEPLEN_CMD decstring 505 { 506 if ($2 > 128) 507 $2 = 128; 508 $$ = $2; 509 } 510 ; 511 512 513 vltime: 514 /* empty */ 515 { 516 $$ = htonl(DEF_VLTIME); 517 } 518 | VLTIME_CMD lifetime 519 { 520 $$ = htonl($2); 521 } 522 ; 523 524 pltime: 525 /* empty */ 526 { 527 $$ = htonl(DEF_PLTIME); 528 } 529 | PLTIME_CMD lifetime 530 { 531 $$ = htonl($2); 532 } 533 534 raf_onlink: 535 /* empty */ 536 { 537 $$ = NOSPEC; 538 } 539 | RAF_ONLINK_CMD flag 540 { 541 $$ = $2; 542 } 543 ; 544 545 raf_auto: 546 /* empty */ 547 { 548 $$ = NOSPEC; 549 } 550 | RAF_AUTO_CMD flag 551 { 552 $$ = $2; 553 } 554 ; 555 556 raf_decrvalid: 557 /* empty */ 558 { 559 $$ = NOSPEC; 560 } 561 | RAF_DECRVALID_CMD flag 562 { 563 $$ = $2; 564 } 565 ; 566 567 raf_decrprefd: 568 /* empty */ 569 { 570 $$ = NOSPEC; 571 } 572 | RAF_DECRPREFD_CMD flag 573 { 574 $$ = $2; 575 } 576 ; 577 578 flag: 579 ON { $$ = ON; } 580 | OFF { $$ = OFF; } 581 ; 582 583 lifetime: 584 decstring 585 | INFINITY 586 { 587 $$ = 0xffffffff; 588 } 589 | days hours minutes seconds 590 { 591 int d, h, m, s; 592 593 d = $1 * 24 * 60 * 60; 594 h = $2 * 60 * 60; 595 m = $3 * 60; 596 s = $4; 597 $$ = d + h + m + s; 598 } 599 ; 600 601 days: 602 /* empty */ 603 { 604 $$ = 0; 605 } 606 | DAYS 607 ; 608 609 hours: 610 /* empty */ 611 { 612 $$ = 0; 613 } 614 | HOURS 615 ; 616 617 minutes: 618 /* empty */ 619 { 620 $$ = 0; 621 } 622 | MINUTES 623 ; 624 625 seconds: 626 /* empty */ 627 { 628 $$ = 0; 629 } 630 | SECONDS 631 ; 632 633 decstring: 634 DECSTRING 635 { 636 int dval; 637 638 dval = atoi($1.cp); 639 $$ = dval; 640 } 641 ; 642 643 %% 644 645 static struct payload_list * 646 pllist_lookup(int seqnum) 647 { 648 struct payload_list *pl; 649 for (pl = pl_head; pl && pl->pl_irr.rr_seqnum != seqnum; 650 pl = pl->pl_next) 651 continue; 652 return (pl); 653 } 654 655 static void 656 pllist_enqueue(struct payload_list *pl_entry) 657 { 658 struct payload_list *pl, *pl_last; 659 660 pl_last = NULL; 661 for (pl = pl_head; 662 pl && pl->pl_irr.rr_seqnum < pl_entry->pl_irr.rr_seqnum; 663 pl_last = pl, pl = pl->pl_next) 664 continue; 665 if (pl_last) 666 pl_last->pl_next = pl_entry; 667 else 668 pl_head = pl_entry; 669 670 return; 671 } 672