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