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