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