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