parse.y revision 1.57
1/* $OpenBSD: parse.y,v 1.57 2002/03/27 18:16:22 mickey Exp $ */ 2 3/* 4 * Copyright (c) 2001 Markus Friedl. All rights reserved. 5 * Copyright (c) 2001 Daniel Hartmeier. 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27%{ 28#include <sys/types.h> 29#include <sys/socket.h> 30#include <sys/ioctl.h> 31#include <net/if.h> 32#include <netinet/in.h> 33#include <netinet/in_systm.h> 34#include <netinet/ip.h> 35#include <netinet/ip_icmp.h> 36#include <netinet/icmp6.h> 37#include <net/pfvar.h> 38#include <arpa/inet.h> 39 40#include <stdio.h> 41#include <stdlib.h> 42#include <ifaddrs.h> 43#include <netdb.h> 44#include <stdarg.h> 45#include <errno.h> 46#include <string.h> 47#include <ctype.h> 48#include <err.h> 49 50#include "pfctl_parser.h" 51 52static struct pfctl *pf = NULL; 53static FILE *fin = NULL; 54static int debug = 0; 55static int lineno = 1; 56static int errors = 0; 57static int natmode = 0; 58 59struct node_if { 60 char ifname[IFNAMSIZ]; 61 u_int8_t not; 62 struct node_if *next; 63}; 64 65struct node_proto { 66 u_int8_t proto; 67 struct node_proto *next; 68}; 69 70struct node_host { 71 struct pf_addr addr; 72 struct pf_addr mask; 73 u_int8_t af; 74 u_int8_t not; 75 u_int8_t noroute; 76 struct node_host *next; 77}; 78 79struct node_port { 80 u_int16_t port[2]; 81 u_int8_t op; 82 struct node_port *next; 83}; 84 85struct node_icmp { 86 u_int8_t code; 87 u_int8_t type; 88 u_int8_t proto; 89 struct node_icmp *next; 90}; 91 92struct peer { 93 struct node_host *host; 94 struct node_port *port; 95}; 96 97int rule_consistent(struct pf_rule *); 98int yyparse(void); 99struct pf_rule_addr *new_addr(void); 100void ipmask(struct pf_addr *, u_int8_t); 101void expand_rule_hosts(struct pf_rule *, 102 struct node_if *, struct node_proto *, 103 struct node_host *, struct node_port *, 104 struct node_host *, struct node_port *, 105 struct node_icmp *); 106void expand_rule_protos(struct pf_rule *, 107 struct node_if *, struct node_proto *, 108 struct node_host *, struct node_port *, 109 struct node_host *, struct node_port *, 110 struct node_icmp *); 111void expand_rule(struct pf_rule *, 112 struct node_if *, struct node_proto *, 113 struct node_host *, struct node_port *, 114 struct node_host *, struct node_port *, 115 struct node_icmp *); 116 117struct sym { 118 struct sym *next; 119 char *nam; 120 char *val; 121}; 122struct sym *symhead = NULL; 123 124int symset(char *name, char *val); 125char * symget(char *name); 126 127struct ifaddrs *ifa0_lookup(char *ifa_name); 128struct ifaddrs *ifa4_lookup(char *ifa_name); 129struct ifaddrs *ifa6_lookup(char *ifa_name); 130 131typedef struct { 132 union { 133 u_int32_t number; 134 int i; 135 char *string; 136 struct { 137 u_int8_t b1; 138 u_int8_t b2; 139 u_int16_t w; 140 } b; 141 struct range { 142 int a; 143 int b; 144 int t; 145 } range; 146 struct node_if *interface; 147 struct node_proto *proto; 148 struct node_icmp *icmp; 149 struct node_host *host; 150 struct node_port *port; 151 struct peer peer; 152 struct { 153 struct peer src, dst; 154 } fromto; 155 struct { 156 char *string; 157 struct pf_addr *addr; 158 u_int8_t rt; 159 u_int8_t af; 160 } route; 161 struct redirection { 162 struct node_host *address; 163 struct range rport; 164 } *redirection; 165 } v; 166 int lineno; 167} YYSTYPE; 168 169%} 170 171%token PASS BLOCK SCRUB RETURN IN OUT LOG LOGALL QUICK ON FROM TO FLAGS 172%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE 173%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF 174%token MINTTL IPV6ADDR ERROR ALLOWOPTS FASTROUTE ROUTETO DUPTO NO LABEL 175%token NOROUTE 176%token <v.string> STRING 177%token <v.number> NUMBER 178%token <v.i> PORTUNARY PORTBINARY 179%type <v.interface> interface if_list if_item_not if_item 180%type <v.number> port icmptype icmp6type minttl 181%type <v.i> no dir log quick af keep nodf allowopts 182%type <v.b> action flag flags blockspec 183%type <v.range> dport rport 184%type <v.proto> proto proto_list proto_item 185%type <v.icmp> icmpspec icmp_list icmp6_list icmp_item icmp6_item 186%type <v.fromto> fromto 187%type <v.peer> ipportspec 188%type <v.host> ipspec xhost host address host_list IPV6ADDR 189%type <v.port> portspec port_list port_item 190%type <v.route> route 191%type <v.redirection> redirection 192%type <v.string> label 193%% 194 195ruleset : /* empty */ 196 | ruleset '\n' 197 | ruleset pfrule '\n' 198 | ruleset natrule '\n' 199 | ruleset binatrule '\n' 200 | ruleset rdrrule '\n' 201 | ruleset varset '\n' 202 | ruleset error '\n' { errors++; } 203 ; 204 205varset : STRING PORTUNARY STRING 206 { 207 if (pf->opts & PF_OPT_VERBOSE) 208 printf("%s = %s\n", $1, $3); 209 if (symset($1, $3) == -1) { 210 yyerror("cannot store variable %s", $1); 211 YYERROR; 212 } 213 } 214 ; 215 216pfrule : action dir log quick interface route af proto fromto flags icmpspec keep nodf minttl allowopts label 217 { 218 struct pf_rule r; 219 220 if (natmode) { 221 yyerror("filter rule not permitted in nat mode"); 222 YYERROR; 223 } 224 memset(&r, 0, sizeof(r)); 225 226 r.action = $1.b1; 227 if ($1.b2) 228 r.rule_flag |= PFRULE_RETURNRST; 229 else 230 r.return_icmp = $1.w; 231 r.direction = $2; 232 r.log = $3; 233 r.quick = $4; 234 235 236 r.af = $7; 237 r.flags = $10.b1; 238 r.flagset = $10.b2; 239 240 r.keep_state = $12; 241 242 if ($13) 243 r.rule_flag |= PFRULE_NODF; 244 if ($14) 245 r.min_ttl = $14; 246 r.allow_opts = $15; 247 248 if ($6.rt) { 249 r.rt = $6.rt; 250 if ($6.string) { 251 memcpy(r.rt_ifname, $6.string, 252 sizeof(r.rt_ifname)); 253 free($6.string); 254 } 255 if ($6.addr) { 256 if (!r.af) 257 r.af = $6.af; 258 else if (r.af != $6.af) { 259 yyerror("address family" 260 " mismatch"); 261 YYERROR; 262 } 263 memcpy(&r.rt_addr, $6.addr, 264 sizeof(r.rt_addr)); 265 free($6.addr); 266 } 267 } 268 269 if ($16) { 270 if (strlen($16) >= PF_RULE_LABEL_SIZE) { 271 yyerror("rule label too long (max " 272 "%d chars)", PF_RULE_LABEL_SIZE-1); 273 YYERROR; 274 } 275 strcpy(r.label, $16); 276 free($16); 277 } 278 279 expand_rule(&r, $5, $8, $9.src.host, $9.src.port, 280 $9.dst.host, $9.dst.port, $11); 281 } 282 ; 283 284action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; } 285 | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } 286 | SCRUB { $$.b1 = PF_SCRUB; $$.b2 = $$.w = 0; } 287 ; 288 289blockspec : /* empty */ { $$.b2 = 0; $$.w = 0; } 290 | RETURNRST { $$.b2 = 1; $$.w = 0;} 291 | RETURNICMP { 292 $$.b2 = 0; 293 $$.w = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 294 } 295 | RETURNICMP6 { 296 $$.b2 = 0; 297 $$.w = (ICMP6_DST_UNREACH << 8) | 298 ICMP6_DST_UNREACH_NOPORT; 299 } 300 | RETURNICMP '(' NUMBER ')' { 301 $$.w = (ICMP_UNREACH << 8) | $3; 302 $$.b2 = 0; 303 } 304 | RETURNICMP '(' STRING ')' { 305 struct icmpcodeent *p; 306 307 if ((p = geticmpcodebyname(ICMP_UNREACH, $3, 308 AF_INET)) == NULL) { 309 yyerror("unknown icmp code %s", $3); 310 YYERROR; 311 } 312 $$.w = (p->type << 8) | p->code; 313 $$.b2 = 0; 314 } 315 | RETURNICMP6 '(' NUMBER ')' { 316 $$.w = (ICMP6_DST_UNREACH << 8) | $3; 317 $$.b2 = 0; 318 } 319 | RETURNICMP6 '(' STRING ')' { 320 struct icmpcodeent *p; 321 322 if ((p = geticmpcodebyname(ICMP6_DST_UNREACH, $3, 323 AF_INET6)) == NULL) { 324 yyerror("unknown icmp code %s", $3); 325 YYERROR; 326 } 327 $$.w = (p->type << 8) | p->code; 328 $$.b2 = 0; 329 } 330 ; 331 332dir : IN { $$ = PF_IN; } 333 | OUT { $$ = PF_OUT; } 334 ; 335 336log : /* empty */ { $$ = 0; } 337 | LOG { $$ = 1; } 338 | LOGALL { $$ = 2; } 339 ; 340 341quick : /* empty */ { $$ = 0; } 342 | QUICK { $$ = 1; } 343 ; 344 345interface : /* empty */ { $$ = NULL; } 346 | ON if_item_not { $$ = $2; } 347 | ON '{' if_list '}' { $$ = $3; } 348 ; 349 350if_list : if_item_not { $$ = $1; } 351 | if_list ',' if_item_not { $3->next = $1; $$ = $3; } 352 ; 353 354if_item_not : '!' if_item { $$ = $2; $$->not = 1; } 355 | if_item { $$ = $1; } 356 357if_item : STRING { 358 if (ifa0_lookup($1) == NULL) { 359 yyerror("unknown interface %s", $1); 360 YYERROR; 361 } 362 $$ = malloc(sizeof(struct node_if)); 363 if ($$ == NULL) 364 err(1, "if_item: malloc"); 365 strlcpy($$->ifname, $1, IFNAMSIZ); 366 $$->not = 0; 367 $$->next = NULL; 368 } 369 ; 370 371af : /* empty */ { $$ = 0; } 372 | INET { $$ = AF_INET; } 373 | INET6 { $$ = AF_INET6; } 374 375proto : /* empty */ { $$ = NULL; } 376 | PROTO proto_item { $$ = $2; } 377 | PROTO '{' proto_list '}' { $$ = $3; } 378 ; 379 380proto_list : proto_item { $$ = $1; } 381 | proto_list ',' proto_item { $3->next = $1; $$ = $3; } 382 ; 383 384proto_item : NUMBER { 385 struct protoent *p; 386 387 if ((p = getprotobynumber($1)) == NULL) { 388 yyerror("unknown protocol %d", $1); 389 YYERROR; 390 } 391 $$ = malloc(sizeof(struct node_proto)); 392 if ($$ == NULL) 393 err(1, "proto_item: malloc"); 394 $$->proto = p->p_proto; 395 $$->next = NULL; 396 } 397 | STRING { 398 struct protoent *p; 399 400 if ((p = getprotobyname($1)) == NULL) { 401 yyerror("unknown protocol %s", $1); 402 YYERROR; 403 } 404 $$ = malloc(sizeof(struct node_proto)); 405 if ($$ == NULL) 406 err(1, "proto_item: malloc"); 407 $$->proto = p->p_proto; 408 $$->next = NULL; 409 } 410 ; 411 412fromto : ALL { 413 $$.src.host = NULL; 414 $$.src.port = NULL; 415 $$.dst.host = NULL; 416 $$.dst.port = NULL; 417 } 418 | FROM ipportspec TO ipportspec { 419 $$.src = $2; 420 $$.dst = $4; 421 } 422 ; 423 424ipportspec : ipspec { $$.host = $1; $$.port = NULL; } 425 | ipspec PORT portspec { 426 $$.host = $1; 427 $$.port = $3; 428 } 429 ; 430 431ipspec : ANY { $$ = NULL; } 432 | xhost { $$ = $1; } 433 | '{' host_list '}' { $$ = $2; } 434 ; 435 436host_list : xhost { $$ = $1; } 437 | host_list ',' xhost { $3->next = $1; $$ = $3; } 438 ; 439 440xhost : '!' host { $$ = $2; $$->not = 1; } 441 | host { $$ = $1; } 442 | NOROUTE { 443 $$ = calloc(1, sizeof(struct node_host)); 444 if ($$ == NULL) 445 err(1, "xhost: calloc"); 446 $$->noroute = 1; 447 } 448 ; 449 450host : address { 451 $$ = $1; 452 if ($$->af == AF_INET) 453 ipmask(&$$->mask, 32); 454 else 455 ipmask(&$$->mask, 128); 456 } 457 | address '/' NUMBER { 458 if ($$->af == AF_INET) { 459 if ($3 < 0 || $3 > 32) { 460 yyerror("illegal netmask value %d", $3); 461 YYERROR; 462 } 463 } else { 464 if ($3 < 0 || $3 > 128) { 465 yyerror("illegal netmask value %d", $3); 466 YYERROR; 467 } 468 } 469 $$ = $1; 470 ipmask(&$$->mask, $3); 471 } 472 ; 473 474address : STRING { 475 struct hostent *hp; 476 struct ifaddrs *ifa; 477 478 if (ifa0_lookup($1)) { 479 /* an interface with this name exists */ 480 if ((ifa = ifa4_lookup($1))) { 481 struct sockaddr_in *sin = 482 (struct sockaddr_in *) 483 ifa->ifa_addr; 484 485 $$ = calloc(1, 486 sizeof(struct node_host)); 487 if ($$ == NULL) 488 err(1, "address: calloc"); 489 $$->af = AF_INET; 490 memcpy(&$$->addr, &sin->sin_addr, 491 sizeof(u_int32_t)); 492 } else if ((ifa = ifa6_lookup($1))) { 493 struct sockaddr_in6 *sin6 = 494 (struct sockaddr_in6 *) 495 ifa->ifa_addr; 496 497 $$ = calloc(1, 498 sizeof(struct node_host)); 499 if ($$ == NULL) 500 err(1, "address: calloc"); 501 $$->af = AF_INET6; 502 memcpy(&$$->addr, &sin6->sin6_addr, 503 sizeof(struct pf_addr)); 504 } else { 505 yyerror("interface %s has no IP " 506 "addresses", $1); 507 YYERROR; 508 } 509 } 510 else if ((hp = gethostbyname2($1, AF_INET)) == NULL) { 511 if ((hp = gethostbyname2($1, AF_INET6)) 512 == NULL) { 513 yyerror("cannot resolve %s", $1); 514 YYERROR; 515 } else { 516 $$ = calloc(1, sizeof(struct node_host)); 517 if ($$ == NULL) 518 err(1, "address: calloc"); 519 $$->af = AF_INET6; 520 memcpy(&$$->addr, hp->h_addr, 521 sizeof(struct pf_addr)); 522 } 523 } else { 524 $$ = calloc(1, sizeof(struct node_host)); 525 if ($$ == NULL) 526 err(1, "address: calloc"); 527 $$->af = AF_INET; 528 memcpy(&$$->addr, hp->h_addr, sizeof(u_int32_t)); 529 } 530 } 531 | NUMBER '.' NUMBER '.' NUMBER '.' NUMBER { 532 if ($1 < 0 || $3 < 0 || $5 < 0 || $7 < 0 || 533 $1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 534 yyerror("illegal ip address %d.%d.%d.%d", 535 $1, $3, $5, $7); 536 YYERROR; 537 } 538 $$ = calloc(1, sizeof(struct node_host)); 539 if ($$ == NULL) 540 err(1, "address: calloc"); 541 $$->af = AF_INET; 542 $$->addr.addr32[0] = htonl(($1 << 24) | 543 ($3 << 16) | ($5 << 8) | $7); 544 } 545 | IPV6ADDR { $$ = $1; } 546 ; 547 548portspec : port_item { $$ = $1; } 549 | '{' port_list '}' { $$ = $2; } 550 ; 551 552port_list : port_item { $$ = $1; } 553 | port_list ',' port_item { $3->next = $1; $$ = $3; } 554 ; 555 556port_item : port { 557 $$ = malloc(sizeof(struct node_port)); 558 if ($$ == NULL) 559 err(1, "port_item: malloc"); 560 $$->port[0] = $1; 561 $$->port[1] = $1; 562 $$->op = PF_OP_EQ; 563 $$->next = NULL; 564 } 565 | PORTUNARY port { 566 $$ = malloc(sizeof(struct node_port)); 567 if ($$ == NULL) 568 err(1, "port_item: malloc"); 569 $$->port[0] = $2; 570 $$->port[1] = $2; 571 $$->op = $1; 572 $$->next = NULL; 573 } 574 | port PORTBINARY port { 575 $$ = malloc(sizeof(struct node_port)); 576 if ($$ == NULL) 577 err(1, "port_item: malloc"); 578 $$->port[0] = $1; 579 $$->port[1] = $3; 580 $$->op = $2; 581 $$->next = NULL; 582 } 583 ; 584 585port : NUMBER { 586 if ($1 < 0 || $1 > 65535) { 587 yyerror("illegal port value %d", $1); 588 YYERROR; 589 } 590 $$ = htons($1); 591 } 592 | STRING { 593 struct servent *s = NULL; 594 595 s = getservbyname($1, "tcp"); 596 if (s == NULL) 597 s = getservbyname($1, "udp"); 598 if (s == NULL) { 599 yyerror("unknown protocol %s", $1); 600 YYERROR; 601 } 602 $$ = s->s_port; 603 } 604 ; 605 606flag : STRING { 607 int f; 608 609 if ((f = parse_flags($1)) < 0) { 610 yyerror("bad flags %s", $1); 611 YYERROR; 612 } 613 $$.b1 = f; 614 } 615 ; 616 617flags : /* empty */ { $$.b1 = 0; $$.b2 = 0; } 618 | FLAGS flag { $$.b1 = $2.b1; $$.b2 = 63; } 619 | FLAGS flag "/" flag { $$.b1 = $2.b1; $$.b2 = $4.b1; } 620 | FLAGS "/" flag { $$.b1 = 0; $$.b2 = $3.b1; } 621 ; 622 623icmpspec : /* empty */ { $$ = NULL; } 624 | ICMPTYPE icmp_item { $$ = $2; } 625 | ICMPTYPE '{' icmp_list '}' { $$ = $3; } 626 | ICMP6TYPE icmp6_item { $$ = $2; } 627 | ICMP6TYPE '{' icmp6_list '}' { $$ = $3; } 628 ; 629 630icmp_list : icmp_item { $$ = $1; } 631 | icmp_list ',' icmp_item { $3->next = $1; $$ = $3; } 632 ; 633 634icmp6_list : icmp6_item { $$ = $1; } 635 | icmp6_list ',' icmp6_item { $3->next = $1; $$ = $3; } 636 ; 637 638icmp_item : icmptype { 639 $$ = malloc(sizeof(struct node_icmp)); 640 if ($$ == NULL) 641 err(1, "icmp_item: malloc"); 642 $$->type = $1; 643 $$->code = 0; 644 $$->proto = IPPROTO_ICMP; 645 $$->next = NULL; 646 } 647 | icmptype CODE NUMBER { 648 $$ = malloc(sizeof(struct node_icmp)); 649 if ($$ == NULL) 650 err(1, "icmp_item: malloc"); 651 if ($3 < 0 || $3 > 255) { 652 yyerror("illegal icmp code %d", $3); 653 YYERROR; 654 } 655 $$->type = $1; 656 $$->code = $3 + 1; 657 $$->proto = IPPROTO_ICMP; 658 $$->next = NULL; 659 } 660 | icmptype CODE STRING { 661 struct icmpcodeent *p; 662 663 $$ = malloc(sizeof(struct node_icmp)); 664 if ($$ == NULL) 665 err(1, "icmp_item: malloc"); 666 $$->type = $1; 667 if ((p = geticmpcodebyname($1, $3, 668 AF_INET)) == NULL) { 669 yyerror("unknown icmp-code %s", $3); 670 YYERROR; 671 } 672 $$->code = p->code + 1; 673 $$->proto = IPPROTO_ICMP; 674 $$->next = NULL; 675 } 676 ; 677 678icmp6_item : icmp6type { 679 $$ = malloc(sizeof(struct node_icmp)); 680 if ($$ == NULL) 681 err(1, "icmp_item: malloc"); 682 $$->type = $1; 683 $$->code = 0; 684 $$->proto = IPPROTO_ICMPV6; 685 $$->next = NULL; 686 } 687 | icmp6type CODE NUMBER { 688 $$ = malloc(sizeof(struct node_icmp)); 689 if ($$ == NULL) 690 err(1, "icmp_item: malloc"); 691 if ($3 < 0 || $3 > 255) { 692 yyerror("illegal icmp6 code %d", $3); 693 YYERROR; 694 } 695 $$->type = $1; 696 $$->code = $3 + 1; 697 $$->proto = IPPROTO_ICMPV6; 698 $$->next = NULL; 699 } 700 | icmp6type CODE STRING { 701 struct icmpcodeent *p; 702 703 $$ = malloc(sizeof(struct node_icmp)); 704 if ($$ == NULL) 705 err(1, "icmp_item: malloc"); 706 $$->type = $1; 707 if ((p = geticmpcodebyname($1, $3, 708 AF_INET6)) == NULL) { 709 yyerror("unknown icmp6-code %s", $3); 710 YYERROR; 711 } 712 $$->code = p->code + 1; 713 $$->proto = IPPROTO_ICMPV6; 714 $$->next = NULL; 715 } 716 ; 717 718icmptype : STRING { 719 struct icmptypeent *p; 720 721 if ((p = geticmptypebyname($1, AF_INET)) == NULL) { 722 yyerror("unknown icmp-type %s", $1); 723 YYERROR; 724 } 725 $$ = p->type + 1; 726 } 727 | NUMBER { 728 if ($1 < 0 || $1 > 255) { 729 yyerror("illegal icmp type %d", $1); 730 YYERROR; 731 } 732 $$ = $1 + 1; 733 } 734 ; 735 736icmp6type : STRING { 737 struct icmptypeent *p; 738 739 if ((p = geticmptypebyname($1, AF_INET6)) == NULL) { 740 yyerror("unknown ipv6-icmp-type %s", $1); 741 YYERROR; 742 } 743 $$ = p->type + 1; 744 } 745 | NUMBER { 746 if ($1 < 0 || $1 > 255) { 747 yyerror("illegal icmp6 type %d", $1); 748 YYERROR; 749 } 750 $$ = $1 + 1; 751 } 752 ; 753 754keep : /* empty */ { $$ = 0; } 755 | KEEP STATE { $$ = PF_STATE_NORMAL; } 756 | MODULATE STATE { $$ = PF_STATE_MODULATE; } 757 ; 758 759minttl : /* empty */ { $$ = 0; } 760 | MINTTL NUMBER { 761 if ($2 < 0 || $2 > 255) { 762 yyerror("illegal min-ttl value %d", $2); 763 YYERROR; 764 } 765 $$ = $2; 766 } 767 ; 768 769nodf : /* empty */ { $$ = 0; } 770 | NODF { $$ = 1; } 771 ; 772 773allowopts : /* empty */ { $$ = 0; } 774 | ALLOWOPTS { $$ = 1; } 775 776label : /* empty */ { $$ = NULL; } 777 | LABEL STRING { 778 if (($$ = strdup($2)) == NULL) { 779 yyerror("rule label strdup() failed"); 780 YYERROR; 781 } 782 } 783 ; 784 785no : /* empty */ { $$ = 0; } 786 | NO { $$ = 1; } 787 ; 788 789rport : port { 790 $$.a = $1; 791 $$.b = $$.t = 0; 792 } 793 | port ':' '*' { 794 $$.a = $1; 795 $$.b = 0; 796 $$.t = PF_RPORT_RANGE; 797 } 798 ; 799 800redirection : /* empty */ { $$ = NULL; } 801 | ARROW address { 802 $$ = malloc(sizeof(struct redirection)); 803 if ($$ == NULL) 804 err(1, "redirection: malloc"); 805 $$->address = $2; 806 $$->rport.a = $$->rport.b = $$->rport.t = 0; 807 } 808 | ARROW address PORT rport { 809 $$ = malloc(sizeof(struct redirection)); 810 if ($$ == NULL) 811 err(1, "redirection: malloc"); 812 $$->address = $2; 813 $$->rport = $4; 814 } 815 ; 816 817natrule : no NAT interface proto FROM ipspec TO ipspec redirection 818 { 819 struct pf_nat nat; 820 821 if (!natmode) { 822 yyerror("nat rule not permitted in filter mode"); 823 YYERROR; 824 } 825 memset(&nat, 0, sizeof(nat)); 826 827 nat.no = $1; 828 if ($3 != NULL) { 829 memcpy(nat.ifname, $3->ifname, 830 sizeof(nat.ifname)); 831 nat.ifnot = $3->not; 832 free($3); 833 } 834 if ($4 != NULL) { 835 nat.proto = $4->proto; 836 free($4); 837 } 838 if ($6 != NULL && $8 != NULL && $6->af != $8->af) { 839 yyerror("nat ip versions must match"); 840 YYERROR; 841 } 842 if ($6 != NULL) { 843 nat.af = $6->af; 844 memcpy(&nat.saddr, &$6->addr, 845 sizeof(nat.saddr)); 846 memcpy(&nat.smask, &$6->mask, 847 sizeof(nat.smask)); 848 nat.snot = $6->not; 849 free($6); 850 } 851 if ($8 != NULL) { 852 nat.af = $8->af; 853 memcpy(&nat.daddr, &$8->addr, 854 sizeof(nat.daddr)); 855 memcpy(&nat.dmask, &$8->mask, 856 sizeof(nat.dmask)); 857 nat.dnot = $8->not; 858 free($8); 859 } 860 861 if (nat.no) { 862 if ($9 != NULL) { 863 yyerror("'no nat' rule does not need '->'"); 864 YYERROR; 865 } 866 } else { 867 if ($9 == NULL || $9->address == NULL) { 868 yyerror("'nat' rule requires '-> address'"); 869 YYERROR; 870 } 871 if (nat.af && $9->address->af != nat.af) { 872 yyerror("nat ip versions must match"); 873 YYERROR; 874 } 875 nat.af = $9->address->af; 876 memcpy(&nat.raddr, &$9->address->addr, 877 sizeof(nat.raddr)); 878 free($9->address); 879 free($9); 880 } 881 882 pfctl_add_nat(pf, &nat); 883 } 884 ; 885 886binatrule : no BINAT interface proto FROM address TO ipspec redirection 887 { 888 struct pf_binat binat; 889 890 if (!natmode) { 891 yyerror("binat rule not permitted in filter mode"); 892 YYERROR; 893 } 894 memset(&binat, 0, sizeof(binat)); 895 896 binat.no = $1; 897 if ($3 != NULL) { 898 memcpy(binat.ifname, $3->ifname, 899 sizeof(binat.ifname)); 900 free($3); 901 } 902 if ($4 != NULL) { 903 binat.proto = $4->proto; 904 free($4); 905 } 906 if ($6 != NULL && $8 != NULL && $6->af != $8->af) { 907 yyerror("binat ip versions must match"); 908 YYERROR; 909 } 910 if ($6 != NULL) { 911 binat.af = $6->af; 912 memcpy(&binat.saddr, &$6->addr, 913 sizeof(binat.saddr)); 914 free($6); 915 } 916 if ($8 != NULL) { 917 binat.af = $8->af; 918 memcpy(&binat.daddr, &$8->addr, 919 sizeof(binat.daddr)); 920 memcpy(&binat.dmask, &$8->mask, 921 sizeof(binat.dmask)); 922 binat.dnot = $8->not; 923 free($8); 924 } 925 926 if (binat.no) { 927 if ($9 != NULL) { 928 yyerror("'no binat' rule does not need" 929 " '->'"); 930 YYERROR; 931 } 932 } else { 933 if ($9 == NULL || $9->address == NULL) { 934 yyerror("'binat' rule requires" 935 " '-> address'"); 936 YYERROR; 937 } 938 if (binat.af && $9->address->af != binat.af) { 939 yyerror("binat ip versions must match"); 940 YYERROR; 941 } 942 binat.af = $9->address->af; 943 memcpy(&binat.raddr, &$9->address->addr, 944 sizeof(binat.raddr)); 945 free($9->address); 946 free($9); 947 } 948 949 pfctl_add_binat(pf, &binat); 950 } 951 952rdrrule : no RDR interface proto FROM ipspec TO ipspec dport redirection 953 { 954 struct pf_rdr rdr; 955 956 if (!natmode) { 957 yyerror("rdr rule not permitted in filter mode"); 958 YYERROR; 959 } 960 memset(&rdr, 0, sizeof(rdr)); 961 962 rdr.no = $1; 963 if ($3 != NULL) { 964 memcpy(rdr.ifname, $3->ifname, 965 sizeof(rdr.ifname)); 966 rdr.ifnot = $3->not; 967 free($3); 968 } 969 if ($4 != NULL) { 970 rdr.proto = $4->proto; 971 free($4); 972 } 973 if ($6 != NULL && $8 != NULL && $6->af != $8->af) { 974 yyerror("rdr ip versions must match"); 975 YYERROR; 976 } 977 if ($6 != NULL) { 978 rdr.af = $6->af; 979 memcpy(&rdr.saddr, &$6->addr, 980 sizeof(rdr.saddr)); 981 memcpy(&rdr.smask, &$6->mask, 982 sizeof(rdr.smask)); 983 rdr.snot = $6->not; 984 free($6); 985 } 986 if ($8 != NULL) { 987 rdr.af = $8->af; 988 memcpy(&rdr.daddr, &$8->addr, 989 sizeof(rdr.daddr)); 990 memcpy(&rdr.dmask, &$8->mask, 991 sizeof(rdr.dmask)); 992 rdr.dnot = $8->not; 993 free($8); 994 } 995 996 rdr.dport = $9.a; 997 rdr.dport2 = $9.b; 998 rdr.opts |= $9.t; 999 1000 if (rdr.no) { 1001 if ($10 != NULL) { 1002 yyerror("'no rdr' rule does not need '->'"); 1003 YYERROR; 1004 } 1005 } else { 1006 if ($10 == NULL || $10->address == NULL) { 1007 yyerror("'rdr' rule requires '-> address'"); 1008 YYERROR; 1009 } 1010 if (rdr.af && $10->address->af != rdr.af) { 1011 yyerror("rdr ip versions must match"); 1012 YYERROR; 1013 } 1014 rdr.af = $10->address->af; 1015 memcpy(&rdr.raddr, &$10->address->addr, 1016 sizeof(rdr.raddr)); 1017 free($10->address); 1018 rdr.rport = $10->rport.a; 1019 rdr.opts |= $10->rport.t; 1020 free($10); 1021 } 1022 1023 if (rdr.proto && rdr.proto != IPPROTO_TCP && 1024 rdr.proto != IPPROTO_UDP && 1025 (rdr.dport || rdr.dport2 || rdr.rport)) { 1026 yyerror("rdr ports are only valid for proto tcp/udp"); 1027 YYERROR; 1028 } 1029 1030 pfctl_add_rdr(pf, &rdr); 1031 } 1032 ; 1033 1034dport : /* empty */ { 1035 $$.a = $$.b = $$.t = 0; 1036 } 1037 | PORT port { 1038 $$.a = $2; 1039 $$.b = $$.t = 0; 1040 } 1041 | PORT port ':' port { 1042 $$.a = $2; 1043 $$.b = $4; 1044 $$.t = PF_DPORT_RANGE; 1045 } 1046 ; 1047 1048route : /* empty */ { 1049 $$.string = NULL; 1050 $$.rt = 0; 1051 $$.addr = NULL; 1052 $$.af = 0; 1053 } 1054 | FASTROUTE { 1055 $$.string = NULL; 1056 $$.rt = PF_FASTROUTE; 1057 $$.addr = NULL; 1058 } 1059 | ROUTETO STRING ':' address { 1060 $$.string = strdup($2); 1061 $$.rt = PF_ROUTETO; 1062 $$.addr = &$4->addr; 1063 $$.af = $4->af; 1064 } 1065 | ROUTETO STRING { 1066 $$.string = strdup($2); 1067 $$.rt = PF_ROUTETO; 1068 $$.addr = NULL; 1069 } 1070 | DUPTO STRING ':' address { 1071 $$.string = strdup($2); 1072 $$.rt = PF_DUPTO; 1073 $$.addr = &$4->addr; 1074 $$.af = $4->af; 1075 } 1076 | DUPTO STRING { 1077 $$.string = strdup($2); 1078 $$.rt = PF_DUPTO; 1079 $$.addr = NULL; 1080 } 1081 ; 1082%% 1083 1084int 1085yyerror(char *fmt, ...) 1086{ 1087 va_list ap; 1088 extern char *infile; 1089 errors = 1; 1090 1091 va_start(ap, fmt); 1092 fprintf(stderr, "%s:%d: ", infile, yylval.lineno); 1093 vfprintf(stderr, fmt, ap); 1094 fprintf(stderr, "\n"); 1095 va_end(ap); 1096 return (0); 1097} 1098 1099int 1100rule_consistent(struct pf_rule *r) 1101{ 1102 int problems = 0; 1103 1104 if (r->action == PF_SCRUB) { 1105 if (r->quick) { 1106 yyerror("quick does not apply to scrub"); 1107 problems++; 1108 } 1109 if (r->keep_state == PF_STATE_MODULATE) { 1110 yyerror("modulate state does not apply to scrub"); 1111 problems++; 1112 } 1113 if (r->keep_state == PF_STATE_NORMAL) { 1114 yyerror("keep state does not apply to scrub"); 1115 problems++; 1116 } 1117 if (r->src.port_op) { 1118 yyerror("src port does not apply to scrub"); 1119 problems++; 1120 } 1121 if (r->dst.port_op) { 1122 yyerror("dst port does not apply to scrub"); 1123 problems++; 1124 } 1125 if (r->type || r->code) { 1126 yyerror("icmp-type/code does not apply to scrub"); 1127 problems++; 1128 } 1129 } else { 1130 if (r->rule_flag & PFRULE_NODF) { 1131 yyerror("nodf only applies to scrub"); 1132 problems++; 1133 } 1134 if (r->min_ttl) { 1135 yyerror("min-ttl only applies to scrub"); 1136 problems++; 1137 } 1138 } 1139 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 1140 (r->src.port_op || r->dst.port_op)) { 1141 yyerror("port only applies to tcp/udp"); 1142 problems++; 1143 } 1144 if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 && 1145 (r->type || r->code)) { 1146 yyerror("icmp-type/code only applies to icmp"); 1147 problems++; 1148 } 1149 if (!r->af && (r->type || r->code)) { 1150 yyerror("must indicate address family with icmp-type/code"); 1151 problems++; 1152 } 1153 if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) || 1154 (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) { 1155 yyerror("icmp version does not match address family"); 1156 problems++; 1157 } 1158 if (!(r->rule_flag & PFRULE_RETURNRST) && r->return_icmp && 1159 ((r->af != AF_INET6 && (r->return_icmp>>8) != ICMP_UNREACH) || 1160 (r->af == AF_INET6 && (r->return_icmp>>8) != ICMP6_DST_UNREACH))) { 1161 yyerror("return-icmp version does not match address family"); 1162 problems++; 1163 } 1164 if (r->keep_state == PF_STATE_MODULATE && r->proto && 1165 r->proto != IPPROTO_TCP) { 1166 yyerror("modulate state can only be applied to TCP rules"); 1167 problems++; 1168 } 1169 if (r->allow_opts && r->action != PF_PASS) { 1170 yyerror("allow-opts can only be specified for pass rules"); 1171 problems++; 1172 } 1173 return (-problems); 1174} 1175 1176struct keywords { 1177 const char *k_name; 1178 int k_val; 1179}; 1180 1181#define CHECK_ROOT(T,r) \ 1182 do { \ 1183 if (r == NULL) { \ 1184 r = malloc(sizeof(T)); \ 1185 if (r == NULL) \ 1186 err(1, "malloc"); \ 1187 memset(r, 0, sizeof(T)); \ 1188 } \ 1189 } while (0) 1190 1191#define FREE_LIST(T,r) \ 1192 do { \ 1193 T *p, *n = r; \ 1194 while (n != NULL) { \ 1195 p = n; \ 1196 n = n->next; \ 1197 free(p); \ 1198 } \ 1199 } while (0) 1200 1201void expand_rule_hosts(struct pf_rule *r, 1202 struct node_if *interface, struct node_proto *proto, 1203 struct node_host *src_hosts, struct node_port *src_ports, 1204 struct node_host *dst_hosts, struct node_port *dst_ports, 1205 struct node_icmp *icmp_type) 1206{ 1207 struct node_host *src_host, *dst_host; 1208 struct node_port *src_port, *dst_port; 1209 int nomatch = 0; 1210 1211 src_host = src_hosts; 1212 while (src_host != NULL) { 1213 src_port = src_ports; 1214 while (src_port != NULL) { 1215 dst_host = dst_hosts; 1216 while (dst_host != NULL) { 1217 dst_port = dst_ports; 1218 while (dst_port != NULL) { 1219 memcpy(r->ifname, interface->ifname, 1220 sizeof(r->ifname)); 1221 r->proto = proto->proto; 1222 r->src.addr = src_host->addr; 1223 r->src.mask = src_host->mask; 1224 r->src.noroute = src_host->noroute; 1225 r->src.not = src_host->not; 1226 r->src.port[0] = src_port->port[0]; 1227 r->src.port[1] = src_port->port[1]; 1228 r->src.port_op = src_port->op; 1229 r->dst.addr = dst_host->addr; 1230 r->dst.mask = dst_host->mask; 1231 r->dst.noroute = dst_host->noroute; 1232 r->dst.not = dst_host->not; 1233 r->dst.port[0] = dst_port->port[0]; 1234 r->dst.port[1] = dst_port->port[1]; 1235 r->dst.port_op = dst_port->op; 1236 r->type = icmp_type->type; 1237 r->code = icmp_type->code; 1238 1239 if ((src_host->af && dst_host->af && 1240 r->af) && (src_host->af != 1241 dst_host->af || 1242 src_host->af != r->af || 1243 dst_host->af != r->af)) { 1244 yyerror("address family" 1245 " mismatch"); 1246 nomatch++; 1247 } else if ((src_host->af && 1248 dst_host->af) && 1249 (src_host->af != dst_host->af)) { 1250 yyerror("address family" 1251 " mismatch"); 1252 nomatch++; 1253 } else if ((src_host->af && r->af) && 1254 (src_host->af != r->af)) { 1255 yyerror("address family" 1256 " mismatch"); 1257 nomatch++; 1258 } else if ((dst_host->af && r->af) && 1259 (dst_host->af != r->af)) { 1260 yyerror("address family" 1261 " mismatch"); 1262 nomatch++; 1263 } else if (src_host->af && !r->af) { 1264 r->af = src_host->af; 1265 } else if (dst_host->af && !r->af) { 1266 r->af= dst_host->af; 1267 } 1268 1269 if (icmp_type->proto && 1270 r->proto != icmp_type->proto) { 1271 yyerror("icmp-type mismatch"); 1272 nomatch++; 1273 } 1274 1275 if (rule_consistent(r) < 0 || nomatch) 1276 yyerror("skipping rule " 1277 "due to errors"); 1278 else { 1279 r->nr = pf->rule_nr++; 1280 pfctl_add_rule(pf, r); 1281 } 1282 dst_port = dst_port->next; 1283 } 1284 dst_host = dst_host->next; 1285 } 1286 src_port = src_port->next; 1287 } 1288 src_host = src_host->next; 1289 } 1290} 1291 1292void expand_rule_protos(struct pf_rule *r, 1293 struct node_if *interface, struct node_proto *protos, 1294 struct node_host *src_hosts, struct node_port *src_ports, 1295 struct node_host *dst_hosts, struct node_port *dst_ports, 1296 struct node_icmp *icmp_types) 1297{ 1298 struct node_proto *proto; 1299 struct node_icmp *icmp_type; 1300 1301 proto = protos; 1302 while (proto != NULL) { 1303 icmp_type = icmp_types; 1304 while (icmp_type != NULL) { 1305 expand_rule_hosts(r, interface, proto, src_hosts, 1306 src_ports, dst_hosts, dst_ports, icmp_type); 1307 icmp_type = icmp_type->next; 1308 } 1309 proto = proto->next; 1310 } 1311} 1312 1313void 1314expand_rule(struct pf_rule *r, 1315 struct node_if *interfaces, struct node_proto *protos, 1316 struct node_host *src_hosts, struct node_port *src_ports, 1317 struct node_host *dst_hosts, struct node_port *dst_ports, 1318 struct node_icmp *icmp_types) 1319{ 1320 struct node_if *interface; 1321 1322 CHECK_ROOT(struct node_if, interfaces); 1323 CHECK_ROOT(struct node_proto, protos); 1324 CHECK_ROOT(struct node_host, src_hosts); 1325 CHECK_ROOT(struct node_port, src_ports); 1326 CHECK_ROOT(struct node_host, dst_hosts); 1327 CHECK_ROOT(struct node_port, dst_ports); 1328 CHECK_ROOT(struct node_icmp, icmp_types); 1329 1330 interface = interfaces; 1331 while (interface != NULL) { 1332 expand_rule_protos(r, interface, protos, src_hosts, 1333 src_ports, dst_hosts, dst_ports, icmp_types); 1334 interface = interface->next; 1335 } 1336 1337 FREE_LIST(struct node_if, interfaces); 1338 FREE_LIST(struct node_proto, protos); 1339 FREE_LIST(struct node_host, src_hosts); 1340 FREE_LIST(struct node_port, src_ports); 1341 FREE_LIST(struct node_host, dst_hosts); 1342 FREE_LIST(struct node_port, dst_ports); 1343 FREE_LIST(struct node_icmp, icmp_types); 1344 1345} 1346 1347#undef FREE_LIST 1348#undef CHECK_ROOT 1349 1350int 1351kw_cmp(k, e) 1352 const void *k, *e; 1353{ 1354 return (strcmp(k, ((struct keywords *)e)->k_name)); 1355} 1356 1357int 1358lookup(char *s) 1359{ 1360 /* this has to be sorted always */ 1361 static const struct keywords keywords[] = { 1362 { "all", ALL}, 1363 { "allow-opts", ALLOWOPTS}, 1364 { "any", ANY}, 1365 { "binat", BINAT}, 1366 { "block", BLOCK}, 1367 { "code", CODE}, 1368 { "dup-to", DUPTO}, 1369 { "fastroute", FASTROUTE}, 1370 { "flags", FLAGS}, 1371 { "from", FROM}, 1372 { "icmp-type", ICMPTYPE}, 1373 { "in", IN}, 1374 { "inet", INET}, 1375 { "inet6", INET6}, 1376 { "ipv6-icmp-type", ICMP6TYPE}, 1377 { "keep", KEEP}, 1378 { "label", LABEL}, 1379 { "log", LOG}, 1380 { "log-all", LOGALL}, 1381 { "min-ttl", MINTTL}, 1382 { "modulate", MODULATE}, 1383 { "nat", NAT}, 1384 { "no", NO}, 1385 { "no-df", NODF}, 1386 { "no-route", NOROUTE}, 1387 { "on", ON}, 1388 { "out", OUT}, 1389 { "pass", PASS}, 1390 { "port", PORT}, 1391 { "proto", PROTO}, 1392 { "quick", QUICK}, 1393 { "rdr", RDR}, 1394 { "return", RETURN}, 1395 { "return-icmp",RETURNICMP}, 1396 { "return-icmp6",RETURNICMP6}, 1397 { "return-rst", RETURNRST}, 1398 { "route-to", ROUTETO}, 1399 { "scrub", SCRUB}, 1400 { "state", STATE}, 1401 { "to", TO}, 1402 }; 1403 const struct keywords *p; 1404 1405 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 1406 sizeof(keywords[0]), kw_cmp); 1407 1408 if (p) { 1409 if (debug > 1) 1410 fprintf(stderr, "%s: %d\n", s, p->k_val); 1411 return (p->k_val); 1412 } else { 1413 if (debug > 1) 1414 fprintf(stderr, "string: %s\n", s); 1415 return (STRING); 1416 } 1417} 1418 1419char *parsebuf; 1420int parseindex; 1421 1422int 1423lgetc(FILE *fin) 1424{ 1425 int c, next; 1426 1427restart: 1428 if (parsebuf) { 1429 /* Reading characters from the parse buffer, instead of input */ 1430 c = parsebuf[parseindex++]; 1431 if (c != '\0') 1432 return (c); 1433 free(parsebuf); 1434 parsebuf = NULL; 1435 parseindex = 0; 1436 goto restart; 1437 } 1438 1439 c = getc(fin); 1440 if (c == '\\') { 1441 next = getc(fin); 1442 if (next != '\n') { 1443 ungetc(next, fin); 1444 return (c); 1445 } 1446 yylval.lineno = lineno; 1447 lineno++; 1448 goto restart; 1449 } 1450 return (c); 1451} 1452 1453int 1454lungetc(int c, FILE *fin) 1455{ 1456 if (parsebuf && parseindex) { 1457 /* XXX breaks on index 0 */ 1458 parseindex--; 1459 return (c); 1460 } 1461 return ungetc(c, fin); 1462} 1463 1464int 1465findeol() 1466{ 1467 int c; 1468 1469 if (parsebuf) { 1470 free(parsebuf); 1471 parsebuf = NULL; 1472 parseindex = 0; 1473 } 1474 1475 /* skip to either EOF or the first real EOL */ 1476 while (1) { 1477 c = lgetc(fin); 1478 if (c == '\\') { 1479 c = lgetc(fin); 1480 if (c == '\n') 1481 continue; 1482 } 1483 if (c == EOF || c == '\n') 1484 break; 1485 } 1486 return (ERROR); 1487} 1488 1489int 1490yylex(void) 1491{ 1492 char buf[8096], *p, *val; 1493 int endc, c, next; 1494 int token; 1495 1496top: 1497 p = buf; 1498 while ((c = lgetc(fin)) == ' ' || c == '\t') 1499 ; 1500 1501 yylval.lineno = lineno; 1502 if (c == '#') 1503 while ((c = lgetc(fin)) != '\n' && c != EOF) 1504 ; 1505 if (c == '$' && parsebuf == NULL) { 1506 while (1) { 1507 if ((c = lgetc(fin)) == EOF) 1508 return (0); 1509 if (p + 1 >= buf + sizeof(buf) - 1) { 1510 yyerror("string too long"); 1511 return (findeol()); 1512 } 1513 if (isalnum(c) || c == '_') { 1514 *p++ = (char)c; 1515 continue; 1516 } 1517 *p = '\0'; 1518 lungetc(c, fin); 1519 break; 1520 } 1521 val = symget(buf); 1522 if (val == NULL) 1523 return (ERROR); 1524 parsebuf = strdup(val); 1525 if (parsebuf == NULL) 1526 err(1, "parsebuf: strdup"); 1527 parseindex = 0; 1528 goto top; 1529 } 1530 1531 switch (c) { 1532 case '\'': 1533 case '"': 1534 endc = c; 1535 while (1) { 1536 if ((c = lgetc(fin)) == EOF) 1537 return (0); 1538 if (c == endc) { 1539 *p = '\0'; 1540 break; 1541 } 1542 if (c == '\n') 1543 continue; 1544 if (p + 1 >= buf + sizeof(buf) - 1) { 1545 yyerror("string too long"); 1546 return (findeol()); 1547 } 1548 *p++ = (char)c; 1549 } 1550 yylval.v.string = strdup(buf); 1551 if (yylval.v.string == NULL) 1552 err(1, "yylex: strdup"); 1553 return (STRING); 1554 case '=': 1555 yylval.v.i = PF_OP_EQ; 1556 return (PORTUNARY); 1557 case '!': 1558 next = lgetc(fin); 1559 if (next == '=') { 1560 yylval.v.i = PF_OP_NE; 1561 return (PORTUNARY); 1562 } 1563 lungetc(next, fin); 1564 break; 1565 case '<': 1566 next = lgetc(fin); 1567 if (next == '>') { 1568 yylval.v.i = PF_OP_XRG; 1569 return (PORTBINARY); 1570 } else if (next == '=') { 1571 yylval.v.i = PF_OP_LE; 1572 } else { 1573 yylval.v.i = PF_OP_LT; 1574 lungetc(next, fin); 1575 } 1576 return (PORTUNARY); 1577 break; 1578 case '>': 1579 next = lgetc(fin); 1580 if (next == '<') { 1581 yylval.v.i = PF_OP_IRG; 1582 return (PORTBINARY); 1583 } else if (next == '=') { 1584 yylval.v.i = PF_OP_GE; 1585 } else { 1586 yylval.v.i = PF_OP_GT; 1587 lungetc(next, fin); 1588 } 1589 return (PORTUNARY); 1590 break; 1591 case '-': 1592 next = lgetc(fin); 1593 if (next == '>') 1594 return (ARROW); 1595 lungetc(next, fin); 1596 break; 1597 } 1598 1599 /* Need to parse v6 addresses before tokenizing numbers. ick */ 1600 if (isxdigit(c) || c == ':') { 1601 struct node_host *node = NULL; 1602 u_int32_t addr[4]; 1603 char lookahead[46]; 1604 int i = 0, notv6addr = 0; 1605 1606 lookahead[i] = c; 1607 1608 while (i < sizeof(lookahead) && 1609 (isxdigit(c) || c == ':' || c == '.')) { 1610 lookahead[++i] = c = lgetc(fin); 1611 } 1612 1613 /* quick check avoids calling inet_pton too often */ 1614 if (isalnum(c)) { 1615 notv6addr++; 1616 } 1617 lungetc(lookahead[i], fin); 1618 lookahead[i] = '\0'; 1619 1620 if(!notv6addr && inet_pton(AF_INET6, lookahead, &addr) == 1) { 1621 node = calloc(1, sizeof(struct node_host)); 1622 node->af = AF_INET6; 1623 memcpy (&node->addr, &addr, sizeof(addr)); 1624 yylval.v.host = node; 1625 return IPV6ADDR; 1626 } else { 1627 free(node); 1628 while (i > 1) { 1629 lungetc(lookahead[--i], fin); 1630 } 1631 c = lookahead[--i]; 1632 } 1633 } 1634 1635 if (isdigit(c)) { 1636 int index = 0, base = 10; 1637 u_int64_t n = 0; 1638 1639 yylval.v.number = 0; 1640 while (1) { 1641 if (base == 10) { 1642 if (!isdigit(c)) 1643 break; 1644 c -= '0'; 1645 } else if (base == 16) { 1646 if (isdigit(c)) 1647 c -= '0'; 1648 else if (c >= 'a' && c <= 'f') 1649 c -= 'a' - 10; 1650 else if (c >= 'A' && c <= 'F') 1651 c -= 'A' - 10; 1652 else 1653 break; 1654 } 1655 n = n * base + c; 1656 1657 if (n > UINT_MAX) { 1658 yyerror("number is too large"); 1659 return (ERROR); 1660 } 1661 c = lgetc(fin); 1662 if (c == EOF) 1663 break; 1664 if (index++ == 0 && n == 0 && c == 'x') { 1665 base = 16; 1666 c = lgetc(fin); 1667 if (c == EOF) 1668 break; 1669 } 1670 } 1671 yylval.v.number = (u_int32_t)n; 1672 1673 if (c != EOF) 1674 lungetc(c, fin); 1675 if (debug > 1) 1676 fprintf(stderr, "number: %d\n", yylval.v.number); 1677 return (NUMBER); 1678 } 1679 1680#define allowed_in_string(x) \ 1681 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 1682 x != '{' && x != '}' && x != '<' && x != '>' && \ 1683 x != '!' && x != '=' && x != '/' && x != '#' && x != ',' && x != ':')) 1684 1685 if (isalnum(c)) { 1686 do { 1687 *p++ = c; 1688 if (p-buf >= sizeof buf) { 1689 yyerror("string too long"); 1690 return (ERROR); 1691 } 1692 } while ((c = lgetc(fin)) != EOF && (allowed_in_string(c))); 1693 lungetc(c, fin); 1694 *p = '\0'; 1695 token = lookup(buf); 1696 yylval.v.string = strdup(buf); 1697 if (yylval.v.string == NULL) 1698 err(1, "yylex: strdup"); 1699 return (token); 1700 } 1701 if (c == '\n') { 1702 yylval.lineno = lineno; 1703 lineno++; 1704 } 1705 if (c == EOF) 1706 return (0); 1707 return (c); 1708} 1709 1710int 1711parse_rules(FILE *input, struct pfctl *xpf) 1712{ 1713 natmode = 0; 1714 fin = input; 1715 pf = xpf; 1716 errors = 0; 1717 yyparse(); 1718 return (errors ? -1 : 0); 1719} 1720 1721int 1722parse_nat(FILE *input, struct pfctl *xpf) 1723{ 1724 natmode = 1; 1725 fin = input; 1726 pf = xpf; 1727 errors = 0; 1728 yyparse(); 1729 return (errors ? -1 : 0); 1730} 1731 1732void 1733ipmask(struct pf_addr *m, u_int8_t b) 1734{ 1735 int i, j = 0; 1736 1737 while (b >= 32) { 1738 m->addr32[j++] = 0xffffffff; 1739 b -= 32; 1740 } 1741 for (i = 31; i > 31-b; --i) 1742 m->addr32[j] |= (1 << i); 1743 if (b) 1744 m->addr32[j] = htonl(m->addr32[j]); 1745} 1746 1747struct pf_rule_addr * 1748new_addr(void) 1749{ 1750 struct pf_rule_addr *ra; 1751 1752 ra = malloc(sizeof(struct pf_rule_addr)); 1753 if (ra == NULL) 1754 err(1, "new_addr: malloc failed"); 1755 memset(ra, 0, sizeof(*ra)); 1756 return (ra); 1757} 1758 1759/* 1760 * Over-designed efficiency is a French and German concept, so how about 1761 * we wait until they discover this ugliness and make it all fancy. 1762 */ 1763int 1764symset(char *nam, char *val) 1765{ 1766 struct sym *sym; 1767 1768 sym = calloc(1, sizeof(*sym)); 1769 if (sym == NULL) 1770 return (-1); 1771 sym->nam = strdup(nam); 1772 if (sym->nam == NULL) { 1773 free(sym); 1774 return (-1); 1775 } 1776 sym->val = strdup(val); 1777 if (sym->val == NULL) { 1778 free(sym->nam); 1779 free(sym); 1780 return (-1); 1781 } 1782 sym->next = symhead; 1783 symhead = sym; 1784 return (0); 1785} 1786 1787char * 1788symget(char *nam) 1789{ 1790 struct sym *sym; 1791 1792 for (sym = symhead; sym; sym = sym->next) 1793 if (strcmp(nam, sym->nam) == 0) 1794 return (sym->val); 1795 return (NULL); 1796} 1797 1798struct ifaddrs **ifa0tab, **ifa4tab, **ifa6tab; 1799int ifa0len, ifa4len, ifa6len; 1800 1801int 1802ifa_comp(const void *p1, const void *p2) 1803{ 1804 struct ifaddrs *ifa1 = *(struct ifaddrs **)p1; 1805 struct ifaddrs *ifa2 = *(struct ifaddrs **)p2; 1806 1807 return strcmp(ifa1->ifa_name, ifa2->ifa_name); 1808} 1809 1810void 1811ifa_load(void) 1812{ 1813 struct ifaddrs *ifap, *ifa; 1814 int ifalen = 0; 1815 1816 if (getifaddrs(&ifap) < 0) 1817 err(1, "getifaddrs"); 1818 for (ifa = ifap; ifa; ifa = ifa->ifa_next) 1819 ifalen++; 1820 /* (over-)allocate tables */ 1821 ifa0tab = malloc(ifalen * sizeof(void *)); 1822 ifa4tab = malloc(ifalen * sizeof(void *)); 1823 ifa6tab = malloc(ifalen * sizeof(void *)); 1824 if (!ifa0tab || !ifa4tab || !ifa6tab) 1825 err(1, "malloc"); 1826 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 1827 if (ifa->ifa_addr->sa_family == AF_LINK) { 1828 if (bsearch(&ifa, ifa0tab, ifa0len, sizeof(void *), 1829 ifa_comp)) 1830 continue; /* take only the first LINK address */ 1831 ifa0tab[ifa0len++] = ifa; 1832 qsort(ifa0tab, ifa0len, sizeof(void *), ifa_comp); 1833 } 1834 if (ifa->ifa_addr->sa_family == AF_INET) { 1835 if (bsearch(&ifa, ifa4tab, ifa4len, sizeof(void *), 1836 ifa_comp)) 1837 continue; /* take only the first IPv4 address */ 1838 ifa4tab[ifa4len++] = ifa; 1839 qsort(ifa4tab, ifa4len, sizeof(void *), ifa_comp); 1840 } 1841 if (ifa->ifa_addr->sa_family == AF_INET6) { 1842 /* XXX - better address selection required! */ 1843 if (bsearch(&ifa, ifa6tab, ifa6len, sizeof(void *), 1844 ifa_comp)) 1845 continue; /* take only the first IPv6 address */ 1846 ifa6tab[ifa6len++] = ifa; 1847 qsort(ifa6tab, ifa6len, sizeof(void *), ifa_comp); 1848 } 1849 } 1850 /* shrink tables */ 1851 ifa0tab = realloc(ifa0tab, ifa0len * sizeof(void *)); 1852 ifa4tab = realloc(ifa4tab, ifa4len * sizeof(void *)); 1853 ifa6tab = realloc(ifa6tab, ifa6len * sizeof(void *)); 1854 if (!ifa0tab || !ifa4tab || !ifa6tab) 1855 err(1, "realloc"); 1856} 1857 1858struct ifaddrs * 1859ifa0_lookup(char *ifa_name) 1860{ 1861 struct ifaddrs ifa, *ifp = &ifa, **ifpp; 1862 1863 if (!ifa0tab) 1864 ifa_load(); 1865 ifa.ifa_name = ifa_name; 1866 ifpp = bsearch(&ifp, ifa0tab, ifa0len, sizeof(void *), ifa_comp); 1867 return ifpp ? *ifpp : NULL; 1868} 1869 1870struct ifaddrs * 1871ifa4_lookup(char *ifa_name) 1872{ 1873 struct ifaddrs ifa, *ifp = &ifa, **ifpp; 1874 1875 if (!ifa4tab) 1876 ifa_load(); 1877 ifa.ifa_name = ifa_name; 1878 ifpp = bsearch(&ifp, ifa4tab, ifa4len, sizeof(void *), ifa_comp); 1879 return ifpp ? *ifpp : NULL; 1880} 1881 1882struct ifaddrs * 1883ifa6_lookup(char *ifa_name) 1884{ 1885 struct ifaddrs ifa, *ifp = &ifa, **ifpp; 1886 1887 if (!ifa6tab) 1888 ifa_load(); 1889 ifa.ifa_name = ifa_name; 1890 ifpp = bsearch(&ifp, ifa6tab, ifa6len, sizeof(void *), ifa_comp); 1891 return ifpp ? *ifpp : NULL; 1892} 1893 1894