parse.y revision 1.522
1/* $OpenBSD: parse.y,v 1.522 2007/09/12 18:49:03 deraadt Exp $ */ 2 3/* 4 * Copyright (c) 2001 Markus Friedl. All rights reserved. 5 * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. 6 * Copyright (c) 2001 Theo de Raadt. All rights reserved. 7 * Copyright (c) 2002,2003 Henning Brauer. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29%{ 30#include <sys/types.h> 31#include <sys/socket.h> 32#include <net/if.h> 33#include <netinet/in.h> 34#include <netinet/in_systm.h> 35#include <netinet/ip.h> 36#include <netinet/ip_icmp.h> 37#include <netinet/icmp6.h> 38#include <net/pfvar.h> 39#include <arpa/inet.h> 40#include <altq/altq.h> 41#include <altq/altq_cbq.h> 42#include <altq/altq_priq.h> 43#include <altq/altq_hfsc.h> 44 45#include <stdio.h> 46#include <stdlib.h> 47#include <netdb.h> 48#include <stdarg.h> 49#include <errno.h> 50#include <string.h> 51#include <ctype.h> 52#include <math.h> 53#include <err.h> 54#include <limits.h> 55#include <pwd.h> 56#include <grp.h> 57#include <md5.h> 58 59#include "pfctl_parser.h" 60#include "pfctl.h" 61 62static struct pfctl *pf = NULL; 63static FILE *fin = NULL; 64static int debug = 0; 65static int lineno = 1; 66static int errors = 0; 67static int rulestate = 0; 68static u_int16_t returnicmpdefault = 69 (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 70static u_int16_t returnicmp6default = 71 (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT; 72static int blockpolicy = PFRULE_DROP; 73static int require_order = 1; 74static int default_statelock; 75 76enum { 77 PFCTL_STATE_NONE, 78 PFCTL_STATE_OPTION, 79 PFCTL_STATE_SCRUB, 80 PFCTL_STATE_QUEUE, 81 PFCTL_STATE_NAT, 82 PFCTL_STATE_FILTER 83}; 84 85struct node_proto { 86 u_int8_t proto; 87 struct node_proto *next; 88 struct node_proto *tail; 89}; 90 91struct node_port { 92 u_int16_t port[2]; 93 u_int8_t op; 94 struct node_port *next; 95 struct node_port *tail; 96}; 97 98struct node_uid { 99 uid_t uid[2]; 100 u_int8_t op; 101 struct node_uid *next; 102 struct node_uid *tail; 103}; 104 105struct node_gid { 106 gid_t gid[2]; 107 u_int8_t op; 108 struct node_gid *next; 109 struct node_gid *tail; 110}; 111 112struct node_icmp { 113 u_int8_t code; 114 u_int8_t type; 115 u_int8_t proto; 116 struct node_icmp *next; 117 struct node_icmp *tail; 118}; 119 120enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK, 121 PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN, 122 PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES, 123 PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK, 124 PF_STATE_OPT_TIMEOUT }; 125 126enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE }; 127 128struct node_state_opt { 129 int type; 130 union { 131 u_int32_t max_states; 132 u_int32_t max_src_states; 133 u_int32_t max_src_conn; 134 struct { 135 u_int32_t limit; 136 u_int32_t seconds; 137 } max_src_conn_rate; 138 struct { 139 u_int8_t flush; 140 char tblname[PF_TABLE_NAME_SIZE]; 141 } overload; 142 u_int32_t max_src_nodes; 143 u_int8_t src_track; 144 u_int32_t statelock; 145 struct { 146 int number; 147 u_int32_t seconds; 148 } timeout; 149 } data; 150 struct node_state_opt *next; 151 struct node_state_opt *tail; 152}; 153 154struct peer { 155 struct node_host *host; 156 struct node_port *port; 157}; 158 159struct node_queue { 160 char queue[PF_QNAME_SIZE]; 161 char parent[PF_QNAME_SIZE]; 162 char ifname[IFNAMSIZ]; 163 int scheduler; 164 struct node_queue *next; 165 struct node_queue *tail; 166} *queues = NULL; 167 168struct node_qassign { 169 char *qname; 170 char *pqname; 171}; 172 173struct filter_opts { 174 int marker; 175#define FOM_FLAGS 0x01 176#define FOM_ICMP 0x02 177#define FOM_TOS 0x04 178#define FOM_KEEP 0x08 179#define FOM_SRCTRACK 0x10 180 struct node_uid *uid; 181 struct node_gid *gid; 182 struct { 183 u_int8_t b1; 184 u_int8_t b2; 185 u_int16_t w; 186 u_int16_t w2; 187 } flags; 188 struct node_icmp *icmpspec; 189 u_int32_t tos; 190 u_int32_t prob; 191 struct { 192 int action; 193 struct node_state_opt *options; 194 } keep; 195 int fragment; 196 int allowopts; 197 char *label; 198 struct node_qassign queues; 199 char *tag; 200 char *match_tag; 201 u_int8_t match_tag_not; 202 u_int rtableid; 203} filter_opts; 204 205struct antispoof_opts { 206 char *label; 207 u_int rtableid; 208} antispoof_opts; 209 210struct scrub_opts { 211 int marker; 212#define SOM_MINTTL 0x01 213#define SOM_MAXMSS 0x02 214#define SOM_FRAGCACHE 0x04 215 int nodf; 216 int minttl; 217 int maxmss; 218 int fragcache; 219 int randomid; 220 int reassemble_tcp; 221 u_int rtableid; 222} scrub_opts; 223 224struct queue_opts { 225 int marker; 226#define QOM_BWSPEC 0x01 227#define QOM_SCHEDULER 0x02 228#define QOM_PRIORITY 0x04 229#define QOM_TBRSIZE 0x08 230#define QOM_QLIMIT 0x10 231 struct node_queue_bw queue_bwspec; 232 struct node_queue_opt scheduler; 233 int priority; 234 int tbrsize; 235 int qlimit; 236} queue_opts; 237 238struct table_opts { 239 int flags; 240 int init_addr; 241 struct node_tinithead init_nodes; 242} table_opts; 243 244struct pool_opts { 245 int marker; 246#define POM_TYPE 0x01 247#define POM_STICKYADDRESS 0x02 248 u_int8_t opts; 249 int type; 250 int staticport; 251 struct pf_poolhashkey *key; 252 253} pool_opts; 254 255 256struct node_hfsc_opts hfsc_opts; 257 258int yyerror(const char *, ...); 259int disallow_table(struct node_host *, const char *); 260int disallow_urpf_failed(struct node_host *, const char *); 261int disallow_alias(struct node_host *, const char *); 262int rule_consistent(struct pf_rule *, int); 263int filter_consistent(struct pf_rule *, int); 264int nat_consistent(struct pf_rule *); 265int rdr_consistent(struct pf_rule *); 266int process_tabledef(char *, struct table_opts *); 267int yyparse(void); 268void expand_label_str(char *, size_t, const char *, const char *); 269void expand_label_if(const char *, char *, size_t, const char *); 270void expand_label_addr(const char *, char *, size_t, u_int8_t, 271 struct node_host *); 272void expand_label_port(const char *, char *, size_t, struct node_port *); 273void expand_label_proto(const char *, char *, size_t, u_int8_t); 274void expand_label_nr(const char *, char *, size_t); 275void expand_label(char *, size_t, const char *, u_int8_t, struct node_host *, 276 struct node_port *, struct node_host *, struct node_port *, 277 u_int8_t); 278void expand_rule(struct pf_rule *, struct node_if *, struct node_host *, 279 struct node_proto *, struct node_os*, struct node_host *, 280 struct node_port *, struct node_host *, struct node_port *, 281 struct node_uid *, struct node_gid *, struct node_icmp *, 282 const char *); 283int expand_altq(struct pf_altq *, struct node_if *, struct node_queue *, 284 struct node_queue_bw bwspec, struct node_queue_opt *); 285int expand_queue(struct pf_altq *, struct node_if *, struct node_queue *, 286 struct node_queue_bw, struct node_queue_opt *); 287int expand_skip_interface(struct node_if *); 288 289int check_rulestate(int); 290int kw_cmp(const void *, const void *); 291int lookup(char *); 292int lgetc(FILE *); 293int lungetc(int); 294int findeol(void); 295int yylex(void); 296int atoul(char *, u_long *); 297int getservice(char *); 298int rule_label(struct pf_rule *, char *); 299 300TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 301struct sym { 302 TAILQ_ENTRY(sym) entries; 303 int used; 304 int persist; 305 char *nam; 306 char *val; 307}; 308 309 310int symset(const char *, const char *, int); 311char *symget(const char *); 312 313void mv_rules(struct pf_ruleset *, struct pf_ruleset *); 314void decide_address_family(struct node_host *, sa_family_t *); 315void remove_invalid_hosts(struct node_host **, sa_family_t *); 316int invalid_redirect(struct node_host *, sa_family_t); 317u_int16_t parseicmpspec(char *, sa_family_t); 318 319TAILQ_HEAD(loadanchorshead, loadanchors) 320 loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead); 321 322struct loadanchors { 323 TAILQ_ENTRY(loadanchors) entries; 324 char *anchorname; 325 char *filename; 326}; 327 328typedef struct { 329 union { 330 int64_t number; 331 int i; 332 char *string; 333 u_int rtableid; 334 struct { 335 u_int8_t b1; 336 u_int8_t b2; 337 u_int16_t w; 338 u_int16_t w2; 339 } b; 340 struct range { 341 int a; 342 int b; 343 int t; 344 } range; 345 struct node_if *interface; 346 struct node_proto *proto; 347 struct node_icmp *icmp; 348 struct node_host *host; 349 struct node_os *os; 350 struct node_port *port; 351 struct node_uid *uid; 352 struct node_gid *gid; 353 struct node_state_opt *state_opt; 354 struct peer peer; 355 struct { 356 struct peer src, dst; 357 struct node_os *src_os; 358 } fromto; 359 struct { 360 struct node_host *host; 361 u_int8_t rt; 362 u_int8_t pool_opts; 363 sa_family_t af; 364 struct pf_poolhashkey *key; 365 } route; 366 struct redirection { 367 struct node_host *host; 368 struct range rport; 369 } *redirection; 370 struct { 371 int action; 372 struct node_state_opt *options; 373 } keep_state; 374 struct { 375 u_int8_t log; 376 u_int8_t logif; 377 u_int8_t quick; 378 } logquick; 379 struct { 380 int neg; 381 char *name; 382 } tagged; 383 struct pf_poolhashkey *hashkey; 384 struct node_queue *queue; 385 struct node_queue_opt queue_options; 386 struct node_queue_bw queue_bwspec; 387 struct node_qassign qassign; 388 struct filter_opts filter_opts; 389 struct antispoof_opts antispoof_opts; 390 struct queue_opts queue_opts; 391 struct scrub_opts scrub_opts; 392 struct table_opts table_opts; 393 struct pool_opts pool_opts; 394 struct node_hfsc_opts hfsc_opts; 395 } v; 396 int lineno; 397} YYSTYPE; 398 399#define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \ 400 (!((addr).iflags & PFI_AFLAG_NOALIAS) || \ 401 !isdigit((addr).v.ifname[strlen((addr).v.ifname)-1]))) 402 403%} 404 405%token PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS 406%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE 407%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF 408%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL 409%token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE 410%token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR 411%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID 412%token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID 413%token ANTISPOOF FOR 414%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY 415%token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT 416%token QUEUE PRIORITY QLIMIT RTABLE 417%token LOAD RULESET_OPTIMIZATION 418%token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE 419%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH 420%token TAGGED TAG IFBOUND FLOATING STATEPOLICY ROUTE 421%token <v.string> STRING 422%token <v.number> NUMBER 423%token <v.i> PORTBINARY 424%type <v.interface> interface if_list if_item_not if_item 425%type <v.number> number icmptype icmp6type uid gid 426%type <v.number> tos not yesno 427%type <v.i> no dir af fragcache optimizer 428%type <v.i> sourcetrack flush unaryop statelock 429%type <v.b> action nataction natpasslog scrubaction 430%type <v.b> flags flag blockspec 431%type <v.range> port rport 432%type <v.hashkey> hashkey 433%type <v.proto> proto proto_list proto_item 434%type <v.number> protoval 435%type <v.icmp> icmpspec 436%type <v.icmp> icmp_list icmp_item 437%type <v.icmp> icmp6_list icmp6_item 438%type <v.number> reticmpspec reticmp6spec 439%type <v.fromto> fromto 440%type <v.peer> ipportspec from to 441%type <v.host> ipspec xhost host dynaddr host_list 442%type <v.host> redir_host_list redirspec 443%type <v.host> route_host route_host_list routespec 444%type <v.os> os xos os_list 445%type <v.port> portspec port_list port_item 446%type <v.uid> uids uid_list uid_item 447%type <v.gid> gids gid_list gid_item 448%type <v.route> route 449%type <v.redirection> redirection redirpool 450%type <v.string> label string tag anchorname 451%type <v.keep_state> keep 452%type <v.state_opt> state_opt_spec state_opt_list state_opt_item 453%type <v.logquick> logquick quick log logopts logopt 454%type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if 455%type <v.qassign> qname 456%type <v.queue> qassign qassign_list qassign_item 457%type <v.queue_options> scheduler 458%type <v.number> cbqflags_list cbqflags_item 459%type <v.number> priqflags_list priqflags_item 460%type <v.hfsc_opts> hfscopts_list hfscopts_item hfsc_opts 461%type <v.queue_bwspec> bandwidth 462%type <v.filter_opts> filter_opts filter_opt filter_opts_l 463%type <v.antispoof_opts> antispoof_opts antispoof_opt antispoof_opts_l 464%type <v.queue_opts> queue_opts queue_opt queue_opts_l 465%type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l 466%type <v.table_opts> table_opts table_opt table_opts_l 467%type <v.pool_opts> pool_opts pool_opt pool_opts_l 468%type <v.tagged> tagged 469%type <v.rtableid> rtable 470%% 471 472ruleset : /* empty */ 473 | ruleset '\n' 474 | ruleset option '\n' 475 | ruleset scrubrule '\n' 476 | ruleset natrule '\n' 477 | ruleset binatrule '\n' 478 | ruleset pfrule '\n' 479 | ruleset anchorrule '\n' 480 | ruleset loadrule '\n' 481 | ruleset altqif '\n' 482 | ruleset queuespec '\n' 483 | ruleset varset '\n' 484 | ruleset antispoof '\n' 485 | ruleset tabledef '\n' 486 | '{' fakeanchor '}' '\n'; 487 | ruleset error '\n' { errors++; } 488 ; 489 490/* 491 * apply to previouslys specified rule: must be careful to note 492 * what that is: pf or nat or binat or rdr 493 */ 494fakeanchor : fakeanchor '\n' 495 | fakeanchor anchorrule '\n' 496 | fakeanchor binatrule '\n' 497 | fakeanchor natrule '\n' 498 | fakeanchor pfrule '\n' 499 | fakeanchor error '\n' 500 ; 501 502optimizer : string { 503 if (!strcmp($1, "none")) 504 $$ = 0; 505 else if (!strcmp($1, "basic")) 506 $$ = PF_OPTIMIZE_BASIC; 507 else if (!strcmp($1, "profile")) 508 $$ = PF_OPTIMIZE_BASIC | PF_OPTIMIZE_PROFILE; 509 else { 510 yyerror("unknown ruleset-optimization %s", $$); 511 YYERROR; 512 } 513 } 514 ; 515 516option : SET OPTIMIZATION STRING { 517 if (check_rulestate(PFCTL_STATE_OPTION)) { 518 free($3); 519 YYERROR; 520 } 521 if (pfctl_set_optimization(pf, $3) != 0) { 522 yyerror("unknown optimization %s", $3); 523 free($3); 524 YYERROR; 525 } 526 free($3); 527 } 528 | SET RULESET_OPTIMIZATION optimizer { 529 if (!(pf->opts & PF_OPT_OPTIMIZE)) { 530 pf->opts |= PF_OPT_OPTIMIZE; 531 pf->optimize = $3; 532 } 533 } 534 | SET TIMEOUT timeout_spec 535 | SET TIMEOUT '{' timeout_list '}' 536 | SET LIMIT limit_spec 537 | SET LIMIT '{' limit_list '}' 538 | SET LOGINTERFACE STRING { 539 if (check_rulestate(PFCTL_STATE_OPTION)) { 540 free($3); 541 YYERROR; 542 } 543 if (pfctl_set_logif(pf, $3) != 0) { 544 yyerror("error setting loginterface %s", $3); 545 free($3); 546 YYERROR; 547 } 548 free($3); 549 } 550 | SET HOSTID number { 551 if ($3 == 0 || $3 > UINT_MAX) { 552 yyerror("hostid must be non-zero"); 553 YYERROR; 554 } 555 if (pfctl_set_hostid(pf, $3) != 0) { 556 yyerror("error setting hostid %08x", $3); 557 YYERROR; 558 } 559 } 560 | SET BLOCKPOLICY DROP { 561 if (pf->opts & PF_OPT_VERBOSE) 562 printf("set block-policy drop\n"); 563 if (check_rulestate(PFCTL_STATE_OPTION)) 564 YYERROR; 565 blockpolicy = PFRULE_DROP; 566 } 567 | SET BLOCKPOLICY RETURN { 568 if (pf->opts & PF_OPT_VERBOSE) 569 printf("set block-policy return\n"); 570 if (check_rulestate(PFCTL_STATE_OPTION)) 571 YYERROR; 572 blockpolicy = PFRULE_RETURN; 573 } 574 | SET REQUIREORDER yesno { 575 if (pf->opts & PF_OPT_VERBOSE) 576 printf("set require-order %s\n", 577 $3 == 1 ? "yes" : "no"); 578 require_order = $3; 579 } 580 | SET FINGERPRINTS STRING { 581 if (pf->opts & PF_OPT_VERBOSE) 582 printf("set fingerprints \"%s\"\n", $3); 583 if (check_rulestate(PFCTL_STATE_OPTION)) { 584 free($3); 585 YYERROR; 586 } 587 if (!pf->anchor->name[0]) { 588 if (pfctl_file_fingerprints(pf->dev, 589 pf->opts, $3)) { 590 yyerror("error loading " 591 "fingerprints %s", $3); 592 free($3); 593 YYERROR; 594 } 595 } 596 free($3); 597 } 598 | SET STATEPOLICY statelock { 599 if (pf->opts & PF_OPT_VERBOSE) 600 switch ($3) { 601 case 0: 602 printf("set state-policy floating\n"); 603 break; 604 case PFRULE_IFBOUND: 605 printf("set state-policy if-bound\n"); 606 break; 607 } 608 default_statelock = $3; 609 } 610 | SET DEBUG STRING { 611 if (check_rulestate(PFCTL_STATE_OPTION)) { 612 free($3); 613 YYERROR; 614 } 615 if (pfctl_set_debug(pf, $3) != 0) { 616 yyerror("error setting debuglevel %s", $3); 617 free($3); 618 YYERROR; 619 } 620 free($3); 621 } 622 | SET SKIP interface { 623 if (expand_skip_interface($3) != 0) { 624 yyerror("error setting skip interface(s)"); 625 YYERROR; 626 } 627 } 628 ; 629 630string : string STRING { 631 if (asprintf(&$$, "%s %s", $1, $2) == -1) 632 err(1, "string: asprintf"); 633 free($1); 634 free($2); 635 } 636 | STRING 637 ; 638 639varset : STRING '=' string { 640 if (pf->opts & PF_OPT_VERBOSE) 641 printf("%s = \"%s\"\n", $1, $3); 642 if (symset($1, $3, 0) == -1) 643 err(1, "cannot store variable %s", $1); 644 free($1); 645 free($3); 646 } 647 ; 648 649anchorname : STRING { $$ = $1; } 650 | /* empty */ { $$ = NULL; } 651 ; 652 653optnl : optnl '\n' 654 | 655 ; 656 657pfa_anchorlist : pfrule optnl 658 | anchorrule optnl 659 | pfa_anchorlist pfrule optnl 660 | pfa_anchorlist anchorrule optnl 661 ; 662 663pfa_anchor : '{' 664 { 665 char ta[PF_ANCHOR_NAME_SIZE]; 666 struct pf_ruleset *rs; 667 668 /* steping into a brace anchor */ 669 pf->asd++; 670 pf->bn++; 671 pf->brace = 1; 672 673 /* create a holding ruleset in the root */ 674 snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn); 675 rs = pf_find_or_create_ruleset(ta); 676 if (rs == NULL) 677 err(1, "pfa_anchor: pf_find_or_create_ruleset"); 678 pf->astack[pf->asd] = rs->anchor; 679 pf->anchor = rs->anchor; 680 } '\n' pfa_anchorlist '}' 681 { 682 pf->alast = pf->anchor; 683 pf->asd--; 684 pf->anchor = pf->astack[pf->asd]; 685 } 686 | /* empty */ 687 ; 688 689anchorrule : ANCHOR anchorname dir quick interface af proto fromto 690 filter_opts pfa_anchor 691 { 692 struct pf_rule r; 693 694 if (check_rulestate(PFCTL_STATE_FILTER)) { 695 if ($2) 696 free($2); 697 YYERROR; 698 } 699 700 if ($2 && ($2[0] == '_' || strstr($2, "/_") != NULL)) { 701 free($2); 702 yyerror("anchor names beginning with '_' " 703 "are reserved for internal use"); 704 YYERROR; 705 } 706 707 memset(&r, 0, sizeof(r)); 708 if (pf->astack[pf->asd + 1]) { 709 /* move inline rules into relative location */ 710 pf_anchor_setup(&r, 711 &pf->astack[pf->asd]->ruleset, 712 $2 ? $2 : pf->alast->name); 713 714 if (r.anchor == NULL) 715 err(1, "anchorrule: unable to " 716 "create ruleset"); 717 718 if (pf->alast != r.anchor) { 719 if (r.anchor->match) { 720 yyerror("inline anchor '%s' " 721 "already exists", 722 r.anchor->name); 723 YYERROR; 724 } 725 mv_rules(&pf->alast->ruleset, 726 &r.anchor->ruleset); 727 } 728 pf_remove_if_empty_ruleset(&pf->alast->ruleset); 729 pf->alast = r.anchor; 730 } else { 731 if (!$2) { 732 yyerror("anchors without explicit " 733 "rules must specify a name"); 734 YYERROR; 735 } 736 } 737 r.direction = $3; 738 r.quick = $4.quick; 739 r.af = $6; 740 r.prob = $9.prob; 741 r.rtableid = $9.rtableid; 742 743 if ($9.match_tag) 744 if (strlcpy(r.match_tagname, $9.match_tag, 745 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 746 yyerror("tag too long, max %u chars", 747 PF_TAG_NAME_SIZE - 1); 748 YYERROR; 749 } 750 r.match_tag_not = $9.match_tag_not; 751 752 decide_address_family($8.src.host, &r.af); 753 decide_address_family($8.dst.host, &r.af); 754 755 expand_rule(&r, $5, NULL, $7, $8.src_os, 756 $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, 757 0, 0, 0, pf->astack[pf->asd + 1] ? 758 pf->alast->name : $2); 759 free($2); 760 pf->astack[pf->asd + 1] = NULL; 761 } 762 | NATANCHOR string interface af proto fromto rtable { 763 struct pf_rule r; 764 765 if (check_rulestate(PFCTL_STATE_NAT)) { 766 free($2); 767 YYERROR; 768 } 769 770 memset(&r, 0, sizeof(r)); 771 r.action = PF_NAT; 772 r.af = $4; 773 r.rtableid = $7; 774 775 decide_address_family($6.src.host, &r.af); 776 decide_address_family($6.dst.host, &r.af); 777 778 expand_rule(&r, $3, NULL, $5, $6.src_os, 779 $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, 780 0, 0, 0, $2); 781 free($2); 782 } 783 | RDRANCHOR string interface af proto fromto rtable { 784 struct pf_rule r; 785 786 if (check_rulestate(PFCTL_STATE_NAT)) { 787 free($2); 788 YYERROR; 789 } 790 791 memset(&r, 0, sizeof(r)); 792 r.action = PF_RDR; 793 r.af = $4; 794 r.rtableid = $7; 795 796 decide_address_family($6.src.host, &r.af); 797 decide_address_family($6.dst.host, &r.af); 798 799 if ($6.src.port != NULL) { 800 yyerror("source port parameter not supported" 801 " in rdr-anchor"); 802 YYERROR; 803 } 804 if ($6.dst.port != NULL) { 805 if ($6.dst.port->next != NULL) { 806 yyerror("destination port list " 807 "expansion not supported in " 808 "rdr-anchor"); 809 YYERROR; 810 } else if ($6.dst.port->op != PF_OP_EQ) { 811 yyerror("destination port operators" 812 " not supported in rdr-anchor"); 813 YYERROR; 814 } 815 r.dst.port[0] = $6.dst.port->port[0]; 816 r.dst.port[1] = $6.dst.port->port[1]; 817 r.dst.port_op = $6.dst.port->op; 818 } 819 820 expand_rule(&r, $3, NULL, $5, $6.src_os, 821 $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, 822 0, 0, 0, $2); 823 free($2); 824 } 825 | BINATANCHOR string interface af proto fromto rtable { 826 struct pf_rule r; 827 828 if (check_rulestate(PFCTL_STATE_NAT)) { 829 free($2); 830 YYERROR; 831 } 832 833 memset(&r, 0, sizeof(r)); 834 r.action = PF_BINAT; 835 r.af = $4; 836 r.rtableid = $7; 837 if ($5 != NULL) { 838 if ($5->next != NULL) { 839 yyerror("proto list expansion" 840 " not supported in binat-anchor"); 841 YYERROR; 842 } 843 r.proto = $5->proto; 844 free($5); 845 } 846 847 if ($6.src.host != NULL || $6.src.port != NULL || 848 $6.dst.host != NULL || $6.dst.port != NULL) { 849 yyerror("fromto parameter not supported" 850 " in binat-anchor"); 851 YYERROR; 852 } 853 854 decide_address_family($6.src.host, &r.af); 855 decide_address_family($6.dst.host, &r.af); 856 857 pfctl_add_rule(pf, &r, $2); 858 free($2); 859 } 860 ; 861 862loadrule : LOAD ANCHOR string FROM string { 863 struct loadanchors *loadanchor; 864 865 if (strlen(pf->anchor->name) + 1 + 866 strlen($3) >= MAXPATHLEN) { 867 yyerror("anchorname %s too long, max %u\n", 868 $3, MAXPATHLEN - 1); 869 free($3); 870 YYERROR; 871 } 872 loadanchor = calloc(1, sizeof(struct loadanchors)); 873 if (loadanchor == NULL) 874 err(1, "loadrule: calloc"); 875 if ((loadanchor->anchorname = malloc(MAXPATHLEN)) == 876 NULL) 877 err(1, "loadrule: malloc"); 878 if (pf->anchor->name[0]) 879 snprintf(loadanchor->anchorname, MAXPATHLEN, 880 "%s/%s", pf->anchor->name, $3); 881 else 882 strlcpy(loadanchor->anchorname, $3, MAXPATHLEN); 883 if ((loadanchor->filename = strdup($5)) == NULL) 884 err(1, "loadrule: strdup"); 885 886 TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor, 887 entries); 888 889 free($3); 890 free($5); 891 }; 892 893scrubaction : no SCRUB { 894 $$.b2 = $$.w = 0; 895 if ($1) 896 $$.b1 = PF_NOSCRUB; 897 else 898 $$.b1 = PF_SCRUB; 899 } 900 ; 901 902scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts 903 { 904 struct pf_rule r; 905 906 if (check_rulestate(PFCTL_STATE_SCRUB)) 907 YYERROR; 908 909 memset(&r, 0, sizeof(r)); 910 911 r.action = $1.b1; 912 r.direction = $2; 913 914 r.log = $3.log; 915 r.logif = $3.logif; 916 if ($3.quick) { 917 yyerror("scrub rules do not support 'quick'"); 918 YYERROR; 919 } 920 921 r.af = $5; 922 if ($8.nodf) 923 r.rule_flag |= PFRULE_NODF; 924 if ($8.randomid) 925 r.rule_flag |= PFRULE_RANDOMID; 926 if ($8.reassemble_tcp) { 927 if (r.direction != PF_INOUT) { 928 yyerror("reassemble tcp rules can not " 929 "specify direction"); 930 YYERROR; 931 } 932 r.rule_flag |= PFRULE_REASSEMBLE_TCP; 933 } 934 if ($8.minttl) 935 r.min_ttl = $8.minttl; 936 if ($8.maxmss) 937 r.max_mss = $8.maxmss; 938 if ($8.fragcache) 939 r.rule_flag |= $8.fragcache; 940 r.rtableid = $8.rtableid; 941 942 expand_rule(&r, $4, NULL, $6, $7.src_os, 943 $7.src.host, $7.src.port, $7.dst.host, $7.dst.port, 944 NULL, NULL, NULL, ""); 945 } 946 ; 947 948scrub_opts : { 949 bzero(&scrub_opts, sizeof scrub_opts); 950 scrub_opts.rtableid = -1; 951 } 952 scrub_opts_l 953 { $$ = scrub_opts; } 954 | /* empty */ { 955 bzero(&scrub_opts, sizeof scrub_opts); 956 scrub_opts.rtableid = -1; 957 $$ = scrub_opts; 958 } 959 ; 960 961scrub_opts_l : scrub_opts_l scrub_opt 962 | scrub_opt 963 ; 964 965scrub_opt : NODF { 966 if (scrub_opts.nodf) { 967 yyerror("no-df cannot be respecified"); 968 YYERROR; 969 } 970 scrub_opts.nodf = 1; 971 } 972 | MINTTL NUMBER { 973 if (scrub_opts.marker & SOM_MINTTL) { 974 yyerror("min-ttl cannot be respecified"); 975 YYERROR; 976 } 977 if ($2 < 0 || $2 > 255) { 978 yyerror("illegal min-ttl value %d", $2); 979 YYERROR; 980 } 981 scrub_opts.marker |= SOM_MINTTL; 982 scrub_opts.minttl = $2; 983 } 984 | MAXMSS NUMBER { 985 if (scrub_opts.marker & SOM_MAXMSS) { 986 yyerror("max-mss cannot be respecified"); 987 YYERROR; 988 } 989 if ($2 < 0 || $2 > 65535) { 990 yyerror("illegal max-mss value %d", $2); 991 YYERROR; 992 } 993 scrub_opts.marker |= SOM_MAXMSS; 994 scrub_opts.maxmss = $2; 995 } 996 | fragcache { 997 if (scrub_opts.marker & SOM_FRAGCACHE) { 998 yyerror("fragcache cannot be respecified"); 999 YYERROR; 1000 } 1001 scrub_opts.marker |= SOM_FRAGCACHE; 1002 scrub_opts.fragcache = $1; 1003 } 1004 | REASSEMBLE STRING { 1005 if (strcasecmp($2, "tcp") != 0) { 1006 yyerror("scrub reassemble supports only tcp, " 1007 "not '%s'", $2); 1008 free($2); 1009 YYERROR; 1010 } 1011 free($2); 1012 if (scrub_opts.reassemble_tcp) { 1013 yyerror("reassemble tcp cannot be respecified"); 1014 YYERROR; 1015 } 1016 scrub_opts.reassemble_tcp = 1; 1017 } 1018 | RANDOMID { 1019 if (scrub_opts.randomid) { 1020 yyerror("random-id cannot be respecified"); 1021 YYERROR; 1022 } 1023 scrub_opts.randomid = 1; 1024 } 1025 | RTABLE NUMBER { 1026 if ($2 < 0 || $2 > RT_TABLEID_MAX) { 1027 yyerror("invalid rtable id"); 1028 YYERROR; 1029 } 1030 scrub_opts.rtableid = $2; 1031 } 1032 ; 1033 1034fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ } 1035 | FRAGMENT FRAGCROP { $$ = PFRULE_FRAGCROP; } 1036 | FRAGMENT FRAGDROP { $$ = PFRULE_FRAGDROP; } 1037 ; 1038 1039antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { 1040 struct pf_rule r; 1041 struct node_host *h = NULL, *hh; 1042 struct node_if *i, *j; 1043 1044 if (check_rulestate(PFCTL_STATE_FILTER)) 1045 YYERROR; 1046 1047 for (i = $3; i; i = i->next) { 1048 bzero(&r, sizeof(r)); 1049 1050 r.action = PF_DROP; 1051 r.direction = PF_IN; 1052 r.log = $2.log; 1053 r.logif = $2.logif; 1054 r.quick = $2.quick; 1055 r.af = $4; 1056 if (rule_label(&r, $5.label)) 1057 YYERROR; 1058 r.rtableid = $5.rtableid; 1059 j = calloc(1, sizeof(struct node_if)); 1060 if (j == NULL) 1061 err(1, "antispoof: calloc"); 1062 if (strlcpy(j->ifname, i->ifname, 1063 sizeof(j->ifname)) >= sizeof(j->ifname)) { 1064 free(j); 1065 yyerror("interface name too long"); 1066 YYERROR; 1067 } 1068 j->not = 1; 1069 if (i->dynamic) { 1070 h = calloc(1, sizeof(*h)); 1071 if (h == NULL) 1072 err(1, "address: calloc"); 1073 h->addr.type = PF_ADDR_DYNIFTL; 1074 set_ipmask(h, 128); 1075 if (strlcpy(h->addr.v.ifname, i->ifname, 1076 sizeof(h->addr.v.ifname)) >= 1077 sizeof(h->addr.v.ifname)) { 1078 free(h); 1079 yyerror( 1080 "interface name too long"); 1081 YYERROR; 1082 } 1083 hh = malloc(sizeof(*hh)); 1084 if (hh == NULL) 1085 err(1, "address: malloc"); 1086 bcopy(h, hh, sizeof(*hh)); 1087 h->addr.iflags = PFI_AFLAG_NETWORK; 1088 } else { 1089 h = ifa_lookup(j->ifname, 1090 PFI_AFLAG_NETWORK); 1091 hh = NULL; 1092 } 1093 1094 if (h != NULL) 1095 expand_rule(&r, j, NULL, NULL, NULL, h, 1096 NULL, NULL, NULL, NULL, NULL, 1097 NULL, ""); 1098 1099 if ((i->ifa_flags & IFF_LOOPBACK) == 0) { 1100 bzero(&r, sizeof(r)); 1101 1102 r.action = PF_DROP; 1103 r.direction = PF_IN; 1104 r.log = $2.log; 1105 r.quick = $2.quick; 1106 r.af = $4; 1107 if (rule_label(&r, $5.label)) 1108 YYERROR; 1109 r.rtableid = $5.rtableid; 1110 if (hh != NULL) 1111 h = hh; 1112 else 1113 h = ifa_lookup(i->ifname, 0); 1114 if (h != NULL) 1115 expand_rule(&r, NULL, NULL, 1116 NULL, NULL, h, NULL, NULL, 1117 NULL, NULL, NULL, NULL, ""); 1118 } else 1119 free(hh); 1120 } 1121 free($5.label); 1122 } 1123 ; 1124 1125antispoof_ifspc : FOR antispoof_if { $$ = $2; } 1126 | FOR '{' antispoof_iflst '}' { $$ = $3; } 1127 ; 1128 1129antispoof_iflst : antispoof_if { $$ = $1; } 1130 | antispoof_iflst comma antispoof_if { 1131 $1->tail->next = $3; 1132 $1->tail = $3; 1133 $$ = $1; 1134 } 1135 ; 1136 1137antispoof_if : if_item { $$ = $1; } 1138 | '(' if_item ')' { 1139 $2->dynamic = 1; 1140 $$ = $2; 1141 } 1142 ; 1143 1144antispoof_opts : { 1145 bzero(&antispoof_opts, sizeof antispoof_opts); 1146 antispoof_opts.rtableid = -1; 1147 } 1148 antispoof_opts_l 1149 { $$ = antispoof_opts; } 1150 | /* empty */ { 1151 bzero(&antispoof_opts, sizeof antispoof_opts); 1152 antispoof_opts.rtableid = -1; 1153 $$ = antispoof_opts; 1154 } 1155 ; 1156 1157antispoof_opts_l : antispoof_opts_l antispoof_opt 1158 | antispoof_opt 1159 ; 1160 1161antispoof_opt : label { 1162 if (antispoof_opts.label) { 1163 yyerror("label cannot be redefined"); 1164 YYERROR; 1165 } 1166 antispoof_opts.label = $1; 1167 } 1168 | RTABLE NUMBER { 1169 if ($2 < 0 || $2 > RT_TABLEID_MAX) { 1170 yyerror("invalid rtable id"); 1171 YYERROR; 1172 } 1173 antispoof_opts.rtableid = $2; 1174 } 1175 ; 1176 1177not : '!' { $$ = 1; } 1178 | /* empty */ { $$ = 0; } 1179 ; 1180 1181tabledef : TABLE '<' STRING '>' table_opts { 1182 struct node_host *h, *nh; 1183 struct node_tinit *ti, *nti; 1184 1185 if (strlen($3) >= PF_TABLE_NAME_SIZE) { 1186 yyerror("table name too long, max %d chars", 1187 PF_TABLE_NAME_SIZE - 1); 1188 free($3); 1189 YYERROR; 1190 } 1191 if (pf->loadopt & PFCTL_FLAG_TABLE) 1192 if (process_tabledef($3, &$5)) { 1193 free($3); 1194 YYERROR; 1195 } 1196 free($3); 1197 for (ti = SIMPLEQ_FIRST(&$5.init_nodes); 1198 ti != SIMPLEQ_END(&$5.init_nodes); ti = nti) { 1199 if (ti->file) 1200 free(ti->file); 1201 for (h = ti->host; h != NULL; h = nh) { 1202 nh = h->next; 1203 free(h); 1204 } 1205 nti = SIMPLEQ_NEXT(ti, entries); 1206 free(ti); 1207 } 1208 } 1209 ; 1210 1211table_opts : { 1212 bzero(&table_opts, sizeof table_opts); 1213 SIMPLEQ_INIT(&table_opts.init_nodes); 1214 } 1215 table_opts_l 1216 { $$ = table_opts; } 1217 | /* empty */ 1218 { 1219 bzero(&table_opts, sizeof table_opts); 1220 SIMPLEQ_INIT(&table_opts.init_nodes); 1221 $$ = table_opts; 1222 } 1223 ; 1224 1225table_opts_l : table_opts_l table_opt 1226 | table_opt 1227 ; 1228 1229table_opt : STRING { 1230 if (!strcmp($1, "const")) 1231 table_opts.flags |= PFR_TFLAG_CONST; 1232 else if (!strcmp($1, "persist")) 1233 table_opts.flags |= PFR_TFLAG_PERSIST; 1234 else { 1235 yyerror("invalid table option '%s'", $1); 1236 free($1); 1237 YYERROR; 1238 } 1239 free($1); 1240 } 1241 | '{' '}' { table_opts.init_addr = 1; } 1242 | '{' host_list '}' { 1243 struct node_host *n; 1244 struct node_tinit *ti; 1245 1246 for (n = $2; n != NULL; n = n->next) { 1247 switch (n->addr.type) { 1248 case PF_ADDR_ADDRMASK: 1249 continue; /* ok */ 1250 case PF_ADDR_RANGE: 1251 yyerror("address ranges are not " 1252 "permitted inside tables"); 1253 break; 1254 case PF_ADDR_DYNIFTL: 1255 yyerror("dynamic addresses are not " 1256 "permitted inside tables"); 1257 break; 1258 case PF_ADDR_TABLE: 1259 yyerror("tables cannot contain tables"); 1260 break; 1261 case PF_ADDR_NOROUTE: 1262 yyerror("\"no-route\" is not permitted " 1263 "inside tables"); 1264 break; 1265 case PF_ADDR_URPFFAILED: 1266 yyerror("\"urpf-failed\" is not " 1267 "permitted inside tables"); 1268 break; 1269 default: 1270 yyerror("unknown address type %d", 1271 n->addr.type); 1272 } 1273 YYERROR; 1274 } 1275 if (!(ti = calloc(1, sizeof(*ti)))) 1276 err(1, "table_opt: calloc"); 1277 ti->host = $2; 1278 SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti, 1279 entries); 1280 table_opts.init_addr = 1; 1281 } 1282 | FILENAME STRING { 1283 struct node_tinit *ti; 1284 1285 if (!(ti = calloc(1, sizeof(*ti)))) 1286 err(1, "table_opt: calloc"); 1287 ti->file = $2; 1288 SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti, 1289 entries); 1290 table_opts.init_addr = 1; 1291 } 1292 ; 1293 1294altqif : ALTQ interface queue_opts QUEUE qassign { 1295 struct pf_altq a; 1296 1297 if (check_rulestate(PFCTL_STATE_QUEUE)) 1298 YYERROR; 1299 1300 memset(&a, 0, sizeof(a)); 1301 if ($3.scheduler.qtype == ALTQT_NONE) { 1302 yyerror("no scheduler specified!"); 1303 YYERROR; 1304 } 1305 a.scheduler = $3.scheduler.qtype; 1306 a.qlimit = $3.qlimit; 1307 a.tbrsize = $3.tbrsize; 1308 if ($5 == NULL) { 1309 yyerror("no child queues specified"); 1310 YYERROR; 1311 } 1312 if (expand_altq(&a, $2, $5, $3.queue_bwspec, 1313 &$3.scheduler)) 1314 YYERROR; 1315 } 1316 ; 1317 1318queuespec : QUEUE STRING interface queue_opts qassign { 1319 struct pf_altq a; 1320 1321 if (check_rulestate(PFCTL_STATE_QUEUE)) { 1322 free($2); 1323 YYERROR; 1324 } 1325 1326 memset(&a, 0, sizeof(a)); 1327 1328 if (strlcpy(a.qname, $2, sizeof(a.qname)) >= 1329 sizeof(a.qname)) { 1330 yyerror("queue name too long (max " 1331 "%d chars)", PF_QNAME_SIZE-1); 1332 free($2); 1333 YYERROR; 1334 } 1335 free($2); 1336 if ($4.tbrsize) { 1337 yyerror("cannot specify tbrsize for queue"); 1338 YYERROR; 1339 } 1340 if ($4.priority > 255) { 1341 yyerror("priority out of range: max 255"); 1342 YYERROR; 1343 } 1344 a.priority = $4.priority; 1345 a.qlimit = $4.qlimit; 1346 a.scheduler = $4.scheduler.qtype; 1347 if (expand_queue(&a, $3, $5, $4.queue_bwspec, 1348 &$4.scheduler)) { 1349 yyerror("errors in queue definition"); 1350 YYERROR; 1351 } 1352 } 1353 ; 1354 1355queue_opts : { 1356 bzero(&queue_opts, sizeof queue_opts); 1357 queue_opts.priority = DEFAULT_PRIORITY; 1358 queue_opts.qlimit = DEFAULT_QLIMIT; 1359 queue_opts.scheduler.qtype = ALTQT_NONE; 1360 queue_opts.queue_bwspec.bw_percent = 100; 1361 } 1362 queue_opts_l 1363 { $$ = queue_opts; } 1364 | /* empty */ { 1365 bzero(&queue_opts, sizeof queue_opts); 1366 queue_opts.priority = DEFAULT_PRIORITY; 1367 queue_opts.qlimit = DEFAULT_QLIMIT; 1368 queue_opts.scheduler.qtype = ALTQT_NONE; 1369 queue_opts.queue_bwspec.bw_percent = 100; 1370 $$ = queue_opts; 1371 } 1372 ; 1373 1374queue_opts_l : queue_opts_l queue_opt 1375 | queue_opt 1376 ; 1377 1378queue_opt : BANDWIDTH bandwidth { 1379 if (queue_opts.marker & QOM_BWSPEC) { 1380 yyerror("bandwidth cannot be respecified"); 1381 YYERROR; 1382 } 1383 queue_opts.marker |= QOM_BWSPEC; 1384 queue_opts.queue_bwspec = $2; 1385 } 1386 | PRIORITY NUMBER { 1387 if (queue_opts.marker & QOM_PRIORITY) { 1388 yyerror("priority cannot be respecified"); 1389 YYERROR; 1390 } 1391 if ($2 < 0 || $2 > 255) { 1392 yyerror("priority out of range: max 255"); 1393 YYERROR; 1394 } 1395 queue_opts.marker |= QOM_PRIORITY; 1396 queue_opts.priority = $2; 1397 } 1398 | QLIMIT NUMBER { 1399 if (queue_opts.marker & QOM_QLIMIT) { 1400 yyerror("qlimit cannot be respecified"); 1401 YYERROR; 1402 } 1403 if ($2 < 0 || $2 > 65535) { 1404 yyerror("qlimit out of range: max 65535"); 1405 YYERROR; 1406 } 1407 queue_opts.marker |= QOM_QLIMIT; 1408 queue_opts.qlimit = $2; 1409 } 1410 | scheduler { 1411 if (queue_opts.marker & QOM_SCHEDULER) { 1412 yyerror("scheduler cannot be respecified"); 1413 YYERROR; 1414 } 1415 queue_opts.marker |= QOM_SCHEDULER; 1416 queue_opts.scheduler = $1; 1417 } 1418 | TBRSIZE NUMBER { 1419 if (queue_opts.marker & QOM_TBRSIZE) { 1420 yyerror("tbrsize cannot be respecified"); 1421 YYERROR; 1422 } 1423 if ($2 < 0 || $2 > 65535) { 1424 yyerror("tbrsize too big: max 65535"); 1425 YYERROR; 1426 } 1427 queue_opts.marker |= QOM_TBRSIZE; 1428 queue_opts.tbrsize = $2; 1429 } 1430 ; 1431 1432bandwidth : STRING { 1433 double bps; 1434 char *cp; 1435 1436 $$.bw_percent = 0; 1437 1438 bps = strtod($1, &cp); 1439 if (cp != NULL) { 1440 if (!strcmp(cp, "b")) 1441 ; /* nothing */ 1442 else if (!strcmp(cp, "Kb")) 1443 bps *= 1000; 1444 else if (!strcmp(cp, "Mb")) 1445 bps *= 1000 * 1000; 1446 else if (!strcmp(cp, "Gb")) 1447 bps *= 1000 * 1000 * 1000; 1448 else if (!strcmp(cp, "%")) { 1449 if (bps < 0 || bps > 100) { 1450 yyerror("bandwidth spec " 1451 "out of range"); 1452 free($1); 1453 YYERROR; 1454 } 1455 $$.bw_percent = bps; 1456 bps = 0; 1457 } else { 1458 yyerror("unknown unit %s", cp); 1459 free($1); 1460 YYERROR; 1461 } 1462 } 1463 free($1); 1464 $$.bw_absolute = (u_int32_t)bps; 1465 } 1466 | NUMBER { 1467 if ($1 < 0 || $1 > UINT_MAX) { 1468 yyerror("bandwidth number too big"); 1469 YYERROR; 1470 } 1471 $$.bw_percent = 0; 1472 $$.bw_absolute = $1; 1473 } 1474 ; 1475 1476scheduler : CBQ { 1477 $$.qtype = ALTQT_CBQ; 1478 $$.data.cbq_opts.flags = 0; 1479 } 1480 | CBQ '(' cbqflags_list ')' { 1481 $$.qtype = ALTQT_CBQ; 1482 $$.data.cbq_opts.flags = $3; 1483 } 1484 | PRIQ { 1485 $$.qtype = ALTQT_PRIQ; 1486 $$.data.priq_opts.flags = 0; 1487 } 1488 | PRIQ '(' priqflags_list ')' { 1489 $$.qtype = ALTQT_PRIQ; 1490 $$.data.priq_opts.flags = $3; 1491 } 1492 | HFSC { 1493 $$.qtype = ALTQT_HFSC; 1494 bzero(&$$.data.hfsc_opts, 1495 sizeof(struct node_hfsc_opts)); 1496 } 1497 | HFSC '(' hfsc_opts ')' { 1498 $$.qtype = ALTQT_HFSC; 1499 $$.data.hfsc_opts = $3; 1500 } 1501 ; 1502 1503cbqflags_list : cbqflags_item { $$ |= $1; } 1504 | cbqflags_list comma cbqflags_item { $$ |= $3; } 1505 ; 1506 1507cbqflags_item : STRING { 1508 if (!strcmp($1, "default")) 1509 $$ = CBQCLF_DEFCLASS; 1510 else if (!strcmp($1, "borrow")) 1511 $$ = CBQCLF_BORROW; 1512 else if (!strcmp($1, "red")) 1513 $$ = CBQCLF_RED; 1514 else if (!strcmp($1, "ecn")) 1515 $$ = CBQCLF_RED|CBQCLF_ECN; 1516 else if (!strcmp($1, "rio")) 1517 $$ = CBQCLF_RIO; 1518 else { 1519 yyerror("unknown cbq flag \"%s\"", $1); 1520 free($1); 1521 YYERROR; 1522 } 1523 free($1); 1524 } 1525 ; 1526 1527priqflags_list : priqflags_item { $$ |= $1; } 1528 | priqflags_list comma priqflags_item { $$ |= $3; } 1529 ; 1530 1531priqflags_item : STRING { 1532 if (!strcmp($1, "default")) 1533 $$ = PRCF_DEFAULTCLASS; 1534 else if (!strcmp($1, "red")) 1535 $$ = PRCF_RED; 1536 else if (!strcmp($1, "ecn")) 1537 $$ = PRCF_RED|PRCF_ECN; 1538 else if (!strcmp($1, "rio")) 1539 $$ = PRCF_RIO; 1540 else { 1541 yyerror("unknown priq flag \"%s\"", $1); 1542 free($1); 1543 YYERROR; 1544 } 1545 free($1); 1546 } 1547 ; 1548 1549hfsc_opts : { 1550 bzero(&hfsc_opts, 1551 sizeof(struct node_hfsc_opts)); 1552 } 1553 hfscopts_list { 1554 $$ = hfsc_opts; 1555 } 1556 ; 1557 1558hfscopts_list : hfscopts_item 1559 | hfscopts_list comma hfscopts_item 1560 ; 1561 1562hfscopts_item : LINKSHARE bandwidth { 1563 if (hfsc_opts.linkshare.used) { 1564 yyerror("linkshare already specified"); 1565 YYERROR; 1566 } 1567 hfsc_opts.linkshare.m2 = $2; 1568 hfsc_opts.linkshare.used = 1; 1569 } 1570 | LINKSHARE '(' bandwidth comma NUMBER comma bandwidth ')' 1571 { 1572 if ($5 < 0 || $5 > INT_MAX) { 1573 yyerror("timing in curve out of range"); 1574 YYERROR; 1575 } 1576 if (hfsc_opts.linkshare.used) { 1577 yyerror("linkshare already specified"); 1578 YYERROR; 1579 } 1580 hfsc_opts.linkshare.m1 = $3; 1581 hfsc_opts.linkshare.d = $5; 1582 hfsc_opts.linkshare.m2 = $7; 1583 hfsc_opts.linkshare.used = 1; 1584 } 1585 | REALTIME bandwidth { 1586 if (hfsc_opts.realtime.used) { 1587 yyerror("realtime already specified"); 1588 YYERROR; 1589 } 1590 hfsc_opts.realtime.m2 = $2; 1591 hfsc_opts.realtime.used = 1; 1592 } 1593 | REALTIME '(' bandwidth comma NUMBER comma bandwidth ')' 1594 { 1595 if ($5 < 0 || $5 > INT_MAX) { 1596 yyerror("timing in curve out of range"); 1597 YYERROR; 1598 } 1599 if (hfsc_opts.realtime.used) { 1600 yyerror("realtime already specified"); 1601 YYERROR; 1602 } 1603 hfsc_opts.realtime.m1 = $3; 1604 hfsc_opts.realtime.d = $5; 1605 hfsc_opts.realtime.m2 = $7; 1606 hfsc_opts.realtime.used = 1; 1607 } 1608 | UPPERLIMIT bandwidth { 1609 if (hfsc_opts.upperlimit.used) { 1610 yyerror("upperlimit already specified"); 1611 YYERROR; 1612 } 1613 hfsc_opts.upperlimit.m2 = $2; 1614 hfsc_opts.upperlimit.used = 1; 1615 } 1616 | UPPERLIMIT '(' bandwidth comma NUMBER comma bandwidth ')' 1617 { 1618 if ($5 < 0 || $5 > INT_MAX) { 1619 yyerror("timing in curve out of range"); 1620 YYERROR; 1621 } 1622 if (hfsc_opts.upperlimit.used) { 1623 yyerror("upperlimit already specified"); 1624 YYERROR; 1625 } 1626 hfsc_opts.upperlimit.m1 = $3; 1627 hfsc_opts.upperlimit.d = $5; 1628 hfsc_opts.upperlimit.m2 = $7; 1629 hfsc_opts.upperlimit.used = 1; 1630 } 1631 | STRING { 1632 if (!strcmp($1, "default")) 1633 hfsc_opts.flags |= HFCF_DEFAULTCLASS; 1634 else if (!strcmp($1, "red")) 1635 hfsc_opts.flags |= HFCF_RED; 1636 else if (!strcmp($1, "ecn")) 1637 hfsc_opts.flags |= HFCF_RED|HFCF_ECN; 1638 else if (!strcmp($1, "rio")) 1639 hfsc_opts.flags |= HFCF_RIO; 1640 else { 1641 yyerror("unknown hfsc flag \"%s\"", $1); 1642 free($1); 1643 YYERROR; 1644 } 1645 free($1); 1646 } 1647 ; 1648 1649qassign : /* empty */ { $$ = NULL; } 1650 | qassign_item { $$ = $1; } 1651 | '{' qassign_list '}' { $$ = $2; } 1652 ; 1653 1654qassign_list : qassign_item { $$ = $1; } 1655 | qassign_list comma qassign_item { 1656 $1->tail->next = $3; 1657 $1->tail = $3; 1658 $$ = $1; 1659 } 1660 ; 1661 1662qassign_item : STRING { 1663 $$ = calloc(1, sizeof(struct node_queue)); 1664 if ($$ == NULL) 1665 err(1, "qassign_item: calloc"); 1666 if (strlcpy($$->queue, $1, sizeof($$->queue)) >= 1667 sizeof($$->queue)) { 1668 yyerror("queue name '%s' too long (max " 1669 "%d chars)", $1, sizeof($$->queue)-1); 1670 free($1); 1671 free($$); 1672 YYERROR; 1673 } 1674 free($1); 1675 $$->next = NULL; 1676 $$->tail = $$; 1677 } 1678 ; 1679 1680pfrule : action dir logquick interface route af proto fromto 1681 filter_opts 1682 { 1683 struct pf_rule r; 1684 struct node_state_opt *o; 1685 struct node_proto *proto; 1686 int srctrack = 0; 1687 int statelock = 0; 1688 int adaptive = 0; 1689 1690 if (check_rulestate(PFCTL_STATE_FILTER)) 1691 YYERROR; 1692 1693 memset(&r, 0, sizeof(r)); 1694 1695 r.action = $1.b1; 1696 switch ($1.b2) { 1697 case PFRULE_RETURNRST: 1698 r.rule_flag |= PFRULE_RETURNRST; 1699 r.return_ttl = $1.w; 1700 break; 1701 case PFRULE_RETURNICMP: 1702 r.rule_flag |= PFRULE_RETURNICMP; 1703 r.return_icmp = $1.w; 1704 r.return_icmp6 = $1.w2; 1705 break; 1706 case PFRULE_RETURN: 1707 r.rule_flag |= PFRULE_RETURN; 1708 r.return_icmp = $1.w; 1709 r.return_icmp6 = $1.w2; 1710 break; 1711 } 1712 r.direction = $2; 1713 r.log = $3.log; 1714 r.logif = $3.logif; 1715 r.quick = $3.quick; 1716 r.prob = $9.prob; 1717 r.rtableid = $9.rtableid; 1718 1719 r.af = $6; 1720 if ($9.tag) 1721 if (strlcpy(r.tagname, $9.tag, 1722 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 1723 yyerror("tag too long, max %u chars", 1724 PF_TAG_NAME_SIZE - 1); 1725 YYERROR; 1726 } 1727 if ($9.match_tag) 1728 if (strlcpy(r.match_tagname, $9.match_tag, 1729 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 1730 yyerror("tag too long, max %u chars", 1731 PF_TAG_NAME_SIZE - 1); 1732 YYERROR; 1733 } 1734 r.match_tag_not = $9.match_tag_not; 1735 if (rule_label(&r, $9.label)) 1736 YYERROR; 1737 free($9.label); 1738 r.flags = $9.flags.b1; 1739 r.flagset = $9.flags.b2; 1740 if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) { 1741 yyerror("flags always false"); 1742 YYERROR; 1743 } 1744 if ($9.flags.b1 || $9.flags.b2 || $8.src_os) { 1745 for (proto = $7; proto != NULL && 1746 proto->proto != IPPROTO_TCP; 1747 proto = proto->next) 1748 ; /* nothing */ 1749 if (proto == NULL && $7 != NULL) { 1750 if ($9.flags.b1 || $9.flags.b2) 1751 yyerror( 1752 "flags only apply to tcp"); 1753 if ($8.src_os) 1754 yyerror( 1755 "OS fingerprinting only " 1756 "apply to tcp"); 1757 YYERROR; 1758 } 1759#if 0 1760 if (($9.flags.b1 & parse_flags("S")) == 0 && 1761 $8.src_os) { 1762 yyerror("OS fingerprinting requires " 1763 "the SYN TCP flag (flags S/SA)"); 1764 YYERROR; 1765 } 1766#endif 1767 } 1768 1769 r.tos = $9.tos; 1770 r.keep_state = $9.keep.action; 1771 1772 /* 'keep state' by default on pass rules. */ 1773 if (!r.keep_state && !r.action && 1774 !($9.marker & FOM_KEEP)) 1775 r.keep_state = PF_STATE_NORMAL; 1776 1777 o = $9.keep.options; 1778 while (o) { 1779 struct node_state_opt *p = o; 1780 1781 switch (o->type) { 1782 case PF_STATE_OPT_MAX: 1783 if (r.max_states) { 1784 yyerror("state option 'max' " 1785 "multiple definitions"); 1786 YYERROR; 1787 } 1788 r.max_states = o->data.max_states; 1789 break; 1790 case PF_STATE_OPT_NOSYNC: 1791 if (r.rule_flag & PFRULE_NOSYNC) { 1792 yyerror("state option 'sync' " 1793 "multiple definitions"); 1794 YYERROR; 1795 } 1796 r.rule_flag |= PFRULE_NOSYNC; 1797 break; 1798 case PF_STATE_OPT_SRCTRACK: 1799 if (srctrack) { 1800 yyerror("state option " 1801 "'source-track' " 1802 "multiple definitions"); 1803 YYERROR; 1804 } 1805 srctrack = o->data.src_track; 1806 r.rule_flag |= PFRULE_SRCTRACK; 1807 break; 1808 case PF_STATE_OPT_MAX_SRC_STATES: 1809 if (r.max_src_states) { 1810 yyerror("state option " 1811 "'max-src-states' " 1812 "multiple definitions"); 1813 YYERROR; 1814 } 1815 if (o->data.max_src_states == 0) { 1816 yyerror("'max-src-states' must " 1817 "be > 0"); 1818 YYERROR; 1819 } 1820 r.max_src_states = 1821 o->data.max_src_states; 1822 r.rule_flag |= PFRULE_SRCTRACK; 1823 break; 1824 case PF_STATE_OPT_OVERLOAD: 1825 if (r.overload_tblname[0]) { 1826 yyerror("multiple 'overload' " 1827 "table definitions"); 1828 YYERROR; 1829 } 1830 if (strlcpy(r.overload_tblname, 1831 o->data.overload.tblname, 1832 PF_TABLE_NAME_SIZE) >= 1833 PF_TABLE_NAME_SIZE) { 1834 yyerror("state option: " 1835 "strlcpy"); 1836 YYERROR; 1837 } 1838 r.flush = o->data.overload.flush; 1839 break; 1840 case PF_STATE_OPT_MAX_SRC_CONN: 1841 if (r.max_src_conn) { 1842 yyerror("state option " 1843 "'max-src-conn' " 1844 "multiple definitions"); 1845 YYERROR; 1846 } 1847 if (o->data.max_src_conn == 0) { 1848 yyerror("'max-src-conn' " 1849 "must be > 0"); 1850 YYERROR; 1851 } 1852 r.max_src_conn = 1853 o->data.max_src_conn; 1854 r.rule_flag |= PFRULE_SRCTRACK | 1855 PFRULE_RULESRCTRACK; 1856 break; 1857 case PF_STATE_OPT_MAX_SRC_CONN_RATE: 1858 if (r.max_src_conn_rate.limit) { 1859 yyerror("state option " 1860 "'max-src-conn-rate' " 1861 "multiple definitions"); 1862 YYERROR; 1863 } 1864 if (!o->data.max_src_conn_rate.limit || 1865 !o->data.max_src_conn_rate.seconds) { 1866 yyerror("'max-src-conn-rate' " 1867 "values must be > 0"); 1868 YYERROR; 1869 } 1870 if (o->data.max_src_conn_rate.limit > 1871 PF_THRESHOLD_MAX) { 1872 yyerror("'max-src-conn-rate' " 1873 "maximum rate must be < %u", 1874 PF_THRESHOLD_MAX); 1875 YYERROR; 1876 } 1877 r.max_src_conn_rate.limit = 1878 o->data.max_src_conn_rate.limit; 1879 r.max_src_conn_rate.seconds = 1880 o->data.max_src_conn_rate.seconds; 1881 r.rule_flag |= PFRULE_SRCTRACK | 1882 PFRULE_RULESRCTRACK; 1883 break; 1884 case PF_STATE_OPT_MAX_SRC_NODES: 1885 if (r.max_src_nodes) { 1886 yyerror("state option " 1887 "'max-src-nodes' " 1888 "multiple definitions"); 1889 YYERROR; 1890 } 1891 if (o->data.max_src_nodes == 0) { 1892 yyerror("'max-src-nodes' must " 1893 "be > 0"); 1894 YYERROR; 1895 } 1896 r.max_src_nodes = 1897 o->data.max_src_nodes; 1898 r.rule_flag |= PFRULE_SRCTRACK | 1899 PFRULE_RULESRCTRACK; 1900 break; 1901 case PF_STATE_OPT_STATELOCK: 1902 if (statelock) { 1903 yyerror("state locking option: " 1904 "multiple definitions"); 1905 YYERROR; 1906 } 1907 statelock = 1; 1908 r.rule_flag |= o->data.statelock; 1909 break; 1910 case PF_STATE_OPT_TIMEOUT: 1911 if (o->data.timeout.number == 1912 PFTM_ADAPTIVE_START || 1913 o->data.timeout.number == 1914 PFTM_ADAPTIVE_END) 1915 adaptive = 1; 1916 if (r.timeout[o->data.timeout.number]) { 1917 yyerror("state timeout %s " 1918 "multiple definitions", 1919 pf_timeouts[o->data. 1920 timeout.number].name); 1921 YYERROR; 1922 } 1923 r.timeout[o->data.timeout.number] = 1924 o->data.timeout.seconds; 1925 } 1926 o = o->next; 1927 free(p); 1928 } 1929 1930 /* 'flags S/SA' by default on stateful rules */ 1931 if (!r.action && !r.flags && !r.flagset && 1932 !$9.fragment && !($9.marker & FOM_FLAGS) && 1933 r.keep_state) { 1934 r.flags = parse_flags("S"); 1935 r.flagset = parse_flags("SA"); 1936 } 1937 if (!adaptive && r.max_states) { 1938 r.timeout[PFTM_ADAPTIVE_START] = 1939 (r.max_states / 10) * 6; 1940 r.timeout[PFTM_ADAPTIVE_END] = 1941 (r.max_states / 10) * 12; 1942 } 1943 if (r.rule_flag & PFRULE_SRCTRACK) { 1944 if (srctrack == PF_SRCTRACK_GLOBAL && 1945 r.max_src_nodes) { 1946 yyerror("'max-src-nodes' is " 1947 "incompatible with " 1948 "'source-track global'"); 1949 YYERROR; 1950 } 1951 if (srctrack == PF_SRCTRACK_GLOBAL && 1952 r.max_src_conn) { 1953 yyerror("'max-src-conn' is " 1954 "incompatible with " 1955 "'source-track global'"); 1956 YYERROR; 1957 } 1958 if (srctrack == PF_SRCTRACK_GLOBAL && 1959 r.max_src_conn_rate.seconds) { 1960 yyerror("'max-src-conn-rate' is " 1961 "incompatible with " 1962 "'source-track global'"); 1963 YYERROR; 1964 } 1965 if (r.timeout[PFTM_SRC_NODE] < 1966 r.max_src_conn_rate.seconds) 1967 r.timeout[PFTM_SRC_NODE] = 1968 r.max_src_conn_rate.seconds; 1969 r.rule_flag |= PFRULE_SRCTRACK; 1970 if (srctrack == PF_SRCTRACK_RULE) 1971 r.rule_flag |= PFRULE_RULESRCTRACK; 1972 } 1973 if (r.keep_state && !statelock) 1974 r.rule_flag |= default_statelock; 1975 1976 if ($9.fragment) 1977 r.rule_flag |= PFRULE_FRAGMENT; 1978 r.allow_opts = $9.allowopts; 1979 1980 decide_address_family($8.src.host, &r.af); 1981 decide_address_family($8.dst.host, &r.af); 1982 1983 if ($5.rt) { 1984 if (!r.direction) { 1985 yyerror("direction must be explicit " 1986 "with rules that specify routing"); 1987 YYERROR; 1988 } 1989 r.rt = $5.rt; 1990 r.rpool.opts = $5.pool_opts; 1991 if ($5.key != NULL) 1992 memcpy(&r.rpool.key, $5.key, 1993 sizeof(struct pf_poolhashkey)); 1994 } 1995 if (r.rt && r.rt != PF_FASTROUTE) { 1996 decide_address_family($5.host, &r.af); 1997 remove_invalid_hosts(&$5.host, &r.af); 1998 if ($5.host == NULL) { 1999 yyerror("no routing address with " 2000 "matching address family found."); 2001 YYERROR; 2002 } 2003 if ((r.rpool.opts & PF_POOL_TYPEMASK) == 2004 PF_POOL_NONE && ($5.host->next != NULL || 2005 $5.host->addr.type == PF_ADDR_TABLE || 2006 DYNIF_MULTIADDR($5.host->addr))) 2007 r.rpool.opts |= PF_POOL_ROUNDROBIN; 2008 if ((r.rpool.opts & PF_POOL_TYPEMASK) != 2009 PF_POOL_ROUNDROBIN && 2010 disallow_table($5.host, "tables are only " 2011 "supported in round-robin routing pools")) 2012 YYERROR; 2013 if ((r.rpool.opts & PF_POOL_TYPEMASK) != 2014 PF_POOL_ROUNDROBIN && 2015 disallow_alias($5.host, "interface (%s) " 2016 "is only supported in round-robin " 2017 "routing pools")) 2018 YYERROR; 2019 if ($5.host->next != NULL) { 2020 if ((r.rpool.opts & PF_POOL_TYPEMASK) != 2021 PF_POOL_ROUNDROBIN) { 2022 yyerror("r.rpool.opts must " 2023 "be PF_POOL_ROUNDROBIN"); 2024 YYERROR; 2025 } 2026 } 2027 } 2028 if ($9.queues.qname != NULL) { 2029 if (strlcpy(r.qname, $9.queues.qname, 2030 sizeof(r.qname)) >= sizeof(r.qname)) { 2031 yyerror("rule qname too long (max " 2032 "%d chars)", sizeof(r.qname)-1); 2033 YYERROR; 2034 } 2035 free($9.queues.qname); 2036 } 2037 if ($9.queues.pqname != NULL) { 2038 if (strlcpy(r.pqname, $9.queues.pqname, 2039 sizeof(r.pqname)) >= sizeof(r.pqname)) { 2040 yyerror("rule pqname too long (max " 2041 "%d chars)", sizeof(r.pqname)-1); 2042 YYERROR; 2043 } 2044 free($9.queues.pqname); 2045 } 2046 2047 expand_rule(&r, $4, $5.host, $7, $8.src_os, 2048 $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, 2049 $9.uid, $9.gid, $9.icmpspec, ""); 2050 } 2051 ; 2052 2053filter_opts : { 2054 bzero(&filter_opts, sizeof filter_opts); 2055 filter_opts.rtableid = -1; 2056 } 2057 filter_opts_l 2058 { $$ = filter_opts; } 2059 | /* empty */ { 2060 bzero(&filter_opts, sizeof filter_opts); 2061 filter_opts.rtableid = -1; 2062 $$ = filter_opts; 2063 } 2064 ; 2065 2066filter_opts_l : filter_opts_l filter_opt 2067 | filter_opt 2068 ; 2069 2070filter_opt : USER uids { 2071 if (filter_opts.uid) 2072 $2->tail->next = filter_opts.uid; 2073 filter_opts.uid = $2; 2074 } 2075 | GROUP gids { 2076 if (filter_opts.gid) 2077 $2->tail->next = filter_opts.gid; 2078 filter_opts.gid = $2; 2079 } 2080 | flags { 2081 if (filter_opts.marker & FOM_FLAGS) { 2082 yyerror("flags cannot be redefined"); 2083 YYERROR; 2084 } 2085 filter_opts.marker |= FOM_FLAGS; 2086 filter_opts.flags.b1 |= $1.b1; 2087 filter_opts.flags.b2 |= $1.b2; 2088 filter_opts.flags.w |= $1.w; 2089 filter_opts.flags.w2 |= $1.w2; 2090 } 2091 | icmpspec { 2092 if (filter_opts.marker & FOM_ICMP) { 2093 yyerror("icmp-type cannot be redefined"); 2094 YYERROR; 2095 } 2096 filter_opts.marker |= FOM_ICMP; 2097 filter_opts.icmpspec = $1; 2098 } 2099 | tos { 2100 if (filter_opts.marker & FOM_TOS) { 2101 yyerror("tos cannot be redefined"); 2102 YYERROR; 2103 } 2104 filter_opts.marker |= FOM_TOS; 2105 filter_opts.tos = $1; 2106 } 2107 | keep { 2108 if (filter_opts.marker & FOM_KEEP) { 2109 yyerror("modulate or keep cannot be redefined"); 2110 YYERROR; 2111 } 2112 filter_opts.marker |= FOM_KEEP; 2113 filter_opts.keep.action = $1.action; 2114 filter_opts.keep.options = $1.options; 2115 } 2116 | FRAGMENT { 2117 filter_opts.fragment = 1; 2118 } 2119 | ALLOWOPTS { 2120 filter_opts.allowopts = 1; 2121 } 2122 | label { 2123 if (filter_opts.label) { 2124 yyerror("label cannot be redefined"); 2125 YYERROR; 2126 } 2127 filter_opts.label = $1; 2128 } 2129 | qname { 2130 if (filter_opts.queues.qname) { 2131 yyerror("queue cannot be redefined"); 2132 YYERROR; 2133 } 2134 filter_opts.queues = $1; 2135 } 2136 | TAG string { 2137 filter_opts.tag = $2; 2138 } 2139 | not TAGGED string { 2140 filter_opts.match_tag = $3; 2141 filter_opts.match_tag_not = $1; 2142 } 2143 | PROBABILITY STRING { 2144 char *e; 2145 double p = strtod($2, &e); 2146 2147 if (*e == '%') { 2148 p *= 0.01; 2149 e++; 2150 } 2151 if (*e) { 2152 yyerror("invalid probability: %s", $2); 2153 free($2); 2154 YYERROR; 2155 } 2156 p = floor(p * (UINT_MAX+1.0) + 0.5); 2157 if (p < 1.0 || p >= (UINT_MAX+1.0)) { 2158 yyerror("invalid probability: %s", $2); 2159 free($2); 2160 YYERROR; 2161 } 2162 filter_opts.prob = (u_int32_t)p; 2163 free($2); 2164 } 2165 | RTABLE NUMBER { 2166 if ($2 < 0 || $2 > RT_TABLEID_MAX) { 2167 yyerror("invalid rtable id"); 2168 YYERROR; 2169 } 2170 filter_opts.rtableid = $2; 2171 } 2172 ; 2173 2174action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; } 2175 | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } 2176 ; 2177 2178blockspec : /* empty */ { 2179 $$.b2 = blockpolicy; 2180 $$.w = returnicmpdefault; 2181 $$.w2 = returnicmp6default; 2182 } 2183 | DROP { 2184 $$.b2 = PFRULE_DROP; 2185 $$.w = 0; 2186 $$.w2 = 0; 2187 } 2188 | RETURNRST { 2189 $$.b2 = PFRULE_RETURNRST; 2190 $$.w = 0; 2191 $$.w2 = 0; 2192 } 2193 | RETURNRST '(' TTL NUMBER ')' { 2194 if ($4 < 0 || $4 > 255) { 2195 yyerror("illegal ttl value %d", $4); 2196 YYERROR; 2197 } 2198 $$.b2 = PFRULE_RETURNRST; 2199 $$.w = $4; 2200 $$.w2 = 0; 2201 } 2202 | RETURNICMP { 2203 $$.b2 = PFRULE_RETURNICMP; 2204 $$.w = returnicmpdefault; 2205 $$.w2 = returnicmp6default; 2206 } 2207 | RETURNICMP6 { 2208 $$.b2 = PFRULE_RETURNICMP; 2209 $$.w = returnicmpdefault; 2210 $$.w2 = returnicmp6default; 2211 } 2212 | RETURNICMP '(' reticmpspec ')' { 2213 $$.b2 = PFRULE_RETURNICMP; 2214 $$.w = $3; 2215 $$.w2 = returnicmpdefault; 2216 } 2217 | RETURNICMP6 '(' reticmp6spec ')' { 2218 $$.b2 = PFRULE_RETURNICMP; 2219 $$.w = returnicmpdefault; 2220 $$.w2 = $3; 2221 } 2222 | RETURNICMP '(' reticmpspec comma reticmp6spec ')' { 2223 $$.b2 = PFRULE_RETURNICMP; 2224 $$.w = $3; 2225 $$.w2 = $5; 2226 } 2227 | RETURN { 2228 $$.b2 = PFRULE_RETURN; 2229 $$.w = returnicmpdefault; 2230 $$.w2 = returnicmp6default; 2231 } 2232 ; 2233 2234reticmpspec : STRING { 2235 if (!($$ = parseicmpspec($1, AF_INET))) { 2236 free($1); 2237 YYERROR; 2238 } 2239 free($1); 2240 } 2241 | NUMBER { 2242 u_int8_t icmptype; 2243 2244 if ($1 < 0 || $1 > 255) { 2245 yyerror("invalid icmp code %lu", $1); 2246 YYERROR; 2247 } 2248 icmptype = returnicmpdefault >> 8; 2249 $$ = (icmptype << 8 | $1); 2250 } 2251 ; 2252 2253reticmp6spec : STRING { 2254 if (!($$ = parseicmpspec($1, AF_INET6))) { 2255 free($1); 2256 YYERROR; 2257 } 2258 free($1); 2259 } 2260 | NUMBER { 2261 u_int8_t icmptype; 2262 2263 if ($1 < 0 || $1 > 255) { 2264 yyerror("invalid icmp code %lu", $1); 2265 YYERROR; 2266 } 2267 icmptype = returnicmp6default >> 8; 2268 $$ = (icmptype << 8 | $1); 2269 } 2270 ; 2271 2272dir : /* empty */ { $$ = 0; } 2273 | IN { $$ = PF_IN; } 2274 | OUT { $$ = PF_OUT; } 2275 ; 2276 2277quick : /* empty */ { $$.quick = 0; } 2278 | QUICK { $$.quick = 1; } 2279 ; 2280 2281logquick : /* empty */ { $$.log = 0; $$.quick = 0; $$.logif = 0; } 2282 | log { $$ = $1; $$.quick = 0; } 2283 | QUICK { $$.quick = 1; $$.log = 0; $$.logif = 0; } 2284 | log QUICK { $$ = $1; $$.quick = 1; } 2285 | QUICK log { $$ = $2; $$.quick = 1; } 2286 ; 2287 2288log : LOG { $$.log = PF_LOG; $$.logif = 0; } 2289 | LOG '(' logopts ')' { 2290 $$.log = PF_LOG | $3.log; 2291 $$.logif = $3.logif; 2292 } 2293 ; 2294 2295logopts : logopt { $$ = $1; } 2296 | logopts comma logopt { 2297 $$.log = $1.log | $3.log; 2298 $$.logif = $3.logif; 2299 if ($$.logif == 0) 2300 $$.logif = $1.logif; 2301 } 2302 ; 2303 2304logopt : ALL { $$.log = PF_LOG_ALL; $$.logif = 0; } 2305 | USER { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; } 2306 | GROUP { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; } 2307 | TO string { 2308 const char *errstr; 2309 u_int i; 2310 2311 $$.log = 0; 2312 if (strncmp($2, "pflog", 5)) { 2313 yyerror("%s: should be a pflog interface", $2); 2314 free($2); 2315 YYERROR; 2316 } 2317 i = strtonum($2 + 5, 0, 255, &errstr); 2318 if (errstr) { 2319 yyerror("%s: %s", $2, errstr); 2320 free($2); 2321 YYERROR; 2322 } 2323 free($2); 2324 $$.logif = i; 2325 } 2326 ; 2327 2328interface : /* empty */ { $$ = NULL; } 2329 | ON if_item_not { $$ = $2; } 2330 | ON '{' if_list '}' { $$ = $3; } 2331 ; 2332 2333if_list : if_item_not { $$ = $1; } 2334 | if_list comma if_item_not { 2335 $1->tail->next = $3; 2336 $1->tail = $3; 2337 $$ = $1; 2338 } 2339 ; 2340 2341if_item_not : not if_item { $$ = $2; $$->not = $1; } 2342 ; 2343 2344if_item : STRING { 2345 struct node_host *n; 2346 2347 $$ = calloc(1, sizeof(struct node_if)); 2348 if ($$ == NULL) 2349 err(1, "if_item: calloc"); 2350 if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >= 2351 sizeof($$->ifname)) { 2352 free($1); 2353 free($$); 2354 yyerror("interface name too long"); 2355 YYERROR; 2356 } 2357 2358 if ((n = ifa_exists($1)) != NULL) 2359 $$->ifa_flags = n->ifa_flags; 2360 2361 free($1); 2362 $$->not = 0; 2363 $$->next = NULL; 2364 $$->tail = $$; 2365 } 2366 ; 2367 2368af : /* empty */ { $$ = 0; } 2369 | INET { $$ = AF_INET; } 2370 | INET6 { $$ = AF_INET6; } 2371 ; 2372 2373proto : /* empty */ { $$ = NULL; } 2374 | PROTO proto_item { $$ = $2; } 2375 | PROTO '{' proto_list '}' { $$ = $3; } 2376 ; 2377 2378proto_list : proto_item { $$ = $1; } 2379 | proto_list comma proto_item { 2380 $1->tail->next = $3; 2381 $1->tail = $3; 2382 $$ = $1; 2383 } 2384 ; 2385 2386proto_item : protoval { 2387 u_int8_t pr; 2388 2389 pr = (u_int8_t)$1; 2390 if (pr == 0) { 2391 yyerror("proto 0 cannot be used"); 2392 YYERROR; 2393 } 2394 $$ = calloc(1, sizeof(struct node_proto)); 2395 if ($$ == NULL) 2396 err(1, "proto_item: calloc"); 2397 $$->proto = pr; 2398 $$->next = NULL; 2399 $$->tail = $$; 2400 } 2401 ; 2402 2403protoval : STRING { 2404 struct protoent *p; 2405 2406 p = getprotobyname($1); 2407 if (p == NULL) { 2408 yyerror("unknown protocol %s", $1); 2409 free($1); 2410 YYERROR; 2411 } 2412 $$ = p->p_proto; 2413 free($1); 2414 } 2415 | NUMBER { 2416 if ($1 < 0 || $1 > 255) { 2417 yyerror("protocol outside range"); 2418 YYERROR; 2419 } 2420 } 2421 ; 2422 2423fromto : ALL { 2424 $$.src.host = NULL; 2425 $$.src.port = NULL; 2426 $$.dst.host = NULL; 2427 $$.dst.port = NULL; 2428 $$.src_os = NULL; 2429 } 2430 | from os to { 2431 $$.src = $1; 2432 $$.src_os = $2; 2433 $$.dst = $3; 2434 } 2435 ; 2436 2437os : /* empty */ { $$ = NULL; } 2438 | OS xos { $$ = $2; } 2439 | OS '{' os_list '}' { $$ = $3; } 2440 ; 2441 2442xos : STRING { 2443 $$ = calloc(1, sizeof(struct node_os)); 2444 if ($$ == NULL) 2445 err(1, "os: calloc"); 2446 $$->os = $1; 2447 $$->tail = $$; 2448 } 2449 ; 2450 2451os_list : xos { $$ = $1; } 2452 | os_list comma xos { 2453 $1->tail->next = $3; 2454 $1->tail = $3; 2455 $$ = $1; 2456 } 2457 ; 2458 2459from : /* empty */ { 2460 $$.host = NULL; 2461 $$.port = NULL; 2462 } 2463 | FROM ipportspec { 2464 $$ = $2; 2465 } 2466 ; 2467 2468to : /* empty */ { 2469 $$.host = NULL; 2470 $$.port = NULL; 2471 } 2472 | TO ipportspec { 2473 if (disallow_urpf_failed($2.host, "\"urpf-failed\" is " 2474 "not permitted in a destination address")) 2475 YYERROR; 2476 $$ = $2; 2477 } 2478 ; 2479 2480ipportspec : ipspec { 2481 $$.host = $1; 2482 $$.port = NULL; 2483 } 2484 | ipspec PORT portspec { 2485 $$.host = $1; 2486 $$.port = $3; 2487 } 2488 | PORT portspec { 2489 $$.host = NULL; 2490 $$.port = $2; 2491 } 2492 ; 2493 2494ipspec : ANY { $$ = NULL; } 2495 | xhost { $$ = $1; } 2496 | '{' host_list '}' { $$ = $2; } 2497 ; 2498 2499host_list : ipspec { $$ = $1; } 2500 | host_list comma ipspec { 2501 if ($3 == NULL) 2502 $$ = $1; 2503 else if ($1 == NULL) 2504 $$ = $3; 2505 else { 2506 $1->tail->next = $3; 2507 $1->tail = $3->tail; 2508 $$ = $1; 2509 } 2510 } 2511 ; 2512 2513xhost : not host { 2514 struct node_host *n; 2515 2516 for (n = $2; n != NULL; n = n->next) 2517 n->not = $1; 2518 $$ = $2; 2519 } 2520 | not NOROUTE { 2521 $$ = calloc(1, sizeof(struct node_host)); 2522 if ($$ == NULL) 2523 err(1, "xhost: calloc"); 2524 $$->addr.type = PF_ADDR_NOROUTE; 2525 $$->next = NULL; 2526 $$->not = $1; 2527 $$->tail = $$; 2528 } 2529 | not URPFFAILED { 2530 $$ = calloc(1, sizeof(struct node_host)); 2531 if ($$ == NULL) 2532 err(1, "xhost: calloc"); 2533 $$->addr.type = PF_ADDR_URPFFAILED; 2534 $$->next = NULL; 2535 $$->not = $1; 2536 $$->tail = $$; 2537 } 2538 ; 2539 2540host : STRING { 2541 if (($$ = host($1)) == NULL) { 2542 /* error. "any" is handled elsewhere */ 2543 free($1); 2544 yyerror("could not parse host specification"); 2545 YYERROR; 2546 } 2547 free($1); 2548 2549 } 2550 | STRING '-' STRING { 2551 struct node_host *b, *e; 2552 2553 if ((b = host($1)) == NULL || (e = host($3)) == NULL) { 2554 free($1); 2555 free($3); 2556 yyerror("could not parse host specification"); 2557 YYERROR; 2558 } 2559 if (b->af != e->af || 2560 b->addr.type != PF_ADDR_ADDRMASK || 2561 e->addr.type != PF_ADDR_ADDRMASK || 2562 unmask(&b->addr.v.a.mask, b->af) != 2563 (b->af == AF_INET ? 32 : 128) || 2564 unmask(&e->addr.v.a.mask, e->af) != 2565 (e->af == AF_INET ? 32 : 128) || 2566 b->next != NULL || b->not || 2567 e->next != NULL || e->not) { 2568 free(b); 2569 free(e); 2570 free($1); 2571 free($3); 2572 yyerror("invalid address range"); 2573 YYERROR; 2574 } 2575 memcpy(&b->addr.v.a.mask, &e->addr.v.a.addr, 2576 sizeof(b->addr.v.a.mask)); 2577 b->addr.type = PF_ADDR_RANGE; 2578 $$ = b; 2579 free(e); 2580 free($1); 2581 free($3); 2582 } 2583 | STRING '/' NUMBER { 2584 char *buf; 2585 2586 if (asprintf(&buf, "%s/%lld", $1, $3) == -1) 2587 err(1, "host: asprintf"); 2588 free($1); 2589 if (($$ = host(buf)) == NULL) { 2590 /* error. "any" is handled elsewhere */ 2591 free(buf); 2592 yyerror("could not parse host specification"); 2593 YYERROR; 2594 } 2595 free(buf); 2596 } 2597 | NUMBER '/' NUMBER { 2598 char *buf; 2599 2600 /* ie. for 10/8 parsing */ 2601 if (asprintf(&buf, "%lld/%lld", $1, $3) == -1) 2602 err(1, "host: asprintf"); 2603 if (($$ = host(buf)) == NULL) { 2604 /* error. "any" is handled elsewhere */ 2605 free(buf); 2606 yyerror("could not parse host specification"); 2607 YYERROR; 2608 } 2609 free(buf); 2610 } 2611 | dynaddr 2612 | dynaddr '/' NUMBER { 2613 struct node_host *n; 2614 2615 if ($3 < 0 || $3 > 128) { 2616 yyerror("bit number too big"); 2617 YYERROR; 2618 } 2619 $$ = $1; 2620 for (n = $1; n != NULL; n = n->next) 2621 set_ipmask(n, $3); 2622 } 2623 | '<' STRING '>' { 2624 if (strlen($2) >= PF_TABLE_NAME_SIZE) { 2625 yyerror("table name '%s' too long", $2); 2626 free($2); 2627 YYERROR; 2628 } 2629 $$ = calloc(1, sizeof(struct node_host)); 2630 if ($$ == NULL) 2631 err(1, "host: calloc"); 2632 $$->addr.type = PF_ADDR_TABLE; 2633 if (strlcpy($$->addr.v.tblname, $2, 2634 sizeof($$->addr.v.tblname)) >= 2635 sizeof($$->addr.v.tblname)) 2636 errx(1, "host: strlcpy"); 2637 free($2); 2638 $$->next = NULL; 2639 $$->tail = $$; 2640 } 2641 | ROUTE STRING { 2642 $$ = calloc(1, sizeof(struct node_host)); 2643 if ($$ == NULL) { 2644 free($2); 2645 err(1, "host: calloc"); 2646 } 2647 $$->addr.type = PF_ADDR_RTLABEL; 2648 if (strlcpy($$->addr.v.rtlabelname, $2, 2649 sizeof($$->addr.v.rtlabelname)) >= 2650 sizeof($$->addr.v.rtlabelname)) { 2651 yyerror("route label too long, max %u chars", 2652 sizeof($$->addr.v.rtlabelname) - 1); 2653 free($2); 2654 free($$); 2655 YYERROR; 2656 } 2657 $$->next = NULL; 2658 $$->tail = $$; 2659 free($2); 2660 } 2661 ; 2662 2663number : NUMBER 2664 | STRING { 2665 u_long ulval; 2666 2667 if (atoul($1, &ulval) == -1) { 2668 yyerror("%s is not a number", $1); 2669 free($1); 2670 YYERROR; 2671 } else 2672 $$ = ulval; 2673 free($1); 2674 } 2675 ; 2676 2677dynaddr : '(' STRING ')' { 2678 int flags = 0; 2679 char *p, *op; 2680 2681 op = $2; 2682 if (!isalpha(op[0])) { 2683 yyerror("invalid interface name '%s'", op); 2684 free(op); 2685 YYERROR; 2686 } 2687 while ((p = strrchr($2, ':')) != NULL) { 2688 if (!strcmp(p+1, "network")) 2689 flags |= PFI_AFLAG_NETWORK; 2690 else if (!strcmp(p+1, "broadcast")) 2691 flags |= PFI_AFLAG_BROADCAST; 2692 else if (!strcmp(p+1, "peer")) 2693 flags |= PFI_AFLAG_PEER; 2694 else if (!strcmp(p+1, "0")) 2695 flags |= PFI_AFLAG_NOALIAS; 2696 else { 2697 yyerror("interface %s has bad modifier", 2698 $2); 2699 free(op); 2700 YYERROR; 2701 } 2702 *p = '\0'; 2703 } 2704 if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { 2705 free(op); 2706 yyerror("illegal combination of " 2707 "interface modifiers"); 2708 YYERROR; 2709 } 2710 $$ = calloc(1, sizeof(struct node_host)); 2711 if ($$ == NULL) 2712 err(1, "address: calloc"); 2713 $$->af = 0; 2714 set_ipmask($$, 128); 2715 $$->addr.type = PF_ADDR_DYNIFTL; 2716 $$->addr.iflags = flags; 2717 if (strlcpy($$->addr.v.ifname, $2, 2718 sizeof($$->addr.v.ifname)) >= 2719 sizeof($$->addr.v.ifname)) { 2720 free(op); 2721 free($$); 2722 yyerror("interface name too long"); 2723 YYERROR; 2724 } 2725 free(op); 2726 $$->next = NULL; 2727 $$->tail = $$; 2728 } 2729 ; 2730 2731portspec : port_item { $$ = $1; } 2732 | '{' port_list '}' { $$ = $2; } 2733 ; 2734 2735port_list : port_item { $$ = $1; } 2736 | port_list comma port_item { 2737 $1->tail->next = $3; 2738 $1->tail = $3; 2739 $$ = $1; 2740 } 2741 ; 2742 2743port_item : port { 2744 $$ = calloc(1, sizeof(struct node_port)); 2745 if ($$ == NULL) 2746 err(1, "port_item: calloc"); 2747 $$->port[0] = $1.a; 2748 $$->port[1] = $1.b; 2749 if ($1.t) 2750 $$->op = PF_OP_RRG; 2751 else 2752 $$->op = PF_OP_EQ; 2753 $$->next = NULL; 2754 $$->tail = $$; 2755 } 2756 | unaryop port { 2757 if ($2.t) { 2758 yyerror("':' cannot be used with an other " 2759 "port operator"); 2760 YYERROR; 2761 } 2762 $$ = calloc(1, sizeof(struct node_port)); 2763 if ($$ == NULL) 2764 err(1, "port_item: calloc"); 2765 $$->port[0] = $2.a; 2766 $$->port[1] = $2.b; 2767 $$->op = $1; 2768 $$->next = NULL; 2769 $$->tail = $$; 2770 } 2771 | port PORTBINARY port { 2772 if ($1.t || $3.t) { 2773 yyerror("':' cannot be used with an other " 2774 "port operator"); 2775 YYERROR; 2776 } 2777 $$ = calloc(1, sizeof(struct node_port)); 2778 if ($$ == NULL) 2779 err(1, "port_item: calloc"); 2780 $$->port[0] = $1.a; 2781 $$->port[1] = $3.a; 2782 $$->op = $2; 2783 $$->next = NULL; 2784 $$->tail = $$; 2785 } 2786 ; 2787 2788port : STRING { 2789 char *p = strchr($1, ':'); 2790 2791 if (p == NULL) { 2792 if (($$.a = getservice($1)) == -1) { 2793 free($1); 2794 YYERROR; 2795 } 2796 $$.b = $$.t = 0; 2797 } else { 2798 int port[2]; 2799 2800 *p++ = 0; 2801 if ((port[0] = getservice($1)) == -1 || 2802 (port[1] = getservice(p)) == -1) { 2803 free($1); 2804 YYERROR; 2805 } 2806 $$.a = port[0]; 2807 $$.b = port[1]; 2808 $$.t = PF_OP_RRG; 2809 } 2810 free($1); 2811 } 2812 | NUMBER { 2813 if ($1 < 0 || $1 > 65535) { 2814 yyerror("illegal port value %lu", $1); 2815 YYERROR; 2816 } 2817 $$.a = ntohs($1); 2818 $$.b = $$.t = 0; 2819 } 2820 ; 2821 2822uids : uid_item { $$ = $1; } 2823 | '{' uid_list '}' { $$ = $2; } 2824 ; 2825 2826uid_list : uid_item { $$ = $1; } 2827 | uid_list comma uid_item { 2828 $1->tail->next = $3; 2829 $1->tail = $3; 2830 $$ = $1; 2831 } 2832 ; 2833 2834uid_item : uid { 2835 $$ = calloc(1, sizeof(struct node_uid)); 2836 if ($$ == NULL) 2837 err(1, "uid_item: calloc"); 2838 $$->uid[0] = $1; 2839 $$->uid[1] = $1; 2840 $$->op = PF_OP_EQ; 2841 $$->next = NULL; 2842 $$->tail = $$; 2843 } 2844 | unaryop uid { 2845 if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 2846 yyerror("user unknown requires operator = or " 2847 "!="); 2848 YYERROR; 2849 } 2850 $$ = calloc(1, sizeof(struct node_uid)); 2851 if ($$ == NULL) 2852 err(1, "uid_item: calloc"); 2853 $$->uid[0] = $2; 2854 $$->uid[1] = $2; 2855 $$->op = $1; 2856 $$->next = NULL; 2857 $$->tail = $$; 2858 } 2859 | uid PORTBINARY uid { 2860 if ($1 == UID_MAX || $3 == UID_MAX) { 2861 yyerror("user unknown requires operator = or " 2862 "!="); 2863 YYERROR; 2864 } 2865 $$ = calloc(1, sizeof(struct node_uid)); 2866 if ($$ == NULL) 2867 err(1, "uid_item: calloc"); 2868 $$->uid[0] = $1; 2869 $$->uid[1] = $3; 2870 $$->op = $2; 2871 $$->next = NULL; 2872 $$->tail = $$; 2873 } 2874 ; 2875 2876uid : STRING { 2877 if (!strcmp($1, "unknown")) 2878 $$ = UID_MAX; 2879 else { 2880 struct passwd *pw; 2881 2882 if ((pw = getpwnam($1)) == NULL) { 2883 yyerror("unknown user %s", $1); 2884 free($1); 2885 YYERROR; 2886 } 2887 $$ = pw->pw_uid; 2888 } 2889 free($1); 2890 } 2891 | NUMBER { 2892 if ($1 < 0 || $1 >= UID_MAX) { 2893 yyerror("illegal uid value %lu", $1); 2894 YYERROR; 2895 } 2896 $$ = $1; 2897 } 2898 ; 2899 2900gids : gid_item { $$ = $1; } 2901 | '{' gid_list '}' { $$ = $2; } 2902 ; 2903 2904gid_list : gid_item { $$ = $1; } 2905 | gid_list comma gid_item { 2906 $1->tail->next = $3; 2907 $1->tail = $3; 2908 $$ = $1; 2909 } 2910 ; 2911 2912gid_item : gid { 2913 $$ = calloc(1, sizeof(struct node_gid)); 2914 if ($$ == NULL) 2915 err(1, "gid_item: calloc"); 2916 $$->gid[0] = $1; 2917 $$->gid[1] = $1; 2918 $$->op = PF_OP_EQ; 2919 $$->next = NULL; 2920 $$->tail = $$; 2921 } 2922 | unaryop gid { 2923 if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 2924 yyerror("group unknown requires operator = or " 2925 "!="); 2926 YYERROR; 2927 } 2928 $$ = calloc(1, sizeof(struct node_gid)); 2929 if ($$ == NULL) 2930 err(1, "gid_item: calloc"); 2931 $$->gid[0] = $2; 2932 $$->gid[1] = $2; 2933 $$->op = $1; 2934 $$->next = NULL; 2935 $$->tail = $$; 2936 } 2937 | gid PORTBINARY gid { 2938 if ($1 == GID_MAX || $3 == GID_MAX) { 2939 yyerror("group unknown requires operator = or " 2940 "!="); 2941 YYERROR; 2942 } 2943 $$ = calloc(1, sizeof(struct node_gid)); 2944 if ($$ == NULL) 2945 err(1, "gid_item: calloc"); 2946 $$->gid[0] = $1; 2947 $$->gid[1] = $3; 2948 $$->op = $2; 2949 $$->next = NULL; 2950 $$->tail = $$; 2951 } 2952 ; 2953 2954gid : STRING { 2955 if (!strcmp($1, "unknown")) 2956 $$ = GID_MAX; 2957 else { 2958 struct group *grp; 2959 2960 if ((grp = getgrnam($1)) == NULL) { 2961 yyerror("unknown group %s", $1); 2962 free($1); 2963 YYERROR; 2964 } 2965 $$ = grp->gr_gid; 2966 } 2967 free($1); 2968 } 2969 | NUMBER { 2970 if ($1 < 0 || $1 >= GID_MAX) { 2971 yyerror("illegal gid value %lu", $1); 2972 YYERROR; 2973 } 2974 $$ = $1; 2975 } 2976 ; 2977 2978flag : STRING { 2979 int f; 2980 2981 if ((f = parse_flags($1)) < 0) { 2982 yyerror("bad flags %s", $1); 2983 free($1); 2984 YYERROR; 2985 } 2986 free($1); 2987 $$.b1 = f; 2988 } 2989 ; 2990 2991flags : FLAGS flag '/' flag { $$.b1 = $2.b1; $$.b2 = $4.b1; } 2992 | FLAGS '/' flag { $$.b1 = 0; $$.b2 = $3.b1; } 2993 | FLAGS ANY { $$.b1 = 0; $$.b2 = 0; } 2994 ; 2995 2996icmpspec : ICMPTYPE icmp_item { $$ = $2; } 2997 | ICMPTYPE '{' icmp_list '}' { $$ = $3; } 2998 | ICMP6TYPE icmp6_item { $$ = $2; } 2999 | ICMP6TYPE '{' icmp6_list '}' { $$ = $3; } 3000 ; 3001 3002icmp_list : icmp_item { $$ = $1; } 3003 | icmp_list comma icmp_item { 3004 $1->tail->next = $3; 3005 $1->tail = $3; 3006 $$ = $1; 3007 } 3008 ; 3009 3010icmp6_list : icmp6_item { $$ = $1; } 3011 | icmp6_list comma icmp6_item { 3012 $1->tail->next = $3; 3013 $1->tail = $3; 3014 $$ = $1; 3015 } 3016 ; 3017 3018icmp_item : icmptype { 3019 $$ = calloc(1, sizeof(struct node_icmp)); 3020 if ($$ == NULL) 3021 err(1, "icmp_item: calloc"); 3022 $$->type = $1; 3023 $$->code = 0; 3024 $$->proto = IPPROTO_ICMP; 3025 $$->next = NULL; 3026 $$->tail = $$; 3027 } 3028 | icmptype CODE STRING { 3029 const struct icmpcodeent *p; 3030 3031 if ((p = geticmpcodebyname($1-1, $3, AF_INET)) == NULL) { 3032 yyerror("unknown icmp-code %s", $3); 3033 free($3); 3034 YYERROR; 3035 } 3036 3037 free($3); 3038 $$ = calloc(1, sizeof(struct node_icmp)); 3039 if ($$ == NULL) 3040 err(1, "icmp_item: calloc"); 3041 $$->type = $1; 3042 $$->code = p->code + 1; 3043 $$->proto = IPPROTO_ICMP; 3044 $$->next = NULL; 3045 $$->tail = $$; 3046 } 3047 | icmptype CODE NUMBER { 3048 if ($3 < 0 || $3 > 255) { 3049 yyerror("illegal icmp-code %lu", $3); 3050 YYERROR; 3051 } 3052 $$ = calloc(1, sizeof(struct node_icmp)); 3053 if ($$ == NULL) 3054 err(1, "icmp_item: calloc"); 3055 $$->type = $1; 3056 $$->code = $3 + 1; 3057 $$->proto = IPPROTO_ICMP; 3058 $$->next = NULL; 3059 $$->tail = $$; 3060 } 3061 ; 3062 3063icmp6_item : icmp6type { 3064 $$ = calloc(1, sizeof(struct node_icmp)); 3065 if ($$ == NULL) 3066 err(1, "icmp_item: calloc"); 3067 $$->type = $1; 3068 $$->code = 0; 3069 $$->proto = IPPROTO_ICMPV6; 3070 $$->next = NULL; 3071 $$->tail = $$; 3072 } 3073 | icmp6type CODE STRING { 3074 const struct icmpcodeent *p; 3075 3076 if ((p = geticmpcodebyname($1-1, $3, AF_INET6)) == NULL) { 3077 yyerror("unknown icmp6-code %s", $3); 3078 free($3); 3079 YYERROR; 3080 } 3081 free($3); 3082 3083 $$ = calloc(1, sizeof(struct node_icmp)); 3084 if ($$ == NULL) 3085 err(1, "icmp_item: calloc"); 3086 $$->type = $1; 3087 $$->code = p->code + 1; 3088 $$->proto = IPPROTO_ICMPV6; 3089 $$->next = NULL; 3090 $$->tail = $$; 3091 } 3092 | icmp6type CODE NUMBER { 3093 if ($3 < 0 || $3 > 255) { 3094 yyerror("illegal icmp-code %lu", $3); 3095 YYERROR; 3096 } 3097 $$ = calloc(1, sizeof(struct node_icmp)); 3098 if ($$ == NULL) 3099 err(1, "icmp_item: calloc"); 3100 $$->type = $1; 3101 $$->code = $3 + 1; 3102 $$->proto = IPPROTO_ICMPV6; 3103 $$->next = NULL; 3104 $$->tail = $$; 3105 } 3106 ; 3107 3108icmptype : STRING { 3109 const struct icmptypeent *p; 3110 3111 if ((p = geticmptypebyname($1, AF_INET)) == NULL) { 3112 yyerror("unknown icmp-type %s", $1); 3113 free($1); 3114 YYERROR; 3115 } 3116 $$ = p->type + 1; 3117 free($1); 3118 } 3119 | NUMBER { 3120 if ($1 < 0 || $1 > 255) { 3121 yyerror("illegal icmp-type %lu", $1); 3122 YYERROR; 3123 } 3124 $$ = $1 + 1; 3125 } 3126 ; 3127 3128icmp6type : STRING { 3129 const struct icmptypeent *p; 3130 3131 if ((p = geticmptypebyname($1, AF_INET6)) == 3132 NULL) { 3133 yyerror("unknown icmp6-type %s", $1); 3134 free($1); 3135 YYERROR; 3136 } 3137 $$ = p->type + 1; 3138 free($1); 3139 } 3140 | NUMBER { 3141 if ($1 < 0 || $1 > 255) { 3142 yyerror("illegal icmp6-type %lu", $1); 3143 YYERROR; 3144 } 3145 $$ = $1 + 1; 3146 } 3147 ; 3148 3149tos : TOS STRING { 3150 if (!strcmp($2, "lowdelay")) 3151 $$ = IPTOS_LOWDELAY; 3152 else if (!strcmp($2, "throughput")) 3153 $$ = IPTOS_THROUGHPUT; 3154 else if (!strcmp($2, "reliability")) 3155 $$ = IPTOS_RELIABILITY; 3156 else if ($2[0] == '0' && $2[1] == 'x') 3157 $$ = strtoul($2, NULL, 16); 3158 else 3159 $$ = 0; /* flag bad argument */ 3160 if (!$$ || $$ > 255) { 3161 yyerror("illegal tos value %s", $2); 3162 free($2); 3163 YYERROR; 3164 } 3165 free($2); 3166 } 3167 | TOS NUMBER { 3168 $$ = $2; 3169 if (!$$ || $$ > 255) { 3170 yyerror("illegal tos value %s", $2); 3171 YYERROR; 3172 } 3173 } 3174 ; 3175 3176sourcetrack : SOURCETRACK { $$ = PF_SRCTRACK; } 3177 | SOURCETRACK GLOBAL { $$ = PF_SRCTRACK_GLOBAL; } 3178 | SOURCETRACK RULE { $$ = PF_SRCTRACK_RULE; } 3179 ; 3180 3181statelock : IFBOUND { 3182 $$ = PFRULE_IFBOUND; 3183 } 3184 | FLOATING { 3185 $$ = 0; 3186 } 3187 ; 3188 3189keep : NO STATE { 3190 $$.action = 0; 3191 $$.options = NULL; 3192 } 3193 | KEEP STATE state_opt_spec { 3194 $$.action = PF_STATE_NORMAL; 3195 $$.options = $3; 3196 } 3197 | MODULATE STATE state_opt_spec { 3198 $$.action = PF_STATE_MODULATE; 3199 $$.options = $3; 3200 } 3201 | SYNPROXY STATE state_opt_spec { 3202 $$.action = PF_STATE_SYNPROXY; 3203 $$.options = $3; 3204 } 3205 ; 3206 3207flush : /* empty */ { $$ = 0; } 3208 | FLUSH { $$ = PF_FLUSH; } 3209 | FLUSH GLOBAL { 3210 $$ = PF_FLUSH | PF_FLUSH_GLOBAL; 3211 } 3212 ; 3213 3214state_opt_spec : '(' state_opt_list ')' { $$ = $2; } 3215 | /* empty */ { $$ = NULL; } 3216 ; 3217 3218state_opt_list : state_opt_item { $$ = $1; } 3219 | state_opt_list comma state_opt_item { 3220 $1->tail->next = $3; 3221 $1->tail = $3; 3222 $$ = $1; 3223 } 3224 ; 3225 3226state_opt_item : MAXIMUM NUMBER { 3227 if ($2 < 0 || $2 > UINT_MAX) { 3228 yyerror("only positive values permitted"); 3229 YYERROR; 3230 } 3231 $$ = calloc(1, sizeof(struct node_state_opt)); 3232 if ($$ == NULL) 3233 err(1, "state_opt_item: calloc"); 3234 $$->type = PF_STATE_OPT_MAX; 3235 $$->data.max_states = $2; 3236 $$->next = NULL; 3237 $$->tail = $$; 3238 } 3239 | NOSYNC { 3240 $$ = calloc(1, sizeof(struct node_state_opt)); 3241 if ($$ == NULL) 3242 err(1, "state_opt_item: calloc"); 3243 $$->type = PF_STATE_OPT_NOSYNC; 3244 $$->next = NULL; 3245 $$->tail = $$; 3246 } 3247 | MAXSRCSTATES NUMBER { 3248 if ($2 < 0 || $2 > UINT_MAX) { 3249 yyerror("only positive values permitted"); 3250 YYERROR; 3251 } 3252 $$ = calloc(1, sizeof(struct node_state_opt)); 3253 if ($$ == NULL) 3254 err(1, "state_opt_item: calloc"); 3255 $$->type = PF_STATE_OPT_MAX_SRC_STATES; 3256 $$->data.max_src_states = $2; 3257 $$->next = NULL; 3258 $$->tail = $$; 3259 } 3260 | MAXSRCCONN NUMBER { 3261 if ($2 < 0 || $2 > UINT_MAX) { 3262 yyerror("only positive values permitted"); 3263 YYERROR; 3264 } 3265 $$ = calloc(1, sizeof(struct node_state_opt)); 3266 if ($$ == NULL) 3267 err(1, "state_opt_item: calloc"); 3268 $$->type = PF_STATE_OPT_MAX_SRC_CONN; 3269 $$->data.max_src_conn = $2; 3270 $$->next = NULL; 3271 $$->tail = $$; 3272 } 3273 | MAXSRCCONNRATE NUMBER '/' NUMBER { 3274 if ($2 < 0 || $2 > UINT_MAX || 3275 $4 < 0 || $4 > UINT_MAX) { 3276 yyerror("only positive values permitted"); 3277 YYERROR; 3278 } 3279 $$ = calloc(1, sizeof(struct node_state_opt)); 3280 if ($$ == NULL) 3281 err(1, "state_opt_item: calloc"); 3282 $$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE; 3283 $$->data.max_src_conn_rate.limit = $2; 3284 $$->data.max_src_conn_rate.seconds = $4; 3285 $$->next = NULL; 3286 $$->tail = $$; 3287 } 3288 | OVERLOAD '<' STRING '>' flush { 3289 if (strlen($3) >= PF_TABLE_NAME_SIZE) { 3290 yyerror("table name '%s' too long", $3); 3291 free($3); 3292 YYERROR; 3293 } 3294 $$ = calloc(1, sizeof(struct node_state_opt)); 3295 if ($$ == NULL) 3296 err(1, "state_opt_item: calloc"); 3297 if (strlcpy($$->data.overload.tblname, $3, 3298 PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE) 3299 errx(1, "state_opt_item: strlcpy"); 3300 free($3); 3301 $$->type = PF_STATE_OPT_OVERLOAD; 3302 $$->data.overload.flush = $5; 3303 $$->next = NULL; 3304 $$->tail = $$; 3305 } 3306 | MAXSRCNODES NUMBER { 3307 if ($2 < 0 || $2 > UINT_MAX) { 3308 yyerror("only positive values permitted"); 3309 YYERROR; 3310 } 3311 $$ = calloc(1, sizeof(struct node_state_opt)); 3312 if ($$ == NULL) 3313 err(1, "state_opt_item: calloc"); 3314 $$->type = PF_STATE_OPT_MAX_SRC_NODES; 3315 $$->data.max_src_nodes = $2; 3316 $$->next = NULL; 3317 $$->tail = $$; 3318 } 3319 | sourcetrack { 3320 $$ = calloc(1, sizeof(struct node_state_opt)); 3321 if ($$ == NULL) 3322 err(1, "state_opt_item: calloc"); 3323 $$->type = PF_STATE_OPT_SRCTRACK; 3324 $$->data.src_track = $1; 3325 $$->next = NULL; 3326 $$->tail = $$; 3327 } 3328 | statelock { 3329 $$ = calloc(1, sizeof(struct node_state_opt)); 3330 if ($$ == NULL) 3331 err(1, "state_opt_item: calloc"); 3332 $$->type = PF_STATE_OPT_STATELOCK; 3333 $$->data.statelock = $1; 3334 $$->next = NULL; 3335 $$->tail = $$; 3336 } 3337 | STRING NUMBER { 3338 int i; 3339 3340 if ($2 < 0 || $2 > UINT_MAX) { 3341 yyerror("only positive values permitted"); 3342 YYERROR; 3343 } 3344 for (i = 0; pf_timeouts[i].name && 3345 strcmp(pf_timeouts[i].name, $1); ++i) 3346 ; /* nothing */ 3347 if (!pf_timeouts[i].name) { 3348 yyerror("illegal timeout name %s", $1); 3349 free($1); 3350 YYERROR; 3351 } 3352 if (strchr(pf_timeouts[i].name, '.') == NULL) { 3353 yyerror("illegal state timeout %s", $1); 3354 free($1); 3355 YYERROR; 3356 } 3357 free($1); 3358 $$ = calloc(1, sizeof(struct node_state_opt)); 3359 if ($$ == NULL) 3360 err(1, "state_opt_item: calloc"); 3361 $$->type = PF_STATE_OPT_TIMEOUT; 3362 $$->data.timeout.number = pf_timeouts[i].timeout; 3363 $$->data.timeout.seconds = $2; 3364 $$->next = NULL; 3365 $$->tail = $$; 3366 } 3367 ; 3368 3369label : LABEL STRING { 3370 $$ = $2; 3371 } 3372 ; 3373 3374qname : QUEUE STRING { 3375 $$.qname = $2; 3376 } 3377 | QUEUE '(' STRING ')' { 3378 $$.qname = $3; 3379 } 3380 | QUEUE '(' STRING comma STRING ')' { 3381 $$.qname = $3; 3382 $$.pqname = $5; 3383 } 3384 ; 3385 3386no : /* empty */ { $$ = 0; } 3387 | NO { $$ = 1; } 3388 ; 3389 3390rport : STRING { 3391 char *p = strchr($1, ':'); 3392 3393 if (p == NULL) { 3394 if (($$.a = getservice($1)) == -1) { 3395 free($1); 3396 YYERROR; 3397 } 3398 $$.b = $$.t = 0; 3399 } else if (!strcmp(p+1, "*")) { 3400 *p = 0; 3401 if (($$.a = getservice($1)) == -1) { 3402 free($1); 3403 YYERROR; 3404 } 3405 $$.b = 0; 3406 $$.t = 1; 3407 } else { 3408 *p++ = 0; 3409 if (($$.a = getservice($1)) == -1 || 3410 ($$.b = getservice(p)) == -1) { 3411 free($1); 3412 YYERROR; 3413 } 3414 if ($$.a == $$.b) 3415 $$.b = 0; 3416 $$.t = 0; 3417 } 3418 free($1); 3419 } 3420 | NUMBER { 3421 if ($1 < 0 || $1 > 65535) { 3422 yyerror("illegal port value %ld", $1); 3423 YYERROR; 3424 } 3425 $$.a = ntohs($1); 3426 $$.b = $$.t = 0; 3427 } 3428 ; 3429 3430redirspec : host { $$ = $1; } 3431 | '{' redir_host_list '}' { $$ = $2; } 3432 ; 3433 3434redir_host_list : host { $$ = $1; } 3435 | redir_host_list comma host { 3436 $1->tail->next = $3; 3437 $1->tail = $3->tail; 3438 $$ = $1; 3439 } 3440 ; 3441 3442redirpool : /* empty */ { $$ = NULL; } 3443 | ARROW redirspec { 3444 $$ = calloc(1, sizeof(struct redirection)); 3445 if ($$ == NULL) 3446 err(1, "redirection: calloc"); 3447 $$->host = $2; 3448 $$->rport.a = $$->rport.b = $$->rport.t = 0; 3449 } 3450 | ARROW redirspec PORT rport { 3451 $$ = calloc(1, sizeof(struct redirection)); 3452 if ($$ == NULL) 3453 err(1, "redirection: calloc"); 3454 $$->host = $2; 3455 $$->rport = $4; 3456 } 3457 ; 3458 3459hashkey : /* empty */ 3460 { 3461 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 3462 if ($$ == NULL) 3463 err(1, "hashkey: calloc"); 3464 $$->key32[0] = arc4random(); 3465 $$->key32[1] = arc4random(); 3466 $$->key32[2] = arc4random(); 3467 $$->key32[3] = arc4random(); 3468 } 3469 | string 3470 { 3471 if (!strncmp($1, "0x", 2)) { 3472 if (strlen($1) != 34) { 3473 free($1); 3474 yyerror("hex key must be 128 bits " 3475 "(32 hex digits) long"); 3476 YYERROR; 3477 } 3478 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 3479 if ($$ == NULL) 3480 err(1, "hashkey: calloc"); 3481 3482 if (sscanf($1, "0x%8x%8x%8x%8x", 3483 &$$->key32[0], &$$->key32[1], 3484 &$$->key32[2], &$$->key32[3]) != 4) { 3485 free($$); 3486 free($1); 3487 yyerror("invalid hex key"); 3488 YYERROR; 3489 } 3490 } else { 3491 MD5_CTX context; 3492 3493 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 3494 if ($$ == NULL) 3495 err(1, "hashkey: calloc"); 3496 MD5Init(&context); 3497 MD5Update(&context, (unsigned char *)$1, 3498 strlen($1)); 3499 MD5Final((unsigned char *)$$, &context); 3500 HTONL($$->key32[0]); 3501 HTONL($$->key32[1]); 3502 HTONL($$->key32[2]); 3503 HTONL($$->key32[3]); 3504 } 3505 free($1); 3506 } 3507 ; 3508 3509pool_opts : { bzero(&pool_opts, sizeof pool_opts); } 3510 pool_opts_l 3511 { $$ = pool_opts; } 3512 | /* empty */ { 3513 bzero(&pool_opts, sizeof pool_opts); 3514 $$ = pool_opts; 3515 } 3516 ; 3517 3518pool_opts_l : pool_opts_l pool_opt 3519 | pool_opt 3520 ; 3521 3522pool_opt : BITMASK { 3523 if (pool_opts.type) { 3524 yyerror("pool type cannot be redefined"); 3525 YYERROR; 3526 } 3527 pool_opts.type = PF_POOL_BITMASK; 3528 } 3529 | RANDOM { 3530 if (pool_opts.type) { 3531 yyerror("pool type cannot be redefined"); 3532 YYERROR; 3533 } 3534 pool_opts.type = PF_POOL_RANDOM; 3535 } 3536 | SOURCEHASH hashkey { 3537 if (pool_opts.type) { 3538 yyerror("pool type cannot be redefined"); 3539 YYERROR; 3540 } 3541 pool_opts.type = PF_POOL_SRCHASH; 3542 pool_opts.key = $2; 3543 } 3544 | ROUNDROBIN { 3545 if (pool_opts.type) { 3546 yyerror("pool type cannot be redefined"); 3547 YYERROR; 3548 } 3549 pool_opts.type = PF_POOL_ROUNDROBIN; 3550 } 3551 | STATICPORT { 3552 if (pool_opts.staticport) { 3553 yyerror("static-port cannot be redefined"); 3554 YYERROR; 3555 } 3556 pool_opts.staticport = 1; 3557 } 3558 | STICKYADDRESS { 3559 if (filter_opts.marker & POM_STICKYADDRESS) { 3560 yyerror("sticky-address cannot be redefined"); 3561 YYERROR; 3562 } 3563 pool_opts.marker |= POM_STICKYADDRESS; 3564 pool_opts.opts |= PF_POOL_STICKYADDR; 3565 } 3566 ; 3567 3568redirection : /* empty */ { $$ = NULL; } 3569 | ARROW host { 3570 $$ = calloc(1, sizeof(struct redirection)); 3571 if ($$ == NULL) 3572 err(1, "redirection: calloc"); 3573 $$->host = $2; 3574 $$->rport.a = $$->rport.b = $$->rport.t = 0; 3575 } 3576 | ARROW host PORT rport { 3577 $$ = calloc(1, sizeof(struct redirection)); 3578 if ($$ == NULL) 3579 err(1, "redirection: calloc"); 3580 $$->host = $2; 3581 $$->rport = $4; 3582 } 3583 ; 3584 3585natpasslog : /* empty */ { $$.b1 = $$.b2 = 0; $$.w2 = 0; } 3586 | PASS { $$.b1 = 1; $$.b2 = 0; $$.w2 = 0; } 3587 | PASS log { $$.b1 = 1; $$.b2 = $2.log; $$.w2 = $2.logif; } 3588 | log { $$.b1 = 0; $$.b2 = $1.log; $$.w2 = $1.logif; } 3589 ; 3590 3591nataction : no NAT natpasslog { 3592 if ($1 && $3.b1) { 3593 yyerror("\"pass\" not valid with \"no\""); 3594 YYERROR; 3595 } 3596 if ($1) 3597 $$.b1 = PF_NONAT; 3598 else 3599 $$.b1 = PF_NAT; 3600 $$.b2 = $3.b1; 3601 $$.w = $3.b2; 3602 $$.w2 = $3.w2; 3603 } 3604 | no RDR natpasslog { 3605 if ($1 && $3.b1) { 3606 yyerror("\"pass\" not valid with \"no\""); 3607 YYERROR; 3608 } 3609 if ($1) 3610 $$.b1 = PF_NORDR; 3611 else 3612 $$.b1 = PF_RDR; 3613 $$.b2 = $3.b1; 3614 $$.w = $3.b2; 3615 $$.w2 = $3.w2; 3616 } 3617 ; 3618 3619natrule : nataction interface af proto fromto tag tagged rtable 3620 redirpool pool_opts 3621 { 3622 struct pf_rule r; 3623 3624 if (check_rulestate(PFCTL_STATE_NAT)) 3625 YYERROR; 3626 3627 memset(&r, 0, sizeof(r)); 3628 3629 r.action = $1.b1; 3630 r.natpass = $1.b2; 3631 r.log = $1.w; 3632 r.logif = $1.w2; 3633 r.af = $3; 3634 3635 if (!r.af) { 3636 if ($5.src.host && $5.src.host->af && 3637 !$5.src.host->ifindex) 3638 r.af = $5.src.host->af; 3639 else if ($5.dst.host && $5.dst.host->af && 3640 !$5.dst.host->ifindex) 3641 r.af = $5.dst.host->af; 3642 } 3643 3644 if ($6 != NULL) 3645 if (strlcpy(r.tagname, $6, PF_TAG_NAME_SIZE) >= 3646 PF_TAG_NAME_SIZE) { 3647 yyerror("tag too long, max %u chars", 3648 PF_TAG_NAME_SIZE - 1); 3649 YYERROR; 3650 } 3651 3652 if ($7.name) 3653 if (strlcpy(r.match_tagname, $7.name, 3654 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 3655 yyerror("tag too long, max %u chars", 3656 PF_TAG_NAME_SIZE - 1); 3657 YYERROR; 3658 } 3659 r.match_tag_not = $7.neg; 3660 r.rtableid = $8; 3661 3662 if (r.action == PF_NONAT || r.action == PF_NORDR) { 3663 if ($9 != NULL) { 3664 yyerror("translation rule with 'no' " 3665 "does not need '->'"); 3666 YYERROR; 3667 } 3668 } else { 3669 if ($9 == NULL || $9->host == NULL) { 3670 yyerror("translation rule requires '-> " 3671 "address'"); 3672 YYERROR; 3673 } 3674 if (!r.af && ! $9->host->ifindex) 3675 r.af = $9->host->af; 3676 3677 remove_invalid_hosts(&$9->host, &r.af); 3678 if (invalid_redirect($9->host, r.af)) 3679 YYERROR; 3680 if (check_netmask($9->host, r.af)) 3681 YYERROR; 3682 3683 r.rpool.proxy_port[0] = ntohs($9->rport.a); 3684 3685 switch (r.action) { 3686 case PF_RDR: 3687 if (!$9->rport.b && $9->rport.t && 3688 $5.dst.port != NULL) { 3689 r.rpool.proxy_port[1] = 3690 ntohs($9->rport.a) + 3691 (ntohs( 3692 $5.dst.port->port[1]) - 3693 ntohs( 3694 $5.dst.port->port[0])); 3695 } else 3696 r.rpool.proxy_port[1] = 3697 ntohs($9->rport.b); 3698 break; 3699 case PF_NAT: 3700 r.rpool.proxy_port[1] = 3701 ntohs($9->rport.b); 3702 if (!r.rpool.proxy_port[0] && 3703 !r.rpool.proxy_port[1]) { 3704 r.rpool.proxy_port[0] = 3705 PF_NAT_PROXY_PORT_LOW; 3706 r.rpool.proxy_port[1] = 3707 PF_NAT_PROXY_PORT_HIGH; 3708 } else if (!r.rpool.proxy_port[1]) 3709 r.rpool.proxy_port[1] = 3710 r.rpool.proxy_port[0]; 3711 break; 3712 default: 3713 break; 3714 } 3715 3716 r.rpool.opts = $10.type; 3717 if ((r.rpool.opts & PF_POOL_TYPEMASK) == 3718 PF_POOL_NONE && ($9->host->next != NULL || 3719 $9->host->addr.type == PF_ADDR_TABLE || 3720 DYNIF_MULTIADDR($9->host->addr))) 3721 r.rpool.opts = PF_POOL_ROUNDROBIN; 3722 if ((r.rpool.opts & PF_POOL_TYPEMASK) != 3723 PF_POOL_ROUNDROBIN && 3724 disallow_table($9->host, "tables are only " 3725 "supported in round-robin redirection " 3726 "pools")) 3727 YYERROR; 3728 if ((r.rpool.opts & PF_POOL_TYPEMASK) != 3729 PF_POOL_ROUNDROBIN && 3730 disallow_alias($9->host, "interface (%s) " 3731 "is only supported in round-robin " 3732 "redirection pools")) 3733 YYERROR; 3734 if ($9->host->next != NULL) { 3735 if ((r.rpool.opts & PF_POOL_TYPEMASK) != 3736 PF_POOL_ROUNDROBIN) { 3737 yyerror("only round-robin " 3738 "valid for multiple " 3739 "redirection addresses"); 3740 YYERROR; 3741 } 3742 } 3743 } 3744 3745 if ($10.key != NULL) 3746 memcpy(&r.rpool.key, $10.key, 3747 sizeof(struct pf_poolhashkey)); 3748 3749 if ($10.opts) 3750 r.rpool.opts |= $10.opts; 3751 3752 if ($10.staticport) { 3753 if (r.action != PF_NAT) { 3754 yyerror("the 'static-port' option is " 3755 "only valid with nat rules"); 3756 YYERROR; 3757 } 3758 if (r.rpool.proxy_port[0] != 3759 PF_NAT_PROXY_PORT_LOW && 3760 r.rpool.proxy_port[1] != 3761 PF_NAT_PROXY_PORT_HIGH) { 3762 yyerror("the 'static-port' option can't" 3763 " be used when specifying a port" 3764 " range"); 3765 YYERROR; 3766 } 3767 r.rpool.proxy_port[0] = 0; 3768 r.rpool.proxy_port[1] = 0; 3769 } 3770 3771 expand_rule(&r, $2, $9 == NULL ? NULL : $9->host, $4, 3772 $5.src_os, $5.src.host, $5.src.port, $5.dst.host, 3773 $5.dst.port, 0, 0, 0, ""); 3774 free($9); 3775 } 3776 ; 3777 3778binatrule : no BINAT natpasslog interface af proto FROM host TO ipspec tag 3779 tagged rtable redirection 3780 { 3781 struct pf_rule binat; 3782 struct pf_pooladdr *pa; 3783 3784 if (check_rulestate(PFCTL_STATE_NAT)) 3785 YYERROR; 3786 if (disallow_urpf_failed($10, "\"urpf-failed\" is not " 3787 "permitted as a binat destination")) 3788 YYERROR; 3789 3790 memset(&binat, 0, sizeof(binat)); 3791 3792 if ($1 && $3.b1) { 3793 yyerror("\"pass\" not valid with \"no\""); 3794 YYERROR; 3795 } 3796 if ($1) 3797 binat.action = PF_NOBINAT; 3798 else 3799 binat.action = PF_BINAT; 3800 binat.natpass = $3.b1; 3801 binat.log = $3.b2; 3802 binat.logif = $3.w2; 3803 binat.af = $5; 3804 if (!binat.af && $8 != NULL && $8->af) 3805 binat.af = $8->af; 3806 if (!binat.af && $10 != NULL && $10->af) 3807 binat.af = $10->af; 3808 3809 if (!binat.af && $14 != NULL && $14->host) 3810 binat.af = $14->host->af; 3811 if (!binat.af) { 3812 yyerror("address family (inet/inet6) " 3813 "undefined"); 3814 YYERROR; 3815 } 3816 3817 if ($4 != NULL) { 3818 memcpy(binat.ifname, $4->ifname, 3819 sizeof(binat.ifname)); 3820 binat.ifnot = $4->not; 3821 free($4); 3822 } 3823 3824 if ($11 != NULL) 3825 if (strlcpy(binat.tagname, $11, 3826 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 3827 yyerror("tag too long, max %u chars", 3828 PF_TAG_NAME_SIZE - 1); 3829 YYERROR; 3830 } 3831 if ($12.name) 3832 if (strlcpy(binat.match_tagname, $12.name, 3833 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 3834 yyerror("tag too long, max %u chars", 3835 PF_TAG_NAME_SIZE - 1); 3836 YYERROR; 3837 } 3838 binat.match_tag_not = $12.neg; 3839 binat.rtableid = $13; 3840 3841 if ($6 != NULL) { 3842 binat.proto = $6->proto; 3843 free($6); 3844 } 3845 3846 if ($8 != NULL && disallow_table($8, "invalid use of " 3847 "table <%s> as the source address of a binat rule")) 3848 YYERROR; 3849 if ($8 != NULL && disallow_alias($8, "invalid use of " 3850 "interface (%s) as the source address of a binat " 3851 "rule")) 3852 YYERROR; 3853 if ($14 != NULL && $14->host != NULL && disallow_table( 3854 $14->host, "invalid use of table <%s> as the " 3855 "redirect address of a binat rule")) 3856 YYERROR; 3857 if ($14 != NULL && $14->host != NULL && disallow_alias( 3858 $14->host, "invalid use of interface (%s) as the " 3859 "redirect address of a binat rule")) 3860 YYERROR; 3861 3862 if ($8 != NULL) { 3863 if ($8->next) { 3864 yyerror("multiple binat ip addresses"); 3865 YYERROR; 3866 } 3867 if ($8->addr.type == PF_ADDR_DYNIFTL) 3868 $8->af = binat.af; 3869 if ($8->af != binat.af) { 3870 yyerror("binat ip versions must match"); 3871 YYERROR; 3872 } 3873 if (check_netmask($8, binat.af)) 3874 YYERROR; 3875 memcpy(&binat.src.addr, &$8->addr, 3876 sizeof(binat.src.addr)); 3877 free($8); 3878 } 3879 if ($10 != NULL) { 3880 if ($10->next) { 3881 yyerror("multiple binat ip addresses"); 3882 YYERROR; 3883 } 3884 if ($10->af != binat.af && $10->af) { 3885 yyerror("binat ip versions must match"); 3886 YYERROR; 3887 } 3888 if (check_netmask($10, binat.af)) 3889 YYERROR; 3890 memcpy(&binat.dst.addr, &$10->addr, 3891 sizeof(binat.dst.addr)); 3892 binat.dst.neg = $10->not; 3893 free($10); 3894 } 3895 3896 if (binat.action == PF_NOBINAT) { 3897 if ($14 != NULL) { 3898 yyerror("'no binat' rule does not need" 3899 " '->'"); 3900 YYERROR; 3901 } 3902 } else { 3903 if ($14 == NULL || $14->host == NULL) { 3904 yyerror("'binat' rule requires" 3905 " '-> address'"); 3906 YYERROR; 3907 } 3908 3909 remove_invalid_hosts(&$14->host, &binat.af); 3910 if (invalid_redirect($14->host, binat.af)) 3911 YYERROR; 3912 if ($14->host->next != NULL) { 3913 yyerror("binat rule must redirect to " 3914 "a single address"); 3915 YYERROR; 3916 } 3917 if (check_netmask($14->host, binat.af)) 3918 YYERROR; 3919 3920 if (!PF_AZERO(&binat.src.addr.v.a.mask, 3921 binat.af) && 3922 !PF_AEQ(&binat.src.addr.v.a.mask, 3923 &$14->host->addr.v.a.mask, binat.af)) { 3924 yyerror("'binat' source mask and " 3925 "redirect mask must be the same"); 3926 YYERROR; 3927 } 3928 3929 TAILQ_INIT(&binat.rpool.list); 3930 pa = calloc(1, sizeof(struct pf_pooladdr)); 3931 if (pa == NULL) 3932 err(1, "binat: calloc"); 3933 pa->addr = $14->host->addr; 3934 pa->ifname[0] = 0; 3935 TAILQ_INSERT_TAIL(&binat.rpool.list, 3936 pa, entries); 3937 3938 free($14); 3939 } 3940 3941 pfctl_add_rule(pf, &binat, ""); 3942 } 3943 ; 3944 3945tag : /* empty */ { $$ = NULL; } 3946 | TAG STRING { $$ = $2; } 3947 ; 3948 3949tagged : /* empty */ { $$.neg = 0; $$.name = NULL; } 3950 | not TAGGED string { $$.neg = $1; $$.name = $3; } 3951 ; 3952 3953rtable : /* empty */ { $$ = -1; } 3954 | RTABLE NUMBER { 3955 if ($2 < 0 || $2 > RT_TABLEID_MAX) { 3956 yyerror("invalid rtable id"); 3957 YYERROR; 3958 } 3959 $$ = $2; 3960 } 3961 ; 3962 3963route_host : STRING { 3964 $$ = calloc(1, sizeof(struct node_host)); 3965 if ($$ == NULL) 3966 err(1, "route_host: calloc"); 3967 $$->ifname = $1; 3968 set_ipmask($$, 128); 3969 $$->next = NULL; 3970 $$->tail = $$; 3971 } 3972 | '(' STRING host ')' { 3973 $$ = $3; 3974 $$->ifname = $2; 3975 } 3976 ; 3977 3978route_host_list : route_host { $$ = $1; } 3979 | route_host_list comma route_host { 3980 if ($1->af == 0) 3981 $1->af = $3->af; 3982 if ($1->af != $3->af) { 3983 yyerror("all pool addresses must be in the " 3984 "same address family"); 3985 YYERROR; 3986 } 3987 $1->tail->next = $3; 3988 $1->tail = $3->tail; 3989 $$ = $1; 3990 } 3991 ; 3992 3993routespec : route_host { $$ = $1; } 3994 | '{' route_host_list '}' { $$ = $2; } 3995 ; 3996 3997route : /* empty */ { 3998 $$.host = NULL; 3999 $$.rt = 0; 4000 $$.pool_opts = 0; 4001 } 4002 | FASTROUTE { 4003 $$.host = NULL; 4004 $$.rt = PF_FASTROUTE; 4005 $$.pool_opts = 0; 4006 } 4007 | ROUTETO routespec pool_opts { 4008 $$.host = $2; 4009 $$.rt = PF_ROUTETO; 4010 $$.pool_opts = $3.type | $3.opts; 4011 if ($3.key != NULL) 4012 $$.key = $3.key; 4013 } 4014 | REPLYTO routespec pool_opts { 4015 $$.host = $2; 4016 $$.rt = PF_REPLYTO; 4017 $$.pool_opts = $3.type | $3.opts; 4018 if ($3.key != NULL) 4019 $$.key = $3.key; 4020 } 4021 | DUPTO routespec pool_opts { 4022 $$.host = $2; 4023 $$.rt = PF_DUPTO; 4024 $$.pool_opts = $3.type | $3.opts; 4025 if ($3.key != NULL) 4026 $$.key = $3.key; 4027 } 4028 ; 4029 4030timeout_spec : STRING NUMBER 4031 { 4032 if (check_rulestate(PFCTL_STATE_OPTION)) { 4033 free($1); 4034 YYERROR; 4035 } 4036 if ($2 < 0 || $2 > UINT_MAX) { 4037 yyerror("only positive values permitted"); 4038 YYERROR; 4039 } 4040 if (pfctl_set_timeout(pf, $1, $2, 0) != 0) { 4041 yyerror("unknown timeout %s", $1); 4042 free($1); 4043 YYERROR; 4044 } 4045 free($1); 4046 } 4047 ; 4048 4049timeout_list : timeout_list comma timeout_spec 4050 | timeout_spec 4051 ; 4052 4053limit_spec : STRING NUMBER 4054 { 4055 if (check_rulestate(PFCTL_STATE_OPTION)) { 4056 free($1); 4057 YYERROR; 4058 } 4059 if ($2 < 0 || $2 > UINT_MAX) { 4060 yyerror("only positive values permitted"); 4061 YYERROR; 4062 } 4063 if (pfctl_set_limit(pf, $1, $2) != 0) { 4064 yyerror("unable to set limit %s %u", $1, $2); 4065 free($1); 4066 YYERROR; 4067 } 4068 free($1); 4069 } 4070 ; 4071 4072limit_list : limit_list comma limit_spec 4073 | limit_spec 4074 ; 4075 4076comma : ',' 4077 | /* empty */ 4078 ; 4079 4080yesno : NO { $$ = 0; } 4081 | STRING { 4082 if (!strcmp($1, "yes")) 4083 $$ = 1; 4084 else { 4085 yyerror("invalid value '%s', expected 'yes' " 4086 "or 'no'", $1); 4087 free($1); 4088 YYERROR; 4089 } 4090 free($1); 4091 } 4092 ; 4093 4094unaryop : '=' { $$ = PF_OP_EQ; } 4095 | '!' '=' { $$ = PF_OP_NE; } 4096 | '<' '=' { $$ = PF_OP_LE; } 4097 | '<' { $$ = PF_OP_LT; } 4098 | '>' '=' { $$ = PF_OP_GE; } 4099 | '>' { $$ = PF_OP_GT; } 4100 ; 4101 4102%% 4103 4104int 4105yyerror(const char *fmt, ...) 4106{ 4107 va_list ap; 4108 extern char *infile; 4109 4110 errors = 1; 4111 va_start(ap, fmt); 4112 fprintf(stderr, "%s:%d: ", infile, yylval.lineno); 4113 vfprintf(stderr, fmt, ap); 4114 fprintf(stderr, "\n"); 4115 va_end(ap); 4116 return (0); 4117} 4118 4119int 4120disallow_table(struct node_host *h, const char *fmt) 4121{ 4122 for (; h != NULL; h = h->next) 4123 if (h->addr.type == PF_ADDR_TABLE) { 4124 yyerror(fmt, h->addr.v.tblname); 4125 return (1); 4126 } 4127 return (0); 4128} 4129 4130int 4131disallow_urpf_failed(struct node_host *h, const char *fmt) 4132{ 4133 for (; h != NULL; h = h->next) 4134 if (h->addr.type == PF_ADDR_URPFFAILED) { 4135 yyerror(fmt); 4136 return (1); 4137 } 4138 return (0); 4139} 4140 4141int 4142disallow_alias(struct node_host *h, const char *fmt) 4143{ 4144 for (; h != NULL; h = h->next) 4145 if (DYNIF_MULTIADDR(h->addr)) { 4146 yyerror(fmt, h->addr.v.tblname); 4147 return (1); 4148 } 4149 return (0); 4150} 4151 4152int 4153rule_consistent(struct pf_rule *r, int anchor_call) 4154{ 4155 int problems = 0; 4156 4157 switch (r->action) { 4158 case PF_PASS: 4159 case PF_DROP: 4160 case PF_SCRUB: 4161 case PF_NOSCRUB: 4162 problems = filter_consistent(r, anchor_call); 4163 break; 4164 case PF_NAT: 4165 case PF_NONAT: 4166 problems = nat_consistent(r); 4167 break; 4168 case PF_RDR: 4169 case PF_NORDR: 4170 problems = rdr_consistent(r); 4171 break; 4172 case PF_BINAT: 4173 case PF_NOBINAT: 4174 default: 4175 break; 4176 } 4177 return (problems); 4178} 4179 4180int 4181filter_consistent(struct pf_rule *r, int anchor_call) 4182{ 4183 int problems = 0; 4184 4185 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 4186 (r->src.port_op || r->dst.port_op)) { 4187 yyerror("port only applies to tcp/udp"); 4188 problems++; 4189 } 4190 if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 && 4191 (r->type || r->code)) { 4192 yyerror("icmp-type/code only applies to icmp"); 4193 problems++; 4194 } 4195 if (!r->af && (r->type || r->code)) { 4196 yyerror("must indicate address family with icmp-type/code"); 4197 problems++; 4198 } 4199 if (r->overload_tblname[0] && 4200 r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) { 4201 yyerror("'overload' requires 'max-src-conn' " 4202 "or 'max-src-conn-rate'"); 4203 problems++; 4204 } 4205 if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) || 4206 (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) { 4207 yyerror("proto %s doesn't match address family %s", 4208 r->proto == IPPROTO_ICMP ? "icmp" : "icmp6", 4209 r->af == AF_INET ? "inet" : "inet6"); 4210 problems++; 4211 } 4212 if (r->allow_opts && r->action != PF_PASS) { 4213 yyerror("allow-opts can only be specified for pass rules"); 4214 problems++; 4215 } 4216 if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op || 4217 r->dst.port_op || r->flagset || r->type || r->code)) { 4218 yyerror("fragments can be filtered only on IP header fields"); 4219 problems++; 4220 } 4221 if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) { 4222 yyerror("return-rst can only be applied to TCP rules"); 4223 problems++; 4224 } 4225 if (r->max_src_nodes && !(r->rule_flag & PFRULE_RULESRCTRACK)) { 4226 yyerror("max-src-nodes requires 'source-track rule'"); 4227 problems++; 4228 } 4229 if (r->action == PF_DROP && r->keep_state) { 4230 yyerror("keep state on block rules doesn't make sense"); 4231 problems++; 4232 } 4233 return (-problems); 4234} 4235 4236int 4237nat_consistent(struct pf_rule *r) 4238{ 4239 return (0); /* yeah! */ 4240} 4241 4242int 4243rdr_consistent(struct pf_rule *r) 4244{ 4245 int problems = 0; 4246 4247 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP) { 4248 if (r->src.port_op) { 4249 yyerror("src port only applies to tcp/udp"); 4250 problems++; 4251 } 4252 if (r->dst.port_op) { 4253 yyerror("dst port only applies to tcp/udp"); 4254 problems++; 4255 } 4256 if (r->rpool.proxy_port[0]) { 4257 yyerror("rpool port only applies to tcp/udp"); 4258 problems++; 4259 } 4260 } 4261 if (r->dst.port_op && 4262 r->dst.port_op != PF_OP_EQ && r->dst.port_op != PF_OP_RRG) { 4263 yyerror("invalid port operator for rdr destination port"); 4264 problems++; 4265 } 4266 return (-problems); 4267} 4268 4269int 4270process_tabledef(char *name, struct table_opts *opts) 4271{ 4272 struct pfr_buffer ab; 4273 struct node_tinit *ti; 4274 4275 bzero(&ab, sizeof(ab)); 4276 ab.pfrb_type = PFRB_ADDRS; 4277 SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) { 4278 if (ti->file) 4279 if (pfr_buf_load(&ab, ti->file, 0, append_addr)) { 4280 if (errno) 4281 yyerror("cannot load \"%s\": %s", 4282 ti->file, strerror(errno)); 4283 else 4284 yyerror("file \"%s\" contains bad data", 4285 ti->file); 4286 goto _error; 4287 } 4288 if (ti->host) 4289 if (append_addr_host(&ab, ti->host, 0, 0)) { 4290 yyerror("cannot create address buffer: %s", 4291 strerror(errno)); 4292 goto _error; 4293 } 4294 } 4295 if (pf->opts & PF_OPT_VERBOSE) 4296 print_tabledef(name, opts->flags, opts->init_addr, 4297 &opts->init_nodes); 4298 if (!(pf->opts & PF_OPT_NOACTION) && 4299 pfctl_define_table(name, opts->flags, opts->init_addr, 4300 pf->anchor->name, &ab, pf->anchor->ruleset.tticket)) { 4301 yyerror("cannot define table %s: %s", name, 4302 pfr_strerror(errno)); 4303 goto _error; 4304 } 4305 pf->tdirty = 1; 4306 pfr_buf_clear(&ab); 4307 return (0); 4308_error: 4309 pfr_buf_clear(&ab); 4310 return (-1); 4311} 4312 4313struct keywords { 4314 const char *k_name; 4315 int k_val; 4316}; 4317 4318/* macro gore, but you should've seen the prior indentation nightmare... */ 4319 4320#define FREE_LIST(T,r) \ 4321 do { \ 4322 T *p, *node = r; \ 4323 while (node != NULL) { \ 4324 p = node; \ 4325 node = node->next; \ 4326 free(p); \ 4327 } \ 4328 } while (0) 4329 4330#define LOOP_THROUGH(T,n,r,C) \ 4331 do { \ 4332 T *n; \ 4333 if (r == NULL) { \ 4334 r = calloc(1, sizeof(T)); \ 4335 if (r == NULL) \ 4336 err(1, "LOOP: calloc"); \ 4337 r->next = NULL; \ 4338 } \ 4339 n = r; \ 4340 while (n != NULL) { \ 4341 do { \ 4342 C; \ 4343 } while (0); \ 4344 n = n->next; \ 4345 } \ 4346 } while (0) 4347 4348void 4349expand_label_str(char *label, size_t len, const char *srch, const char *repl) 4350{ 4351 char *tmp; 4352 char *p, *q; 4353 4354 if ((tmp = calloc(1, len)) == NULL) 4355 err(1, "expand_label_str: calloc"); 4356 p = q = label; 4357 while ((q = strstr(p, srch)) != NULL) { 4358 *q = '\0'; 4359 if ((strlcat(tmp, p, len) >= len) || 4360 (strlcat(tmp, repl, len) >= len)) 4361 errx(1, "expand_label: label too long"); 4362 q += strlen(srch); 4363 p = q; 4364 } 4365 if (strlcat(tmp, p, len) >= len) 4366 errx(1, "expand_label: label too long"); 4367 strlcpy(label, tmp, len); /* always fits */ 4368 free(tmp); 4369} 4370 4371void 4372expand_label_if(const char *name, char *label, size_t len, const char *ifname) 4373{ 4374 if (strstr(label, name) != NULL) { 4375 if (!*ifname) 4376 expand_label_str(label, len, name, "any"); 4377 else 4378 expand_label_str(label, len, name, ifname); 4379 } 4380} 4381 4382void 4383expand_label_addr(const char *name, char *label, size_t len, sa_family_t af, 4384 struct node_host *h) 4385{ 4386 char tmp[64], tmp_not[66]; 4387 4388 if (strstr(label, name) != NULL) { 4389 switch (h->addr.type) { 4390 case PF_ADDR_DYNIFTL: 4391 snprintf(tmp, sizeof(tmp), "(%s)", h->addr.v.ifname); 4392 break; 4393 case PF_ADDR_TABLE: 4394 snprintf(tmp, sizeof(tmp), "<%s>", h->addr.v.tblname); 4395 break; 4396 case PF_ADDR_NOROUTE: 4397 snprintf(tmp, sizeof(tmp), "no-route"); 4398 break; 4399 case PF_ADDR_URPFFAILED: 4400 snprintf(tmp, sizeof(tmp), "urpf-failed"); 4401 break; 4402 case PF_ADDR_ADDRMASK: 4403 if (!af || (PF_AZERO(&h->addr.v.a.addr, af) && 4404 PF_AZERO(&h->addr.v.a.mask, af))) 4405 snprintf(tmp, sizeof(tmp), "any"); 4406 else { 4407 char a[48]; 4408 int bits; 4409 4410 if (inet_ntop(af, &h->addr.v.a.addr, a, 4411 sizeof(a)) == NULL) 4412 snprintf(tmp, sizeof(tmp), "?"); 4413 else { 4414 bits = unmask(&h->addr.v.a.mask, af); 4415 if ((af == AF_INET && bits < 32) || 4416 (af == AF_INET6 && bits < 128)) 4417 snprintf(tmp, sizeof(tmp), 4418 "%s/%d", a, bits); 4419 else 4420 snprintf(tmp, sizeof(tmp), 4421 "%s", a); 4422 } 4423 } 4424 break; 4425 default: 4426 snprintf(tmp, sizeof(tmp), "?"); 4427 break; 4428 } 4429 4430 if (h->not) { 4431 snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp); 4432 expand_label_str(label, len, name, tmp_not); 4433 } else 4434 expand_label_str(label, len, name, tmp); 4435 } 4436} 4437 4438void 4439expand_label_port(const char *name, char *label, size_t len, 4440 struct node_port *port) 4441{ 4442 char a1[6], a2[6], op[13] = ""; 4443 4444 if (strstr(label, name) != NULL) { 4445 snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0])); 4446 snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1])); 4447 if (!port->op) 4448 ; 4449 else if (port->op == PF_OP_IRG) 4450 snprintf(op, sizeof(op), "%s><%s", a1, a2); 4451 else if (port->op == PF_OP_XRG) 4452 snprintf(op, sizeof(op), "%s<>%s", a1, a2); 4453 else if (port->op == PF_OP_EQ) 4454 snprintf(op, sizeof(op), "%s", a1); 4455 else if (port->op == PF_OP_NE) 4456 snprintf(op, sizeof(op), "!=%s", a1); 4457 else if (port->op == PF_OP_LT) 4458 snprintf(op, sizeof(op), "<%s", a1); 4459 else if (port->op == PF_OP_LE) 4460 snprintf(op, sizeof(op), "<=%s", a1); 4461 else if (port->op == PF_OP_GT) 4462 snprintf(op, sizeof(op), ">%s", a1); 4463 else if (port->op == PF_OP_GE) 4464 snprintf(op, sizeof(op), ">=%s", a1); 4465 expand_label_str(label, len, name, op); 4466 } 4467} 4468 4469void 4470expand_label_proto(const char *name, char *label, size_t len, u_int8_t proto) 4471{ 4472 struct protoent *pe; 4473 char n[4]; 4474 4475 if (strstr(label, name) != NULL) { 4476 pe = getprotobynumber(proto); 4477 if (pe != NULL) 4478 expand_label_str(label, len, name, pe->p_name); 4479 else { 4480 snprintf(n, sizeof(n), "%u", proto); 4481 expand_label_str(label, len, name, n); 4482 } 4483 } 4484} 4485 4486void 4487expand_label_nr(const char *name, char *label, size_t len) 4488{ 4489 char n[11]; 4490 4491 if (strstr(label, name) != NULL) { 4492 snprintf(n, sizeof(n), "%u", pf->anchor->match); 4493 expand_label_str(label, len, name, n); 4494 } 4495} 4496 4497void 4498expand_label(char *label, size_t len, const char *ifname, sa_family_t af, 4499 struct node_host *src_host, struct node_port *src_port, 4500 struct node_host *dst_host, struct node_port *dst_port, 4501 u_int8_t proto) 4502{ 4503 expand_label_if("$if", label, len, ifname); 4504 expand_label_addr("$srcaddr", label, len, af, src_host); 4505 expand_label_addr("$dstaddr", label, len, af, dst_host); 4506 expand_label_port("$srcport", label, len, src_port); 4507 expand_label_port("$dstport", label, len, dst_port); 4508 expand_label_proto("$proto", label, len, proto); 4509 expand_label_nr("$nr", label, len); 4510} 4511 4512int 4513expand_altq(struct pf_altq *a, struct node_if *interfaces, 4514 struct node_queue *nqueues, struct node_queue_bw bwspec, 4515 struct node_queue_opt *opts) 4516{ 4517 struct pf_altq pa, pb; 4518 char qname[PF_QNAME_SIZE]; 4519 struct node_queue *n; 4520 struct node_queue_bw bw; 4521 int errs = 0; 4522 4523 if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) { 4524 FREE_LIST(struct node_if, interfaces); 4525 FREE_LIST(struct node_queue, nqueues); 4526 return (0); 4527 } 4528 4529 LOOP_THROUGH(struct node_if, interface, interfaces, 4530 memcpy(&pa, a, sizeof(struct pf_altq)); 4531 if (strlcpy(pa.ifname, interface->ifname, 4532 sizeof(pa.ifname)) >= sizeof(pa.ifname)) 4533 errx(1, "expand_altq: strlcpy"); 4534 4535 if (interface->not) { 4536 yyerror("altq on ! <interface> is not supported"); 4537 errs++; 4538 } else { 4539 if (eval_pfaltq(pf, &pa, &bwspec, opts)) 4540 errs++; 4541 else 4542 if (pfctl_add_altq(pf, &pa)) 4543 errs++; 4544 4545 if (pf->opts & PF_OPT_VERBOSE) { 4546 print_altq(&pf->paltq->altq, 0, 4547 &bwspec, opts); 4548 if (nqueues && nqueues->tail) { 4549 printf("queue { "); 4550 LOOP_THROUGH(struct node_queue, queue, 4551 nqueues, 4552 printf("%s ", 4553 queue->queue); 4554 ); 4555 printf("}"); 4556 } 4557 printf("\n"); 4558 } 4559 4560 if (pa.scheduler == ALTQT_CBQ || 4561 pa.scheduler == ALTQT_HFSC) { 4562 /* now create a root queue */ 4563 memset(&pb, 0, sizeof(struct pf_altq)); 4564 if (strlcpy(qname, "root_", sizeof(qname)) >= 4565 sizeof(qname)) 4566 errx(1, "expand_altq: strlcpy"); 4567 if (strlcat(qname, interface->ifname, 4568 sizeof(qname)) >= sizeof(qname)) 4569 errx(1, "expand_altq: strlcat"); 4570 if (strlcpy(pb.qname, qname, 4571 sizeof(pb.qname)) >= sizeof(pb.qname)) 4572 errx(1, "expand_altq: strlcpy"); 4573 if (strlcpy(pb.ifname, interface->ifname, 4574 sizeof(pb.ifname)) >= sizeof(pb.ifname)) 4575 errx(1, "expand_altq: strlcpy"); 4576 pb.qlimit = pa.qlimit; 4577 pb.scheduler = pa.scheduler; 4578 bw.bw_absolute = pa.ifbandwidth; 4579 bw.bw_percent = 0; 4580 if (eval_pfqueue(pf, &pb, &bw, opts)) 4581 errs++; 4582 else 4583 if (pfctl_add_altq(pf, &pb)) 4584 errs++; 4585 } 4586 4587 LOOP_THROUGH(struct node_queue, queue, nqueues, 4588 n = calloc(1, sizeof(struct node_queue)); 4589 if (n == NULL) 4590 err(1, "expand_altq: calloc"); 4591 if (pa.scheduler == ALTQT_CBQ || 4592 pa.scheduler == ALTQT_HFSC) 4593 if (strlcpy(n->parent, qname, 4594 sizeof(n->parent)) >= 4595 sizeof(n->parent)) 4596 errx(1, "expand_altq: strlcpy"); 4597 if (strlcpy(n->queue, queue->queue, 4598 sizeof(n->queue)) >= sizeof(n->queue)) 4599 errx(1, "expand_altq: strlcpy"); 4600 if (strlcpy(n->ifname, interface->ifname, 4601 sizeof(n->ifname)) >= sizeof(n->ifname)) 4602 errx(1, "expand_altq: strlcpy"); 4603 n->scheduler = pa.scheduler; 4604 n->next = NULL; 4605 n->tail = n; 4606 if (queues == NULL) 4607 queues = n; 4608 else { 4609 queues->tail->next = n; 4610 queues->tail = n; 4611 } 4612 ); 4613 } 4614 ); 4615 FREE_LIST(struct node_if, interfaces); 4616 FREE_LIST(struct node_queue, nqueues); 4617 4618 return (errs); 4619} 4620 4621int 4622expand_queue(struct pf_altq *a, struct node_if *interfaces, 4623 struct node_queue *nqueues, struct node_queue_bw bwspec, 4624 struct node_queue_opt *opts) 4625{ 4626 struct node_queue *n, *nq; 4627 struct pf_altq pa; 4628 u_int8_t found = 0; 4629 u_int8_t errs = 0; 4630 4631 if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) { 4632 FREE_LIST(struct node_queue, nqueues); 4633 return (0); 4634 } 4635 4636 if (queues == NULL) { 4637 yyerror("queue %s has no parent", a->qname); 4638 FREE_LIST(struct node_queue, nqueues); 4639 return (1); 4640 } 4641 4642 LOOP_THROUGH(struct node_if, interface, interfaces, 4643 LOOP_THROUGH(struct node_queue, tqueue, queues, 4644 if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE) && 4645 (interface->ifname[0] == 0 || 4646 (!interface->not && !strncmp(interface->ifname, 4647 tqueue->ifname, IFNAMSIZ)) || 4648 (interface->not && strncmp(interface->ifname, 4649 tqueue->ifname, IFNAMSIZ)))) { 4650 /* found ourself in queues */ 4651 found++; 4652 4653 memcpy(&pa, a, sizeof(struct pf_altq)); 4654 4655 if (pa.scheduler != ALTQT_NONE && 4656 pa.scheduler != tqueue->scheduler) { 4657 yyerror("exactly one scheduler type " 4658 "per interface allowed"); 4659 return (1); 4660 } 4661 pa.scheduler = tqueue->scheduler; 4662 4663 /* scheduler dependent error checking */ 4664 switch (pa.scheduler) { 4665 case ALTQT_PRIQ: 4666 if (nqueues != NULL) { 4667 yyerror("priq queues cannot " 4668 "have child queues"); 4669 return (1); 4670 } 4671 if (bwspec.bw_absolute > 0 || 4672 bwspec.bw_percent < 100) { 4673 yyerror("priq doesn't take " 4674 "bandwidth"); 4675 return (1); 4676 } 4677 break; 4678 default: 4679 break; 4680 } 4681 4682 if (strlcpy(pa.ifname, tqueue->ifname, 4683 sizeof(pa.ifname)) >= sizeof(pa.ifname)) 4684 errx(1, "expand_queue: strlcpy"); 4685 if (strlcpy(pa.parent, tqueue->parent, 4686 sizeof(pa.parent)) >= sizeof(pa.parent)) 4687 errx(1, "expand_queue: strlcpy"); 4688 4689 if (eval_pfqueue(pf, &pa, &bwspec, opts)) 4690 errs++; 4691 else 4692 if (pfctl_add_altq(pf, &pa)) 4693 errs++; 4694 4695 for (nq = nqueues; nq != NULL; nq = nq->next) { 4696 if (!strcmp(a->qname, nq->queue)) { 4697 yyerror("queue cannot have " 4698 "itself as child"); 4699 errs++; 4700 continue; 4701 } 4702 n = calloc(1, 4703 sizeof(struct node_queue)); 4704 if (n == NULL) 4705 err(1, "expand_queue: calloc"); 4706 if (strlcpy(n->parent, a->qname, 4707 sizeof(n->parent)) >= 4708 sizeof(n->parent)) 4709 errx(1, "expand_queue strlcpy"); 4710 if (strlcpy(n->queue, nq->queue, 4711 sizeof(n->queue)) >= 4712 sizeof(n->queue)) 4713 errx(1, "expand_queue strlcpy"); 4714 if (strlcpy(n->ifname, tqueue->ifname, 4715 sizeof(n->ifname)) >= 4716 sizeof(n->ifname)) 4717 errx(1, "expand_queue strlcpy"); 4718 n->scheduler = tqueue->scheduler; 4719 n->next = NULL; 4720 n->tail = n; 4721 if (queues == NULL) 4722 queues = n; 4723 else { 4724 queues->tail->next = n; 4725 queues->tail = n; 4726 } 4727 } 4728 if ((pf->opts & PF_OPT_VERBOSE) && ( 4729 (found == 1 && interface->ifname[0] == 0) || 4730 (found > 0 && interface->ifname[0] != 0))) { 4731 print_queue(&pf->paltq->altq, 0, 4732 &bwspec, interface->ifname[0] != 0, 4733 opts); 4734 if (nqueues && nqueues->tail) { 4735 printf("{ "); 4736 LOOP_THROUGH(struct node_queue, 4737 queue, nqueues, 4738 printf("%s ", 4739 queue->queue); 4740 ); 4741 printf("}"); 4742 } 4743 printf("\n"); 4744 } 4745 } 4746 ); 4747 ); 4748 4749 FREE_LIST(struct node_queue, nqueues); 4750 FREE_LIST(struct node_if, interfaces); 4751 4752 if (!found) { 4753 yyerror("queue %s has no parent", a->qname); 4754 errs++; 4755 } 4756 4757 if (errs) 4758 return (1); 4759 else 4760 return (0); 4761} 4762 4763void 4764expand_rule(struct pf_rule *r, 4765 struct node_if *interfaces, struct node_host *rpool_hosts, 4766 struct node_proto *protos, struct node_os *src_oses, 4767 struct node_host *src_hosts, struct node_port *src_ports, 4768 struct node_host *dst_hosts, struct node_port *dst_ports, 4769 struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types, 4770 const char *anchor_call) 4771{ 4772 sa_family_t af = r->af; 4773 int added = 0, error = 0; 4774 char ifname[IF_NAMESIZE]; 4775 char label[PF_RULE_LABEL_SIZE]; 4776 char tagname[PF_TAG_NAME_SIZE]; 4777 char match_tagname[PF_TAG_NAME_SIZE]; 4778 struct pf_pooladdr *pa; 4779 struct node_host *h; 4780 u_int8_t flags, flagset, keep_state; 4781 4782 if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label)) 4783 errx(1, "expand_rule: strlcpy"); 4784 if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname)) 4785 errx(1, "expand_rule: strlcpy"); 4786 if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >= 4787 sizeof(match_tagname)) 4788 errx(1, "expand_rule: strlcpy"); 4789 flags = r->flags; 4790 flagset = r->flagset; 4791 keep_state = r->keep_state; 4792 4793 LOOP_THROUGH(struct node_if, interface, interfaces, 4794 LOOP_THROUGH(struct node_proto, proto, protos, 4795 LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types, 4796 LOOP_THROUGH(struct node_host, src_host, src_hosts, 4797 LOOP_THROUGH(struct node_port, src_port, src_ports, 4798 LOOP_THROUGH(struct node_os, src_os, src_oses, 4799 LOOP_THROUGH(struct node_host, dst_host, dst_hosts, 4800 LOOP_THROUGH(struct node_port, dst_port, dst_ports, 4801 LOOP_THROUGH(struct node_uid, uid, uids, 4802 LOOP_THROUGH(struct node_gid, gid, gids, 4803 4804 r->af = af; 4805 /* for link-local IPv6 address, interface must match up */ 4806 if ((r->af && src_host->af && r->af != src_host->af) || 4807 (r->af && dst_host->af && r->af != dst_host->af) || 4808 (src_host->af && dst_host->af && 4809 src_host->af != dst_host->af) || 4810 (src_host->ifindex && dst_host->ifindex && 4811 src_host->ifindex != dst_host->ifindex) || 4812 (src_host->ifindex && *interface->ifname && 4813 src_host->ifindex != if_nametoindex(interface->ifname)) || 4814 (dst_host->ifindex && *interface->ifname && 4815 dst_host->ifindex != if_nametoindex(interface->ifname))) 4816 continue; 4817 if (!r->af && src_host->af) 4818 r->af = src_host->af; 4819 else if (!r->af && dst_host->af) 4820 r->af = dst_host->af; 4821 4822 if (*interface->ifname) 4823 strlcpy(r->ifname, interface->ifname, 4824 sizeof(r->ifname)); 4825 else if (if_indextoname(src_host->ifindex, ifname)) 4826 strlcpy(r->ifname, ifname, sizeof(r->ifname)); 4827 else if (if_indextoname(dst_host->ifindex, ifname)) 4828 strlcpy(r->ifname, ifname, sizeof(r->ifname)); 4829 else 4830 memset(r->ifname, '\0', sizeof(r->ifname)); 4831 4832 if (strlcpy(r->label, label, sizeof(r->label)) >= 4833 sizeof(r->label)) 4834 errx(1, "expand_rule: strlcpy"); 4835 if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >= 4836 sizeof(r->tagname)) 4837 errx(1, "expand_rule: strlcpy"); 4838 if (strlcpy(r->match_tagname, match_tagname, 4839 sizeof(r->match_tagname)) >= sizeof(r->match_tagname)) 4840 errx(1, "expand_rule: strlcpy"); 4841 expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af, 4842 src_host, src_port, dst_host, dst_port, proto->proto); 4843 expand_label(r->tagname, PF_TAG_NAME_SIZE, r->ifname, r->af, 4844 src_host, src_port, dst_host, dst_port, proto->proto); 4845 expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r->ifname, 4846 r->af, src_host, src_port, dst_host, dst_port, 4847 proto->proto); 4848 4849 error += check_netmask(src_host, r->af); 4850 error += check_netmask(dst_host, r->af); 4851 4852 r->ifnot = interface->not; 4853 r->proto = proto->proto; 4854 r->src.addr = src_host->addr; 4855 r->src.neg = src_host->not; 4856 r->src.port[0] = src_port->port[0]; 4857 r->src.port[1] = src_port->port[1]; 4858 r->src.port_op = src_port->op; 4859 r->dst.addr = dst_host->addr; 4860 r->dst.neg = dst_host->not; 4861 r->dst.port[0] = dst_port->port[0]; 4862 r->dst.port[1] = dst_port->port[1]; 4863 r->dst.port_op = dst_port->op; 4864 r->uid.op = uid->op; 4865 r->uid.uid[0] = uid->uid[0]; 4866 r->uid.uid[1] = uid->uid[1]; 4867 r->gid.op = gid->op; 4868 r->gid.gid[0] = gid->gid[0]; 4869 r->gid.gid[1] = gid->gid[1]; 4870 r->type = icmp_type->type; 4871 r->code = icmp_type->code; 4872 4873 if ((keep_state == PF_STATE_MODULATE || 4874 keep_state == PF_STATE_SYNPROXY) && 4875 r->proto && r->proto != IPPROTO_TCP) 4876 r->keep_state = PF_STATE_NORMAL; 4877 else 4878 r->keep_state = keep_state; 4879 4880 if (r->proto && r->proto != IPPROTO_TCP) { 4881 r->flags = 0; 4882 r->flagset = 0; 4883 } else { 4884 r->flags = flags; 4885 r->flagset = flagset; 4886 } 4887 if (icmp_type->proto && r->proto != icmp_type->proto) { 4888 yyerror("icmp-type mismatch"); 4889 error++; 4890 } 4891 4892 if (src_os && src_os->os) { 4893 r->os_fingerprint = pfctl_get_fingerprint(src_os->os); 4894 if ((pf->opts & PF_OPT_VERBOSE2) && 4895 r->os_fingerprint == PF_OSFP_NOMATCH) 4896 fprintf(stderr, 4897 "warning: unknown '%s' OS fingerprint\n", 4898 src_os->os); 4899 } else { 4900 r->os_fingerprint = PF_OSFP_ANY; 4901 } 4902 4903 TAILQ_INIT(&r->rpool.list); 4904 for (h = rpool_hosts; h != NULL; h = h->next) { 4905 pa = calloc(1, sizeof(struct pf_pooladdr)); 4906 if (pa == NULL) 4907 err(1, "expand_rule: calloc"); 4908 pa->addr = h->addr; 4909 if (h->ifname != NULL) { 4910 if (strlcpy(pa->ifname, h->ifname, 4911 sizeof(pa->ifname)) >= 4912 sizeof(pa->ifname)) 4913 errx(1, "expand_rule: strlcpy"); 4914 } else 4915 pa->ifname[0] = 0; 4916 TAILQ_INSERT_TAIL(&r->rpool.list, pa, entries); 4917 } 4918 4919 if (rule_consistent(r, anchor_call[0]) < 0 || error) 4920 yyerror("skipping rule due to errors"); 4921 else { 4922 r->nr = pf->astack[pf->asd]->match++; 4923 pfctl_add_rule(pf, r, anchor_call); 4924 added++; 4925 } 4926 4927 )))))))))); 4928 4929 FREE_LIST(struct node_if, interfaces); 4930 FREE_LIST(struct node_proto, protos); 4931 FREE_LIST(struct node_host, src_hosts); 4932 FREE_LIST(struct node_port, src_ports); 4933 FREE_LIST(struct node_os, src_oses); 4934 FREE_LIST(struct node_host, dst_hosts); 4935 FREE_LIST(struct node_port, dst_ports); 4936 FREE_LIST(struct node_uid, uids); 4937 FREE_LIST(struct node_gid, gids); 4938 FREE_LIST(struct node_icmp, icmp_types); 4939 FREE_LIST(struct node_host, rpool_hosts); 4940 4941 if (!added) 4942 yyerror("rule expands to no valid combination"); 4943} 4944 4945int 4946expand_skip_interface(struct node_if *interfaces) 4947{ 4948 int errs = 0; 4949 4950 if (!interfaces || (!interfaces->next && !interfaces->not && 4951 !strcmp(interfaces->ifname, "none"))) { 4952 if (pf->opts & PF_OPT_VERBOSE) 4953 printf("set skip on none\n"); 4954 errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0); 4955 return (errs); 4956 } 4957 4958 if (pf->opts & PF_OPT_VERBOSE) 4959 printf("set skip on {"); 4960 LOOP_THROUGH(struct node_if, interface, interfaces, 4961 if (pf->opts & PF_OPT_VERBOSE) 4962 printf(" %s", interface->ifname); 4963 if (interface->not) { 4964 yyerror("skip on ! <interface> is not supported"); 4965 errs++; 4966 } else 4967 errs += pfctl_set_interface_flags(pf, 4968 interface->ifname, PFI_IFLAG_SKIP, 1); 4969 ); 4970 if (pf->opts & PF_OPT_VERBOSE) 4971 printf(" }\n"); 4972 4973 FREE_LIST(struct node_if, interfaces); 4974 4975 if (errs) 4976 return (1); 4977 else 4978 return (0); 4979} 4980 4981#undef FREE_LIST 4982#undef LOOP_THROUGH 4983 4984int 4985check_rulestate(int desired_state) 4986{ 4987 if (require_order && (rulestate > desired_state)) { 4988 yyerror("Rules must be in order: options, normalization, " 4989 "queueing, translation, filtering"); 4990 return (1); 4991 } 4992 rulestate = desired_state; 4993 return (0); 4994} 4995 4996int 4997kw_cmp(const void *k, const void *e) 4998{ 4999 return (strcmp(k, ((const struct keywords *)e)->k_name)); 5000} 5001 5002int 5003lookup(char *s) 5004{ 5005 /* this has to be sorted always */ 5006 static const struct keywords keywords[] = { 5007 { "all", ALL}, 5008 { "allow-opts", ALLOWOPTS}, 5009 { "altq", ALTQ}, 5010 { "anchor", ANCHOR}, 5011 { "antispoof", ANTISPOOF}, 5012 { "any", ANY}, 5013 { "bandwidth", BANDWIDTH}, 5014 { "binat", BINAT}, 5015 { "binat-anchor", BINATANCHOR}, 5016 { "bitmask", BITMASK}, 5017 { "block", BLOCK}, 5018 { "block-policy", BLOCKPOLICY}, 5019 { "cbq", CBQ}, 5020 { "code", CODE}, 5021 { "crop", FRAGCROP}, 5022 { "debug", DEBUG}, 5023 { "drop", DROP}, 5024 { "drop-ovl", FRAGDROP}, 5025 { "dup-to", DUPTO}, 5026 { "fastroute", FASTROUTE}, 5027 { "file", FILENAME}, 5028 { "fingerprints", FINGERPRINTS}, 5029 { "flags", FLAGS}, 5030 { "floating", FLOATING}, 5031 { "flush", FLUSH}, 5032 { "for", FOR}, 5033 { "fragment", FRAGMENT}, 5034 { "from", FROM}, 5035 { "global", GLOBAL}, 5036 { "group", GROUP}, 5037 { "hfsc", HFSC}, 5038 { "hostid", HOSTID}, 5039 { "icmp-type", ICMPTYPE}, 5040 { "icmp6-type", ICMP6TYPE}, 5041 { "if-bound", IFBOUND}, 5042 { "in", IN}, 5043 { "inet", INET}, 5044 { "inet6", INET6}, 5045 { "keep", KEEP}, 5046 { "label", LABEL}, 5047 { "limit", LIMIT}, 5048 { "linkshare", LINKSHARE}, 5049 { "load", LOAD}, 5050 { "log", LOG}, 5051 { "loginterface", LOGINTERFACE}, 5052 { "max", MAXIMUM}, 5053 { "max-mss", MAXMSS}, 5054 { "max-src-conn", MAXSRCCONN}, 5055 { "max-src-conn-rate", MAXSRCCONNRATE}, 5056 { "max-src-nodes", MAXSRCNODES}, 5057 { "max-src-states", MAXSRCSTATES}, 5058 { "min-ttl", MINTTL}, 5059 { "modulate", MODULATE}, 5060 { "nat", NAT}, 5061 { "nat-anchor", NATANCHOR}, 5062 { "no", NO}, 5063 { "no-df", NODF}, 5064 { "no-route", NOROUTE}, 5065 { "no-sync", NOSYNC}, 5066 { "on", ON}, 5067 { "optimization", OPTIMIZATION}, 5068 { "os", OS}, 5069 { "out", OUT}, 5070 { "overload", OVERLOAD}, 5071 { "pass", PASS}, 5072 { "port", PORT}, 5073 { "priority", PRIORITY}, 5074 { "priq", PRIQ}, 5075 { "probability", PROBABILITY}, 5076 { "proto", PROTO}, 5077 { "qlimit", QLIMIT}, 5078 { "queue", QUEUE}, 5079 { "quick", QUICK}, 5080 { "random", RANDOM}, 5081 { "random-id", RANDOMID}, 5082 { "rdr", RDR}, 5083 { "rdr-anchor", RDRANCHOR}, 5084 { "realtime", REALTIME}, 5085 { "reassemble", REASSEMBLE}, 5086 { "reply-to", REPLYTO}, 5087 { "require-order", REQUIREORDER}, 5088 { "return", RETURN}, 5089 { "return-icmp", RETURNICMP}, 5090 { "return-icmp6", RETURNICMP6}, 5091 { "return-rst", RETURNRST}, 5092 { "round-robin", ROUNDROBIN}, 5093 { "route", ROUTE}, 5094 { "route-to", ROUTETO}, 5095 { "rtable", RTABLE}, 5096 { "rule", RULE}, 5097 { "ruleset-optimization", RULESET_OPTIMIZATION}, 5098 { "scrub", SCRUB}, 5099 { "set", SET}, 5100 { "skip", SKIP}, 5101 { "source-hash", SOURCEHASH}, 5102 { "source-track", SOURCETRACK}, 5103 { "state", STATE}, 5104 { "state-policy", STATEPOLICY}, 5105 { "static-port", STATICPORT}, 5106 { "sticky-address", STICKYADDRESS}, 5107 { "synproxy", SYNPROXY}, 5108 { "table", TABLE}, 5109 { "tag", TAG}, 5110 { "tagged", TAGGED}, 5111 { "tbrsize", TBRSIZE}, 5112 { "timeout", TIMEOUT}, 5113 { "to", TO}, 5114 { "tos", TOS}, 5115 { "ttl", TTL}, 5116 { "upperlimit", UPPERLIMIT}, 5117 { "urpf-failed", URPFFAILED}, 5118 { "user", USER}, 5119 }; 5120 const struct keywords *p; 5121 5122 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 5123 sizeof(keywords[0]), kw_cmp); 5124 5125 if (p) { 5126 if (debug > 1) 5127 fprintf(stderr, "%s: %d\n", s, p->k_val); 5128 return (p->k_val); 5129 } else { 5130 if (debug > 1) 5131 fprintf(stderr, "string: %s\n", s); 5132 return (STRING); 5133 } 5134} 5135 5136#define MAXPUSHBACK 128 5137 5138char *parsebuf; 5139int parseindex; 5140char pushback_buffer[MAXPUSHBACK]; 5141int pushback_index = 0; 5142 5143int 5144lgetc(FILE *f) 5145{ 5146 int c, next; 5147 5148 if (parsebuf) { 5149 /* Read character from the parsebuffer instead of input. */ 5150 if (parseindex >= 0) { 5151 c = parsebuf[parseindex++]; 5152 if (c != '\0') 5153 return (c); 5154 parsebuf = NULL; 5155 } else 5156 parseindex++; 5157 } 5158 5159 if (pushback_index) 5160 return (pushback_buffer[--pushback_index]); 5161 5162 while ((c = getc(f)) == '\\') { 5163 next = getc(f); 5164 if (next != '\n') { 5165 c = next; 5166 break; 5167 } 5168 yylval.lineno = lineno; 5169 lineno++; 5170 } 5171 if (c == '\t' || c == ' ') { 5172 /* Compress blanks to a single space. */ 5173 do { 5174 c = getc(f); 5175 } while (c == '\t' || c == ' '); 5176 ungetc(c, f); 5177 c = ' '; 5178 } 5179 5180 return (c); 5181} 5182 5183int 5184lungetc(int c) 5185{ 5186 if (c == EOF) 5187 return (EOF); 5188 if (parsebuf) { 5189 parseindex--; 5190 if (parseindex >= 0) 5191 return (c); 5192 } 5193 if (pushback_index < MAXPUSHBACK-1) 5194 return (pushback_buffer[pushback_index++] = c); 5195 else 5196 return (EOF); 5197} 5198 5199int 5200findeol(void) 5201{ 5202 int c; 5203 5204 parsebuf = NULL; 5205 pushback_index = 0; 5206 5207 /* skip to either EOF or the first real EOL */ 5208 while (1) { 5209 c = lgetc(fin); 5210 if (c == '\n') { 5211 lineno++; 5212 break; 5213 } 5214 if (c == EOF) 5215 break; 5216 } 5217 return (ERROR); 5218} 5219 5220int 5221yylex(void) 5222{ 5223 char buf[8096]; 5224 char *p, *val; 5225 int endc, c, next; 5226 int token; 5227 5228top: 5229 p = buf; 5230 while ((c = lgetc(fin)) == ' ') 5231 ; /* nothing */ 5232 5233 yylval.lineno = lineno; 5234 if (c == '#') 5235 while ((c = lgetc(fin)) != '\n' && c != EOF) 5236 ; /* nothing */ 5237 if (c == '$' && parsebuf == NULL) { 5238 while (1) { 5239 if ((c = lgetc(fin)) == EOF) 5240 return (0); 5241 5242 if (p + 1 >= buf + sizeof(buf) - 1) { 5243 yyerror("string too long"); 5244 return (findeol()); 5245 } 5246 if (isalnum(c) || c == '_') { 5247 *p++ = (char)c; 5248 continue; 5249 } 5250 *p = '\0'; 5251 lungetc(c); 5252 break; 5253 } 5254 val = symget(buf); 5255 if (val == NULL) { 5256 yyerror("macro '%s' not defined", buf); 5257 return (findeol()); 5258 } 5259 parsebuf = val; 5260 parseindex = 0; 5261 goto top; 5262 } 5263 5264 switch (c) { 5265 case '\'': 5266 case '"': 5267 endc = c; 5268 while (1) { 5269 if ((c = lgetc(fin)) == EOF) 5270 return (0); 5271 if (c == endc) { 5272 *p = '\0'; 5273 break; 5274 } 5275 if (c == '\n') { 5276 lineno++; 5277 continue; 5278 } 5279 if (p + 1 >= buf + sizeof(buf) - 1) { 5280 yyerror("string too long"); 5281 return (findeol()); 5282 } 5283 *p++ = (char)c; 5284 } 5285 yylval.v.string = strdup(buf); 5286 if (yylval.v.string == NULL) 5287 err(1, "yylex: strdup"); 5288 return (STRING); 5289 case '<': 5290 next = lgetc(fin); 5291 if (next == '>') { 5292 yylval.v.i = PF_OP_XRG; 5293 return (PORTBINARY); 5294 } 5295 lungetc(next); 5296 break; 5297 case '>': 5298 next = lgetc(fin); 5299 if (next == '<') { 5300 yylval.v.i = PF_OP_IRG; 5301 return (PORTBINARY); 5302 } 5303 lungetc(next); 5304 break; 5305 case '-': 5306 next = lgetc(fin); 5307 if (next == '>') 5308 return (ARROW); 5309 lungetc(next); 5310 break; 5311 } 5312 5313#define allowed_to_end_number(x) \ 5314 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}') 5315 5316 if (c == '-' || isdigit(c)) { 5317 do { 5318 *p++ = c; 5319 if ((unsigned)(p-buf) >= sizeof(buf)) { 5320 yyerror("string too long"); 5321 return (findeol()); 5322 } 5323 } while ((c = lgetc(fin)) != EOF && isdigit(c)); 5324 lungetc(c); 5325 5326 if (p == buf + 1 && buf[0] == '-') 5327 goto nodigits; 5328 if (c == EOF || allowed_to_end_number(c)) { 5329 const char *errstr = NULL; 5330 5331 *p = '\0'; 5332 yylval.v.number = strtonum(buf, LLONG_MIN, 5333 LLONG_MAX, &errstr); 5334 if (errstr) { 5335 yyerror("\"%s\" invalid number: %s", 5336 buf, errstr); 5337 return (findeol()); 5338 } 5339 return (NUMBER); 5340 } else { 5341nodigits: 5342 while (p > buf + 1) 5343 lungetc(*--p); 5344 c = *--p; 5345 if (c == '-') 5346 return (c); 5347 } 5348 } 5349 5350#define allowed_in_string(x) \ 5351 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 5352 x != '{' && x != '}' && x != '<' && x != '>' && \ 5353 x != '!' && x != '=' && x != '/' && x != '#' && \ 5354 x != ',')) 5355 5356 if (isalnum(c) || c == ':' || c == '_') { 5357 do { 5358 *p++ = c; 5359 if ((unsigned)(p-buf) >= sizeof(buf)) { 5360 yyerror("string too long"); 5361 return (findeol()); 5362 } 5363 } while ((c = lgetc(fin)) != EOF && (allowed_in_string(c))); 5364 lungetc(c); 5365 *p = '\0'; 5366 if ((token = lookup(buf)) == STRING) 5367 if ((yylval.v.string = strdup(buf)) == NULL) 5368 err(1, "yylex: strdup"); 5369 return (token); 5370 } 5371 if (c == '\n') { 5372 yylval.lineno = lineno; 5373 lineno++; 5374 } 5375 if (c == EOF) 5376 return (0); 5377 return (c); 5378} 5379 5380int 5381parse_rules(FILE *input, struct pfctl *xpf) 5382{ 5383 struct sym *sym, *next; 5384 5385 fin = input; 5386 pf = xpf; 5387 lineno = 1; 5388 errors = 0; 5389 rulestate = PFCTL_STATE_NONE; 5390 returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 5391 returnicmp6default = 5392 (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT; 5393 blockpolicy = PFRULE_DROP; 5394 require_order = 1; 5395 5396 yyparse(); 5397 5398 /* Free macros and check which have not been used. */ 5399 for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) { 5400 next = TAILQ_NEXT(sym, entries); 5401 if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used) 5402 fprintf(stderr, "warning: macro '%s' not " 5403 "used\n", sym->nam); 5404 free(sym->nam); 5405 free(sym->val); 5406 TAILQ_REMOVE(&symhead, sym, entries); 5407 free(sym); 5408 } 5409 5410 return (errors ? -1 : 0); 5411} 5412 5413/* 5414 * Over-designed efficiency is a French and German concept, so how about 5415 * we wait until they discover this ugliness and make it all fancy. 5416 */ 5417int 5418symset(const char *nam, const char *val, int persist) 5419{ 5420 struct sym *sym; 5421 5422 for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam); 5423 sym = TAILQ_NEXT(sym, entries)) 5424 ; /* nothing */ 5425 5426 if (sym != NULL) { 5427 if (sym->persist == 1) 5428 return (0); 5429 else { 5430 free(sym->nam); 5431 free(sym->val); 5432 TAILQ_REMOVE(&symhead, sym, entries); 5433 free(sym); 5434 } 5435 } 5436 if ((sym = calloc(1, sizeof(*sym))) == NULL) 5437 return (-1); 5438 5439 sym->nam = strdup(nam); 5440 if (sym->nam == NULL) { 5441 free(sym); 5442 return (-1); 5443 } 5444 sym->val = strdup(val); 5445 if (sym->val == NULL) { 5446 free(sym->nam); 5447 free(sym); 5448 return (-1); 5449 } 5450 sym->used = 0; 5451 sym->persist = persist; 5452 TAILQ_INSERT_TAIL(&symhead, sym, entries); 5453 return (0); 5454} 5455 5456int 5457pfctl_cmdline_symset(char *s) 5458{ 5459 char *sym, *val; 5460 int ret; 5461 5462 if ((val = strrchr(s, '=')) == NULL) 5463 return (-1); 5464 5465 if ((sym = malloc(strlen(s) - strlen(val) + 1)) == NULL) 5466 err(1, "pfctl_cmdline_symset: malloc"); 5467 5468 strlcpy(sym, s, strlen(s) - strlen(val) + 1); 5469 5470 ret = symset(sym, val + 1, 1); 5471 free(sym); 5472 5473 return (ret); 5474} 5475 5476char * 5477symget(const char *nam) 5478{ 5479 struct sym *sym; 5480 5481 TAILQ_FOREACH(sym, &symhead, entries) 5482 if (strcmp(nam, sym->nam) == 0) { 5483 sym->used = 1; 5484 return (sym->val); 5485 } 5486 return (NULL); 5487} 5488 5489void 5490mv_rules(struct pf_ruleset *src, struct pf_ruleset *dst) 5491{ 5492 int i; 5493 struct pf_rule *r; 5494 5495 for (i = 0; i < PF_RULESET_MAX; ++i) { 5496 while ((r = TAILQ_FIRST(src->rules[i].active.ptr)) 5497 != NULL) { 5498 TAILQ_REMOVE(src->rules[i].active.ptr, r, entries); 5499 TAILQ_INSERT_TAIL(dst->rules[i].active.ptr, r, entries); 5500 dst->anchor->match++; 5501 } 5502 src->anchor->match = 0; 5503 while ((r = TAILQ_FIRST(src->rules[i].inactive.ptr)) 5504 != NULL) { 5505 TAILQ_REMOVE(src->rules[i].inactive.ptr, r, entries); 5506 TAILQ_INSERT_TAIL(dst->rules[i].inactive.ptr, 5507 r, entries); 5508 } 5509 } 5510} 5511 5512void 5513decide_address_family(struct node_host *n, sa_family_t *af) 5514{ 5515 if (*af != 0 || n == NULL) 5516 return; 5517 *af = n->af; 5518 while ((n = n->next) != NULL) { 5519 if (n->af != *af) { 5520 *af = 0; 5521 return; 5522 } 5523 } 5524} 5525 5526void 5527remove_invalid_hosts(struct node_host **nh, sa_family_t *af) 5528{ 5529 struct node_host *n = *nh, *prev = NULL; 5530 5531 while (n != NULL) { 5532 if (*af && n->af && n->af != *af) { 5533 /* unlink and free n */ 5534 struct node_host *next = n->next; 5535 5536 /* adjust tail pointer */ 5537 if (n == (*nh)->tail) 5538 (*nh)->tail = prev; 5539 /* adjust previous node's next pointer */ 5540 if (prev == NULL) 5541 *nh = next; 5542 else 5543 prev->next = next; 5544 /* free node */ 5545 if (n->ifname != NULL) 5546 free(n->ifname); 5547 free(n); 5548 n = next; 5549 } else { 5550 if (n->af && !*af) 5551 *af = n->af; 5552 prev = n; 5553 n = n->next; 5554 } 5555 } 5556} 5557 5558int 5559invalid_redirect(struct node_host *nh, sa_family_t af) 5560{ 5561 if (!af) { 5562 struct node_host *n; 5563 5564 /* tables and dyniftl are ok without an address family */ 5565 for (n = nh; n != NULL; n = n->next) { 5566 if (n->addr.type != PF_ADDR_TABLE && 5567 n->addr.type != PF_ADDR_DYNIFTL) { 5568 yyerror("address family not given and " 5569 "translation address expands to multiple " 5570 "address families"); 5571 return (1); 5572 } 5573 } 5574 } 5575 if (nh == NULL) { 5576 yyerror("no translation address with matching address family " 5577 "found."); 5578 return (1); 5579 } 5580 return (0); 5581} 5582 5583int 5584atoul(char *s, u_long *ulvalp) 5585{ 5586 u_long ulval; 5587 char *ep; 5588 5589 errno = 0; 5590 ulval = strtoul(s, &ep, 0); 5591 if (s[0] == '\0' || *ep != '\0') 5592 return (-1); 5593 if (errno == ERANGE && ulval == ULONG_MAX) 5594 return (-1); 5595 *ulvalp = ulval; 5596 return (0); 5597} 5598 5599int 5600getservice(char *n) 5601{ 5602 struct servent *s; 5603 u_long ulval; 5604 5605 if (atoul(n, &ulval) == 0) { 5606 if (ulval > 65535) { 5607 yyerror("illegal port value %lu", ulval); 5608 return (-1); 5609 } 5610 return (htons(ulval)); 5611 } else { 5612 s = getservbyname(n, "tcp"); 5613 if (s == NULL) 5614 s = getservbyname(n, "udp"); 5615 if (s == NULL) { 5616 yyerror("unknown port %s", n); 5617 return (-1); 5618 } 5619 return (s->s_port); 5620 } 5621} 5622 5623int 5624rule_label(struct pf_rule *r, char *s) 5625{ 5626 if (s) { 5627 if (strlcpy(r->label, s, sizeof(r->label)) >= 5628 sizeof(r->label)) { 5629 yyerror("rule label too long (max %d chars)", 5630 sizeof(r->label)-1); 5631 return (-1); 5632 } 5633 } 5634 return (0); 5635} 5636 5637u_int16_t 5638parseicmpspec(char *w, sa_family_t af) 5639{ 5640 const struct icmpcodeent *p; 5641 u_long ulval; 5642 u_int8_t icmptype; 5643 5644 if (af == AF_INET) 5645 icmptype = returnicmpdefault >> 8; 5646 else 5647 icmptype = returnicmp6default >> 8; 5648 5649 if (atoul(w, &ulval) == -1) { 5650 if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) { 5651 yyerror("unknown icmp code %s", w); 5652 return (0); 5653 } 5654 ulval = p->code; 5655 } 5656 if (ulval > 255) { 5657 yyerror("invalid icmp code %lu", ulval); 5658 return (0); 5659 } 5660 return (icmptype << 8 | ulval); 5661} 5662 5663int 5664pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans) 5665{ 5666 struct loadanchors *la; 5667 FILE *fin; 5668 5669 TAILQ_FOREACH(la, &loadanchorshead, entries) { 5670 if (pf->opts & PF_OPT_VERBOSE) 5671 fprintf(stderr, "\nLoading anchor %s from %s\n", 5672 la->anchorname, la->filename); 5673 if ((fin = pfctl_fopen(la->filename, "r")) == NULL) { 5674 warn("%s", la->filename); 5675 continue; 5676 } 5677 if (pfctl_rules(dev, la->filename, fin, pf->opts, pf->optimize, 5678 la->anchorname, trans) == -1) 5679 return (-1); 5680 } 5681 5682 return (0); 5683} 5684