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