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