parse.y revision 1.111
1/* $OpenBSD: parse.y,v 1.111 2002/07/05 16:48:44 henning 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#include <pwd.h> 50 51#include "pfctl_parser.h" 52 53static struct pfctl *pf = NULL; 54static FILE *fin = NULL; 55static int debug = 0; 56static int lineno = 1; 57static int errors = 0; 58static int rulestate = 0; 59 60enum {PFCTL_STATE_NONE=0, PFCTL_STATE_OPTION=1, 61 PFCTL_STATE_SCRUB=2, PFCTL_STATE_NAT=3, 62 PFCTL_STATE_FILTER=4}; 63 64struct node_if { 65 char ifname[IFNAMSIZ]; 66 u_int8_t not; 67 struct node_if *next; 68}; 69 70struct node_proto { 71 u_int8_t proto; 72 struct node_proto *next; 73}; 74 75struct node_host { 76 struct pf_addr_wrap addr; 77 struct pf_addr mask; 78 u_int8_t af; 79 u_int8_t not; 80 u_int8_t noroute; 81 struct node_host *next; 82 u_int32_t ifindex; /* link-local IPv6 addrs */ 83}; 84 85struct node_port { 86 u_int16_t port[2]; 87 u_int8_t op; 88 struct node_port *next; 89}; 90 91struct node_uid { 92 uid_t uid[2]; 93 u_int8_t op; 94 struct node_uid *next; 95}; 96 97struct node_gid { 98 gid_t gid[2]; 99 u_int8_t op; 100 struct node_gid *next; 101}; 102 103struct node_icmp { 104 u_int8_t code; 105 u_int8_t type; 106 u_int8_t proto; 107 struct node_icmp *next; 108}; 109 110enum { PF_STATE_OPT_MAX=0, PF_STATE_OPT_TIMEOUT=1 }; 111struct node_state_opt { 112 int type; 113 union { 114 u_int32_t max_states; 115 struct { 116 int number; 117 u_int32_t seconds; 118 } timeout; 119 } data; 120 struct node_state_opt *next; 121}; 122 123struct peer { 124 struct node_host *host; 125 struct node_port *port; 126}; 127 128int rule_consistent(struct pf_rule *); 129int yyparse(void); 130void ipmask(struct pf_addr *, u_int8_t); 131void expand_rdr(struct pf_rdr *, struct node_if *, struct node_host *, 132 struct node_host *); 133void expand_nat(struct pf_nat *, struct node_host *, struct node_port *, 134 struct node_host *, struct node_port *); 135void expand_label_addr(const char *, char *, u_int8_t, struct node_host *); 136void expand_label_port(const char *, char *, struct node_port *); 137void expand_label_proto(const char *, char *, u_int8_t); 138void expand_label_nr(const char *, char *); 139void expand_label(char *, u_int8_t, struct node_host *, struct node_port *, 140 struct node_host *, struct node_port *, u_int8_t); 141void expand_rule(struct pf_rule *, struct node_if *, struct node_proto *, 142 struct node_host *, struct node_port *, struct node_host *, 143 struct node_port *, struct node_uid *, struct node_gid *, 144 struct node_icmp *); 145int check_rulestate(int); 146 147struct sym { 148 struct sym *next; 149 char *nam; 150 char *val; 151}; 152struct sym *symhead = NULL; 153 154int symset(const char *name, const char *val); 155char * symget(const char *name); 156 157struct ifaddrs *ifa0_lookup(char *ifa_name); 158struct ifaddrs *ifa4_lookup(char *ifa_name); 159struct ifaddrs *ifa6_lookup(char *ifa_name); 160 161typedef struct { 162 union { 163 u_int32_t number; 164 int i; 165 char *string; 166 struct { 167 u_int8_t b1; 168 u_int8_t b2; 169 u_int16_t w; 170 } b; 171 struct range { 172 int a; 173 int b; 174 int t; 175 } range; 176 struct node_if *interface; 177 struct node_proto *proto; 178 struct node_icmp *icmp; 179 struct node_host *host; 180 struct node_port *port; 181 struct node_uid *uid; 182 struct node_gid *gid; 183 struct node_state_opt *state_opt; 184 struct peer peer; 185 struct { 186 struct peer src, dst; 187 } fromto; 188 struct { 189 char *string; 190 struct pf_addr *addr; 191 u_int8_t rt; 192 u_int8_t af; 193 } route; 194 struct redirection { 195 struct node_host *address; 196 struct range rport; 197 } *redirection; 198 struct { 199 int action; 200 struct node_state_opt *options; 201 } keep_state; 202 } v; 203 int lineno; 204} YYSTYPE; 205 206%} 207 208%token PASS BLOCK SCRUB RETURN IN OUT LOG LOGALL QUICK ON FROM TO FLAGS 209%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE 210%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF 211%token MINTTL IPV6ADDR ERROR ALLOWOPTS FASTROUTE ROUTETO DUPTO NO LABEL 212%token NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL 213%token FRAGNORM FRAGDROP FRAGCROP 214%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE 215%token <v.string> STRING 216%token <v.number> NUMBER 217%token <v.i> PORTUNARY PORTBINARY 218%type <v.interface> interface if_list if_item_not if_item 219%type <v.number> port icmptype icmp6type minttl uid gid maxmss 220%type <v.i> no dir log quick af nodf allowopts fragment fragcache 221%type <v.b> action flag flags blockspec 222%type <v.range> dport rport 223%type <v.proto> proto proto_list proto_item 224%type <v.icmp> icmpspec icmp_list icmp6_list icmp_item icmp6_item 225%type <v.fromto> fromto 226%type <v.peer> ipportspec 227%type <v.host> ipspec xhost host address host_list IPV6ADDR 228%type <v.port> portspec port_list port_item 229%type <v.uid> uids uid_list uid_item 230%type <v.gid> gids gid_list gid_item 231%type <v.route> route 232%type <v.redirection> redirection 233%type <v.string> label 234%type <v.keep_state> keep 235%type <v.state_opt> state_opt_spec state_opt_list state_opt_item 236%type <v.timeout_spec> timeout_spec timeout_list 237%type <v.limit_spec> limit_spec limit_list 238%% 239 240ruleset : /* empty */ 241 | ruleset '\n' 242 | ruleset option '\n' 243 | ruleset scrubrule '\n' 244 | ruleset natrule '\n' 245 | ruleset binatrule '\n' 246 | ruleset rdrrule '\n' 247 | ruleset pfrule '\n' 248 | ruleset varset '\n' 249 | ruleset error '\n' { errors++; } 250 ; 251 252option : SET OPTIMIZATION STRING 253 { 254 if (pf->opts & PF_OPT_VERBOSE) 255 printf("set optimization %s\n", $3); 256 if (check_rulestate(PFCTL_STATE_OPTION)) 257 YYERROR; 258 if (pfctl_set_optimization(pf, $3) != 0) { 259 yyerror("unknown optimization %s", $3); 260 YYERROR; 261 } 262 } 263 | SET TIMEOUT timeout_spec 264 | SET TIMEOUT '{' timeout_list '}' 265 | SET LIMIT limit_spec 266 | SET LIMIT '{' limit_list '}' 267 | SET LOGINTERFACE STRING 268 { 269 if (pf->opts & PF_OPT_VERBOSE) 270 printf("set loginterface %s\n", $3); 271 if (check_rulestate(PFCTL_STATE_OPTION)) 272 YYERROR; 273 if (pfctl_set_logif(pf, $3) != 0) { 274 yyerror("error setting loginterface %s", $3); 275 YYERROR; 276 } 277 } 278 ; 279 280varset : STRING PORTUNARY STRING 281 { 282 if (pf->opts & PF_OPT_VERBOSE) 283 printf("%s = %s\n", $1, $3); 284 if (symset($1, $3) == -1) { 285 yyerror("cannot store variable %s", $1); 286 YYERROR; 287 } 288 } 289 ; 290 291scrubrule : SCRUB dir interface fromto nodf minttl maxmss fragcache 292 { 293 struct pf_rule r; 294 295 if (check_rulestate(PFCTL_STATE_SCRUB)) 296 YYERROR; 297 298 memset(&r, 0, sizeof(r)); 299 300 r.action = PF_SCRUB; 301 r.direction = $2; 302 303 if ($3) { 304 if ($3->not) { 305 yyerror("scrub rules don't support " 306 "'! <if>'"); 307 YYERROR; 308 } else if ($3->next) { 309 yyerror("scrub rules don't support " 310 "{} expansion"); 311 YYERROR; 312 } 313 memcpy(r.ifname, $3->ifname, 314 sizeof(r.ifname)); 315 } 316 if ($5) 317 r.rule_flag |= PFRULE_NODF; 318 if ($6) 319 r.min_ttl = $6; 320 if ($7) 321 r.max_mss = $7; 322 if ($8) 323 r.rule_flag |= $8; 324 325 r.nr = pf->rule_nr++; 326 pfctl_add_rule(pf, &r); 327 328 } 329 ; 330 331pfrule : action dir log quick interface route af proto fromto 332 uids gids flags icmpspec keep fragment allowopts label 333 { 334 struct pf_rule r; 335 struct node_state_opt *o; 336 337 if (check_rulestate(PFCTL_STATE_FILTER)) 338 YYERROR; 339 340 memset(&r, 0, sizeof(r)); 341 342 r.action = $1.b1; 343 if ($1.b2) { 344 r.rule_flag |= PFRULE_RETURNRST; 345 r.return_ttl = $1.w; 346 } else 347 r.return_icmp = $1.w; 348 r.direction = $2; 349 r.log = $3; 350 r.quick = $4; 351 352 if ($5->not) { 353 yyerror("'pass/block on ! $interface' isn't " 354 "supported."); 355 YYERROR; 356 } 357 358 r.af = $7; 359 r.flags = $12.b1; 360 r.flagset = $12.b2; 361 362 r.keep_state = $14.action; 363 o = $14.options; 364 while (o) { 365 struct node_state_opt *p = o; 366 367 switch (o->type) { 368 case PF_STATE_OPT_MAX: 369 if (r.max_states) { 370 yyerror("state option 'max' " 371 "multiple definitions"); 372 YYERROR; 373 } 374 r.max_states = o->data.max_states; 375 break; 376 case PF_STATE_OPT_TIMEOUT: 377 if (r.timeout[o->data.timeout.number]) { 378 yyerror("state timeout %s " 379 "multiple definitions", 380 pf_timeouts[o->data. 381 timeout.number].name); 382 YYERROR; 383 } 384 r.timeout[o->data.timeout.number] = 385 o->data.timeout.seconds; 386 } 387 o = o->next; 388 free(p); 389 } 390 391 if ($15) 392 r.rule_flag |= PFRULE_FRAGMENT; 393 r.allow_opts = $16; 394 395 if ($6.rt) { 396 r.rt = $6.rt; 397 if ($6.string) { 398 memcpy(r.rt_ifname, $6.string, 399 sizeof(r.rt_ifname)); 400 free($6.string); 401 } 402 if ($6.addr) { 403 if (!r.af) 404 r.af = $6.af; 405 else if (r.af != $6.af) { 406 yyerror("address family" 407 " mismatch"); 408 YYERROR; 409 } 410 memcpy(&r.rt_addr, $6.addr, 411 sizeof(r.rt_addr)); 412 free($6.addr); 413 } 414 } 415 416 if ($17) { 417 if (strlen($17) >= PF_RULE_LABEL_SIZE) { 418 yyerror("rule label too long (max " 419 "%d chars)", PF_RULE_LABEL_SIZE-1); 420 YYERROR; 421 } 422 strlcpy(r.label, $17, sizeof(r.label)); 423 free($17); 424 } 425 426 expand_rule(&r, $5, $8, $9.src.host, $9.src.port, 427 $9.dst.host, $9.dst.port, $10, $11, $13); 428 } 429 ; 430 431action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; } 432 | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } 433 ; 434 435blockspec : /* empty */ { $$.b2 = 0; $$.w = 0; } 436 | RETURNRST { $$.b2 = 1; $$.w = 0; } 437 | RETURNRST '(' TTL NUMBER ')' { 438 $$.w = $4; 439 $$.b2 = 1; 440 } 441 | RETURNICMP { 442 $$.b2 = 0; 443 $$.w = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 444 } 445 | RETURNICMP6 { 446 $$.b2 = 0; 447 $$.w = (ICMP6_DST_UNREACH << 8) | 448 ICMP6_DST_UNREACH_NOPORT; 449 } 450 | RETURNICMP '(' NUMBER ')' { 451 $$.w = (ICMP_UNREACH << 8) | $3; 452 $$.b2 = 0; 453 } 454 | RETURNICMP '(' STRING ')' { 455 const struct icmpcodeent *p; 456 457 if ((p = geticmpcodebyname(ICMP_UNREACH, $3, 458 AF_INET)) == NULL) { 459 yyerror("unknown icmp code %s", $3); 460 YYERROR; 461 } 462 $$.w = (p->type << 8) | p->code; 463 $$.b2 = 0; 464 } 465 | RETURNICMP6 '(' NUMBER ')' { 466 $$.w = (ICMP6_DST_UNREACH << 8) | $3; 467 $$.b2 = 0; 468 } 469 | RETURNICMP6 '(' STRING ')' { 470 const struct icmpcodeent *p; 471 472 if ((p = geticmpcodebyname(ICMP6_DST_UNREACH, $3, 473 AF_INET6)) == NULL) { 474 yyerror("unknown icmp code %s", $3); 475 YYERROR; 476 } 477 $$.w = (p->type << 8) | p->code; 478 $$.b2 = 0; 479 } 480 ; 481 482fragcache : /* empty */ { $$ = 0; } 483 | fragment FRAGNORM { $$ = 0; /* default */ } 484 | fragment FRAGCROP { $$ = PFRULE_FRAGCROP; } 485 | fragment FRAGDROP { $$ = PFRULE_FRAGDROP; } 486 ; 487 488 489dir : IN { $$ = PF_IN; } 490 | OUT { $$ = PF_OUT; } 491 ; 492 493log : /* empty */ { $$ = 0; } 494 | LOG { $$ = 1; } 495 | LOGALL { $$ = 2; } 496 ; 497 498quick : /* empty */ { $$ = 0; } 499 | QUICK { $$ = 1; } 500 ; 501 502interface : /* empty */ { $$ = NULL; } 503 | ON if_item_not { $$ = $2; } 504 | ON '{' if_list '}' { $$ = $3; } 505 ; 506 507if_list : if_item_not { $$ = $1; } 508 | if_list ',' if_item_not { $3->next = $1; $$ = $3; } 509 ; 510 511if_item_not : '!' if_item { $$ = $2; $$->not = 1; } 512 | if_item { $$ = $1; } 513 514if_item : STRING { 515 if (ifa0_lookup($1) == 0) { 516 yyerror("unknown interface %s", $1); 517 YYERROR; 518 } 519 $$ = malloc(sizeof(struct node_if)); 520 if ($$ == NULL) 521 err(1, "if_item: malloc"); 522 strlcpy($$->ifname, $1, IFNAMSIZ); 523 $$->not = 0; 524 $$->next = NULL; 525 } 526 ; 527 528af : /* empty */ { $$ = 0; } 529 | INET { $$ = AF_INET; } 530 | INET6 { $$ = AF_INET6; } 531 532proto : /* empty */ { $$ = NULL; } 533 | PROTO proto_item { $$ = $2; } 534 | PROTO '{' proto_list '}' { $$ = $3; } 535 ; 536 537proto_list : proto_item { $$ = $1; } 538 | proto_list ',' proto_item { $3->next = $1; $$ = $3; } 539 ; 540 541proto_item : NUMBER { 542 struct protoent *p; 543 544 if ((p = getprotobynumber($1)) == NULL) { 545 yyerror("unknown protocol %d", $1); 546 YYERROR; 547 } 548 $$ = malloc(sizeof(struct node_proto)); 549 if ($$ == NULL) 550 err(1, "proto_item: malloc"); 551 $$->proto = p->p_proto; 552 $$->next = NULL; 553 } 554 | STRING { 555 struct protoent *p; 556 557 if ((p = getprotobyname($1)) == NULL) { 558 yyerror("unknown protocol %s", $1); 559 YYERROR; 560 } 561 $$ = malloc(sizeof(struct node_proto)); 562 if ($$ == NULL) 563 err(1, "proto_item: malloc"); 564 $$->proto = p->p_proto; 565 $$->next = NULL; 566 } 567 ; 568 569fromto : ALL { 570 $$.src.host = NULL; 571 $$.src.port = NULL; 572 $$.dst.host = NULL; 573 $$.dst.port = NULL; 574 } 575 | FROM ipportspec TO ipportspec { 576 $$.src = $2; 577 $$.dst = $4; 578 } 579 ; 580 581ipportspec : ipspec { $$.host = $1; $$.port = NULL; } 582 | ipspec PORT portspec { 583 $$.host = $1; 584 $$.port = $3; 585 } 586 ; 587 588ipspec : ANY { $$ = NULL; } 589 | xhost { $$ = $1; } 590 | '{' host_list '}' { $$ = $2; } 591 ; 592 593host_list : xhost { $$ = $1; } 594 | host_list ',' xhost { 595 /* both $1 and $3 may be lists, so join them */ 596 $$ = $3; 597 while ($3->next) 598 $3 = $3->next; 599 $3->next = $1; 600 } 601 ; 602 603xhost : '!' host { 604 struct node_host *h; 605 for (h = $2; h; h = h->next) 606 h->not = 1; 607 $$ = $2; 608 } 609 | host { $$ = $1; } 610 | NOROUTE { 611 $$ = calloc(1, sizeof(struct node_host)); 612 if ($$ == NULL) 613 err(1, "xhost: calloc"); 614 $$->noroute = 1; 615 } 616 ; 617 618host : address { 619 struct node_host *n; 620 for (n = $1; n; n = n->next) 621 if (n->af == AF_INET) 622 ipmask(&n->mask, 32); 623 else 624 ipmask(&n->mask, 128); 625 $$ = $1; 626 } 627 | address '/' NUMBER { 628 struct node_host *n; 629 for (n = $1; n; n = n->next) { 630 if ($1->af == AF_INET) { 631 if ($3 < 0 || $3 > 32) { 632 yyerror( 633 "illegal netmask value %d", 634 $3); 635 YYERROR; 636 } 637 } else { 638 if ($3 < 0 || $3 > 128) { 639 yyerror( 640 "illegal netmask value %d", 641 $3); 642 YYERROR; 643 } 644 } 645 ipmask(&n->mask, $3); 646 } 647 $$ = $1; 648 } 649 ; 650 651address : '(' STRING ')' { 652 $$ = calloc(1, sizeof(struct node_host)); 653 if ($$ == NULL) 654 err(1, "address: calloc"); 655 $$->af = 0; 656 $$->addr.addr_dyn = (struct pf_addr_dyn *)1; 657 strncpy($$->addr.addr.pfa.ifname, $2, 658 sizeof($$->addr.addr.pfa.ifname)); 659 } 660 | STRING { 661 if (ifa0_lookup($1)) { 662 struct ifaddrs *ifa; 663 664 /* an interface with this name exists */ 665 if ((ifa = ifa4_lookup($1))) { 666 struct sockaddr_in *sin = 667 (struct sockaddr_in *) 668 ifa->ifa_addr; 669 670 $$ = calloc(1, 671 sizeof(struct node_host)); 672 if ($$ == NULL) 673 err(1, "address: calloc"); 674 $$->af = AF_INET; 675 $$->addr.addr_dyn = NULL; 676 memcpy(&$$->addr.addr, &sin->sin_addr, 677 sizeof(u_int32_t)); 678 } else if ((ifa = ifa6_lookup($1))) { 679 struct sockaddr_in6 *sin6 = 680 (struct sockaddr_in6 *) 681 ifa->ifa_addr; 682 683 $$ = calloc(1, 684 sizeof(struct node_host)); 685 if ($$ == NULL) 686 err(1, "address: calloc"); 687 $$->af = AF_INET6; 688 $$->addr.addr_dyn = NULL; 689 memcpy(&$$->addr.addr, &sin6->sin6_addr, 690 sizeof(struct pf_addr)); 691 } else { 692 yyerror("interface %s has no IP " 693 "addresses", $1); 694 YYERROR; 695 } 696 } else { 697 struct node_host *h = NULL, *n; 698 struct addrinfo hints, *res0, *res; 699 int error; 700 701 memset(&hints, 0, sizeof(hints)); 702 hints.ai_family = PF_UNSPEC; 703 hints.ai_socktype = SOCK_STREAM; /* DUMMY */ 704 error = getaddrinfo($1, NULL, &hints, &res0); 705 if (error) { 706 yyerror("cannot resolve %s: %s", 707 $1, gai_strerror(error)); 708 YYERROR; 709 } 710 for (res = res0; res; res = res->ai_next) { 711 if (res->ai_family != AF_INET && 712 res->ai_family != AF_INET6) 713 continue; 714 n = calloc(1, sizeof(struct node_host)); 715 if (n == NULL) 716 err(1, "address: calloc"); 717 n->af = res->ai_family; 718 n->addr.addr_dyn = NULL; 719 if (res->ai_family == AF_INET) 720 memcpy(&n->addr.addr, 721 &((struct sockaddr_in *) 722 res->ai_addr) 723 ->sin_addr.s_addr, 724 sizeof(struct in_addr)); 725 else { 726 memcpy(&n->addr.addr, 727 &((struct sockaddr_in6 *) 728 res->ai_addr) 729 ->sin6_addr.s6_addr, 730 sizeof(struct in6_addr)); 731 n->ifindex = 732 ((struct sockaddr_in6 *) 733 res->ai_addr) 734 ->sin6_scope_id; 735 } 736 n->next = h; 737 h = n; 738 } 739 freeaddrinfo(res0); 740 if (h == NULL) { 741 yyerror("no IP address found for %s", $1); 742 YYERROR; 743 } 744 $$ = h; 745 } 746 } 747 | NUMBER '.' NUMBER '.' NUMBER '.' NUMBER { 748 if ($1 < 0 || $3 < 0 || $5 < 0 || $7 < 0 || 749 $1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 750 yyerror("illegal ip address %d.%d.%d.%d", 751 $1, $3, $5, $7); 752 YYERROR; 753 } 754 $$ = calloc(1, sizeof(struct node_host)); 755 if ($$ == NULL) 756 err(1, "address: calloc"); 757 $$->af = AF_INET; 758 $$->addr.addr_dyn = NULL; 759 $$->addr.addr.addr32[0] = htonl(($1 << 24) | 760 ($3 << 16) | ($5 << 8) | $7); 761 } 762 | IPV6ADDR { $$ = $1; } 763 ; 764 765portspec : port_item { $$ = $1; } 766 | '{' port_list '}' { $$ = $2; } 767 ; 768 769port_list : port_item { $$ = $1; } 770 | port_list ',' port_item { $3->next = $1; $$ = $3; } 771 ; 772 773port_item : port { 774 $$ = malloc(sizeof(struct node_port)); 775 if ($$ == NULL) 776 err(1, "port_item: malloc"); 777 $$->port[0] = $1; 778 $$->port[1] = $1; 779 $$->op = PF_OP_EQ; 780 $$->next = NULL; 781 } 782 | PORTUNARY port { 783 $$ = malloc(sizeof(struct node_port)); 784 if ($$ == NULL) 785 err(1, "port_item: malloc"); 786 $$->port[0] = $2; 787 $$->port[1] = $2; 788 $$->op = $1; 789 $$->next = NULL; 790 } 791 | port PORTBINARY port { 792 $$ = malloc(sizeof(struct node_port)); 793 if ($$ == NULL) 794 err(1, "port_item: malloc"); 795 $$->port[0] = $1; 796 $$->port[1] = $3; 797 $$->op = $2; 798 $$->next = NULL; 799 } 800 ; 801 802port : NUMBER { 803 if ($1 < 0 || $1 > 65535) { 804 yyerror("illegal port value %d", $1); 805 YYERROR; 806 } 807 $$ = htons($1); 808 } 809 | STRING { 810 struct servent *s = NULL; 811 812 s = getservbyname($1, "tcp"); 813 if (s == NULL) 814 s = getservbyname($1, "udp"); 815 if (s == NULL) { 816 yyerror("unknown protocol %s", $1); 817 YYERROR; 818 } 819 $$ = s->s_port; 820 } 821 ; 822 823uids : /* empty */ { $$ = NULL; } 824 | USER uid_item { $$ = $2; } 825 | USER '{' uid_list '}' { $$ = $3; } 826 ; 827 828uid_list : uid_item { $$ = $1; } 829 | uid_list ',' uid_item { $3->next = $1; $$ = $3; } 830 ; 831 832uid_item : uid { 833 $$ = malloc(sizeof(struct node_uid)); 834 if ($$ == NULL) 835 err(1, "uid_item: malloc"); 836 $$->uid[0] = $1; 837 $$->uid[1] = $1; 838 $$->op = PF_OP_EQ; 839 $$->next = NULL; 840 } 841 | PORTUNARY uid { 842 if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 843 yyerror("user unknown requires operator = or !="); 844 YYERROR; 845 } 846 $$ = malloc(sizeof(struct node_uid)); 847 if ($$ == NULL) 848 err(1, "uid_item: malloc"); 849 $$->uid[0] = $2; 850 $$->uid[1] = $2; 851 $$->op = $1; 852 $$->next = NULL; 853 } 854 | uid PORTBINARY uid { 855 if ($1 == UID_MAX || $3 == UID_MAX) { 856 yyerror("user unknown requires operator = or !="); 857 YYERROR; 858 } 859 $$ = malloc(sizeof(struct node_uid)); 860 if ($$ == NULL) 861 err(1, "uid_item: malloc"); 862 $$->uid[0] = $1; 863 $$->uid[1] = $3; 864 $$->op = $2; 865 $$->next = NULL; 866 } 867 ; 868 869uid : NUMBER { 870 if ($1 < 0 || $1 >= UID_MAX) { 871 yyerror("illegal uid value %u", $1); 872 YYERROR; 873 } 874 $$ = $1; 875 } 876 | STRING { 877 if (!strcmp($1, "unknown")) 878 $$ = UID_MAX; 879 else { 880 struct passwd *pw; 881 882 if ((pw = getpwnam($1)) == NULL) { 883 yyerror("unknown user %s", $1); 884 YYERROR; 885 } 886 $$ = pw->pw_uid; 887 } 888 } 889 ; 890 891gids : /* empty */ { $$ = NULL; } 892 | GROUP gid_item { $$ = $2; } 893 | GROUP '{' gid_list '}' { $$ = $3; } 894 ; 895 896gid_list : gid_item { $$ = $1; } 897 | gid_list ',' gid_item { $3->next = $1; $$ = $3; } 898 ; 899 900gid_item : gid { 901 $$ = malloc(sizeof(struct node_gid)); 902 if ($$ == NULL) 903 err(1, "gid_item: malloc"); 904 $$->gid[0] = $1; 905 $$->gid[1] = $1; 906 $$->op = PF_OP_EQ; 907 $$->next = NULL; 908 } 909 | PORTUNARY gid { 910 if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 911 yyerror("group unknown requires operator = or !="); 912 YYERROR; 913 } 914 $$ = malloc(sizeof(struct node_gid)); 915 if ($$ == NULL) 916 err(1, "gid_item: malloc"); 917 $$->gid[0] = $2; 918 $$->gid[1] = $2; 919 $$->op = $1; 920 $$->next = NULL; 921 } 922 | gid PORTBINARY gid { 923 if ($1 == GID_MAX || $3 == GID_MAX) { 924 yyerror("group unknown requires operator = or !="); 925 YYERROR; 926 } 927 $$ = malloc(sizeof(struct node_gid)); 928 if ($$ == NULL) 929 err(1, "gid_item: malloc"); 930 $$->gid[0] = $1; 931 $$->gid[1] = $3; 932 $$->op = $2; 933 $$->next = NULL; 934 } 935 ; 936 937gid : NUMBER { 938 if ($1 < 0 || $1 >= GID_MAX) { 939 yyerror("illegal gid value %u", $1); 940 YYERROR; 941 } 942 $$ = $1; 943 } 944 | STRING { 945 if (!strcmp($1, "unknown")) 946 $$ = GID_MAX; 947 else { 948 struct passwd *pw; 949 950 if ((pw = getpwnam($1)) == NULL) { 951 yyerror("unknown group %s", $1); 952 YYERROR; 953 } 954 $$ = pw->pw_uid; 955 } 956 } 957 ; 958 959flag : STRING { 960 int f; 961 962 if ((f = parse_flags($1)) < 0) { 963 yyerror("bad flags %s", $1); 964 YYERROR; 965 } 966 $$.b1 = f; 967 } 968 ; 969 970flags : /* empty */ { $$.b1 = 0; $$.b2 = 0; } 971 | FLAGS flag { $$.b1 = $2.b1; $$.b2 = PF_TH_ALL; } 972 | FLAGS flag "/" flag { $$.b1 = $2.b1; $$.b2 = $4.b1; } 973 | FLAGS "/" flag { $$.b1 = 0; $$.b2 = $3.b1; } 974 ; 975 976icmpspec : /* empty */ { $$ = NULL; } 977 | ICMPTYPE icmp_item { $$ = $2; } 978 | ICMPTYPE '{' icmp_list '}' { $$ = $3; } 979 | ICMP6TYPE icmp6_item { $$ = $2; } 980 | ICMP6TYPE '{' icmp6_list '}' { $$ = $3; } 981 ; 982 983icmp_list : icmp_item { $$ = $1; } 984 | icmp_list ',' icmp_item { $3->next = $1; $$ = $3; } 985 ; 986 987icmp6_list : icmp6_item { $$ = $1; } 988 | icmp6_list ',' icmp6_item { $3->next = $1; $$ = $3; } 989 ; 990 991icmp_item : icmptype { 992 $$ = malloc(sizeof(struct node_icmp)); 993 if ($$ == NULL) 994 err(1, "icmp_item: malloc"); 995 $$->type = $1; 996 $$->code = 0; 997 $$->proto = IPPROTO_ICMP; 998 $$->next = NULL; 999 } 1000 | icmptype CODE NUMBER { 1001 $$ = malloc(sizeof(struct node_icmp)); 1002 if ($$ == NULL) 1003 err(1, "icmp_item: malloc"); 1004 if ($3 < 0 || $3 > 255) { 1005 yyerror("illegal icmp code %d", $3); 1006 YYERROR; 1007 } 1008 $$->type = $1; 1009 $$->code = $3 + 1; 1010 $$->proto = IPPROTO_ICMP; 1011 $$->next = NULL; 1012 } 1013 | icmptype CODE STRING { 1014 const struct icmpcodeent *p; 1015 1016 $$ = malloc(sizeof(struct node_icmp)); 1017 if ($$ == NULL) 1018 err(1, "icmp_item: malloc"); 1019 $$->type = $1; 1020 if ((p = geticmpcodebyname($1, $3, 1021 AF_INET)) == NULL) { 1022 yyerror("unknown icmp-code %s", $3); 1023 YYERROR; 1024 } 1025 $$->code = p->code + 1; 1026 $$->proto = IPPROTO_ICMP; 1027 $$->next = NULL; 1028 } 1029 ; 1030 1031icmp6_item : icmp6type { 1032 $$ = malloc(sizeof(struct node_icmp)); 1033 if ($$ == NULL) 1034 err(1, "icmp_item: malloc"); 1035 $$->type = $1; 1036 $$->code = 0; 1037 $$->proto = IPPROTO_ICMPV6; 1038 $$->next = NULL; 1039 } 1040 | icmp6type CODE NUMBER { 1041 $$ = malloc(sizeof(struct node_icmp)); 1042 if ($$ == NULL) 1043 err(1, "icmp_item: malloc"); 1044 if ($3 < 0 || $3 > 255) { 1045 yyerror("illegal icmp6 code %d", $3); 1046 YYERROR; 1047 } 1048 $$->type = $1; 1049 $$->code = $3 + 1; 1050 $$->proto = IPPROTO_ICMPV6; 1051 $$->next = NULL; 1052 } 1053 | icmp6type CODE STRING { 1054 const struct icmpcodeent *p; 1055 1056 $$ = malloc(sizeof(struct node_icmp)); 1057 if ($$ == NULL) 1058 err(1, "icmp_item: malloc"); 1059 $$->type = $1; 1060 if ((p = geticmpcodebyname($1, $3, 1061 AF_INET6)) == NULL) { 1062 yyerror("unknown icmp6-code %s", $3); 1063 YYERROR; 1064 } 1065 $$->code = p->code + 1; 1066 $$->proto = IPPROTO_ICMPV6; 1067 $$->next = NULL; 1068 } 1069 ; 1070 1071icmptype : STRING { 1072 const struct icmptypeent *p; 1073 1074 if ((p = geticmptypebyname($1, AF_INET)) == NULL) { 1075 yyerror("unknown icmp-type %s", $1); 1076 YYERROR; 1077 } 1078 $$ = p->type + 1; 1079 } 1080 | NUMBER { 1081 if ($1 < 0 || $1 > 255) { 1082 yyerror("illegal icmp type %d", $1); 1083 YYERROR; 1084 } 1085 $$ = $1 + 1; 1086 } 1087 ; 1088 1089icmp6type : STRING { 1090 const struct icmptypeent *p; 1091 1092 if ((p = geticmptypebyname($1, AF_INET6)) == NULL) { 1093 yyerror("unknown ipv6-icmp-type %s", $1); 1094 YYERROR; 1095 } 1096 $$ = p->type + 1; 1097 } 1098 | NUMBER { 1099 if ($1 < 0 || $1 > 255) { 1100 yyerror("illegal icmp6 type %d", $1); 1101 YYERROR; 1102 } 1103 $$ = $1 + 1; 1104 } 1105 ; 1106 1107keep : /* empty */ { 1108 $$.action = 0; 1109 $$.options = NULL; 1110 } 1111 | KEEP STATE state_opt_spec { 1112 $$.action = PF_STATE_NORMAL; 1113 $$.options = $3; 1114 } 1115 | MODULATE STATE state_opt_spec { 1116 $$.action = PF_STATE_MODULATE; 1117 $$.options = $3; 1118 } 1119 ; 1120 1121state_opt_spec : /* empty */ { $$ = NULL; } 1122 | '(' state_opt_list ')' { $$ = $2; } 1123 ; 1124 1125state_opt_list : state_opt_item { $$ = $1; } 1126 | state_opt_list ',' state_opt_item { 1127 $$ = $1; 1128 while ($1->next) 1129 $1 = $1->next; 1130 $1->next = $3; 1131 } 1132 ; 1133 1134state_opt_item : MAXIMUM NUMBER { 1135 if ($2 <= 0) { 1136 yyerror("illegal states max value %d", $2); 1137 YYERROR; 1138 } 1139 $$ = calloc(1, sizeof(struct node_state_opt)); 1140 if ($$ == NULL) 1141 err(1, "state_opt_item: calloc"); 1142 $$->type = PF_STATE_OPT_MAX; 1143 $$->data.max_states = $2; 1144 $$->next = NULL; 1145 } 1146 | STRING NUMBER { 1147 int i; 1148 1149 for (i = 0; pf_timeouts[i].name && 1150 strcmp(pf_timeouts[i].name, $1); ++i); 1151 if (!pf_timeouts[i].name) { 1152 yyerror("illegal timeout name %s", $1); 1153 YYERROR; 1154 } 1155 if (strchr(pf_timeouts[i].name, '.') == NULL) { 1156 yyerror("illegal state timeout %s", $1); 1157 YYERROR; 1158 } 1159 if ($2 < 0) { 1160 yyerror("illegal timeout value %d", $2); 1161 YYERROR; 1162 } 1163 $$ = calloc(1, sizeof(struct node_state_opt)); 1164 if ($$ == NULL) 1165 err(1, "state_opt_item: calloc"); 1166 $$->type = PF_STATE_OPT_TIMEOUT; 1167 $$->data.timeout.number = pf_timeouts[i].timeout; 1168 $$->data.timeout.seconds = $2; 1169 $$->next = NULL; 1170 } 1171 ; 1172 1173fragment : /* empty */ { $$ = 0; } 1174 | FRAGMENT { $$ = 1; } 1175 1176minttl : /* empty */ { $$ = 0; } 1177 | MINTTL NUMBER { 1178 if ($2 < 0 || $2 > 255) { 1179 yyerror("illegal min-ttl value %d", $2); 1180 YYERROR; 1181 } 1182 $$ = $2; 1183 } 1184 ; 1185 1186nodf : /* empty */ { $$ = 0; } 1187 | NODF { $$ = 1; } 1188 ; 1189 1190maxmss : /* empty */ { $$ = 0; } 1191 | MAXMSS NUMBER { 1192 if ($2 < 0) { 1193 yyerror("illegal max-mss value %d", $2); 1194 YYERROR; 1195 } 1196 $$ = $2; 1197 } 1198 ; 1199 1200allowopts : /* empty */ { $$ = 0; } 1201 | ALLOWOPTS { $$ = 1; } 1202 1203label : /* empty */ { $$ = NULL; } 1204 | LABEL STRING { 1205 if (($$ = strdup($2)) == NULL) { 1206 yyerror("rule label strdup() failed"); 1207 YYERROR; 1208 } 1209 } 1210 ; 1211 1212no : /* empty */ { $$ = 0; } 1213 | NO { $$ = 1; } 1214 ; 1215 1216rport : port { 1217 $$.a = $1; 1218 $$.b = $$.t = 0; 1219 } 1220 | port ':' port { 1221 $$.a = $1; 1222 $$.b = $3; 1223 $$.t = PF_RPORT_RANGE; 1224 } 1225 | port ':' '*' { 1226 $$.a = $1; 1227 $$.b = 0; 1228 $$.t = PF_RPORT_RANGE; 1229 } 1230 ; 1231 1232redirection : /* empty */ { $$ = NULL; } 1233 | ARROW address { 1234 $$ = malloc(sizeof(struct redirection)); 1235 if ($$ == NULL) 1236 err(1, "redirection: malloc"); 1237 if ($2->next) { 1238 yyerror("multiple ip addresses"); 1239 YYERROR; 1240 } 1241 $$->address = $2; 1242 $$->rport.a = $$->rport.b = $$->rport.t = 0; 1243 } 1244 | ARROW address PORT rport { 1245 $$ = malloc(sizeof(struct redirection)); 1246 if ($$ == NULL) 1247 err(1, "redirection: malloc"); 1248 if ($2->next) { 1249 yyerror("multiple ip addresses"); 1250 YYERROR; 1251 } 1252 $$->address = $2; 1253 $$->rport = $4; 1254 } 1255 ; 1256 1257natrule : no NAT interface af proto fromto redirection 1258 { 1259 struct pf_nat nat; 1260 1261 if (check_rulestate(PFCTL_STATE_NAT)) 1262 YYERROR; 1263 1264 memset(&nat, 0, sizeof(nat)); 1265 1266 nat.no = $1; 1267 if ($3 != NULL) { 1268 memcpy(nat.ifname, $3->ifname, 1269 sizeof(nat.ifname)); 1270 nat.ifnot = $3->not; 1271 free($3); 1272 } 1273 nat.af = $4; 1274 if ($5 != NULL) { 1275 nat.proto = $5->proto; 1276 free($5); 1277 } 1278 if (nat.no) { 1279 if ($7 != NULL) { 1280 yyerror("'no nat' rule does not need '->'"); 1281 YYERROR; 1282 } 1283 } else { 1284 if ($7 == NULL || $7->address == NULL) { 1285 yyerror("'nat' rule requires '-> address'"); 1286 YYERROR; 1287 } 1288 memcpy(&nat.raddr, &$7->address->addr, 1289 sizeof(nat.raddr)); 1290 nat.proxy_port[0] = ntohs($7->rport.a); 1291 nat.proxy_port[1] = ntohs($7->rport.b); 1292 if (!nat.proxy_port[0] && !nat.proxy_port[1]) { 1293 nat.proxy_port[0] = 1294 PF_NAT_PROXY_PORT_LOW; 1295 nat.proxy_port[1] = 1296 PF_NAT_PROXY_PORT_HIGH; 1297 } else if (!nat.proxy_port[1]) 1298 nat.proxy_port[1] = nat.proxy_port[0]; 1299 free($7->address); 1300 free($7); 1301 } 1302 1303 expand_nat(&nat, $6.src.host, $6.src.port, 1304 $6.dst.host, $6.dst.port); 1305 } 1306 ; 1307 1308binatrule : no BINAT interface af proto FROM address TO ipspec redirection 1309 { 1310 struct pf_binat binat; 1311 1312 if (check_rulestate(PFCTL_STATE_NAT)) 1313 YYERROR; 1314 1315 memset(&binat, 0, sizeof(binat)); 1316 1317 binat.no = $1; 1318 if ($3 != NULL) { 1319 memcpy(binat.ifname, $3->ifname, 1320 sizeof(binat.ifname)); 1321 free($3); 1322 } 1323 binat.af = $4; 1324 if ($5 != NULL) { 1325 binat.proto = $5->proto; 1326 free($5); 1327 } 1328 if ($7 != NULL && $9 != NULL && $7->af != $9->af) { 1329 yyerror("binat ip versions must match"); 1330 YYERROR; 1331 } 1332 if ($7 != NULL) { 1333 if ($7->next) { 1334 yyerror("multiple binat ip addresses"); 1335 YYERROR; 1336 } 1337 if ($7->addr.addr_dyn != NULL) { 1338 if (!binat.af) { 1339 yyerror("address family (inet/" 1340 "inet6) undefined"); 1341 YYERROR; 1342 } 1343 $7->af = binat.af; 1344 } 1345 if (binat.af && $7->af != binat.af) { 1346 yyerror("binat ip versions must match"); 1347 YYERROR; 1348 } 1349 binat.af = $7->af; 1350 memcpy(&binat.saddr, &$7->addr, 1351 sizeof(binat.saddr)); 1352 free($7); 1353 } 1354 if ($9 != NULL) { 1355 if ($9->next) { 1356 yyerror("multiple binat ip addresses"); 1357 YYERROR; 1358 } 1359 if ($9->addr.addr_dyn != NULL) { 1360 if (!binat.af) { 1361 yyerror("address family (inet/" 1362 "inet6) undefined"); 1363 YYERROR; 1364 } 1365 $9->af = binat.af; 1366 } 1367 if (binat.af && $9->af != binat.af) { 1368 yyerror("binat ip versions must match"); 1369 YYERROR; 1370 } 1371 binat.af = $9->af; 1372 memcpy(&binat.daddr, &$9->addr, 1373 sizeof(binat.daddr)); 1374 memcpy(&binat.dmask, &$9->mask, 1375 sizeof(binat.dmask)); 1376 binat.dnot = $9->not; 1377 free($9); 1378 } 1379 1380 if (binat.no) { 1381 if ($10 != NULL) { 1382 yyerror("'no binat' rule does not need" 1383 " '->'"); 1384 YYERROR; 1385 } 1386 } else { 1387 if ($10 == NULL || $10->address == NULL) { 1388 yyerror("'binat' rule requires" 1389 " '-> address'"); 1390 YYERROR; 1391 } 1392 if ($10->address->addr.addr_dyn != NULL) { 1393 if (!binat.af) { 1394 yyerror("address family (inet/" 1395 "inet6) undefined"); 1396 YYERROR; 1397 } 1398 $10->address->af = binat.af; 1399 } 1400 if (binat.af && $10->address->af != binat.af) { 1401 yyerror("binat ip versions must match"); 1402 YYERROR; 1403 } 1404 binat.af = $10->address->af; 1405 memcpy(&binat.raddr, &$10->address->addr, 1406 sizeof(binat.raddr)); 1407 free($10->address); 1408 free($10); 1409 } 1410 1411 pfctl_add_binat(pf, &binat); 1412 } 1413 1414rdrrule : no RDR interface af proto FROM ipspec TO ipspec dport redirection 1415 { 1416 struct pf_rdr rdr; 1417 1418 if (check_rulestate(PFCTL_STATE_NAT)) 1419 YYERROR; 1420 1421 memset(&rdr, 0, sizeof(rdr)); 1422 1423 rdr.no = $1; 1424 if ($3 != NULL) { 1425 memcpy(rdr.ifname, $3->ifname, 1426 sizeof(rdr.ifname)); 1427 rdr.ifnot = $3->not; 1428 } 1429 rdr.af = $4; 1430 if ($5 != NULL) { 1431 rdr.proto = $5->proto; 1432 free($5); 1433 } 1434 if ($7 != NULL) { 1435 memcpy(&rdr.saddr, &$7->addr, 1436 sizeof(rdr.saddr)); 1437 memcpy(&rdr.smask, &$7->mask, 1438 sizeof(rdr.smask)); 1439 rdr.snot = $7->not; 1440 } 1441 if ($9 != NULL) { 1442 memcpy(&rdr.daddr, &$9->addr, 1443 sizeof(rdr.daddr)); 1444 memcpy(&rdr.dmask, &$9->mask, 1445 sizeof(rdr.dmask)); 1446 rdr.dnot = $9->not; 1447 } 1448 1449 rdr.dport = $10.a; 1450 rdr.dport2 = $10.b; 1451 rdr.opts |= $10.t; 1452 1453 if (rdr.no) { 1454 if ($11 != NULL) { 1455 yyerror("'no rdr' rule does not need '->'"); 1456 YYERROR; 1457 } 1458 } else { 1459 if ($11 == NULL || $11->address == NULL) { 1460 yyerror("'rdr' rule requires '-> address'"); 1461 YYERROR; 1462 } 1463 memcpy(&rdr.raddr, &$11->address->addr, 1464 sizeof(rdr.raddr)); 1465 free($11->address); 1466 rdr.rport = $11->rport.a; 1467 rdr.opts |= $11->rport.t; 1468 free($11); 1469 } 1470 1471 if (rdr.proto && rdr.proto != IPPROTO_TCP && 1472 rdr.proto != IPPROTO_UDP && 1473 (rdr.dport || rdr.dport2 || rdr.rport)) { 1474 yyerror("rdr ports are only valid for proto tcp/udp"); 1475 YYERROR; 1476 } 1477 1478 expand_rdr(&rdr, $3, $7, $9); 1479 } 1480 ; 1481 1482dport : /* empty */ { 1483 $$.a = $$.b = $$.t = 0; 1484 } 1485 | PORT port { 1486 $$.a = $2; 1487 $$.b = $$.t = 0; 1488 } 1489 | PORT port ':' port { 1490 $$.a = $2; 1491 $$.b = $4; 1492 $$.t = PF_DPORT_RANGE; 1493 } 1494 ; 1495 1496route : /* empty */ { 1497 $$.string = NULL; 1498 $$.rt = 0; 1499 $$.addr = NULL; 1500 $$.af = 0; 1501 } 1502 | FASTROUTE { 1503 $$.string = NULL; 1504 $$.rt = PF_FASTROUTE; 1505 $$.addr = NULL; 1506 } 1507 | ROUTETO STRING ':' address { 1508 $$.string = strdup($2); 1509 $$.rt = PF_ROUTETO; 1510 if ($4->addr.addr_dyn != NULL) { 1511 yyerror("route-to does not support" 1512 " dynamic addresses"); 1513 YYERROR; 1514 } 1515 if ($4->next) { 1516 yyerror("multiple routeto ip addresses"); 1517 YYERROR; 1518 } 1519 $$.addr = &$4->addr.addr; 1520 $$.af = $4->af; 1521 } 1522 | ROUTETO STRING { 1523 $$.string = strdup($2); 1524 $$.rt = PF_ROUTETO; 1525 $$.addr = NULL; 1526 } 1527 | DUPTO STRING ':' address { 1528 $$.string = strdup($2); 1529 $$.rt = PF_DUPTO; 1530 if ($4->addr.addr_dyn != NULL) { 1531 yyerror("dup-to does not support" 1532 " dynamic addresses"); 1533 YYERROR; 1534 } 1535 if ($4->next) { 1536 yyerror("multiple dupto ip addresses"); 1537 YYERROR; 1538 } 1539 $$.addr = &$4->addr.addr; 1540 $$.af = $4->af; 1541 } 1542 | DUPTO STRING { 1543 $$.string = strdup($2); 1544 $$.rt = PF_DUPTO; 1545 $$.addr = NULL; 1546 } 1547 ; 1548 1549timeout_spec : STRING NUMBER 1550 { 1551 if (pf->opts & PF_OPT_VERBOSE) 1552 printf("set timeout %s %us\n", $1, $2); 1553 if (check_rulestate(PFCTL_STATE_OPTION)) 1554 YYERROR; 1555 if (pfctl_set_timeout(pf, $1, $2) != 0) { 1556 yyerror("unknown timeout %s", $1); 1557 YYERROR; 1558 } 1559 } 1560 ; 1561 1562timeout_list : timeout_list ',' timeout_spec 1563 | timeout_spec 1564 ; 1565 1566limit_spec : STRING NUMBER 1567 { 1568 if (pf->opts & PF_OPT_VERBOSE) 1569 printf("set limit %s %u\n", $1, $2); 1570 if (check_rulestate(PFCTL_STATE_OPTION)) 1571 YYERROR; 1572 if (pfctl_set_limit(pf, $1, $2) != 0) { 1573 yyerror("unable to set limit %s %u", $1, $2); 1574 YYERROR; 1575 } 1576 } 1577 1578limit_list : limit_list ',' limit_spec 1579 | limit_spec 1580 ; 1581 1582%% 1583 1584int 1585yyerror(char *fmt, ...) 1586{ 1587 va_list ap; 1588 extern char *infile; 1589 errors = 1; 1590 1591 va_start(ap, fmt); 1592 fprintf(stderr, "%s:%d: ", infile, yylval.lineno); 1593 vfprintf(stderr, fmt, ap); 1594 fprintf(stderr, "\n"); 1595 va_end(ap); 1596 return (0); 1597} 1598 1599int 1600rule_consistent(struct pf_rule *r) 1601{ 1602 int problems = 0; 1603 1604 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 1605 (r->src.port_op || r->dst.port_op)) { 1606 yyerror("port only applies to tcp/udp"); 1607 problems++; 1608 } 1609 if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 && 1610 (r->type || r->code)) { 1611 yyerror("icmp-type/code only applies to icmp"); 1612 problems++; 1613 } 1614 if (!r->af && (r->type || r->code)) { 1615 yyerror("must indicate address family with icmp-type/code"); 1616 problems++; 1617 } 1618 if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) || 1619 (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) { 1620 yyerror("icmp version does not match address family"); 1621 problems++; 1622 } 1623 if (!(r->rule_flag & PFRULE_RETURNRST) && r->return_icmp && 1624 ((r->af != AF_INET6 && (r->return_icmp>>8) != ICMP_UNREACH) || 1625 (r->af == AF_INET6 && (r->return_icmp>>8) != ICMP6_DST_UNREACH))) { 1626 yyerror("return-icmp version does not match address family"); 1627 problems++; 1628 } 1629 if (r->keep_state == PF_STATE_MODULATE && r->proto && 1630 r->proto != IPPROTO_TCP) { 1631 yyerror("modulate state can only be applied to TCP rules"); 1632 problems++; 1633 } 1634 if (r->allow_opts && r->action != PF_PASS) { 1635 yyerror("allow-opts can only be specified for pass rules"); 1636 problems++; 1637 } 1638 if (!r->af && (r->src.addr.addr_dyn != NULL || 1639 r->dst.addr.addr_dyn != NULL)) { 1640 yyerror("dynamic addresses require address family (inet/inet6)"); 1641 problems++; 1642 } 1643 if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op || 1644 r->dst.port_op || r->flagset || r->type || r->code)) { 1645 yyerror("fragments can be filtered only on IP header fields"); 1646 problems++; 1647 } 1648 return (-problems); 1649} 1650 1651struct keywords { 1652 const char *k_name; 1653 int k_val; 1654}; 1655 1656/* macro gore, but you should've seen the prior indentation nightmare... */ 1657 1658#define CHECK_ROOT(T,r) \ 1659 do { \ 1660 if (r == NULL) { \ 1661 r = malloc(sizeof(T)); \ 1662 if (r == NULL) \ 1663 err(1, "malloc"); \ 1664 memset(r, 0, sizeof(T)); \ 1665 } \ 1666 } while (0) 1667 1668#define FREE_LIST(T,r) \ 1669 do { \ 1670 T *p, *n = r; \ 1671 while (n != NULL) { \ 1672 p = n; \ 1673 n = n->next; \ 1674 free(p); \ 1675 } \ 1676 } while (0) 1677 1678#define LOOP_THROUGH(T,n,r,C) \ 1679 do { \ 1680 T *n = r; \ 1681 while (n != NULL) { \ 1682 do { \ 1683 C; \ 1684 } while (0); \ 1685 n = n->next; \ 1686 } \ 1687 } while (0) 1688 1689void 1690expand_label_addr(const char *name, char *label, u_int8_t af, 1691 struct node_host *host) 1692{ 1693 char tmp[PF_RULE_LABEL_SIZE]; 1694 char *p; 1695 1696 while ((p = strstr(label, name)) != NULL) { 1697 tmp[0] = 0; 1698 1699 strlcat(tmp, label, p-label+1); 1700 1701 if (host->not) 1702 strlcat(tmp, "! ", PF_RULE_LABEL_SIZE); 1703 if (host->addr.addr_dyn != NULL) { 1704 strlcat(tmp, "(", PF_RULE_LABEL_SIZE); 1705 strlcat(tmp, host->addr.addr.pfa.ifname, 1706 PF_RULE_LABEL_SIZE); 1707 strlcat(tmp, ")", PF_RULE_LABEL_SIZE); 1708 } else if (!af || (PF_AZERO(&host->addr.addr, af) && 1709 PF_AZERO(&host->mask, af))) 1710 strlcat(tmp, "any", PF_RULE_LABEL_SIZE); 1711 else { 1712 char a[48]; 1713 int bits; 1714 1715 if (inet_ntop(af, &host->addr.addr, a, 1716 sizeof(a)) == NULL) 1717 strlcat(a, "?", sizeof(a)); 1718 strlcat(tmp, a, PF_RULE_LABEL_SIZE); 1719 bits = unmask(&host->mask, af); 1720 a[0] = 0; 1721 if ((af == AF_INET && bits < 32) || 1722 (af == AF_INET6 && bits < 128)) 1723 snprintf(a, sizeof(a), "/%u", bits); 1724 strlcat(tmp, a, PF_RULE_LABEL_SIZE); 1725 } 1726 strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE); 1727 strncpy(label, tmp, PF_RULE_LABEL_SIZE); 1728 } 1729} 1730 1731void 1732expand_label_port(const char *name, char *label, struct node_port *port) 1733{ 1734 char tmp[PF_RULE_LABEL_SIZE]; 1735 char *p; 1736 char a1[6], a2[6], op[13]; 1737 1738 while ((p = strstr(label, name)) != NULL) { 1739 tmp[0] = 0; 1740 1741 strlcat(tmp, label, p-label+1); 1742 1743 snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0])); 1744 snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1])); 1745 if (!port->op) 1746 op[0] = 0; 1747 else if (port->op == PF_OP_IRG) 1748 snprintf(op, sizeof(op), "%s><%s", a1, a2); 1749 else if (port->op == PF_OP_XRG) 1750 snprintf(op, sizeof(op), "%s<>%s", a1, a2); 1751 else if (port->op == PF_OP_EQ) 1752 snprintf(op, sizeof(op), "%s", a1); 1753 else if (port->op == PF_OP_NE) 1754 snprintf(op, sizeof(op), "!=%s", a1); 1755 else if (port->op == PF_OP_LT) 1756 snprintf(op, sizeof(op), "<%s", a1); 1757 else if (port->op == PF_OP_LE) 1758 snprintf(op, sizeof(op), "<=%s", a1); 1759 else if (port->op == PF_OP_GT) 1760 snprintf(op, sizeof(op), ">%s", a1); 1761 else if (port->op == PF_OP_GE) 1762 snprintf(op, sizeof(op), ">=%s", a1); 1763 strlcat(tmp, op, PF_RULE_LABEL_SIZE); 1764 strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE); 1765 strncpy(label, tmp, PF_RULE_LABEL_SIZE); 1766 } 1767} 1768 1769void 1770expand_label_proto(const char *name, char *label, u_int8_t proto) 1771{ 1772 char tmp[PF_RULE_LABEL_SIZE]; 1773 char *p; 1774 struct protoent *pe; 1775 1776 while ((p = strstr(label, name)) != NULL) { 1777 tmp[0] = 0; 1778 strlcat(tmp, label, p-label+1); 1779 pe = getprotobynumber(proto); 1780 if (pe != NULL) 1781 strlcat(tmp, pe->p_name, PF_RULE_LABEL_SIZE); 1782 else 1783 snprintf(tmp+strlen(tmp), PF_RULE_LABEL_SIZE-strlen(tmp), 1784 "%u", proto); 1785 strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE); 1786 strncpy(label, tmp, PF_RULE_LABEL_SIZE); 1787 } 1788} 1789 1790void 1791expand_label_nr(const char *name, char *label) 1792{ 1793 char tmp[PF_RULE_LABEL_SIZE]; 1794 char *p; 1795 1796 while ((p = strstr(label, name)) != NULL) { 1797 tmp[0] = 0; 1798 strlcat(tmp, label, p-label+1); 1799 snprintf(tmp+strlen(tmp), PF_RULE_LABEL_SIZE-strlen(tmp), 1800 "%u", pf->rule_nr); 1801 strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE); 1802 strncpy(label, tmp, PF_RULE_LABEL_SIZE); 1803 } 1804} 1805 1806void 1807expand_label(char *label, u_int8_t af, 1808 struct node_host *src_host, struct node_port *src_port, 1809 struct node_host *dst_host, struct node_port *dst_port, 1810 u_int8_t proto) 1811{ 1812 expand_label_addr("$srcaddr", label, af, src_host); 1813 expand_label_addr("$dstaddr", label, af, dst_host); 1814 expand_label_port("$srcport", label, src_port); 1815 expand_label_port("$dstport", label, dst_port); 1816 expand_label_proto("$proto", label, proto); 1817 expand_label_nr("$nr", label); 1818} 1819 1820void 1821expand_rule(struct pf_rule *r, 1822 struct node_if *interfaces, struct node_proto *protos, 1823 struct node_host *src_hosts, struct node_port *src_ports, 1824 struct node_host *dst_hosts, struct node_port *dst_ports, 1825 struct node_uid *uids, struct node_gid *gids, 1826 struct node_icmp *icmp_types) 1827{ 1828 int af = r->af, nomatch = 0, added = 0; 1829 char ifname[IF_NAMESIZE]; 1830 char label[PF_RULE_LABEL_SIZE]; 1831 1832 strlcpy(label, r->label, sizeof(label)); 1833 1834 CHECK_ROOT(struct node_if, interfaces); 1835 CHECK_ROOT(struct node_proto, protos); 1836 CHECK_ROOT(struct node_host, src_hosts); 1837 CHECK_ROOT(struct node_port, src_ports); 1838 CHECK_ROOT(struct node_host, dst_hosts); 1839 CHECK_ROOT(struct node_port, dst_ports); 1840 CHECK_ROOT(struct node_uid, uids); 1841 CHECK_ROOT(struct node_gid, gids); 1842 CHECK_ROOT(struct node_icmp, icmp_types); 1843 1844 LOOP_THROUGH(struct node_if, interface, interfaces, 1845 LOOP_THROUGH(struct node_proto, proto, protos, 1846 LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types, 1847 LOOP_THROUGH(struct node_host, src_host, src_hosts, 1848 LOOP_THROUGH(struct node_port, src_port, src_ports, 1849 LOOP_THROUGH(struct node_host, dst_host, dst_hosts, 1850 LOOP_THROUGH(struct node_port, dst_port, dst_ports, 1851 LOOP_THROUGH(struct node_uid, uid, uids, 1852 LOOP_THROUGH(struct node_gid, gid, gids, 1853 1854 r->af = af; 1855 /* for link-local IPv6 address, interface must match up */ 1856 if ((r->af && src_host->af && r->af != src_host->af) || 1857 (r->af && dst_host->af && r->af != dst_host->af) || 1858 (src_host->af && dst_host->af && 1859 src_host->af != dst_host->af) || 1860 (src_host->ifindex && dst_host->ifindex && 1861 src_host->ifindex != dst_host->ifindex) || 1862 (src_host->ifindex && if_nametoindex(interface->ifname) && 1863 src_host->ifindex != if_nametoindex(interface->ifname)) || 1864 (dst_host->ifindex && if_nametoindex(interface->ifname) && 1865 dst_host->ifindex != if_nametoindex(interface->ifname))) 1866 continue; 1867 if (!r->af && src_host->af) 1868 r->af = src_host->af; 1869 else if (!r->af && dst_host->af) 1870 r->af = dst_host->af; 1871 1872 if (if_indextoname(src_host->ifindex, ifname)) 1873 memcpy(r->ifname, ifname, sizeof(r->ifname)); 1874 else if (if_indextoname(dst_host->ifindex, ifname)) 1875 memcpy(r->ifname, ifname, sizeof(r->ifname)); 1876 else 1877 memcpy(r->ifname, interface->ifname, sizeof(r->ifname)); 1878 1879 strlcpy(r->label, label, PF_RULE_LABEL_SIZE); 1880 expand_label(r->label, r->af, src_host, src_port, 1881 dst_host, dst_port, proto->proto); 1882 r->proto = proto->proto; 1883 r->src.addr = src_host->addr; 1884 r->src.mask = src_host->mask; 1885 r->src.noroute = src_host->noroute; 1886 r->src.not = src_host->not; 1887 r->src.port[0] = src_port->port[0]; 1888 r->src.port[1] = src_port->port[1]; 1889 r->src.port_op = src_port->op; 1890 r->dst.addr = dst_host->addr; 1891 r->dst.mask = dst_host->mask; 1892 r->dst.noroute = dst_host->noroute; 1893 r->dst.not = dst_host->not; 1894 r->dst.port[0] = dst_port->port[0]; 1895 r->dst.port[1] = dst_port->port[1]; 1896 r->dst.port_op = dst_port->op; 1897 r->uid.op = uid->op; 1898 r->uid.uid[0] = uid->uid[0]; 1899 r->uid.uid[1] = uid->uid[1]; 1900 r->gid.op = gid->op; 1901 r->gid.gid[0] = gid->gid[0]; 1902 r->gid.gid[1] = gid->gid[1]; 1903 r->type = icmp_type->type; 1904 r->code = icmp_type->code; 1905 1906 if (icmp_type->proto && r->proto != icmp_type->proto) { 1907 yyerror("icmp-type mismatch"); 1908 nomatch++; 1909 } 1910 1911 if (rule_consistent(r) < 0 || nomatch) 1912 yyerror("skipping rule due to errors"); 1913 else { 1914 r->nr = pf->rule_nr++; 1915 pfctl_add_rule(pf, r); 1916 added++; 1917 } 1918 1919 ))))))))); 1920 1921 FREE_LIST(struct node_if, interfaces); 1922 FREE_LIST(struct node_proto, protos); 1923 FREE_LIST(struct node_host, src_hosts); 1924 FREE_LIST(struct node_port, src_ports); 1925 FREE_LIST(struct node_host, dst_hosts); 1926 FREE_LIST(struct node_port, dst_ports); 1927 FREE_LIST(struct node_uid, uids); 1928 FREE_LIST(struct node_gid, gids); 1929 FREE_LIST(struct node_icmp, icmp_types); 1930 1931 if (!added) 1932 yyerror("rule expands to no valid combination"); 1933} 1934 1935void 1936expand_nat(struct pf_nat *n, struct node_host *src_hosts, 1937 struct node_port *src_ports, struct node_host *dst_hosts, 1938 struct node_port *dst_ports) 1939{ 1940 int af = n->af, added = 0; 1941 1942 CHECK_ROOT(struct node_host, src_hosts); 1943 CHECK_ROOT(struct node_port, src_ports); 1944 CHECK_ROOT(struct node_host, dst_hosts); 1945 CHECK_ROOT(struct node_port, dst_ports); 1946 1947 LOOP_THROUGH(struct node_host, src_host, src_hosts, 1948 LOOP_THROUGH(struct node_port, src_port, src_ports, 1949 LOOP_THROUGH(struct node_host, dst_host, dst_hosts, 1950 LOOP_THROUGH(struct node_port, dst_port, dst_ports, 1951 1952 n->af = af; 1953 if ((n->af && src_host->af && n->af != src_host->af) || 1954 (n->af && dst_host->af && n->af != dst_host->af) || 1955 (src_host->af && dst_host->af && 1956 src_host->af != dst_host->af)) 1957 continue; 1958 if (!n->af && src_host->af) 1959 n->af = src_host->af; 1960 else if (!n->af && dst_host->af) 1961 n->af = dst_host->af; 1962 if (!n->af && n->raddr.addr_dyn != NULL) { 1963 yyerror("address family (inet/inet6) undefined"); 1964 continue; 1965 } 1966 1967 n->src.addr = src_host->addr; 1968 n->src.mask = src_host->mask; 1969 n->src.noroute = src_host->noroute; 1970 n->src.not = src_host->not; 1971 n->src.port[0] = src_port->port[0]; 1972 n->src.port[1] = src_port->port[1]; 1973 n->src.port_op = src_port->op; 1974 n->dst.addr = dst_host->addr; 1975 n->dst.mask = dst_host->mask; 1976 n->dst.noroute = dst_host->noroute; 1977 n->dst.not = dst_host->not; 1978 n->dst.port[0] = dst_port->port[0]; 1979 n->dst.port[1] = dst_port->port[1]; 1980 n->dst.port_op = dst_port->op; 1981 1982 pfctl_add_nat(pf, n); 1983 added++; 1984 1985 )))); 1986 1987 FREE_LIST(struct node_host, src_hosts); 1988 FREE_LIST(struct node_port, src_ports); 1989 FREE_LIST(struct node_host, dst_hosts); 1990 FREE_LIST(struct node_port, dst_ports); 1991 1992 if (!added) 1993 yyerror("nat rule expands to no valid combinations"); 1994} 1995 1996void 1997expand_rdr(struct pf_rdr *r, struct node_if *interfaces, 1998 struct node_host *src_hosts, 1999 struct node_host *dst_hosts) 2000{ 2001 int af = r->af, added = 0; 2002 char ifname[IF_NAMESIZE]; 2003 2004 CHECK_ROOT(struct node_if, interfaces); 2005 CHECK_ROOT(struct node_host, src_hosts); 2006 CHECK_ROOT(struct node_host, dst_hosts); 2007 2008 LOOP_THROUGH(struct node_if, interface, interfaces, 2009 LOOP_THROUGH(struct node_host, src_host, src_hosts, 2010 LOOP_THROUGH(struct node_host, dst_host, dst_hosts, 2011 2012 r->af = af; 2013 if ((r->af && src_host->af && r->af != src_host->af) || 2014 (r->af && dst_host->af && r->af != dst_host->af) || 2015 (src_host->af && dst_host->af && 2016 src_host->af != dst_host->af) || 2017 (src_host->ifindex && dst_host->ifindex && 2018 src_host->ifindex != dst_host->ifindex) || 2019 (src_host->ifindex && if_nametoindex(interface->ifname) && 2020 src_host->ifindex != if_nametoindex(interface->ifname)) || 2021 (dst_host->ifindex && if_nametoindex(interface->ifname) && 2022 dst_host->ifindex != if_nametoindex(interface->ifname))) 2023 continue; 2024 2025 if (!r->af && src_host->af) 2026 r->af = src_host->af; 2027 else if (!r->af && dst_host->af) 2028 r->af = dst_host->af; 2029 if (!r->af && (r->saddr.addr_dyn != NULL || 2030 r->daddr.addr_dyn != NULL || r->raddr.addr_dyn)) { 2031 yyerror("address family (inet/inet6) undefined"); 2032 continue; 2033 } 2034 2035 if (if_indextoname(src_host->ifindex, ifname)) 2036 memcpy(r->ifname, ifname, sizeof(r->ifname)); 2037 else if (if_indextoname(dst_host->ifindex, ifname)) 2038 memcpy(r->ifname, ifname, sizeof(r->ifname)); 2039 else 2040 memcpy(r->ifname, interface->ifname, sizeof(r->ifname)); 2041 2042 r->saddr = src_host->addr; 2043 r->smask = src_host->mask; 2044 r->daddr = dst_host->addr; 2045 r->dmask = dst_host->mask; 2046 2047 pfctl_add_rdr(pf, r); 2048 added++; 2049 ))); 2050 2051 FREE_LIST(struct node_if, interfaces); 2052 FREE_LIST(struct node_host, src_hosts); 2053 FREE_LIST(struct node_host, dst_hosts); 2054 2055 if (!added) 2056 yyerror("rdr rule expands to no valid combination"); 2057} 2058 2059#undef FREE_LIST 2060#undef CHECK_ROOT 2061#undef LOOP_THROUGH 2062 2063int 2064check_rulestate(int desired_state) 2065{ 2066 if (rulestate > desired_state) { 2067 yyerror("Rules must be in order: options, scrub, nat, filter"); 2068 return (1); 2069 } 2070 rulestate = desired_state; 2071 return (0); 2072} 2073 2074int 2075kw_cmp(k, e) 2076 const void *k, *e; 2077{ 2078 return (strcmp(k, ((struct keywords *)e)->k_name)); 2079} 2080 2081int 2082lookup(char *s) 2083{ 2084 /* this has to be sorted always */ 2085 static const struct keywords keywords[] = { 2086 { "all", ALL}, 2087 { "allow-opts", ALLOWOPTS}, 2088 { "any", ANY}, 2089 { "binat", BINAT}, 2090 { "block", BLOCK}, 2091 { "code", CODE}, 2092 { "crop", FRAGCROP}, 2093 { "drop-ovl", FRAGDROP}, 2094 { "dup-to", DUPTO}, 2095 { "fastroute", FASTROUTE}, 2096 { "flags", FLAGS}, 2097 { "fragment", FRAGMENT}, 2098 { "from", FROM}, 2099 { "group", GROUP}, 2100 { "icmp-type", ICMPTYPE}, 2101 { "in", IN}, 2102 { "inet", INET}, 2103 { "inet6", INET6}, 2104 { "ipv6-icmp-type", ICMP6TYPE}, 2105 { "keep", KEEP}, 2106 { "label", LABEL}, 2107 { "limit", LIMIT}, 2108 { "log", LOG}, 2109 { "log-all", LOGALL}, 2110 { "loginterface", LOGINTERFACE}, 2111 { "max", MAXIMUM}, 2112 { "max-mss", MAXMSS}, 2113 { "min-ttl", MINTTL}, 2114 { "modulate", MODULATE}, 2115 { "nat", NAT}, 2116 { "no", NO}, 2117 { "no-df", NODF}, 2118 { "no-route", NOROUTE}, 2119 { "on", ON}, 2120 { "optimization", OPTIMIZATION}, 2121 { "out", OUT}, 2122 { "pass", PASS}, 2123 { "port", PORT}, 2124 { "proto", PROTO}, 2125 { "quick", QUICK}, 2126 { "rdr", RDR}, 2127 { "reassemble", FRAGNORM}, 2128 { "return", RETURN}, 2129 { "return-icmp",RETURNICMP}, 2130 { "return-icmp6",RETURNICMP6}, 2131 { "return-rst", RETURNRST}, 2132 { "route-to", ROUTETO}, 2133 { "scrub", SCRUB}, 2134 { "set", SET}, 2135 { "state", STATE}, 2136 { "timeout", TIMEOUT}, 2137 { "to", TO}, 2138 { "ttl", TTL}, 2139 { "user", USER}, 2140 }; 2141 const struct keywords *p; 2142 2143 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 2144 sizeof(keywords[0]), kw_cmp); 2145 2146 if (p) { 2147 if (debug > 1) 2148 fprintf(stderr, "%s: %d\n", s, p->k_val); 2149 return (p->k_val); 2150 } else { 2151 if (debug > 1) 2152 fprintf(stderr, "string: %s\n", s); 2153 return (STRING); 2154 } 2155} 2156 2157#define MAXPUSHBACK 128 2158 2159char *parsebuf; 2160int parseindex; 2161char pushback_buffer[MAXPUSHBACK]; 2162int pushback_index = 0; 2163 2164int 2165lgetc(FILE *fin) 2166{ 2167 int c, next; 2168 2169 if (parsebuf) { 2170 /* Reading characters from the parse buffer, instead of input */ 2171 if (parseindex >= 0) { 2172 c = parsebuf[parseindex++]; 2173 if (c != '\0') 2174 return (c); 2175 parsebuf = NULL; 2176 } else 2177 parseindex++; 2178 } 2179 2180 if (pushback_index) 2181 return (pushback_buffer[--pushback_index]); 2182 2183 while ((c = getc(fin)) == '\\') { 2184 next = getc(fin); 2185 if (next != '\n') { 2186 ungetc(next, fin); 2187 break; 2188 } 2189 yylval.lineno = lineno; 2190 lineno++; 2191 } 2192 return (c); 2193} 2194 2195int 2196lungetc(int c, FILE *fin) 2197{ 2198 if (c == EOF) 2199 return (EOF); 2200 if (parsebuf) { 2201 parseindex--; 2202 if (parseindex >= 0) 2203 return (c); 2204 } 2205 if (pushback_index < MAXPUSHBACK-1) 2206 return (pushback_buffer[pushback_index++] = c); 2207 else 2208 return (EOF); 2209} 2210 2211int 2212findeol() 2213{ 2214 int c; 2215 2216 parsebuf = NULL; 2217 pushback_index = 0; 2218 2219 /* skip to either EOF or the first real EOL */ 2220 while (1) { 2221 c = lgetc(fin); 2222 if (c == '\\') { 2223 c = lgetc(fin); 2224 if (c == '\n') 2225 continue; 2226 } 2227 if (c == EOF || c == '\n') 2228 break; 2229 } 2230 return (ERROR); 2231} 2232 2233int 2234yylex(void) 2235{ 2236 char buf[8096], *p, *val; 2237 int endc, c, next; 2238 int token; 2239 2240top: 2241 p = buf; 2242 while ((c = lgetc(fin)) == ' ' || c == '\t') 2243 ; 2244 2245 yylval.lineno = lineno; 2246 if (c == '#') 2247 while ((c = lgetc(fin)) != '\n' && c != EOF) 2248 ; 2249 if (c == '$' && parsebuf == NULL) { 2250 while (1) { 2251 if ((c = lgetc(fin)) == EOF) 2252 return (0); 2253 if (p + 1 >= buf + sizeof(buf) - 1) { 2254 yyerror("string too long"); 2255 return (findeol()); 2256 } 2257 if (isalnum(c) || c == '_') { 2258 *p++ = (char)c; 2259 continue; 2260 } 2261 *p = '\0'; 2262 lungetc(c, fin); 2263 break; 2264 } 2265 val = symget(buf); 2266 if (val == NULL) 2267 return (ERROR); 2268 parsebuf = val; 2269 parseindex = 0; 2270 goto top; 2271 } 2272 2273 switch (c) { 2274 case '\'': 2275 case '"': 2276 endc = c; 2277 while (1) { 2278 if ((c = lgetc(fin)) == EOF) 2279 return (0); 2280 if (c == endc) { 2281 *p = '\0'; 2282 break; 2283 } 2284 if (c == '\n') 2285 continue; 2286 if (p + 1 >= buf + sizeof(buf) - 1) { 2287 yyerror("string too long"); 2288 return (findeol()); 2289 } 2290 *p++ = (char)c; 2291 } 2292 yylval.v.string = strdup(buf); 2293 if (yylval.v.string == NULL) 2294 err(1, "yylex: strdup"); 2295 return (STRING); 2296 case '=': 2297 yylval.v.i = PF_OP_EQ; 2298 return (PORTUNARY); 2299 case '!': 2300 next = lgetc(fin); 2301 if (next == '=') { 2302 yylval.v.i = PF_OP_NE; 2303 return (PORTUNARY); 2304 } 2305 lungetc(next, fin); 2306 break; 2307 case '<': 2308 next = lgetc(fin); 2309 if (next == '>') { 2310 yylval.v.i = PF_OP_XRG; 2311 return (PORTBINARY); 2312 } else if (next == '=') { 2313 yylval.v.i = PF_OP_LE; 2314 } else { 2315 yylval.v.i = PF_OP_LT; 2316 lungetc(next, fin); 2317 } 2318 return (PORTUNARY); 2319 break; 2320 case '>': 2321 next = lgetc(fin); 2322 if (next == '<') { 2323 yylval.v.i = PF_OP_IRG; 2324 return (PORTBINARY); 2325 } else if (next == '=') { 2326 yylval.v.i = PF_OP_GE; 2327 } else { 2328 yylval.v.i = PF_OP_GT; 2329 lungetc(next, fin); 2330 } 2331 return (PORTUNARY); 2332 break; 2333 case '-': 2334 next = lgetc(fin); 2335 if (next == '>') 2336 return (ARROW); 2337 lungetc(next, fin); 2338 break; 2339 } 2340 2341 /* Need to parse v6 addresses before tokenizing numbers. ick */ 2342 if (isxdigit(c) || c == ':') { 2343 struct node_host *node = NULL; 2344 u_int32_t addr[4]; 2345 char lookahead[46]; 2346 int i = 0; 2347 struct addrinfo hints, *res; 2348 2349 lookahead[i] = c; 2350 2351 while (i < sizeof(lookahead) && 2352 (isalnum(c) || c == ':' || c == '.' || c == '%')) { 2353 lookahead[++i] = c = lgetc(fin); 2354 } 2355 2356 /* quick check avoids calling inet_pton too often */ 2357 lungetc(lookahead[i], fin); 2358 lookahead[i] = '\0'; 2359 2360 memset(&hints, 0, sizeof(hints)); 2361 hints.ai_family = AF_INET6; 2362 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 2363 hints.ai_flags = AI_NUMERICHOST; 2364 if (getaddrinfo(lookahead, "0", &hints, &res) == 0) { 2365 node = calloc(1, sizeof(struct node_host)); 2366 if (node == NULL) 2367 err(1, "yylex: calloc"); 2368 node->af = AF_INET6; 2369 node->addr.addr_dyn = NULL; 2370 memcpy(&node->addr.addr, 2371 &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 2372 sizeof(addr)); 2373 node->ifindex = ((struct sockaddr_in6 *)res->ai_addr) 2374 ->sin6_scope_id; 2375 yylval.v.host = node; 2376 return IPV6ADDR; 2377 freeaddrinfo(res); 2378 } else { 2379 free(node); 2380 while (i > 1) 2381 lungetc(lookahead[--i], fin); 2382 c = lookahead[--i]; 2383 } 2384 } 2385 2386 if (isdigit(c)) { 2387 int index = 0, base = 10; 2388 u_int64_t n = 0; 2389 2390 yylval.v.number = 0; 2391 while (1) { 2392 if (base == 10) { 2393 if (!isdigit(c)) 2394 break; 2395 c -= '0'; 2396 } else if (base == 16) { 2397 if (isdigit(c)) 2398 c -= '0'; 2399 else if (c >= 'a' && c <= 'f') 2400 c -= 'a' - 10; 2401 else if (c >= 'A' && c <= 'F') 2402 c -= 'A' - 10; 2403 else 2404 break; 2405 } 2406 n = n * base + c; 2407 2408 if (n > UINT_MAX) { 2409 yyerror("number is too large"); 2410 return (ERROR); 2411 } 2412 c = lgetc(fin); 2413 if (c == EOF) 2414 break; 2415 if (index++ == 0 && n == 0 && c == 'x') { 2416 base = 16; 2417 c = lgetc(fin); 2418 if (c == EOF) 2419 break; 2420 } 2421 } 2422 yylval.v.number = (u_int32_t)n; 2423 2424 if (c != EOF) 2425 lungetc(c, fin); 2426 if (debug > 1) 2427 fprintf(stderr, "number: %d\n", yylval.v.number); 2428 return (NUMBER); 2429 } 2430 2431#define allowed_in_string(x) \ 2432 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 2433 x != '{' && x != '}' && x != '<' && x != '>' && \ 2434 x != '!' && x != '=' && x != '/' && x != '#' && \ 2435 x != ',' && x != ':' && x != '(' && x != ')')) 2436 2437 if (isalnum(c)) { 2438 do { 2439 *p++ = c; 2440 if (p-buf >= sizeof buf) { 2441 yyerror("string too long"); 2442 return (ERROR); 2443 } 2444 } while ((c = lgetc(fin)) != EOF && (allowed_in_string(c))); 2445 lungetc(c, fin); 2446 *p = '\0'; 2447 token = lookup(buf); 2448 yylval.v.string = strdup(buf); 2449 if (yylval.v.string == NULL) 2450 err(1, "yylex: strdup"); 2451 return (token); 2452 } 2453 if (c == '\n') { 2454 yylval.lineno = lineno; 2455 lineno++; 2456 } 2457 if (c == EOF) 2458 return (0); 2459 return (c); 2460} 2461 2462int 2463parse_rules(FILE *input, struct pfctl *xpf) 2464{ 2465 fin = input; 2466 pf = xpf; 2467 lineno = 1; 2468 errors = 0; 2469 rulestate = PFCTL_STATE_NONE; 2470 yyparse(); 2471 return (errors ? -1 : 0); 2472} 2473 2474void 2475ipmask(struct pf_addr *m, u_int8_t b) 2476{ 2477 int i, j = 0; 2478 2479 while (b >= 32) { 2480 m->addr32[j++] = 0xffffffff; 2481 b -= 32; 2482 } 2483 for (i = 31; i > 31-b; --i) 2484 m->addr32[j] |= (1 << i); 2485 if (b) 2486 m->addr32[j] = htonl(m->addr32[j]); 2487} 2488 2489/* 2490 * Over-designed efficiency is a French and German concept, so how about 2491 * we wait until they discover this ugliness and make it all fancy. 2492 */ 2493int 2494symset(const char *nam, const char *val) 2495{ 2496 struct sym *sym; 2497 2498 sym = calloc(1, sizeof(*sym)); 2499 if (sym == NULL) 2500 return (-1); 2501 sym->nam = strdup(nam); 2502 if (sym->nam == NULL) { 2503 free(sym); 2504 return (-1); 2505 } 2506 sym->val = strdup(val); 2507 if (sym->val == NULL) { 2508 free(sym->nam); 2509 free(sym); 2510 return (-1); 2511 } 2512 sym->next = symhead; 2513 symhead = sym; 2514 return (0); 2515} 2516 2517char * 2518symget(const char *nam) 2519{ 2520 struct sym *sym; 2521 2522 for (sym = symhead; sym; sym = sym->next) 2523 if (strcmp(nam, sym->nam) == 0) 2524 return (sym->val); 2525 return (NULL); 2526} 2527 2528struct ifaddrs **ifa0tab, **ifa4tab, **ifa6tab; 2529int ifa0len, ifa4len, ifa6len; 2530 2531int 2532ifa_comp(const void *p1, const void *p2) 2533{ 2534 struct ifaddrs *ifa1 = *(struct ifaddrs **)p1; 2535 struct ifaddrs *ifa2 = *(struct ifaddrs **)p2; 2536 2537 return strcmp(ifa1->ifa_name, ifa2->ifa_name); 2538} 2539 2540void 2541ifa_load(void) 2542{ 2543 struct ifaddrs *ifap, *ifa; 2544 void *p; 2545 int ifalen = 0; 2546 2547 if (getifaddrs(&ifap) < 0) 2548 err(1, "getifaddrs"); 2549 for (ifa = ifap; ifa; ifa = ifa->ifa_next) 2550 ifalen++; 2551 /* (over-)allocate tables */ 2552 ifa0tab = malloc(ifalen * sizeof(void *)); 2553 ifa4tab = malloc(ifalen * sizeof(void *)); 2554 ifa6tab = malloc(ifalen * sizeof(void *)); 2555 if (!ifa0tab || !ifa4tab || !ifa6tab) 2556 err(1, "malloc"); 2557 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 2558 if (ifa->ifa_addr->sa_family == AF_LINK) { 2559 if (bsearch(&ifa, ifa0tab, ifa0len, sizeof(void *), 2560 ifa_comp)) 2561 continue; /* take only the first LINK address */ 2562 ifa0tab[ifa0len++] = ifa; 2563 qsort(ifa0tab, ifa0len, sizeof(void *), ifa_comp); 2564 } 2565 if (ifa->ifa_addr->sa_family == AF_INET) { 2566 if (bsearch(&ifa, ifa4tab, ifa4len, sizeof(void *), 2567 ifa_comp)) 2568 continue; /* take only the first IPv4 address */ 2569 ifa4tab[ifa4len++] = ifa; 2570 qsort(ifa4tab, ifa4len, sizeof(void *), ifa_comp); 2571 } 2572 if (ifa->ifa_addr->sa_family == AF_INET6) { 2573 /* XXX - better address selection required! */ 2574 if (bsearch(&ifa, ifa6tab, ifa6len, sizeof(void *), 2575 ifa_comp)) 2576 continue; /* take only the first IPv6 address */ 2577 ifa6tab[ifa6len++] = ifa; 2578 qsort(ifa6tab, ifa6len, sizeof(void *), ifa_comp); 2579 } 2580 } 2581 /* shrink tables */ 2582 if ((p = realloc(ifa0tab, ifa0len * sizeof(void *))) == NULL) { 2583 free(ifa0tab); 2584 ifa0tab = NULL; 2585 } else 2586 ifa0tab = p; 2587 if ((p = realloc(ifa4tab, ifa4len * sizeof(void *))) == NULL) { 2588 free(ifa4tab); 2589 ifa4tab = NULL; 2590 } else 2591 ifa4tab = p; 2592 if ((p = realloc(ifa6tab, ifa6len * sizeof(void *))) == NULL) { 2593 free(ifa6tab); 2594 ifa6tab = NULL; 2595 } else 2596 ifa6tab = p; 2597 if (!ifa0tab || !ifa4tab || !ifa6tab) 2598 err(1, "realloc"); 2599} 2600 2601struct ifaddrs * 2602ifa0_lookup(char *ifa_name) 2603{ 2604 struct ifaddrs ifa, *ifp = &ifa, **ifpp; 2605 2606 if (!ifa0tab) 2607 ifa_load(); 2608 ifa.ifa_name = ifa_name; 2609 ifpp = bsearch(&ifp, ifa0tab, ifa0len, sizeof(void *), ifa_comp); 2610 return ifpp ? *ifpp : NULL; 2611} 2612 2613struct ifaddrs * 2614ifa4_lookup(char *ifa_name) 2615{ 2616 struct ifaddrs ifa, *ifp = &ifa, **ifpp; 2617 2618 if (!ifa4tab) 2619 ifa_load(); 2620 ifa.ifa_name = ifa_name; 2621 ifpp = bsearch(&ifp, ifa4tab, ifa4len, sizeof(void *), ifa_comp); 2622 return ifpp ? *ifpp : NULL; 2623} 2624 2625struct ifaddrs * 2626ifa6_lookup(char *ifa_name) 2627{ 2628 struct ifaddrs ifa, *ifp = &ifa, **ifpp; 2629 2630 if (!ifa6tab) 2631 ifa_load(); 2632 ifa.ifa_name = ifa_name; 2633 ifpp = bsearch(&ifp, ifa6tab, ifa6len, sizeof(void *), ifa_comp); 2634 return ifpp ? *ifpp : NULL; 2635} 2636 2637