parser.y revision 55505
1/* 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the project nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: head/usr.sbin/rrenumd/parser.y 55505 2000-01-06 12:40:54Z shin $ 30 */ 31 32%{ 33#include <sys/param.h> 34#include <sys/ioctl.h> 35#include <sys/socket.h> 36#include <sys/uio.h> 37 38#include <net/if.h> 39#include <net/if_var.h> 40 41#include <netinet/in.h> 42#include <netinet/in_var.h> 43#include <netinet/icmp6.h> 44 45#include <netdb.h> 46#include <string.h> 47 48#include "rrenumd.h" 49 50struct config_is_set { 51 u_short cis_dest : 1; 52} cis; 53 54struct dst_list *dl_head; 55struct payload_list *pl_head, ple_cur; 56u_int retry; 57char errbuf[LINE_MAX]; 58 59extern int lineno; 60extern void yyerror __P((const char *s)); 61static struct payload_list * pllist_lookup __P((int seqnum)); 62static void pllist_enqueue __P((struct payload_list *pl_entry)); 63 64#define MAX_RETRYNUM 10 /* upper limit of retry in this rrenumd program */ 65#define MAX_SEQNUM 256 /* upper limit of seqnum in this rrenumd program */ 66#define NOSPEC -1 67 68%} 69 70%union { 71 u_long num; 72 struct { 73 char *cp; 74 int len; 75 } cs; 76 struct in_addr addr4; 77 struct in6_addr addr6; 78 struct { 79 struct in6_addr addr; 80 u_char plen; 81 } prefix; 82 struct dst_list *dl; 83 struct payload_list *pl; 84 struct sockaddr *sa; 85} 86 87%token <num> ADD CHANGE SETGLOBAL 88%token DEBUG_CMD DEST_CMD RETRY_CMD SEQNUM_CMD 89%token MATCH_PREFIX_CMD MAXLEN_CMD MINLEN_CMD 90%token USE_PREFIX_CMD KEEPLEN_CMD 91%token VLTIME_CMD PLTIME_CMD 92%token RAF_ONLINK_CMD RAF_AUTO_CMD RAF_DECRVALID_CMD RAF_DECRPREFD_CMD 93%token <num> DAYS HOURS MINUTES SECONDS INFINITY 94%token <num> ON OFF 95%token BCL ECL EOS ERROR 96%token <cs> NAME HOSTNAME QSTRING DECSTRING 97%token <addr4> IPV4ADDR 98%token <addr6> IPV6ADDR 99%token <num> PREFIXLEN 100 101%type <num> retrynum seqnum rrenum_cmd 102%type <num> prefixlen maxlen minlen keeplen vltime pltime 103%type <num> lifetime days hours minutes seconds 104%type <num> decstring 105%type <num> raf_onlink raf_auto raf_decrvalid raf_decrprefd flag 106%type <dl> dest_addrs dest_addr sin6 107%type <pl> rrenum_statement 108%type <cs> ifname 109%type <prefix> prefixval 110 111%% 112config: 113 /* empty */ 114 | statements 115 ; 116 117statements: 118 statement 119 | statements statement 120 ; 121 122statement: 123 debug_statement 124 | destination_statement 125 | rrenum_statement_without_seqnum 126 | rrenum_statement_with_seqnum 127 | error EOS 128 { 129 yyerrok; 130 } 131 | EOS 132 ; 133 134debug_statement: 135 DEBUG_CMD flag EOS 136 { 137#ifdef YYDEBUG 138 yydebug = $2; 139#endif /* YYDEBUG */ 140 } 141 ; 142 143destination_statement: 144 DEST_CMD dest_addrs retrynum EOS 145 { 146 dl_head = $2; 147 retry = $3; 148 } 149 ; 150 151dest_addrs: 152 dest_addr 153 | dest_addrs dest_addr 154 { 155 $2->dl_next = $1; 156 $$ = $2; 157 } 158 ; 159 160dest_addr : 161 sin6 162 { 163 with_v6dest = 1; 164 } 165 | sin6 ifname 166 { 167 struct sockaddr_in6 *sin6; 168 169 sin6 = (struct sockaddr_in6 *)$1->dl_dst; 170 sin6->sin6_scope_id = if_nametoindex($2.cp); 171 with_v6dest = 1; 172 $$ = $1; 173 } 174 | HOSTNAME 175 { 176 struct sockaddr_storage *ss; 177 struct addrinfo hints, *res; 178 int error; 179 180 memset(&hints, 0, sizeof(hints)); 181 hints.ai_flags = AI_CANONNAME; 182 hints.ai_family = AF_INET6; 183 hints.ai_socktype = SOCK_RAW; 184 hints.ai_protocol = 0; 185 error = getaddrinfo($1.cp, 0, &hints, &res); 186 if (error) { 187 sprintf(errbuf, "name resolution failed for %s" 188 ":%s", $1, gai_strerror(error)); 189 yyerror(errbuf); 190 } 191 ss = (struct sockaddr_storage *)malloc(sizeof(*ss)); 192 memset(ss, 0, sizeof(*ss)); 193 memcpy(ss, res->ai_addr, res->ai_addr->sa_len); 194 freeaddrinfo(res); 195 196 $$ = (struct dst_list *) 197 malloc(sizeof(struct dst_list)); 198 memset($$, 0, sizeof(struct dst_list)); 199 $$->dl_dst = (struct sockaddr *)ss; 200 } 201 ; 202 203sin6: 204 IPV6ADDR 205 { 206 struct sockaddr_in6 *sin6; 207 208 sin6 = (struct sockaddr_in6 *)malloc(sizeof(*sin6)); 209 memset(sin6, 0, sizeof(*sin6)); 210 sin6->sin6_len = sizeof(*sin6); 211 sin6->sin6_family = AF_INET6; 212 sin6->sin6_addr = $1; 213 214 $$ = (struct dst_list *) 215 malloc(sizeof(struct dst_list)); 216 memset($$, 0, sizeof(struct dst_list)); 217 $$->dl_dst = (struct sockaddr *)sin6; 218 } 219 220ifname: 221 NAME 222 { 223 $$.cp = strdup($1.cp); 224 $$.len = $1.len; 225 } 226 | QSTRING 227 { 228 $1.cp[$1.len - 1] = 0; 229 $$.cp = strdup(&$1.cp[1]); 230 $$.len = $1.len - 2; 231 } 232 ; 233 234retrynum: 235 /* empty */ 236 { 237 $$ = 2; 238 } 239 | RETRY_CMD decstring 240 { 241 if ($2 > MAX_RETRYNUM) 242 $2 = MAX_RETRYNUM; 243 $$ = $2; 244 } 245 ; 246 247rrenum_statement_with_seqnum: 248 SEQNUM_CMD seqnum 249 { 250 if (pllist_lookup($2)) { 251 sprintf(errbuf, "duplicate seqnum %d specified" 252 " at %d", $2, lineno); 253 yyerror(errbuf); 254 } 255 } 256 BCL rrenum_statement EOS ECL EOS 257 { 258 $5->pl_irr.rr_seqnum = $2; 259 pllist_enqueue($5); 260 } 261 ; 262 263seqnum: 264 /* empty */ 265 { 266 $$ = 0; 267 } 268 | decstring 269 { 270 if ($1 > MAX_SEQNUM) { 271 sprintf(errbuf, "seqnum %d is illegal for this" 272 " program. should be between 0 and %d", 273 $1, MAX_SEQNUM); 274 yyerror(errbuf); 275 } 276 $$ = $1; 277 } 278 ; 279 280rrenum_statement_without_seqnum: 281 rrenum_statement EOS 282 { 283 if (pllist_lookup(0)) { 284 sprintf(errbuf, "duplicate seqnum %d specified" 285 " at %d", 0, lineno); 286 yyerror(errbuf); 287 } 288 $1->pl_irr.rr_seqnum = 0; 289 pllist_enqueue($1); 290 } 291 ; 292 293rrenum_statement: 294 match_prefix_definition use_prefix_definition 295 { 296 $$ = (struct payload_list *) 297 malloc(sizeof(struct payload_list)); 298 memcpy($$, &ple_cur, sizeof(ple_cur)); 299 } 300 ; 301 302match_prefix_definition: 303 rrenum_cmd MATCH_PREFIX_CMD prefixval maxlen minlen 304 { 305 struct icmp6_router_renum *irr; 306 struct rr_pco_match *rpm; 307 308 irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; 309 rpm = (struct rr_pco_match *)(irr + 1); 310 memset(rpm, 0, sizeof(*rpm)); 311 312 rpm->rpm_code = $1; 313 rpm->rpm_prefix = $3.addr; 314 rpm->rpm_matchlen = $3.plen; 315 rpm->rpm_maxlen = $4; 316 rpm->rpm_minlen = $5; 317 } 318 ; 319 320rrenum_cmd: 321 /* empty */ 322 { 323 $$ = RPM_PCO_ADD; 324 } 325 | ADD 326 | CHANGE 327 | SETGLOBAL 328 ; 329 330prefixval: 331 IPV6ADDR prefixlen 332 { 333 $$.addr = $1; 334 $$.plen = $2; 335 } 336 ; 337 338prefixlen: 339 /* empty */ 340 { 341 $$ = 64; 342 } 343 | PREFIXLEN 344 ; 345 346maxlen: 347 /* empty */ 348 { 349 $$ = 128; 350 } 351 | MAXLEN_CMD decstring 352 { 353 if ($2 > 128) 354 $2 = 128; 355 $$ = $2; 356 } 357 ; 358 359minlen: 360 /* empty */ 361 { 362 $$ = 0; 363 } 364 | MINLEN_CMD decstring 365 { 366 if ($2 > 128) 367 $2 = 128; 368 $$ = $2; 369 } 370 ; 371 372use_prefix_definition: 373 /* empty */ 374 { 375 struct icmp6_router_renum *irr; 376 struct rr_pco_match *rpm; 377 struct rr_pco_use *rpu; 378 379 irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; 380 rpm = (struct rr_pco_match *)(irr + 1); 381 rpu = (struct rr_pco_use *)(rpm + 1); 382 memset(rpu, 0, sizeof(*rpu)); 383 } 384 | USE_PREFIX_CMD prefixval keeplen use_prefix_values 385 { 386 struct icmp6_router_renum *irr; 387 struct rr_pco_match *rpm; 388 struct rr_pco_use *rpu; 389 390 irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; 391 rpm = (struct rr_pco_match *)(irr + 1); 392 rpu = (struct rr_pco_use *)(rpm + 1); 393 394 rpu->rpu_prefix = $2.addr; 395 rpu->rpu_uselen = $2.plen; 396 rpu->rpu_keeplen = $3; 397 } 398 ; 399 400use_prefix_values: 401 /* empty */ 402 { 403 struct icmp6_router_renum *irr; 404 struct rr_pco_match *rpm; 405 struct rr_pco_use *rpu; 406 407 irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; 408 rpm = (struct rr_pco_match *)(irr + 1); 409 rpu = (struct rr_pco_use *)(rpm + 1); 410 memset(rpu, 0, sizeof(*rpu)); 411 412 rpu->rpu_vltime = DEF_VLTIME; 413 rpu->rpu_pltime = DEF_PLTIME; 414 rpu->rpu_ramask = 0; 415 rpu->rpu_flags = 0; 416 } 417 | BCL vltime pltime raf_onlink raf_auto raf_decrvalid raf_decrprefd ECL 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 memset(rpu, 0, sizeof(*rpu)); 427 428 rpu->rpu_vltime = $2; 429 rpu->rpu_pltime = $3; 430 if ($4 == NOSPEC) 431 rpu->rpu_ramask &= 432 ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; 433 else { 434 rpu->rpu_ramask |= 435 ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; 436 if ($4 == ON) 437 rpu->rpu_raflags |= 438 ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; 439 else 440 rpu->rpu_raflags &= 441 ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; 442 } 443 if ($5 == NOSPEC) 444 rpu->rpu_ramask &= 445 ICMP6_RR_PCOUSE_RAFLAGS_AUTO; 446 else { 447 rpu->rpu_ramask |= 448 ICMP6_RR_PCOUSE_RAFLAGS_AUTO; 449 if ($5 == ON) 450 rpu->rpu_raflags |= 451 ICMP6_RR_PCOUSE_RAFLAGS_AUTO; 452 else 453 rpu->rpu_raflags &= 454 ~ICMP6_RR_PCOUSE_RAFLAGS_AUTO; 455 } 456 rpu->rpu_flags = 0; 457 if ($6 == ON) 458 rpu->rpu_flags |= 459 ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME; 460 if ($7 == ON) 461 rpu->rpu_flags |= 462 ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME; 463 } 464 ; 465 466keeplen: 467 /* empty */ 468 { 469 $$ = 0; 470 } 471 | KEEPLEN_CMD decstring 472 { 473 if ($2 > 128) 474 $2 = 128; 475 $$ = $2; 476 } 477 ; 478 479 480vltime: 481 /* empty */ 482 { 483 $$ = DEF_VLTIME; 484 } 485 | VLTIME_CMD lifetime 486 { 487 $$ = htonl($2); 488 } 489 ; 490 491pltime: 492 /* empty */ 493 { 494 $$ = DEF_PLTIME; 495 } 496 | PLTIME_CMD lifetime 497 { 498 $$ = htonl($2); 499 } 500 501raf_onlink: 502 /* empty */ 503 { 504 $$ = NOSPEC; 505 } 506 | RAF_ONLINK_CMD flag 507 { 508 $$ = $2; 509 } 510 ; 511 512raf_auto: 513 /* empty */ 514 { 515 $$ = NOSPEC; 516 } 517 | RAF_AUTO_CMD flag 518 { 519 $$ = $2; 520 } 521 ; 522 523raf_decrvalid: 524 /* empty */ 525 { 526 $$ = NOSPEC; 527 } 528 | RAF_DECRVALID_CMD flag 529 { 530 $$ = $2; 531 } 532 ; 533 534raf_decrprefd: 535 /* empty */ 536 { 537 $$ = NOSPEC; 538 } 539 | RAF_DECRPREFD_CMD flag 540 { 541 $$ = $2; 542 } 543 ; 544 545flag: 546 ON 547 | OFF 548 ; 549 550lifetime: 551 decstring 552 | INFINITY 553 { 554 $$ = 0xffffffff; 555 } 556 | days hours minutes seconds 557 { 558 int d, h, m, s; 559 560 d = $1 * 24 * 60 * 60; 561 h = $2 * 60 * 60; 562 m = $3 * 60; 563 s = $4; 564 $$ = d + h + m + s; 565 } 566 ; 567 568days: 569 /* empty */ 570 { 571 $$ = 0; 572 } 573 | DAYS 574 ; 575 576hours: 577 /* empty */ 578 { 579 $$ = 0; 580 } 581 | HOURS 582 ; 583 584minutes: 585 /* empty */ 586 { 587 $$ = 0; 588 } 589 | MINUTES 590 ; 591 592seconds: 593 /* empty */ 594 { 595 $$ = 0; 596 } 597 | SECONDS 598 ; 599 600decstring: 601 DECSTRING 602 { 603 int dval; 604 605 dval = atoi($1.cp); 606 $$ = dval; 607 } 608 ; 609 610%% 611 612static struct payload_list * 613pllist_lookup(int seqnum) 614{ 615 struct payload_list *pl; 616 for (pl = pl_head; pl && pl->pl_irr.rr_seqnum != seqnum; 617 pl = pl->pl_next) 618 continue; 619 return (pl); 620} 621 622static void 623pllist_enqueue(struct payload_list *pl_entry) 624{ 625 struct payload_list *pl, *pl_last; 626 if (pl_head == NULL) { 627 pl_head = pl_entry; 628 return; 629 } 630 for (pl = pl_head; 631 pl && pl->pl_irr.rr_seqnum < pl_entry->pl_irr.rr_seqnum; 632 pl_last = pl, pl = pl->pl_next) 633 continue; 634 pl_last->pl_next = pl_entry; 635 636 return; 637} 638