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