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 #if 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 rr_pco_match *rpm; 339 340 rpm = &ple_cur.pl_rpm; 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