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