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