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