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