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