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