parse.y revision 1.666
1/* $OpenBSD: parse.y,v 1.666 2017/11/25 22:26:25 sashan 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}; 215 216struct redirspec { 217 struct redirection *rdr; 218 struct pool_opts pool_opts; 219 int binat; 220 int af; 221}; 222 223struct filter_opts { 224 int marker; 225#define FOM_FLAGS 0x0001 226#define FOM_ICMP 0x0002 227#define FOM_TOS 0x0004 228#define FOM_KEEP 0x0008 229#define FOM_SRCTRACK 0x0010 230#define FOM_MINTTL 0x0020 231#define FOM_MAXMSS 0x0040 232#define FOM_AFTO 0x0080 233#define FOM_SETTOS 0x0100 234#define FOM_SCRUB_TCP 0x0200 235#define FOM_SETPRIO 0x0400 236#define FOM_ONCE 0x1000 237#define FOM_PRIO 0x2000 238 struct node_uid *uid; 239 struct node_gid *gid; 240 struct node_if *rcv; 241 struct { 242 u_int8_t b1; 243 u_int8_t b2; 244 u_int16_t w; 245 u_int16_t w2; 246 } flags; 247 struct node_icmp *icmpspec; 248 u_int32_t tos; 249 u_int32_t prob; 250 struct { 251 int action; 252 struct node_state_opt *options; 253 } keep; 254 int fragment; 255 int allowopts; 256 char *label; 257 struct node_qassign queues; 258 char *tag; 259 char *match_tag; 260 u_int8_t match_tag_not; 261 u_int rtableid; 262 u_int8_t prio; 263 u_int8_t set_prio[2]; 264 struct divertspec divert; 265 struct divertspec divert_packet; 266 struct redirspec nat; 267 struct redirspec rdr; 268 struct redirspec rroute; 269 270 /* scrub opts */ 271 int nodf; 272 int minttl; 273 int settos; 274 int randomid; 275 int max_mss; 276 277 /* route opts */ 278 struct { 279 struct node_host *host; 280 u_int8_t rt; 281 u_int8_t pool_opts; 282 sa_family_t af; 283 struct pf_poolhashkey *key; 284 } route; 285 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 r.divert_packet.port = $8.divert_packet.port; 1917 1918 expand_rule(&r, 0, $4, &$8.nat, &$8.rdr, &$8.rroute, $6, 1919 $7.src_os, 1920 $7.src.host, $7.src.port, $7.dst.host, $7.dst.port, 1921 $8.uid, $8.gid, $8.rcv, $8.icmpspec, ""); 1922 } 1923 ; 1924 1925filter_opts : { 1926 bzero(&filter_opts, sizeof filter_opts); 1927 filter_opts.rtableid = -1; 1928 } 1929 filter_opts_l 1930 { $$ = filter_opts; } 1931 | /* empty */ { 1932 bzero(&filter_opts, sizeof filter_opts); 1933 filter_opts.rtableid = -1; 1934 $$ = filter_opts; 1935 } 1936 ; 1937 1938filter_opts_l : filter_opts_l filter_opt 1939 | filter_opt 1940 ; 1941 1942filter_opt : USER uids { 1943 if (filter_opts.uid) 1944 $2->tail->next = filter_opts.uid; 1945 filter_opts.uid = $2; 1946 } 1947 | GROUP gids { 1948 if (filter_opts.gid) 1949 $2->tail->next = filter_opts.gid; 1950 filter_opts.gid = $2; 1951 } 1952 | flags { 1953 if (filter_opts.marker & FOM_FLAGS) { 1954 yyerror("flags cannot be redefined"); 1955 YYERROR; 1956 } 1957 filter_opts.marker |= FOM_FLAGS; 1958 filter_opts.flags.b1 |= $1.b1; 1959 filter_opts.flags.b2 |= $1.b2; 1960 filter_opts.flags.w |= $1.w; 1961 filter_opts.flags.w2 |= $1.w2; 1962 } 1963 | icmpspec { 1964 if (filter_opts.marker & FOM_ICMP) { 1965 yyerror("icmp-type cannot be redefined"); 1966 YYERROR; 1967 } 1968 filter_opts.marker |= FOM_ICMP; 1969 filter_opts.icmpspec = $1; 1970 } 1971 | PRIO NUMBER { 1972 if (filter_opts.marker & FOM_PRIO) { 1973 yyerror("prio cannot be redefined"); 1974 YYERROR; 1975 } 1976 if ($2 < 0 || $2 > IFQ_MAXPRIO) { 1977 yyerror("prio must be 0 - %u", IFQ_MAXPRIO); 1978 YYERROR; 1979 } 1980 filter_opts.marker |= FOM_PRIO; 1981 filter_opts.prio = $2; 1982 } 1983 | TOS tos { 1984 if (filter_opts.marker & FOM_TOS) { 1985 yyerror("tos cannot be redefined"); 1986 YYERROR; 1987 } 1988 filter_opts.marker |= FOM_TOS; 1989 filter_opts.tos = $2; 1990 } 1991 | keep { 1992 if (filter_opts.marker & FOM_KEEP) { 1993 yyerror("modulate or keep cannot be redefined"); 1994 YYERROR; 1995 } 1996 filter_opts.marker |= FOM_KEEP; 1997 filter_opts.keep.action = $1.action; 1998 filter_opts.keep.options = $1.options; 1999 } 2000 | FRAGMENT { 2001 filter_opts.fragment = 1; 2002 } 2003 | ALLOWOPTS { 2004 filter_opts.allowopts = 1; 2005 } 2006 | LABEL label { 2007 if (filter_opts.label) { 2008 yyerror("label cannot be redefined"); 2009 YYERROR; 2010 } 2011 filter_opts.label = $2; 2012 } 2013 | QUEUE qname { 2014 if (filter_opts.queues.qname) { 2015 yyerror("queue cannot be redefined"); 2016 YYERROR; 2017 } 2018 filter_opts.queues = $2; 2019 } 2020 | TAG string { 2021 filter_opts.tag = $2; 2022 } 2023 | not TAGGED string { 2024 filter_opts.match_tag = $3; 2025 filter_opts.match_tag_not = $1; 2026 } 2027 | PROBABILITY probability { 2028 double p; 2029 2030 p = floor($2 * UINT_MAX + 0.5); 2031 if (p < 0.0 || p > UINT_MAX) { 2032 yyerror("invalid probability: %g%%", $2 * 100); 2033 YYERROR; 2034 } 2035 filter_opts.prob = (u_int32_t)p; 2036 if (filter_opts.prob == 0) 2037 filter_opts.prob = 1; 2038 } 2039 | RTABLE NUMBER { 2040 if ($2 < 0 || $2 > RT_TABLEID_MAX) { 2041 yyerror("invalid rtable id"); 2042 YYERROR; 2043 } 2044 filter_opts.rtableid = $2; 2045 } 2046 | DIVERTTO STRING PORT portplain { 2047 if ((filter_opts.divert.addr = host($2, pf->opts)) == NULL) { 2048 yyerror("could not parse divert address: %s", 2049 $2); 2050 free($2); 2051 YYERROR; 2052 } 2053 free($2); 2054 filter_opts.divert.port = $4.a; 2055 if (!filter_opts.divert.port) { 2056 yyerror("invalid divert port: %u", ntohs($4.a)); 2057 YYERROR; 2058 } 2059 } 2060 | DIVERTREPLY { 2061 filter_opts.divert.port = 1; /* some random value */ 2062 } 2063 | DIVERTPACKET PORT number { 2064 /* 2065 * If IP reassembly was not turned off, also 2066 * forcibly enable TCP reassembly by default. 2067 */ 2068 if (pf->reassemble & PF_REASS_ENABLED) 2069 filter_opts.marker |= FOM_SCRUB_TCP; 2070 2071 if ($3 < 1 || $3 > 65535) { 2072 yyerror("invalid divert port"); 2073 YYERROR; 2074 } 2075 2076 filter_opts.divert_packet.port = htons($3); 2077 } 2078 | SCRUB '(' scrub_opts ')' { 2079 filter_opts.nodf = $3.nodf; 2080 filter_opts.minttl = $3.minttl; 2081 filter_opts.randomid = $3.randomid; 2082 filter_opts.max_mss = $3.maxmss; 2083 if ($3.reassemble_tcp) 2084 filter_opts.marker |= FOM_SCRUB_TCP; 2085 filter_opts.marker |= $3.marker; 2086 } 2087 | NATTO redirpool pool_opts { 2088 if (filter_opts.nat.rdr) { 2089 yyerror("cannot respecify nat-to/binat-to"); 2090 YYERROR; 2091 } 2092 filter_opts.nat.rdr = $2; 2093 memcpy(&filter_opts.nat.pool_opts, &$3, 2094 sizeof(filter_opts.nat.pool_opts)); 2095 } 2096 | AFTO af FROM redirpool pool_opts { 2097 if (filter_opts.nat.rdr) { 2098 yyerror("cannot respecify af-to"); 2099 YYERROR; 2100 } 2101 if ($2 == 0) { 2102 yyerror("no target address family specified"); 2103 YYERROR; 2104 } 2105 filter_opts.nat.af = $2; 2106 filter_opts.nat.rdr = $4; 2107 memcpy(&filter_opts.nat.pool_opts, &$5, 2108 sizeof(filter_opts.nat.pool_opts)); 2109 filter_opts.rdr.rdr = 2110 calloc(1, sizeof(struct redirection)); 2111 bzero(&filter_opts.rdr.pool_opts, 2112 sizeof(filter_opts.rdr.pool_opts)); 2113 filter_opts.marker |= FOM_AFTO; 2114 } 2115 | AFTO af FROM redirpool pool_opts TO redirpool pool_opts { 2116 if (filter_opts.nat.rdr) { 2117 yyerror("cannot respecify af-to"); 2118 YYERROR; 2119 } 2120 if ($2 == 0) { 2121 yyerror("no address family specified"); 2122 YYERROR; 2123 } 2124 if (($4->host->af && $4->host->af != $2) || 2125 ($7->host->af && $7->host->af != $2)) { 2126 yyerror("af-to addresses must be in the " 2127 "target address family"); 2128 YYERROR; 2129 } 2130 filter_opts.nat.af = $2; 2131 filter_opts.nat.rdr = $4; 2132 memcpy(&filter_opts.nat.pool_opts, &$5, 2133 sizeof(filter_opts.nat.pool_opts)); 2134 filter_opts.rdr.af = $2; 2135 filter_opts.rdr.rdr = $7; 2136 memcpy(&filter_opts.nat.pool_opts, &$8, 2137 sizeof(filter_opts.nat.pool_opts)); 2138 filter_opts.marker |= FOM_AFTO; 2139 } 2140 | RDRTO redirpool pool_opts { 2141 if (filter_opts.rdr.rdr) { 2142 yyerror("cannot respecify rdr-to"); 2143 YYERROR; 2144 } 2145 filter_opts.rdr.rdr = $2; 2146 memcpy(&filter_opts.rdr.pool_opts, &$3, 2147 sizeof(filter_opts.rdr.pool_opts)); 2148 } 2149 | BINATTO redirpool pool_opts { 2150 if (filter_opts.nat.rdr) { 2151 yyerror("cannot respecify nat-to/binat-to"); 2152 YYERROR; 2153 } 2154 filter_opts.nat.rdr = $2; 2155 filter_opts.nat.binat = 1; 2156 memcpy(&filter_opts.nat.pool_opts, &$3, 2157 sizeof(filter_opts.nat.pool_opts)); 2158 filter_opts.nat.pool_opts.staticport = 1; 2159 } 2160 | ROUTETO routespec pool_opts { 2161 filter_opts.route.host = $2; 2162 filter_opts.route.rt = PF_ROUTETO; 2163 filter_opts.route.pool_opts = $3.type | $3.opts; 2164 memcpy(&filter_opts.rroute.pool_opts, &$3, 2165 sizeof(filter_opts.rroute.pool_opts)); 2166 if ($3.key != NULL) 2167 filter_opts.route.key = $3.key; 2168 } 2169 | REPLYTO routespec pool_opts { 2170 filter_opts.route.host = $2; 2171 filter_opts.route.rt = PF_REPLYTO; 2172 filter_opts.route.pool_opts = $3.type | $3.opts; 2173 if ($3.key != NULL) 2174 filter_opts.route.key = $3.key; 2175 } 2176 | DUPTO routespec pool_opts { 2177 filter_opts.route.host = $2; 2178 filter_opts.route.rt = PF_DUPTO; 2179 filter_opts.route.pool_opts = $3.type | $3.opts; 2180 memcpy(&filter_opts.rroute.pool_opts, &$3, 2181 sizeof(filter_opts.rroute.pool_opts)); 2182 if ($3.key != NULL) 2183 filter_opts.route.key = $3.key; 2184 } 2185 | not RECEIVEDON if_item { 2186 if (filter_opts.rcv) { 2187 yyerror("cannot respecify received-on"); 2188 YYERROR; 2189 } 2190 filter_opts.rcv = $3; 2191 filter_opts.rcv->not = $1; 2192 } 2193 | ONCE { 2194 filter_opts.marker |= FOM_ONCE; 2195 } 2196 | MAXPKTRATE NUMBER '/' NUMBER { 2197 if ($2 < 0 || $2 > UINT_MAX || 2198 $4 < 0 || $4 > UINT_MAX) { 2199 yyerror("only positive values permitted"); 2200 YYERROR; 2201 } 2202 if (filter_opts.pktrate.limit) { 2203 yyerror("cannot respecify max-pkt-rate"); 2204 YYERROR; 2205 } 2206 filter_opts.pktrate.limit = $2; 2207 filter_opts.pktrate.seconds = $4; 2208 } 2209 | filter_sets 2210 ; 2211 2212filter_sets : SET '(' filter_sets_l ')' { $$ = filter_opts; } 2213 | SET filter_set { $$ = filter_opts; } 2214 ; 2215 2216filter_sets_l : filter_sets_l comma filter_set 2217 | filter_set 2218 ; 2219 2220filter_set : prio { 2221 if (filter_opts.marker & FOM_SETPRIO) { 2222 yyerror("prio cannot be redefined"); 2223 YYERROR; 2224 } 2225 filter_opts.marker |= FOM_SETPRIO; 2226 filter_opts.set_prio[0] = $1.b1; 2227 filter_opts.set_prio[1] = $1.b2; 2228 } 2229 | QUEUE qname { 2230 if (filter_opts.queues.qname) { 2231 yyerror("queue cannot be redefined"); 2232 YYERROR; 2233 } 2234 filter_opts.queues = $2; 2235 } 2236 | TOS tos { 2237 if (filter_opts.marker & FOM_SETTOS) { 2238 yyerror("tos cannot be respecified"); 2239 YYERROR; 2240 } 2241 filter_opts.marker |= FOM_SETTOS; 2242 filter_opts.settos = $2; 2243 } 2244 ; 2245 2246prio : PRIO NUMBER { 2247 if ($2 < 0 || $2 > IFQ_MAXPRIO) { 2248 yyerror("prio must be 0 - %u", IFQ_MAXPRIO); 2249 YYERROR; 2250 } 2251 $$.b1 = $$.b2 = $2; 2252 } 2253 | PRIO '(' NUMBER comma NUMBER ')' { 2254 if ($3 < 0 || $3 > IFQ_MAXPRIO || 2255 $5 < 0 || $5 > IFQ_MAXPRIO) { 2256 yyerror("prio must be 0 - %u", IFQ_MAXPRIO); 2257 YYERROR; 2258 } 2259 $$.b1 = $3; 2260 $$.b2 = $5; 2261 } 2262 ; 2263 2264probability : STRING { 2265 char *e; 2266 double p = strtod($1, &e); 2267 2268 if (*e == '%') { 2269 p *= 0.01; 2270 e++; 2271 } 2272 if (*e) { 2273 yyerror("invalid probability: %s", $1); 2274 free($1); 2275 YYERROR; 2276 } 2277 free($1); 2278 $$ = p; 2279 } 2280 | NUMBER { 2281 $$ = (double)$1; 2282 } 2283 ; 2284 2285 2286action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; } 2287 | MATCH { $$.b1 = PF_MATCH; $$.b2 = $$.w = 0; } 2288 | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } 2289 ; 2290 2291blockspec : /* empty */ { 2292 $$.b2 = blockpolicy; 2293 $$.w = returnicmpdefault; 2294 $$.w2 = returnicmp6default; 2295 } 2296 | DROP { 2297 $$.b2 = PFRULE_DROP; 2298 $$.w = 0; 2299 $$.w2 = 0; 2300 } 2301 | RETURNRST { 2302 $$.b2 = PFRULE_RETURNRST; 2303 $$.w = 0; 2304 $$.w2 = 0; 2305 } 2306 | RETURNRST '(' TTL NUMBER ')' { 2307 if ($4 < 0 || $4 > 255) { 2308 yyerror("illegal ttl value %d", $4); 2309 YYERROR; 2310 } 2311 $$.b2 = PFRULE_RETURNRST; 2312 $$.w = $4; 2313 $$.w2 = 0; 2314 } 2315 | RETURNICMP { 2316 $$.b2 = PFRULE_RETURNICMP; 2317 $$.w = returnicmpdefault; 2318 $$.w2 = returnicmp6default; 2319 } 2320 | RETURNICMP6 { 2321 $$.b2 = PFRULE_RETURNICMP; 2322 $$.w = returnicmpdefault; 2323 $$.w2 = returnicmp6default; 2324 } 2325 | RETURNICMP '(' reticmpspec ')' { 2326 $$.b2 = PFRULE_RETURNICMP; 2327 $$.w = $3; 2328 $$.w2 = returnicmpdefault; 2329 } 2330 | RETURNICMP6 '(' reticmp6spec ')' { 2331 $$.b2 = PFRULE_RETURNICMP; 2332 $$.w = returnicmpdefault; 2333 $$.w2 = $3; 2334 } 2335 | RETURNICMP '(' reticmpspec comma reticmp6spec ')' { 2336 $$.b2 = PFRULE_RETURNICMP; 2337 $$.w = $3; 2338 $$.w2 = $5; 2339 } 2340 | RETURN { 2341 $$.b2 = PFRULE_RETURN; 2342 $$.w = returnicmpdefault; 2343 $$.w2 = returnicmp6default; 2344 } 2345 ; 2346 2347reticmpspec : STRING { 2348 if (!($$ = parseicmpspec($1, AF_INET))) { 2349 free($1); 2350 YYERROR; 2351 } 2352 free($1); 2353 } 2354 | NUMBER { 2355 u_int8_t icmptype; 2356 2357 if ($1 < 0 || $1 > 255) { 2358 yyerror("invalid icmp code %lu", $1); 2359 YYERROR; 2360 } 2361 icmptype = returnicmpdefault >> 8; 2362 $$ = (icmptype << 8 | $1); 2363 } 2364 ; 2365 2366reticmp6spec : STRING { 2367 if (!($$ = parseicmpspec($1, AF_INET6))) { 2368 free($1); 2369 YYERROR; 2370 } 2371 free($1); 2372 } 2373 | NUMBER { 2374 u_int8_t icmptype; 2375 2376 if ($1 < 0 || $1 > 255) { 2377 yyerror("invalid icmp code %lu", $1); 2378 YYERROR; 2379 } 2380 icmptype = returnicmp6default >> 8; 2381 $$ = (icmptype << 8 | $1); 2382 } 2383 ; 2384 2385dir : /* empty */ { $$ = PF_INOUT; } 2386 | IN { $$ = PF_IN; } 2387 | OUT { $$ = PF_OUT; } 2388 ; 2389 2390quick : /* empty */ { $$.quick = 0; } 2391 | QUICK { $$.quick = 1; } 2392 ; 2393 2394logquick : /* empty */ { $$.log = 0; $$.quick = 0; $$.logif = 0; } 2395 | log { $$ = $1; $$.quick = 0; } 2396 | QUICK { $$.quick = 1; $$.log = 0; $$.logif = 0; } 2397 | log QUICK { $$ = $1; $$.quick = 1; } 2398 | QUICK log { $$ = $2; $$.quick = 1; } 2399 ; 2400 2401log : LOG { $$.log = PF_LOG; $$.logif = 0; } 2402 | LOG '(' logopts ')' { 2403 $$.log = PF_LOG | $3.log; 2404 $$.logif = $3.logif; 2405 } 2406 ; 2407 2408logopts : logopt { $$ = $1; } 2409 | logopts comma logopt { 2410 $$.log = $1.log | $3.log; 2411 $$.logif = $3.logif; 2412 if ($$.logif == 0) 2413 $$.logif = $1.logif; 2414 } 2415 ; 2416 2417logopt : ALL { $$.log = PF_LOG_ALL; $$.logif = 0; } 2418 | MATCHES { $$.log = PF_LOG_MATCHES; $$.logif = 0; } 2419 | USER { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; } 2420 | GROUP { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; } 2421 | TO string { 2422 const char *errstr; 2423 u_int i; 2424 2425 $$.log = 0; 2426 if (strncmp($2, "pflog", 5)) { 2427 yyerror("%s: should be a pflog interface", $2); 2428 free($2); 2429 YYERROR; 2430 } 2431 i = strtonum($2 + 5, 0, 255, &errstr); 2432 if (errstr) { 2433 yyerror("%s: %s", $2, errstr); 2434 free($2); 2435 YYERROR; 2436 } 2437 free($2); 2438 $$.logif = i; 2439 } 2440 ; 2441 2442interface : /* empty */ { $$ = NULL; } 2443 | ON if_item_not { $$ = $2; } 2444 | ON '{' optnl if_list '}' { $$ = $4; } 2445 ; 2446 2447if_list : if_item_not optnl { $$ = $1; } 2448 | if_list comma if_item_not optnl { 2449 $1->tail->next = $3; 2450 $1->tail = $3; 2451 $$ = $1; 2452 } 2453 ; 2454 2455if_item_not : not if_item { $$ = $2; $$->not = $1; } 2456 ; 2457 2458if_item : STRING { 2459 struct node_host *n; 2460 2461 $$ = calloc(1, sizeof(struct node_if)); 2462 if ($$ == NULL) 2463 err(1, "if_item: calloc"); 2464 if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >= 2465 sizeof($$->ifname)) { 2466 free($1); 2467 free($$); 2468 yyerror("interface name too long"); 2469 YYERROR; 2470 } 2471 2472 if ((n = ifa_exists($1)) != NULL) 2473 $$->ifa_flags = n->ifa_flags; 2474 2475 free($1); 2476 $$->not = 0; 2477 $$->next = NULL; 2478 $$->tail = $$; 2479 } 2480 | ANY { 2481 $$ = calloc(1, sizeof(struct node_if)); 2482 if ($$ == NULL) 2483 err(1, "if_item: calloc"); 2484 strlcpy($$->ifname, "any", sizeof($$->ifname)); 2485 $$->not = 0; 2486 $$->next = NULL; 2487 $$->tail = $$; 2488 } 2489 | RDOMAIN NUMBER { 2490 if ($2 < 0 || $2 > RT_TABLEID_MAX) { 2491 yyerror("rdomain outside range"); 2492 YYERROR; 2493 } 2494 $$ = calloc(1, sizeof(struct node_if)); 2495 if ($$ == NULL) 2496 err(1, "if_item: calloc"); 2497 $$->not = 0; 2498 $$->use_rdomain = 1; 2499 $$->rdomain = $2; 2500 $$->next = NULL; 2501 $$->tail = $$; 2502 } 2503 ; 2504 2505af : /* empty */ { $$ = 0; } 2506 | INET { $$ = AF_INET; } 2507 | INET6 { $$ = AF_INET6; } 2508 ; 2509 2510proto : /* empty */ { $$ = NULL; } 2511 | PROTO proto_item { $$ = $2; } 2512 | PROTO '{' optnl proto_list '}' { $$ = $4; } 2513 ; 2514 2515proto_list : proto_item optnl { $$ = $1; } 2516 | proto_list comma proto_item optnl { 2517 $1->tail->next = $3; 2518 $1->tail = $3; 2519 $$ = $1; 2520 } 2521 ; 2522 2523proto_item : protoval { 2524 u_int8_t pr; 2525 2526 pr = (u_int8_t)$1; 2527 if (pr == 0) { 2528 yyerror("proto 0 cannot be used"); 2529 YYERROR; 2530 } 2531 $$ = calloc(1, sizeof(struct node_proto)); 2532 if ($$ == NULL) 2533 err(1, "proto_item: calloc"); 2534 $$->proto = pr; 2535 $$->next = NULL; 2536 $$->tail = $$; 2537 } 2538 ; 2539 2540protoval : STRING { 2541 struct protoent *p; 2542 2543 p = getprotobyname($1); 2544 if (p == NULL) { 2545 yyerror("unknown protocol %s", $1); 2546 free($1); 2547 YYERROR; 2548 } 2549 $$ = p->p_proto; 2550 free($1); 2551 } 2552 | NUMBER { 2553 if ($1 < 0 || $1 > 255) { 2554 yyerror("protocol outside range"); 2555 YYERROR; 2556 } 2557 } 2558 ; 2559 2560fromto : ALL { 2561 $$.src.host = NULL; 2562 $$.src.port = NULL; 2563 $$.dst.host = NULL; 2564 $$.dst.port = NULL; 2565 $$.src_os = NULL; 2566 } 2567 | from os to { 2568 $$.src = $1; 2569 $$.src_os = $2; 2570 $$.dst = $3; 2571 } 2572 ; 2573 2574os : /* empty */ { $$ = NULL; } 2575 | OS xos { $$ = $2; } 2576 | OS '{' optnl os_list '}' { $$ = $4; } 2577 ; 2578 2579xos : STRING { 2580 $$ = calloc(1, sizeof(struct node_os)); 2581 if ($$ == NULL) 2582 err(1, "os: calloc"); 2583 $$->os = $1; 2584 $$->tail = $$; 2585 } 2586 ; 2587 2588os_list : xos optnl { $$ = $1; } 2589 | os_list comma xos optnl { 2590 $1->tail->next = $3; 2591 $1->tail = $3; 2592 $$ = $1; 2593 } 2594 ; 2595 2596from : /* empty */ { 2597 $$.host = NULL; 2598 $$.port = NULL; 2599 } 2600 | FROM ipportspec { 2601 $$ = $2; 2602 } 2603 ; 2604 2605to : /* empty */ { 2606 $$.host = NULL; 2607 $$.port = NULL; 2608 } 2609 | TO ipportspec { 2610 if (disallow_urpf_failed($2.host, "\"urpf-failed\" is " 2611 "not permitted in a destination address")) 2612 YYERROR; 2613 $$ = $2; 2614 } 2615 ; 2616 2617ipportspec : ipspec { 2618 $$.host = $1; 2619 $$.port = NULL; 2620 } 2621 | ipspec PORT portspec { 2622 $$.host = $1; 2623 $$.port = $3; 2624 } 2625 | PORT portspec { 2626 $$.host = NULL; 2627 $$.port = $2; 2628 } 2629 ; 2630 2631optnl : '\n' optnl 2632 | /* empty */ 2633 ; 2634 2635ipspec : ANY { $$ = NULL; } 2636 | xhost { $$ = $1; } 2637 | '{' optnl host_list '}' { $$ = $3; } 2638 ; 2639 2640 2641host_list : ipspec optnl { $$ = $1; } 2642 | host_list comma ipspec optnl { 2643 if ($1 == NULL) { 2644 freehostlist($3); 2645 $$ = $1; 2646 } else if ($3 == NULL) { 2647 freehostlist($1); 2648 $$ = $3; 2649 } else { 2650 $1->tail->next = $3; 2651 $1->tail = $3->tail; 2652 $$ = $1; 2653 } 2654 } 2655 ; 2656 2657xhost : not host { 2658 struct node_host *n; 2659 2660 for (n = $2; n != NULL; n = n->next) 2661 n->not = $1; 2662 $$ = $2; 2663 } 2664 | not NOROUTE { 2665 $$ = calloc(1, sizeof(struct node_host)); 2666 if ($$ == NULL) 2667 err(1, "xhost: calloc"); 2668 $$->addr.type = PF_ADDR_NOROUTE; 2669 $$->next = NULL; 2670 $$->not = $1; 2671 $$->tail = $$; 2672 } 2673 | not URPFFAILED { 2674 $$ = calloc(1, sizeof(struct node_host)); 2675 if ($$ == NULL) 2676 err(1, "xhost: calloc"); 2677 $$->addr.type = PF_ADDR_URPFFAILED; 2678 $$->next = NULL; 2679 $$->not = $1; 2680 $$->tail = $$; 2681 } 2682 ; 2683 2684optweight : WEIGHT NUMBER { 2685 if ($2 < 1 || $2 > USHRT_MAX) { 2686 yyerror("weight out of range"); 2687 YYERROR; 2688 } 2689 $$ = $2; 2690 } 2691 | /* empty */ { $$ = 0; } 2692 ; 2693 2694host : STRING { 2695 if (($$ = host($1, pf->opts)) == NULL) { 2696 /* error. "any" is handled elsewhere */ 2697 free($1); 2698 yyerror("could not parse host specification"); 2699 YYERROR; 2700 } 2701 free($1); 2702 2703 } 2704 | STRING '-' STRING { 2705 struct node_host *b, *e; 2706 2707 if ((b = host($1, pf->opts)) == NULL || 2708 (e = host($3, pf->opts)) == NULL) { 2709 free($1); 2710 free($3); 2711 yyerror("could not parse host specification"); 2712 YYERROR; 2713 } 2714 if (b->af != e->af || 2715 b->addr.type != PF_ADDR_ADDRMASK || 2716 e->addr.type != PF_ADDR_ADDRMASK || 2717 unmask(&b->addr.v.a.mask, b->af) != 2718 (b->af == AF_INET ? 32 : 128) || 2719 unmask(&e->addr.v.a.mask, e->af) != 2720 (e->af == AF_INET ? 32 : 128) || 2721 b->next != NULL || b->not || 2722 e->next != NULL || e->not) { 2723 free(b); 2724 free(e); 2725 free($1); 2726 free($3); 2727 yyerror("invalid address range"); 2728 YYERROR; 2729 } 2730 memcpy(&b->addr.v.a.mask, &e->addr.v.a.addr, 2731 sizeof(b->addr.v.a.mask)); 2732 b->addr.type = PF_ADDR_RANGE; 2733 $$ = b; 2734 free(e); 2735 free($1); 2736 free($3); 2737 } 2738 | STRING '/' NUMBER { 2739 char *buf; 2740 2741 if (asprintf(&buf, "%s/%lld", $1, $3) == -1) 2742 err(1, "host: asprintf"); 2743 free($1); 2744 if (($$ = host(buf, pf->opts)) == NULL) { 2745 /* error. "any" is handled elsewhere */ 2746 free(buf); 2747 yyerror("could not parse host specification"); 2748 YYERROR; 2749 } 2750 free(buf); 2751 } 2752 | NUMBER '/' NUMBER { 2753 char *buf; 2754 2755 /* ie. for 10/8 parsing */ 2756 if (asprintf(&buf, "%lld/%lld", $1, $3) == -1) 2757 err(1, "host: asprintf"); 2758 if (($$ = host(buf, pf->opts)) == NULL) { 2759 /* error. "any" is handled elsewhere */ 2760 free(buf); 2761 yyerror("could not parse host specification"); 2762 YYERROR; 2763 } 2764 free(buf); 2765 } 2766 | dynaddr 2767 | dynaddr '/' NUMBER { 2768 struct node_host *n; 2769 2770 if ($3 < 0 || $3 > 128) { 2771 yyerror("bit number too big"); 2772 YYERROR; 2773 } 2774 $$ = $1; 2775 for (n = $1; n != NULL; n = n->next) 2776 set_ipmask(n, $3); 2777 } 2778 | '<' STRING '>' { 2779 if (strlen($2) >= PF_TABLE_NAME_SIZE) { 2780 yyerror("table name '%s' too long", $2); 2781 free($2); 2782 YYERROR; 2783 } 2784 $$ = calloc(1, sizeof(struct node_host)); 2785 if ($$ == NULL) 2786 err(1, "host: calloc"); 2787 $$->addr.type = PF_ADDR_TABLE; 2788 if (strlcpy($$->addr.v.tblname, $2, 2789 sizeof($$->addr.v.tblname)) >= 2790 sizeof($$->addr.v.tblname)) 2791 errx(1, "host: strlcpy"); 2792 free($2); 2793 $$->next = NULL; 2794 $$->tail = $$; 2795 } 2796 | ROUTE STRING { 2797 $$ = calloc(1, sizeof(struct node_host)); 2798 if ($$ == NULL) { 2799 free($2); 2800 err(1, "host: calloc"); 2801 } 2802 $$->addr.type = PF_ADDR_RTLABEL; 2803 if (strlcpy($$->addr.v.rtlabelname, $2, 2804 sizeof($$->addr.v.rtlabelname)) >= 2805 sizeof($$->addr.v.rtlabelname)) { 2806 yyerror("route label too long, max %u chars", 2807 sizeof($$->addr.v.rtlabelname) - 1); 2808 free($2); 2809 free($$); 2810 YYERROR; 2811 } 2812 $$->next = NULL; 2813 $$->tail = $$; 2814 free($2); 2815 } 2816 ; 2817 2818number : NUMBER 2819 | STRING { 2820 u_long ulval; 2821 2822 if (atoul($1, &ulval) == -1) { 2823 yyerror("%s is not a number", $1); 2824 free($1); 2825 YYERROR; 2826 } else 2827 $$ = ulval; 2828 free($1); 2829 } 2830 ; 2831 2832dynaddr : '(' STRING ')' { 2833 int flags = 0; 2834 char *p, *op; 2835 2836 op = $2; 2837 if (!isalpha((unsigned char)op[0])) { 2838 yyerror("invalid interface name '%s'", op); 2839 free(op); 2840 YYERROR; 2841 } 2842 while ((p = strrchr($2, ':')) != NULL) { 2843 if (!strcmp(p+1, "network")) 2844 flags |= PFI_AFLAG_NETWORK; 2845 else if (!strcmp(p+1, "broadcast")) 2846 flags |= PFI_AFLAG_BROADCAST; 2847 else if (!strcmp(p+1, "peer")) 2848 flags |= PFI_AFLAG_PEER; 2849 else if (!strcmp(p+1, "0")) 2850 flags |= PFI_AFLAG_NOALIAS; 2851 else { 2852 yyerror("interface %s has bad modifier", 2853 $2); 2854 free(op); 2855 YYERROR; 2856 } 2857 *p = '\0'; 2858 } 2859 if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { 2860 free(op); 2861 yyerror("illegal combination of " 2862 "interface modifiers"); 2863 YYERROR; 2864 } 2865 $$ = calloc(1, sizeof(struct node_host)); 2866 if ($$ == NULL) 2867 err(1, "address: calloc"); 2868 $$->af = 0; 2869 set_ipmask($$, 128); 2870 $$->addr.type = PF_ADDR_DYNIFTL; 2871 $$->addr.iflags = flags; 2872 if (strlcpy($$->addr.v.ifname, $2, 2873 sizeof($$->addr.v.ifname)) >= 2874 sizeof($$->addr.v.ifname)) { 2875 free(op); 2876 free($$); 2877 yyerror("interface name too long"); 2878 YYERROR; 2879 } 2880 free(op); 2881 $$->next = NULL; 2882 $$->tail = $$; 2883 } 2884 ; 2885 2886portspec : port_item { $$ = $1; } 2887 | '{' optnl port_list '}' { $$ = $3; } 2888 ; 2889 2890port_list : port_item optnl { $$ = $1; } 2891 | port_list comma port_item optnl { 2892 $1->tail->next = $3; 2893 $1->tail = $3; 2894 $$ = $1; 2895 } 2896 ; 2897 2898port_item : portrange { 2899 $$ = calloc(1, sizeof(struct node_port)); 2900 if ($$ == NULL) 2901 err(1, "port_item: calloc"); 2902 $$->port[0] = $1.a; 2903 $$->port[1] = $1.b; 2904 if ($1.t) 2905 $$->op = PF_OP_RRG; 2906 else 2907 $$->op = PF_OP_EQ; 2908 $$->next = NULL; 2909 $$->tail = $$; 2910 } 2911 | unaryop portrange { 2912 if ($2.t) { 2913 yyerror("':' cannot be used with an other " 2914 "port operator"); 2915 YYERROR; 2916 } 2917 $$ = calloc(1, sizeof(struct node_port)); 2918 if ($$ == NULL) 2919 err(1, "port_item: calloc"); 2920 $$->port[0] = $2.a; 2921 $$->port[1] = $2.b; 2922 $$->op = $1; 2923 $$->next = NULL; 2924 $$->tail = $$; 2925 } 2926 | portrange PORTBINARY portrange { 2927 if ($1.t || $3.t) { 2928 yyerror("':' cannot be used with an other " 2929 "port operator"); 2930 YYERROR; 2931 } 2932 $$ = calloc(1, sizeof(struct node_port)); 2933 if ($$ == NULL) 2934 err(1, "port_item: calloc"); 2935 $$->port[0] = $1.a; 2936 $$->port[1] = $3.a; 2937 $$->op = $2; 2938 $$->next = NULL; 2939 $$->tail = $$; 2940 } 2941 ; 2942 2943portplain : numberstring { 2944 if (parseport($1, &$$, 0) == -1) { 2945 free($1); 2946 YYERROR; 2947 } 2948 free($1); 2949 } 2950 ; 2951 2952portrange : numberstring { 2953 if (parseport($1, &$$, PPORT_RANGE) == -1) { 2954 free($1); 2955 YYERROR; 2956 } 2957 free($1); 2958 } 2959 ; 2960 2961uids : uid_item { $$ = $1; } 2962 | '{' optnl uid_list '}' { $$ = $3; } 2963 ; 2964 2965uid_list : uid_item optnl { $$ = $1; } 2966 | uid_list comma uid_item optnl { 2967 $1->tail->next = $3; 2968 $1->tail = $3; 2969 $$ = $1; 2970 } 2971 ; 2972 2973uid_item : uid { 2974 $$ = calloc(1, sizeof(struct node_uid)); 2975 if ($$ == NULL) 2976 err(1, "uid_item: calloc"); 2977 $$->uid[0] = $1; 2978 $$->uid[1] = $1; 2979 $$->op = PF_OP_EQ; 2980 $$->next = NULL; 2981 $$->tail = $$; 2982 } 2983 | unaryop uid { 2984 if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 2985 yyerror("user unknown requires operator = or " 2986 "!="); 2987 YYERROR; 2988 } 2989 $$ = calloc(1, sizeof(struct node_uid)); 2990 if ($$ == NULL) 2991 err(1, "uid_item: calloc"); 2992 $$->uid[0] = $2; 2993 $$->uid[1] = $2; 2994 $$->op = $1; 2995 $$->next = NULL; 2996 $$->tail = $$; 2997 } 2998 | uid PORTBINARY uid { 2999 if ($1 == UID_MAX || $3 == UID_MAX) { 3000 yyerror("user unknown requires operator = or " 3001 "!="); 3002 YYERROR; 3003 } 3004 $$ = calloc(1, sizeof(struct node_uid)); 3005 if ($$ == NULL) 3006 err(1, "uid_item: calloc"); 3007 $$->uid[0] = $1; 3008 $$->uid[1] = $3; 3009 $$->op = $2; 3010 $$->next = NULL; 3011 $$->tail = $$; 3012 } 3013 ; 3014 3015uid : STRING { 3016 if (!strcmp($1, "unknown")) 3017 $$ = UID_MAX; 3018 else { 3019 struct passwd *pw; 3020 3021 if ((pw = getpwnam($1)) == NULL) { 3022 yyerror("unknown user %s", $1); 3023 free($1); 3024 YYERROR; 3025 } 3026 $$ = pw->pw_uid; 3027 } 3028 free($1); 3029 } 3030 | NUMBER { 3031 if ($1 < 0 || $1 >= UID_MAX) { 3032 yyerror("illegal uid value %lu", $1); 3033 YYERROR; 3034 } 3035 $$ = $1; 3036 } 3037 ; 3038 3039gids : gid_item { $$ = $1; } 3040 | '{' optnl gid_list '}' { $$ = $3; } 3041 ; 3042 3043gid_list : gid_item optnl { $$ = $1; } 3044 | gid_list comma gid_item optnl { 3045 $1->tail->next = $3; 3046 $1->tail = $3; 3047 $$ = $1; 3048 } 3049 ; 3050 3051gid_item : gid { 3052 $$ = calloc(1, sizeof(struct node_gid)); 3053 if ($$ == NULL) 3054 err(1, "gid_item: calloc"); 3055 $$->gid[0] = $1; 3056 $$->gid[1] = $1; 3057 $$->op = PF_OP_EQ; 3058 $$->next = NULL; 3059 $$->tail = $$; 3060 } 3061 | unaryop gid { 3062 if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 3063 yyerror("group unknown requires operator = or " 3064 "!="); 3065 YYERROR; 3066 } 3067 $$ = calloc(1, sizeof(struct node_gid)); 3068 if ($$ == NULL) 3069 err(1, "gid_item: calloc"); 3070 $$->gid[0] = $2; 3071 $$->gid[1] = $2; 3072 $$->op = $1; 3073 $$->next = NULL; 3074 $$->tail = $$; 3075 } 3076 | gid PORTBINARY gid { 3077 if ($1 == GID_MAX || $3 == GID_MAX) { 3078 yyerror("group unknown requires operator = or " 3079 "!="); 3080 YYERROR; 3081 } 3082 $$ = calloc(1, sizeof(struct node_gid)); 3083 if ($$ == NULL) 3084 err(1, "gid_item: calloc"); 3085 $$->gid[0] = $1; 3086 $$->gid[1] = $3; 3087 $$->op = $2; 3088 $$->next = NULL; 3089 $$->tail = $$; 3090 } 3091 ; 3092 3093gid : STRING { 3094 if (!strcmp($1, "unknown")) 3095 $$ = GID_MAX; 3096 else { 3097 struct group *grp; 3098 3099 if ((grp = getgrnam($1)) == NULL) { 3100 yyerror("unknown group %s", $1); 3101 free($1); 3102 YYERROR; 3103 } 3104 $$ = grp->gr_gid; 3105 } 3106 free($1); 3107 } 3108 | NUMBER { 3109 if ($1 < 0 || $1 >= GID_MAX) { 3110 yyerror("illegal gid value %lu", $1); 3111 YYERROR; 3112 } 3113 $$ = $1; 3114 } 3115 ; 3116 3117flag : STRING { 3118 int f; 3119 3120 if ((f = parse_flags($1)) < 0) { 3121 yyerror("bad flags %s", $1); 3122 free($1); 3123 YYERROR; 3124 } 3125 free($1); 3126 $$.b1 = f; 3127 } 3128 ; 3129 3130flags : FLAGS flag '/' flag { $$.b1 = $2.b1; $$.b2 = $4.b1; } 3131 | FLAGS '/' flag { $$.b1 = 0; $$.b2 = $3.b1; } 3132 | FLAGS ANY { $$.b1 = 0; $$.b2 = 0; } 3133 ; 3134 3135icmpspec : ICMPTYPE icmp_item { $$ = $2; } 3136 | ICMPTYPE '{' optnl icmp_list '}' { $$ = $4; } 3137 | ICMP6TYPE icmp6_item { $$ = $2; } 3138 | ICMP6TYPE '{' optnl icmp6_list '}' { $$ = $4; } 3139 ; 3140 3141icmp_list : icmp_item optnl { $$ = $1; } 3142 | icmp_list comma icmp_item optnl { 3143 $1->tail->next = $3; 3144 $1->tail = $3; 3145 $$ = $1; 3146 } 3147 ; 3148 3149icmp6_list : icmp6_item optnl { $$ = $1; } 3150 | icmp6_list comma icmp6_item optnl { 3151 $1->tail->next = $3; 3152 $1->tail = $3; 3153 $$ = $1; 3154 } 3155 ; 3156 3157icmp_item : icmptype { 3158 $$ = calloc(1, sizeof(struct node_icmp)); 3159 if ($$ == NULL) 3160 err(1, "icmp_item: calloc"); 3161 $$->type = $1; 3162 $$->code = 0; 3163 $$->proto = IPPROTO_ICMP; 3164 $$->next = NULL; 3165 $$->tail = $$; 3166 } 3167 | icmptype CODE STRING { 3168 const struct icmpcodeent *p; 3169 3170 if ((p = geticmpcodebyname($1-1, $3, AF_INET)) == NULL) { 3171 yyerror("unknown icmp-code %s", $3); 3172 free($3); 3173 YYERROR; 3174 } 3175 3176 free($3); 3177 $$ = calloc(1, sizeof(struct node_icmp)); 3178 if ($$ == NULL) 3179 err(1, "icmp_item: calloc"); 3180 $$->type = $1; 3181 $$->code = p->code + 1; 3182 $$->proto = IPPROTO_ICMP; 3183 $$->next = NULL; 3184 $$->tail = $$; 3185 } 3186 | icmptype CODE NUMBER { 3187 if ($3 < 0 || $3 > 255) { 3188 yyerror("illegal icmp-code %lu", $3); 3189 YYERROR; 3190 } 3191 $$ = calloc(1, sizeof(struct node_icmp)); 3192 if ($$ == NULL) 3193 err(1, "icmp_item: calloc"); 3194 $$->type = $1; 3195 $$->code = $3 + 1; 3196 $$->proto = IPPROTO_ICMP; 3197 $$->next = NULL; 3198 $$->tail = $$; 3199 } 3200 ; 3201 3202icmp6_item : icmp6type { 3203 $$ = calloc(1, sizeof(struct node_icmp)); 3204 if ($$ == NULL) 3205 err(1, "icmp_item: calloc"); 3206 $$->type = $1; 3207 $$->code = 0; 3208 $$->proto = IPPROTO_ICMPV6; 3209 $$->next = NULL; 3210 $$->tail = $$; 3211 } 3212 | icmp6type CODE STRING { 3213 const struct icmpcodeent *p; 3214 3215 if ((p = geticmpcodebyname($1-1, $3, AF_INET6)) == NULL) { 3216 yyerror("unknown icmp6-code %s", $3); 3217 free($3); 3218 YYERROR; 3219 } 3220 free($3); 3221 3222 $$ = calloc(1, sizeof(struct node_icmp)); 3223 if ($$ == NULL) 3224 err(1, "icmp_item: calloc"); 3225 $$->type = $1; 3226 $$->code = p->code + 1; 3227 $$->proto = IPPROTO_ICMPV6; 3228 $$->next = NULL; 3229 $$->tail = $$; 3230 } 3231 | icmp6type CODE NUMBER { 3232 if ($3 < 0 || $3 > 255) { 3233 yyerror("illegal icmp-code %lu", $3); 3234 YYERROR; 3235 } 3236 $$ = calloc(1, sizeof(struct node_icmp)); 3237 if ($$ == NULL) 3238 err(1, "icmp_item: calloc"); 3239 $$->type = $1; 3240 $$->code = $3 + 1; 3241 $$->proto = IPPROTO_ICMPV6; 3242 $$->next = NULL; 3243 $$->tail = $$; 3244 } 3245 ; 3246 3247icmptype : STRING { 3248 const struct icmptypeent *p; 3249 3250 if ((p = geticmptypebyname($1, AF_INET)) == NULL) { 3251 yyerror("unknown icmp-type %s", $1); 3252 free($1); 3253 YYERROR; 3254 } 3255 $$ = p->type + 1; 3256 free($1); 3257 } 3258 | NUMBER { 3259 if ($1 < 0 || $1 > 255) { 3260 yyerror("illegal icmp-type %lu", $1); 3261 YYERROR; 3262 } 3263 $$ = $1 + 1; 3264 } 3265 ; 3266 3267icmp6type : STRING { 3268 const struct icmptypeent *p; 3269 3270 if ((p = geticmptypebyname($1, AF_INET6)) == 3271 NULL) { 3272 yyerror("unknown icmp6-type %s", $1); 3273 free($1); 3274 YYERROR; 3275 } 3276 $$ = p->type + 1; 3277 free($1); 3278 } 3279 | NUMBER { 3280 if ($1 < 0 || $1 > 255) { 3281 yyerror("illegal icmp6-type %lu", $1); 3282 YYERROR; 3283 } 3284 $$ = $1 + 1; 3285 } 3286 ; 3287 3288tos : STRING { 3289 int val; 3290 char *end; 3291 3292 if (map_tos($1, &val)) 3293 $$ = val; 3294 else if ($1[0] == '0' && $1[1] == 'x') { 3295 errno = 0; 3296 $$ = strtoul($1, &end, 16); 3297 if (errno || *end != '\0') 3298 $$ = 256; 3299 } else 3300 $$ = 256; /* flag bad argument */ 3301 if ($$ < 0 || $$ > 255) { 3302 yyerror("illegal tos value %s", $1); 3303 free($1); 3304 YYERROR; 3305 } 3306 free($1); 3307 } 3308 | NUMBER { 3309 $$ = $1; 3310 if ($$ < 0 || $$ > 255) { 3311 yyerror("illegal tos value %lld", $1); 3312 YYERROR; 3313 } 3314 } 3315 ; 3316 3317sourcetrack : /* empty */ { $$ = PF_SRCTRACK; } 3318 | GLOBAL { $$ = PF_SRCTRACK_GLOBAL; } 3319 | RULE { $$ = PF_SRCTRACK_RULE; } 3320 ; 3321 3322statelock : IFBOUND { 3323 $$ = PFRULE_IFBOUND; 3324 } 3325 | FLOATING { 3326 $$ = 0; 3327 } 3328 ; 3329 3330keep : NO STATE { 3331 $$.action = 0; 3332 $$.options = NULL; 3333 } 3334 | KEEP STATE state_opt_spec { 3335 $$.action = PF_STATE_NORMAL; 3336 $$.options = $3; 3337 } 3338 | MODULATE STATE state_opt_spec { 3339 $$.action = PF_STATE_MODULATE; 3340 $$.options = $3; 3341 } 3342 | SYNPROXY STATE state_opt_spec { 3343 $$.action = PF_STATE_SYNPROXY; 3344 $$.options = $3; 3345 } 3346 ; 3347 3348flush : /* empty */ { $$ = 0; } 3349 | FLUSH { $$ = PF_FLUSH; } 3350 | FLUSH GLOBAL { 3351 $$ = PF_FLUSH | PF_FLUSH_GLOBAL; 3352 } 3353 ; 3354 3355state_opt_spec : '(' state_opt_list ')' { $$ = $2; } 3356 | /* empty */ { $$ = NULL; } 3357 ; 3358 3359state_opt_list : state_opt_item { $$ = $1; } 3360 | state_opt_list comma state_opt_item { 3361 $1->tail->next = $3; 3362 $1->tail = $3; 3363 $$ = $1; 3364 } 3365 ; 3366 3367state_opt_item : MAXIMUM NUMBER { 3368 if ($2 < 0 || $2 > UINT_MAX) { 3369 yyerror("only positive values permitted"); 3370 YYERROR; 3371 } 3372 $$ = calloc(1, sizeof(struct node_state_opt)); 3373 if ($$ == NULL) 3374 err(1, "state_opt_item: calloc"); 3375 $$->type = PF_STATE_OPT_MAX; 3376 $$->data.max_states = $2; 3377 $$->next = NULL; 3378 $$->tail = $$; 3379 } 3380 | NOSYNC { 3381 $$ = calloc(1, sizeof(struct node_state_opt)); 3382 if ($$ == NULL) 3383 err(1, "state_opt_item: calloc"); 3384 $$->type = PF_STATE_OPT_NOSYNC; 3385 $$->next = NULL; 3386 $$->tail = $$; 3387 } 3388 | MAXSRCSTATES NUMBER { 3389 if ($2 < 0 || $2 > UINT_MAX) { 3390 yyerror("only positive values permitted"); 3391 YYERROR; 3392 } 3393 $$ = calloc(1, sizeof(struct node_state_opt)); 3394 if ($$ == NULL) 3395 err(1, "state_opt_item: calloc"); 3396 $$->type = PF_STATE_OPT_MAX_SRC_STATES; 3397 $$->data.max_src_states = $2; 3398 $$->next = NULL; 3399 $$->tail = $$; 3400 } 3401 | MAXSRCCONN NUMBER { 3402 if ($2 < 0 || $2 > UINT_MAX) { 3403 yyerror("only positive values permitted"); 3404 YYERROR; 3405 } 3406 $$ = calloc(1, sizeof(struct node_state_opt)); 3407 if ($$ == NULL) 3408 err(1, "state_opt_item: calloc"); 3409 $$->type = PF_STATE_OPT_MAX_SRC_CONN; 3410 $$->data.max_src_conn = $2; 3411 $$->next = NULL; 3412 $$->tail = $$; 3413 } 3414 | MAXSRCCONNRATE NUMBER '/' NUMBER { 3415 if ($2 < 0 || $2 > UINT_MAX || 3416 $4 < 0 || $4 > UINT_MAX) { 3417 yyerror("only positive values permitted"); 3418 YYERROR; 3419 } 3420 $$ = calloc(1, sizeof(struct node_state_opt)); 3421 if ($$ == NULL) 3422 err(1, "state_opt_item: calloc"); 3423 $$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE; 3424 $$->data.max_src_conn_rate.limit = $2; 3425 $$->data.max_src_conn_rate.seconds = $4; 3426 $$->next = NULL; 3427 $$->tail = $$; 3428 } 3429 | OVERLOAD '<' STRING '>' flush { 3430 if (strlen($3) >= PF_TABLE_NAME_SIZE) { 3431 yyerror("table name '%s' too long", $3); 3432 free($3); 3433 YYERROR; 3434 } 3435 $$ = calloc(1, sizeof(struct node_state_opt)); 3436 if ($$ == NULL) 3437 err(1, "state_opt_item: calloc"); 3438 if (strlcpy($$->data.overload.tblname, $3, 3439 PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE) 3440 errx(1, "state_opt_item: strlcpy"); 3441 free($3); 3442 $$->type = PF_STATE_OPT_OVERLOAD; 3443 $$->data.overload.flush = $5; 3444 $$->next = NULL; 3445 $$->tail = $$; 3446 } 3447 | MAXSRCNODES NUMBER { 3448 if ($2 < 0 || $2 > UINT_MAX) { 3449 yyerror("only positive values permitted"); 3450 YYERROR; 3451 } 3452 $$ = calloc(1, sizeof(struct node_state_opt)); 3453 if ($$ == NULL) 3454 err(1, "state_opt_item: calloc"); 3455 $$->type = PF_STATE_OPT_MAX_SRC_NODES; 3456 $$->data.max_src_nodes = $2; 3457 $$->next = NULL; 3458 $$->tail = $$; 3459 } 3460 | SOURCETRACK sourcetrack { 3461 $$ = calloc(1, sizeof(struct node_state_opt)); 3462 if ($$ == NULL) 3463 err(1, "state_opt_item: calloc"); 3464 $$->type = PF_STATE_OPT_SRCTRACK; 3465 $$->data.src_track = $2; 3466 $$->next = NULL; 3467 $$->tail = $$; 3468 } 3469 | statelock { 3470 $$ = calloc(1, sizeof(struct node_state_opt)); 3471 if ($$ == NULL) 3472 err(1, "state_opt_item: calloc"); 3473 $$->type = PF_STATE_OPT_STATELOCK; 3474 $$->data.statelock = $1; 3475 $$->next = NULL; 3476 $$->tail = $$; 3477 } 3478 | SLOPPY { 3479 $$ = calloc(1, sizeof(struct node_state_opt)); 3480 if ($$ == NULL) 3481 err(1, "state_opt_item: calloc"); 3482 $$->type = PF_STATE_OPT_SLOPPY; 3483 $$->next = NULL; 3484 $$->tail = $$; 3485 } 3486 | PFLOW { 3487 $$ = calloc(1, sizeof(struct node_state_opt)); 3488 if ($$ == NULL) 3489 err(1, "state_opt_item: calloc"); 3490 $$->type = PF_STATE_OPT_PFLOW; 3491 $$->next = NULL; 3492 $$->tail = $$; 3493 } 3494 | STRING NUMBER { 3495 int i; 3496 3497 if ($2 < 0 || $2 > UINT_MAX) { 3498 yyerror("only positive values permitted"); 3499 YYERROR; 3500 } 3501 for (i = 0; pf_timeouts[i].name && 3502 strcmp(pf_timeouts[i].name, $1); ++i) 3503 ; /* nothing */ 3504 if (!pf_timeouts[i].name) { 3505 yyerror("illegal timeout name %s", $1); 3506 free($1); 3507 YYERROR; 3508 } 3509 if (strchr(pf_timeouts[i].name, '.') == NULL) { 3510 yyerror("illegal state timeout %s", $1); 3511 free($1); 3512 YYERROR; 3513 } 3514 free($1); 3515 $$ = calloc(1, sizeof(struct node_state_opt)); 3516 if ($$ == NULL) 3517 err(1, "state_opt_item: calloc"); 3518 $$->type = PF_STATE_OPT_TIMEOUT; 3519 $$->data.timeout.number = pf_timeouts[i].timeout; 3520 $$->data.timeout.seconds = $2; 3521 $$->next = NULL; 3522 $$->tail = $$; 3523 } 3524 ; 3525 3526label : STRING { 3527 $$ = $1; 3528 } 3529 ; 3530 3531qname : STRING { 3532 struct pfctl_qsitem *qsi; 3533 3534 if ((qsi = pfctl_find_queue($1, &qspecs)) == NULL) { 3535 yyerror("queue %s is not defined", $1); 3536 YYERROR; 3537 } 3538 $$.qname = $1; 3539 $$.pqname = NULL; 3540 } 3541 | '(' STRING ')' { 3542 struct pfctl_qsitem *qsi; 3543 3544 if ((qsi = pfctl_find_queue($2, &qspecs)) == NULL) { 3545 yyerror("queue %s is not defined", $2); 3546 YYERROR; 3547 } 3548 $$.qname = $2; 3549 $$.pqname = NULL; 3550 } 3551 | '(' STRING comma STRING ')' { 3552 struct pfctl_qsitem *qsi, *pqsi; 3553 3554 if ((qsi = pfctl_find_queue($2, &qspecs)) == NULL) { 3555 yyerror("queue %s is not defined", $2); 3556 YYERROR; 3557 } 3558 if ((pqsi = pfctl_find_queue($4, &qspecs)) == NULL) { 3559 yyerror("queue %s is not defined", $4); 3560 YYERROR; 3561 } 3562 $$.qname = $2; 3563 $$.pqname = $4; 3564 } 3565 ; 3566 3567portstar : numberstring { 3568 if (parseport($1, &$$, PPORT_RANGE|PPORT_STAR) == -1) { 3569 free($1); 3570 YYERROR; 3571 } 3572 free($1); 3573 } 3574 ; 3575 3576redirspec : host optweight { 3577 if ($2 > 0) { 3578 struct node_host *n; 3579 for (n = $1; n != NULL; n = n->next) 3580 n->weight = $2; 3581 } 3582 $$ = $1; 3583 } 3584 | '{' optnl redir_host_list '}' { $$ = $3; } 3585 ; 3586 3587redir_host_list : host optweight optnl { 3588 if ($1->addr.type != PF_ADDR_ADDRMASK) { 3589 free($1); 3590 yyerror("only addresses can be listed for " 3591 "redirection pools "); 3592 YYERROR; 3593 } 3594 if ($2 > 0) { 3595 struct node_host *n; 3596 for (n = $1; n != NULL; n = n->next) 3597 n->weight = $2; 3598 } 3599 $$ = $1; 3600 } 3601 | redir_host_list comma host optweight optnl { 3602 $1->tail->next = $3; 3603 $1->tail = $3->tail; 3604 if ($4 > 0) { 3605 struct node_host *n; 3606 for (n = $3; n != NULL; n = n->next) 3607 n->weight = $4; 3608 } 3609 $$ = $1; 3610 } 3611 ; 3612 3613redirpool : redirspec { 3614 $$ = calloc(1, sizeof(struct redirection)); 3615 if ($$ == NULL) 3616 err(1, "redirection: calloc"); 3617 $$->host = $1; 3618 $$->rport.a = $$->rport.b = $$->rport.t = 0; 3619 } 3620 | redirspec PORT portstar { 3621 $$ = calloc(1, sizeof(struct redirection)); 3622 if ($$ == NULL) 3623 err(1, "redirection: calloc"); 3624 $$->host = $1; 3625 $$->rport = $3; 3626 } 3627 ; 3628 3629hashkey : /* empty */ 3630 { 3631 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 3632 if ($$ == NULL) 3633 err(1, "hashkey: calloc"); 3634 $$->key32[0] = arc4random(); 3635 $$->key32[1] = arc4random(); 3636 $$->key32[2] = arc4random(); 3637 $$->key32[3] = arc4random(); 3638 } 3639 | string 3640 { 3641 if (!strncmp($1, "0x", 2)) { 3642 if (strlen($1) != 34) { 3643 free($1); 3644 yyerror("hex key must be 128 bits " 3645 "(32 hex digits) long"); 3646 YYERROR; 3647 } 3648 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 3649 if ($$ == NULL) 3650 err(1, "hashkey: calloc"); 3651 3652 if (sscanf($1, "0x%8x%8x%8x%8x", 3653 &$$->key32[0], &$$->key32[1], 3654 &$$->key32[2], &$$->key32[3]) != 4) { 3655 free($$); 3656 free($1); 3657 yyerror("invalid hex key"); 3658 YYERROR; 3659 } 3660 } else { 3661 MD5_CTX context; 3662 3663 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 3664 if ($$ == NULL) 3665 err(1, "hashkey: calloc"); 3666 MD5Init(&context); 3667 MD5Update(&context, (unsigned char *)$1, 3668 strlen($1)); 3669 MD5Final((unsigned char *)$$, &context); 3670 HTONL($$->key32[0]); 3671 HTONL($$->key32[1]); 3672 HTONL($$->key32[2]); 3673 HTONL($$->key32[3]); 3674 } 3675 free($1); 3676 } 3677 ; 3678 3679pool_opts : { bzero(&pool_opts, sizeof pool_opts); } 3680 pool_opts_l 3681 { $$ = pool_opts; } 3682 | /* empty */ { 3683 bzero(&pool_opts, sizeof pool_opts); 3684 $$ = pool_opts; 3685 } 3686 ; 3687 3688pool_opts_l : pool_opts_l pool_opt 3689 | pool_opt 3690 ; 3691 3692pool_opt : BITMASK { 3693 if (pool_opts.type) { 3694 yyerror("pool type cannot be redefined"); 3695 YYERROR; 3696 } 3697 pool_opts.type = PF_POOL_BITMASK; 3698 } 3699 | RANDOM { 3700 if (pool_opts.type) { 3701 yyerror("pool type cannot be redefined"); 3702 YYERROR; 3703 } 3704 pool_opts.type = PF_POOL_RANDOM; 3705 } 3706 | SOURCEHASH hashkey { 3707 if (pool_opts.type) { 3708 yyerror("pool type cannot be redefined"); 3709 YYERROR; 3710 } 3711 pool_opts.type = PF_POOL_SRCHASH; 3712 pool_opts.key = $2; 3713 } 3714 | ROUNDROBIN { 3715 if (pool_opts.type) { 3716 yyerror("pool type cannot be redefined"); 3717 YYERROR; 3718 } 3719 pool_opts.type = PF_POOL_ROUNDROBIN; 3720 } 3721 | LEASTSTATES { 3722 if (pool_opts.type) { 3723 yyerror("pool type cannot be redefined"); 3724 YYERROR; 3725 } 3726 pool_opts.type = PF_POOL_LEASTSTATES; 3727 } 3728 | STATICPORT { 3729 if (pool_opts.staticport) { 3730 yyerror("static-port cannot be redefined"); 3731 YYERROR; 3732 } 3733 pool_opts.staticport = 1; 3734 } 3735 | STICKYADDRESS { 3736 if (filter_opts.marker & POM_STICKYADDRESS) { 3737 yyerror("sticky-address cannot be redefined"); 3738 YYERROR; 3739 } 3740 pool_opts.marker |= POM_STICKYADDRESS; 3741 pool_opts.opts |= PF_POOL_STICKYADDR; 3742 } 3743 ; 3744 3745route_host : STRING { 3746 /* try to find @if0 address specs */ 3747 if (strrchr($1, '@') != NULL) { 3748 if (($$ = host($1, pf->opts)) == NULL) { 3749 yyerror("invalid host for route spec"); 3750 YYERROR; 3751 } 3752 free($1); 3753 } else { 3754 $$ = calloc(1, sizeof(struct node_host)); 3755 if ($$ == NULL) 3756 err(1, "route_host: calloc"); 3757 $$->ifname = $1; 3758 $$->addr.type = PF_ADDR_NONE; 3759 set_ipmask($$, 128); 3760 $$->next = NULL; 3761 $$->tail = $$; 3762 } 3763 } 3764 | STRING '/' STRING { 3765 char *buf; 3766 3767 if (asprintf(&buf, "%s/%s", $1, $3) == -1) 3768 err(1, "host: asprintf"); 3769 free($1); 3770 if (($$ = host(buf, pf->opts)) == NULL) { 3771 /* error. "any" is handled elsewhere */ 3772 free(buf); 3773 yyerror("could not parse host specification"); 3774 YYERROR; 3775 } 3776 free(buf); 3777 } 3778 | '<' STRING '>' { 3779 if (strlen($2) >= PF_TABLE_NAME_SIZE) { 3780 yyerror("table name '%s' too long", $2); 3781 free($2); 3782 YYERROR; 3783 } 3784 $$ = calloc(1, sizeof(struct node_host)); 3785 if ($$ == NULL) 3786 err(1, "host: calloc"); 3787 $$->addr.type = PF_ADDR_TABLE; 3788 if (strlcpy($$->addr.v.tblname, $2, 3789 sizeof($$->addr.v.tblname)) >= 3790 sizeof($$->addr.v.tblname)) 3791 errx(1, "host: strlcpy"); 3792 free($2); 3793 $$->next = NULL; 3794 $$->tail = $$; 3795 } 3796 | dynaddr '/' NUMBER { 3797 struct node_host *n; 3798 3799 if ($3 < 0 || $3 > 128) { 3800 yyerror("bit number too big"); 3801 YYERROR; 3802 } 3803 $$ = $1; 3804 for (n = $1; n != NULL; n = n->next) 3805 set_ipmask(n, $3); 3806 } 3807 | '(' STRING host ')' { 3808 struct node_host *n; 3809 3810 $$ = $3; 3811 /* XXX check masks, only full mask should be allowed */ 3812 for (n = $3; n != NULL; n = n->next) { 3813 if ($$->ifname) { 3814 yyerror("cannot specify interface twice " 3815 "in route spec"); 3816 YYERROR; 3817 } 3818 if (($$->ifname = strdup($2)) == NULL) 3819 errx(1, "host: strdup"); 3820 } 3821 free($2); 3822 } 3823 ; 3824 3825route_host_list : route_host optweight optnl { 3826 if ($2 > 0) { 3827 struct node_host *n; 3828 for (n = $1; n != NULL; n = n->next) 3829 n->weight = $2; 3830 } 3831 $$ = $1; 3832 } 3833 | route_host_list comma route_host optweight optnl { 3834 if ($1->af == 0) 3835 $1->af = $3->af; 3836 if ($1->af != $3->af) { 3837 yyerror("all pool addresses must be in the " 3838 "same address family"); 3839 YYERROR; 3840 } 3841 $1->tail->next = $3; 3842 $1->tail = $3->tail; 3843 if ($4 > 0) { 3844 struct node_host *n; 3845 for (n = $3; n != NULL; n = n->next) 3846 n->weight = $4; 3847 } 3848 $$ = $1; 3849 } 3850 ; 3851 3852routespec : route_host optweight { 3853 if ($2 > 0) { 3854 struct node_host *n; 3855 for (n = $1; n != NULL; n = n->next) 3856 n->weight = $2; 3857 } 3858 $$ = $1; 3859 } 3860 | '{' optnl route_host_list '}' { $$ = $3; } 3861 ; 3862 3863timeout_spec : STRING NUMBER 3864 { 3865 if ($2 < 0 || $2 > UINT_MAX) { 3866 yyerror("only positive values permitted"); 3867 YYERROR; 3868 } 3869 if (pfctl_set_timeout(pf, $1, $2, 0) != 0) { 3870 yyerror("unknown timeout %s", $1); 3871 free($1); 3872 YYERROR; 3873 } 3874 free($1); 3875 } 3876 ; 3877 3878timeout_list : timeout_list comma timeout_spec optnl 3879 | timeout_spec optnl 3880 ; 3881 3882limit_spec : STRING NUMBER 3883 { 3884 if ($2 < 0 || $2 > UINT_MAX) { 3885 yyerror("only positive values permitted"); 3886 YYERROR; 3887 } 3888 if (pfctl_set_limit(pf, $1, $2) != 0) { 3889 yyerror("unable to set limit %s %u", $1, $2); 3890 free($1); 3891 YYERROR; 3892 } 3893 free($1); 3894 } 3895 ; 3896 3897limit_list : limit_list comma limit_spec optnl 3898 | limit_spec optnl 3899 ; 3900 3901comma : ',' 3902 | /* empty */ 3903 ; 3904 3905yesno : NO { $$ = 0; } 3906 | STRING { 3907 if (!strcmp($1, "yes")) 3908 $$ = 1; 3909 else { 3910 yyerror("invalid value '%s', expected 'yes' " 3911 "or 'no'", $1); 3912 free($1); 3913 YYERROR; 3914 } 3915 free($1); 3916 } 3917 ; 3918 3919unaryop : '=' { $$ = PF_OP_EQ; } 3920 | NE { $$ = PF_OP_NE; } 3921 | LE { $$ = PF_OP_LE; } 3922 | '<' { $$ = PF_OP_LT; } 3923 | GE { $$ = PF_OP_GE; } 3924 | '>' { $$ = PF_OP_GT; } 3925 ; 3926 3927%% 3928 3929int 3930yyerror(const char *fmt, ...) 3931{ 3932 va_list ap; 3933 3934 file->errors++; 3935 va_start(ap, fmt); 3936 fprintf(stderr, "%s:%d: ", file->name, yylval.lineno); 3937 vfprintf(stderr, fmt, ap); 3938 fprintf(stderr, "\n"); 3939 va_end(ap); 3940 return (0); 3941} 3942 3943int 3944disallow_table(struct node_host *h, const char *fmt) 3945{ 3946 for (; h != NULL; h = h->next) 3947 if (h->addr.type == PF_ADDR_TABLE) { 3948 yyerror(fmt, h->addr.v.tblname); 3949 return (1); 3950 } 3951 return (0); 3952} 3953 3954int 3955disallow_urpf_failed(struct node_host *h, const char *fmt) 3956{ 3957 for (; h != NULL; h = h->next) 3958 if (h->addr.type == PF_ADDR_URPFFAILED) { 3959 yyerror(fmt); 3960 return (1); 3961 } 3962 return (0); 3963} 3964 3965int 3966disallow_alias(struct node_host *h, const char *fmt) 3967{ 3968 for (; h != NULL; h = h->next) 3969 if (DYNIF_MULTIADDR(h->addr)) { 3970 yyerror(fmt, h->addr.v.tblname); 3971 return (1); 3972 } 3973 return (0); 3974} 3975 3976int 3977rule_consistent(struct pf_rule *r, int anchor_call) 3978{ 3979 int problems = 0; 3980 3981 if (r->proto != IPPROTO_TCP && r->os_fingerprint != PF_OSFP_ANY) { 3982 yyerror("os only applies to tcp"); 3983 problems++; 3984 } 3985 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 3986 (r->src.port_op || r->dst.port_op)) { 3987 yyerror("port only applies to tcp/udp"); 3988 problems++; 3989 } 3990 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 3991 r->uid.op) { 3992 yyerror("user only applies to tcp/udp"); 3993 problems++; 3994 } 3995 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 3996 r->gid.op) { 3997 yyerror("group only applies to tcp/udp"); 3998 problems++; 3999 } 4000 if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 && 4001 (r->type || r->code)) { 4002 yyerror("icmp-type/code only applies to icmp"); 4003 problems++; 4004 } 4005 if (!r->af && (r->type || r->code)) { 4006 yyerror("must indicate address family with icmp-type/code"); 4007 problems++; 4008 } 4009 if (r->rule_flag & PFRULE_AFTO && r->af == r->naf) { 4010 yyerror("must indicate different address family with af-to"); 4011 problems++; 4012 } 4013 if (r->overload_tblname[0] && 4014 r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) { 4015 yyerror("'overload' requires 'max-src-conn' " 4016 "or 'max-src-conn-rate'"); 4017 problems++; 4018 } 4019 if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) || 4020 (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) { 4021 yyerror("proto %s doesn't match address family %s", 4022 r->proto == IPPROTO_ICMP ? "icmp" : "icmp6", 4023 r->af == AF_INET ? "inet" : "inet6"); 4024 problems++; 4025 } 4026 if (r->allow_opts && r->action != PF_PASS) { 4027 yyerror("allow-opts can only be specified for pass rules"); 4028 problems++; 4029 } 4030 if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op || 4031 r->dst.port_op || r->flagset || r->type || r->code)) { 4032 yyerror("fragments can be filtered only on IP header fields"); 4033 problems++; 4034 } 4035 if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) { 4036 yyerror("return-rst can only be applied to TCP rules"); 4037 problems++; 4038 } 4039 if (r->max_src_nodes && !(r->rule_flag & PFRULE_RULESRCTRACK)) { 4040 yyerror("max-src-nodes requires 'source-track rule'"); 4041 problems++; 4042 } 4043 if (r->action != PF_PASS && r->keep_state) { 4044 yyerror("keep state is great, but only for pass rules"); 4045 problems++; 4046 } 4047 if (r->rule_flag & PFRULE_STATESLOPPY && 4048 (r->keep_state == PF_STATE_MODULATE || 4049 r->keep_state == PF_STATE_SYNPROXY)) { 4050 yyerror("sloppy state matching cannot be used with " 4051 "synproxy state or modulate state"); 4052 problems++; 4053 } 4054 if ((r->nat.addr.type != PF_ADDR_NONE || 4055 r->rdr.addr.type != PF_ADDR_NONE) && 4056 r->action != PF_MATCH && !r->keep_state) { 4057 yyerror("nat-to and rdr-to require keep state"); 4058 problems++; 4059 } 4060 if (r->direction == PF_INOUT && (r->nat.addr.type != PF_ADDR_NONE || 4061 r->rdr.addr.type != PF_ADDR_NONE)) { 4062 yyerror("nat-to and rdr-to require a direction"); 4063 problems++; 4064 } 4065 if (r->af == AF_INET6 && (r->scrub_flags & 4066 (PFSTATE_NODF|PFSTATE_RANDOMID))) { 4067 yyerror("address family inet6 does not support scrub options " 4068 "no-df, random-id"); 4069 problems++; 4070 } 4071 4072 /* Basic rule sanity check. */ 4073 switch (r->action) { 4074 case PF_MATCH: 4075 if (r->divert.port) { 4076 yyerror("divert is not supported on match rules"); 4077 problems++; 4078 } 4079 if (r->divert_packet.port) { 4080 yyerror("divert is not supported on match rules"); 4081 problems++; 4082 } 4083 if (r->rt) { 4084 yyerror("route-to, reply-to and dup-to " 4085 "are not supported on match rules"); 4086 problems++; 4087 } 4088 if (r->rule_flag & PFRULE_AFTO) { 4089 yyerror("af-to is not supported on match rules"); 4090 problems++; 4091 } 4092 break; 4093 case PF_DROP: 4094 if (r->rt) { 4095 yyerror("route-to, reply-to and dup-to " 4096 "are not supported on block rules"); 4097 problems++; 4098 } 4099 break; 4100 default:; 4101 } 4102 return (-problems); 4103} 4104 4105int 4106process_tabledef(char *name, struct table_opts *opts, int popts) 4107{ 4108 struct pfr_buffer ab; 4109 struct node_tinit *ti; 4110 4111 bzero(&ab, sizeof(ab)); 4112 ab.pfrb_type = PFRB_ADDRS; 4113 SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) { 4114 if (ti->file) 4115 if (pfr_buf_load(&ab, ti->file, 0, popts)) { 4116 if (errno) 4117 yyerror("cannot load \"%s\": %s", 4118 ti->file, strerror(errno)); 4119 else 4120 yyerror("file \"%s\" contains bad data", 4121 ti->file); 4122 goto _error; 4123 } 4124 if (ti->host) 4125 if (append_addr_host(&ab, ti->host, 0, 0)) { 4126 yyerror("cannot create address buffer: %s", 4127 strerror(errno)); 4128 goto _error; 4129 } 4130 } 4131 if (pf->opts & PF_OPT_VERBOSE) 4132 print_tabledef(name, opts->flags, opts->init_addr, 4133 &opts->init_nodes); 4134 if (!(pf->opts & PF_OPT_NOACTION) && 4135 pfctl_define_table(name, opts->flags, opts->init_addr, 4136 pf->anchor->path, &ab, pf->anchor->ruleset.tticket)) { 4137 yyerror("cannot define table %s: %s", name, 4138 pfr_strerror(errno)); 4139 goto _error; 4140 } 4141 pf->tdirty = 1; 4142 pfr_buf_clear(&ab); 4143 return (0); 4144_error: 4145 pfr_buf_clear(&ab); 4146 return (-1); 4147} 4148 4149struct keywords { 4150 const char *k_name; 4151 int k_val; 4152}; 4153 4154/* macro gore, but you should've seen the prior indentation nightmare... */ 4155 4156#define FREE_LIST(T,r) \ 4157 do { \ 4158 T *p, *node = r; \ 4159 while (node != NULL) { \ 4160 p = node; \ 4161 node = node->next; \ 4162 free(p); \ 4163 } \ 4164 } while (0) 4165 4166#define LOOP_THROUGH(T,n,r,C) \ 4167 do { \ 4168 T *n; \ 4169 if (r == NULL) { \ 4170 r = calloc(1, sizeof(T)); \ 4171 if (r == NULL) \ 4172 err(1, "LOOP: calloc"); \ 4173 r->next = NULL; \ 4174 } \ 4175 n = r; \ 4176 while (n != NULL) { \ 4177 do { \ 4178 C; \ 4179 } while (0); \ 4180 n = n->next; \ 4181 } \ 4182 } while (0) 4183 4184void 4185expand_label_str(char *label, size_t len, const char *srch, const char *repl) 4186{ 4187 char *tmp; 4188 char *p, *q; 4189 4190 if ((tmp = calloc(1, len)) == NULL) 4191 err(1, "expand_label_str: calloc"); 4192 p = q = label; 4193 while ((q = strstr(p, srch)) != NULL) { 4194 *q = '\0'; 4195 if ((strlcat(tmp, p, len) >= len) || 4196 (strlcat(tmp, repl, len) >= len)) 4197 errx(1, "expand_label: label too long"); 4198 q += strlen(srch); 4199 p = q; 4200 } 4201 if (strlcat(tmp, p, len) >= len) 4202 errx(1, "expand_label: label too long"); 4203 strlcpy(label, tmp, len); /* always fits */ 4204 free(tmp); 4205} 4206 4207void 4208expand_label_if(const char *name, char *label, size_t len, const char *ifname) 4209{ 4210 if (strstr(label, name) != NULL) { 4211 if (!*ifname) 4212 expand_label_str(label, len, name, "any"); 4213 else 4214 expand_label_str(label, len, name, ifname); 4215 } 4216} 4217 4218void 4219expand_label_addr(const char *name, char *label, size_t len, sa_family_t af, 4220 struct node_host *h) 4221{ 4222 char tmp[64], tmp_not[66]; 4223 4224 if (strstr(label, name) != NULL) { 4225 switch (h->addr.type) { 4226 case PF_ADDR_DYNIFTL: 4227 snprintf(tmp, sizeof(tmp), "(%s)", h->addr.v.ifname); 4228 break; 4229 case PF_ADDR_TABLE: 4230 snprintf(tmp, sizeof(tmp), "<%s>", h->addr.v.tblname); 4231 break; 4232 case PF_ADDR_NOROUTE: 4233 snprintf(tmp, sizeof(tmp), "no-route"); 4234 break; 4235 case PF_ADDR_URPFFAILED: 4236 snprintf(tmp, sizeof(tmp), "urpf-failed"); 4237 break; 4238 case PF_ADDR_ADDRMASK: 4239 if (!af || (PF_AZERO(&h->addr.v.a.addr, af) && 4240 PF_AZERO(&h->addr.v.a.mask, af))) 4241 snprintf(tmp, sizeof(tmp), "any"); 4242 else { 4243 char a[48]; 4244 int bits; 4245 4246 if (inet_ntop(af, &h->addr.v.a.addr, a, 4247 sizeof(a)) == NULL) 4248 snprintf(tmp, sizeof(tmp), "?"); 4249 else { 4250 bits = unmask(&h->addr.v.a.mask, af); 4251 if ((af == AF_INET && bits < 32) || 4252 (af == AF_INET6 && bits < 128)) 4253 snprintf(tmp, sizeof(tmp), 4254 "%s/%d", a, bits); 4255 else 4256 snprintf(tmp, sizeof(tmp), 4257 "%s", a); 4258 } 4259 } 4260 break; 4261 default: 4262 snprintf(tmp, sizeof(tmp), "?"); 4263 break; 4264 } 4265 4266 if (h->not) { 4267 snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp); 4268 expand_label_str(label, len, name, tmp_not); 4269 } else 4270 expand_label_str(label, len, name, tmp); 4271 } 4272} 4273 4274void 4275expand_label_port(const char *name, char *label, size_t len, 4276 struct node_port *port) 4277{ 4278 char a1[6], a2[6], op[13] = ""; 4279 4280 if (strstr(label, name) != NULL) { 4281 snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0])); 4282 snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1])); 4283 if (!port->op) 4284 ; 4285 else if (port->op == PF_OP_IRG) 4286 snprintf(op, sizeof(op), "%s><%s", a1, a2); 4287 else if (port->op == PF_OP_XRG) 4288 snprintf(op, sizeof(op), "%s<>%s", a1, a2); 4289 else if (port->op == PF_OP_EQ) 4290 snprintf(op, sizeof(op), "%s", a1); 4291 else if (port->op == PF_OP_NE) 4292 snprintf(op, sizeof(op), "!=%s", a1); 4293 else if (port->op == PF_OP_LT) 4294 snprintf(op, sizeof(op), "<%s", a1); 4295 else if (port->op == PF_OP_LE) 4296 snprintf(op, sizeof(op), "<=%s", a1); 4297 else if (port->op == PF_OP_GT) 4298 snprintf(op, sizeof(op), ">%s", a1); 4299 else if (port->op == PF_OP_GE) 4300 snprintf(op, sizeof(op), ">=%s", a1); 4301 expand_label_str(label, len, name, op); 4302 } 4303} 4304 4305void 4306expand_label_proto(const char *name, char *label, size_t len, u_int8_t proto) 4307{ 4308 struct protoent *pe; 4309 char n[4]; 4310 4311 if (strstr(label, name) != NULL) { 4312 pe = getprotobynumber(proto); 4313 if (pe != NULL) 4314 expand_label_str(label, len, name, pe->p_name); 4315 else { 4316 snprintf(n, sizeof(n), "%u", proto); 4317 expand_label_str(label, len, name, n); 4318 } 4319 } 4320} 4321 4322void 4323expand_label_nr(const char *name, char *label, size_t len) 4324{ 4325 char n[11]; 4326 4327 if (strstr(label, name) != NULL) { 4328 snprintf(n, sizeof(n), "%u", pf->anchor->match); 4329 expand_label_str(label, len, name, n); 4330 } 4331} 4332 4333void 4334expand_label(char *label, size_t len, const char *ifname, sa_family_t af, 4335 struct node_host *src_host, struct node_port *src_port, 4336 struct node_host *dst_host, struct node_port *dst_port, 4337 u_int8_t proto) 4338{ 4339 expand_label_if("$if", label, len, ifname); 4340 expand_label_addr("$srcaddr", label, len, af, src_host); 4341 expand_label_addr("$dstaddr", label, len, af, dst_host); 4342 expand_label_port("$srcport", label, len, src_port); 4343 expand_label_port("$dstport", label, len, dst_port); 4344 expand_label_proto("$proto", label, len, proto); 4345 expand_label_nr("$nr", label, len); 4346} 4347 4348int 4349expand_queue(char *qname, struct node_if *interfaces, struct queue_opts *opts) 4350{ 4351 struct pf_queuespec qspec; 4352 4353 LOOP_THROUGH(struct node_if, interface, interfaces, 4354 bzero(&qspec, sizeof(qspec)); 4355 if (!opts->parent && (opts->marker & QOM_BWSPEC)) 4356 opts->flags |= PFQS_ROOTCLASS; 4357 if (!(opts->marker & QOM_BWSPEC) && 4358 !(opts->marker & QOM_FLOWS)) { 4359 yyerror("no bandwidth or flow specification"); 4360 return (1); 4361 } 4362 if (strlcpy(qspec.qname, qname, sizeof(qspec.qname)) >= 4363 sizeof(qspec.qname)) { 4364 yyerror("queuename too long"); 4365 return (1); 4366 } 4367 if (opts->parent && strlcpy(qspec.parent, opts->parent, 4368 sizeof(qspec.parent)) >= sizeof(qspec.parent)) { 4369 yyerror("parent too long"); 4370 return (1); 4371 } 4372 if (strlcpy(qspec.ifname, interface->ifname, 4373 sizeof(qspec.ifname)) >= sizeof(qspec.ifname)) { 4374 yyerror("interface too long"); 4375 return (1); 4376 } 4377 qspec.realtime.m1.absolute = opts->realtime.m1.bw_absolute; 4378 qspec.realtime.m1.percent = opts->realtime.m1.bw_percent; 4379 qspec.realtime.m2.absolute = opts->realtime.m2.bw_absolute; 4380 qspec.realtime.m2.percent = opts->realtime.m2.bw_percent; 4381 qspec.realtime.d = opts->realtime.d; 4382 4383 qspec.linkshare.m1.absolute = opts->linkshare.m1.bw_absolute; 4384 qspec.linkshare.m1.percent = opts->linkshare.m1.bw_percent; 4385 qspec.linkshare.m2.absolute = opts->linkshare.m2.bw_absolute; 4386 qspec.linkshare.m2.percent = opts->linkshare.m2.bw_percent; 4387 qspec.linkshare.d = opts->linkshare.d; 4388 4389 qspec.upperlimit.m1.absolute = opts->upperlimit.m1.bw_absolute; 4390 qspec.upperlimit.m1.percent = opts->upperlimit.m1.bw_percent; 4391 qspec.upperlimit.m2.absolute = opts->upperlimit.m2.bw_absolute; 4392 qspec.upperlimit.m2.percent = opts->upperlimit.m2.bw_percent; 4393 qspec.upperlimit.d = opts->upperlimit.d; 4394 4395 qspec.flowqueue.flows = opts->flowqueue.flows; 4396 qspec.flowqueue.quantum = opts->flowqueue.quantum; 4397 qspec.flowqueue.interval = opts->flowqueue.interval; 4398 qspec.flowqueue.target = opts->flowqueue.target; 4399 4400 qspec.flags = opts->flags; 4401 qspec.qlimit = opts->qlimit; 4402 4403 if (pfctl_add_queue(pf, &qspec)) { 4404 yyerror("cannot add queue"); 4405 return (1); 4406 } 4407 ); 4408 4409 FREE_LIST(struct node_if, interfaces); 4410 return (0); 4411} 4412 4413int 4414expand_divertspec(struct pf_rule *r, struct divertspec *ds) 4415{ 4416 struct node_host *n; 4417 4418 if (ds->port == 0) 4419 return (0); 4420 4421 r->divert.port = ds->port; 4422 4423 if (r->direction == PF_OUT) { 4424 if (ds->addr) { 4425 yyerror("address specified for outgoing divert"); 4426 return (1); 4427 } 4428 bzero(&r->divert.addr, sizeof(r->divert.addr)); 4429 return (0); 4430 } 4431 4432 if (!ds->addr) { 4433 yyerror("no address specified for incoming divert"); 4434 return (1); 4435 } 4436 if (r->af) { 4437 for (n = ds->addr; n != NULL; n = n->next) 4438 if (n->af == r->af) 4439 break; 4440 if (n == NULL) { 4441 yyerror("address family mismatch for divert"); 4442 return (1); 4443 } 4444 r->divert.addr = n->addr.v.a.addr; 4445 } else { 4446 r->af = ds->addr->af; 4447 r->divert.addr = ds->addr->addr.v.a.addr; 4448 } 4449 return (0); 4450} 4451 4452int 4453collapse_redirspec(struct pf_pool *rpool, struct pf_rule *r, 4454 struct redirspec *rs, u_int8_t allow_if) 4455{ 4456 struct pf_opt_tbl *tbl = NULL; 4457 struct node_host *h, *hprev = NULL; 4458 struct pf_rule_addr ra; 4459 int af = 0, naddr = 0; 4460 4461 if (!rs || !rs->rdr || rs->rdr->host == NULL) { 4462 rpool->addr.type = PF_ADDR_NONE; 4463 return (0); 4464 } 4465 4466 if (r->rule_flag & PFRULE_AFTO) 4467 r->naf = rs->af; 4468 4469 for (h = rs->rdr->host; h != NULL; h = h->next) { 4470 /* set rule address family if redirect spec has one */ 4471 if (rs->af && !r->af && !af) { 4472 /* swap address families for af-to */ 4473 if (r->naf == AF_INET6) 4474 af = AF_INET; 4475 else if (r->naf == AF_INET) 4476 af = AF_INET6; 4477 else 4478 af = rs->af; 4479 } 4480 if (h->af && !r->naf) { /* nat-to/rdr-to case */ 4481 /* skip if the rule af doesn't match redirect af */ 4482 if (r->af && r->af != h->af) 4483 continue; 4484 /* 4485 * fail if the chosen af is not universal for 4486 * all addresses in the redirect address pool 4487 */ 4488 if (!r->af && af && af != h->af) { 4489 yyerror("%s spec contains addresses with " 4490 "different address families", 4491 allow_if ? "routing" : "translation"); 4492 return (1); 4493 } 4494 } else if (h->af) { /* af-to case */ 4495 /* 4496 * fail if the redirect spec af is not universal 4497 * for all addresses in the redirect address pool 4498 */ 4499 if (rs->af && rs->af != h->af) { 4500 yyerror("%s spec contains addresses that " 4501 "don't match target address family", 4502 allow_if ? "routing" : "translation"); 4503 return (1); 4504 } 4505 } 4506 /* else if (!h->af): 4507 * we silently allow any not af-specific host specs, 4508 * e.g. (em0) and let the kernel deal with them 4509 */ 4510 4511 /* if we haven't selected the rule af yet, now it's time */ 4512 if (!r->af && !af) 4513 af = h->af; 4514 4515 if (naddr == 0) { /* the first host */ 4516 rpool->addr = h->addr; 4517 if (!allow_if && h->ifname) { 4518 yyerror("@if not permitted for translation"); 4519 return (1); 4520 } 4521 if (h->ifname && strlcpy(rpool->ifname, h->ifname, 4522 sizeof(rpool->ifname)) >= sizeof(rpool->ifname)) 4523 errx(1, "collapse_redirspec: strlcpy"); 4524 hprev = h; /* in case we need to conver to a table */ 4525 } else { /* multiple hosts */ 4526 if (rs->pool_opts.type && 4527 !PF_POOL_DYNTYPE(rs->pool_opts.type)) { 4528 yyerror("pool type is not valid for multiple " 4529 "translation or routing addresses"); 4530 return (1); 4531 } 4532 if ((hprev && hprev->addr.type != PF_ADDR_ADDRMASK) && 4533 (hprev && hprev->addr.type != PF_ADDR_NONE) && 4534 h->addr.type != PF_ADDR_ADDRMASK && 4535 h->addr.type != PF_ADDR_NONE) { 4536 yyerror("multiple tables or dynamic interfaces " 4537 "not supported for translation or routing"); 4538 return (1); 4539 } 4540 if (!allow_if && h->ifname) { 4541 yyerror("@if not permitted for translation"); 4542 return (1); 4543 } 4544 if (hprev) { 4545 /* 4546 * undo some damage and convert the single 4547 * host pool to the table 4548 */ 4549 memset(&ra, 0, sizeof(ra)); 4550 memset(rpool->ifname, 0, sizeof(rpool->ifname)); 4551 ra.addr = hprev->addr; 4552 ra.weight = hprev->weight; 4553 if (add_opt_table(pf, &tbl, 4554 hprev->af, &ra, hprev->ifname)) 4555 return (1); 4556 hprev = NULL; 4557 } 4558 memset(&ra, 0, sizeof(ra)); 4559 ra.addr = h->addr; 4560 ra.weight = h->weight; 4561 if (add_opt_table(pf, &tbl, 4562 h->af, &ra, h->ifname)) 4563 return (1); 4564 } 4565 naddr++; 4566 } 4567 /* set rule af to the one chosen above */ 4568 if (!r->af && af) 4569 r->af = af; 4570 if (!naddr) { 4571 yyerror("af mismatch in %s spec", 4572 allow_if ? "routing" : "translation"); 4573 return (1); 4574 } 4575 if (tbl) { 4576 if ((pf->opts & PF_OPT_NOACTION) == 0 && 4577 pf_opt_create_table(pf, tbl)) 4578 return (1); 4579 4580 pf->tdirty = 1; 4581 4582 if (pf->opts & PF_OPT_VERBOSE) 4583 print_tabledef(tbl->pt_name, 4584 PFR_TFLAG_CONST | tbl->pt_flags, 4585 1, &tbl->pt_nodes); 4586 4587 memset(&rpool->addr, 0, sizeof(rpool->addr)); 4588 rpool->addr.type = PF_ADDR_TABLE; 4589 strlcpy(rpool->addr.v.tblname, tbl->pt_name, 4590 sizeof(rpool->addr.v.tblname)); 4591 4592 pfr_buf_clear(tbl->pt_buf); 4593 free(tbl->pt_buf); 4594 tbl->pt_buf = NULL; 4595 free(tbl); 4596 } 4597 return (0); 4598} 4599 4600 4601int 4602apply_redirspec(struct pf_pool *rpool, struct pf_rule *r, struct redirspec *rs, 4603 int isrdr, struct node_port *np) 4604{ 4605 if (!rs || !rs->rdr) 4606 return (0); 4607 4608 rpool->proxy_port[0] = ntohs(rs->rdr->rport.a); 4609 4610 if (isrdr) { 4611 if (!rs->rdr->rport.b && rs->rdr->rport.t) { 4612 rpool->proxy_port[1] = ntohs(rs->rdr->rport.a) + 4613 (ntohs(np->port[1]) - ntohs(np->port[0])); 4614 } else 4615 rpool->proxy_port[1] = ntohs(rs->rdr->rport.b); 4616 } else { 4617 rpool->proxy_port[1] = ntohs(rs->rdr->rport.b); 4618 if (!rpool->proxy_port[0] && !rpool->proxy_port[1]) { 4619 rpool->proxy_port[0] = PF_NAT_PROXY_PORT_LOW; 4620 rpool->proxy_port[1] = PF_NAT_PROXY_PORT_HIGH; 4621 } else if (!rpool->proxy_port[1]) 4622 rpool->proxy_port[1] = rpool->proxy_port[0]; 4623 } 4624 4625 rpool->opts = rs->pool_opts.type; 4626 if ((rpool->opts & PF_POOL_TYPEMASK) == PF_POOL_NONE && 4627 (rpool->addr.type == PF_ADDR_TABLE || 4628 DYNIF_MULTIADDR(rpool->addr))) 4629 rpool->opts |= PF_POOL_ROUNDROBIN; 4630 4631 if (!PF_POOL_DYNTYPE(rpool->opts) && 4632 (disallow_table(rs->rdr->host, 4633 "tables are not supported by pool type") || 4634 disallow_alias(rs->rdr->host, 4635 "interface (%s) is not supported by pool type"))) 4636 return (1); 4637 4638 if (rs->pool_opts.key != NULL) 4639 memcpy(&rpool->key, rs->pool_opts.key, 4640 sizeof(struct pf_poolhashkey)); 4641 4642 if (rs->pool_opts.opts) 4643 rpool->opts |= rs->pool_opts.opts; 4644 4645 if (rs->pool_opts.staticport) { 4646 if (isrdr) { 4647 yyerror("the 'static-port' option is only valid with " 4648 "nat rules"); 4649 return (1); 4650 } 4651 if (rpool->proxy_port[0] != PF_NAT_PROXY_PORT_LOW && 4652 rpool->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) { 4653 yyerror("the 'static-port' option can't be used when " 4654 "specifying a port range"); 4655 return (1); 4656 } 4657 rpool->proxy_port[0] = 0; 4658 rpool->proxy_port[1] = 0; 4659 } 4660 4661 return (0); 4662} 4663 4664 4665void 4666expand_rule(struct pf_rule *r, int keeprule, struct node_if *interfaces, 4667 struct redirspec *nat, struct redirspec *rdr, struct redirspec *rroute, 4668 struct node_proto *protos, struct node_os *src_oses, 4669 struct node_host *src_hosts, struct node_port *src_ports, 4670 struct node_host *dst_hosts, struct node_port *dst_ports, 4671 struct node_uid *uids, struct node_gid *gids, struct node_if *rcv, 4672 struct node_icmp *icmp_types, const char *anchor_call) 4673{ 4674 sa_family_t af = r->af; 4675 int added = 0, error = 0; 4676 char ifname[IF_NAMESIZE]; 4677 char label[PF_RULE_LABEL_SIZE]; 4678 char tagname[PF_TAG_NAME_SIZE]; 4679 char match_tagname[PF_TAG_NAME_SIZE]; 4680 u_int8_t flags, flagset, keep_state; 4681 struct node_host *srch, *dsth, *osrch, *odsth; 4682 struct redirspec binat; 4683 struct pf_rule rb; 4684 int dir = r->direction; 4685 4686 if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label)) 4687 errx(1, "expand_rule: strlcpy"); 4688 if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname)) 4689 errx(1, "expand_rule: strlcpy"); 4690 if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >= 4691 sizeof(match_tagname)) 4692 errx(1, "expand_rule: strlcpy"); 4693 flags = r->flags; 4694 flagset = r->flagset; 4695 keep_state = r->keep_state; 4696 4697 r->src.addr.type = r->dst.addr.type = PF_ADDR_ADDRMASK; 4698 4699 LOOP_THROUGH(struct node_if, interface, interfaces, 4700 LOOP_THROUGH(struct node_proto, proto, protos, 4701 LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types, 4702 LOOP_THROUGH(struct node_host, src_host, src_hosts, 4703 LOOP_THROUGH(struct node_host, dst_host, dst_hosts, 4704 LOOP_THROUGH(struct node_port, src_port, src_ports, 4705 LOOP_THROUGH(struct node_port, dst_port, dst_ports, 4706 LOOP_THROUGH(struct node_os, src_os, src_oses, 4707 LOOP_THROUGH(struct node_uid, uid, uids, 4708 LOOP_THROUGH(struct node_gid, gid, gids, 4709 4710 r->af = af; 4711 4712 error += collapse_redirspec(&r->rdr, r, rdr, 0); 4713 error += collapse_redirspec(&r->nat, r, nat, 0); 4714 error += collapse_redirspec(&r->route, r, rroute, 1); 4715 4716 /* disallow @if in from or to for the time being */ 4717 if ((src_host->addr.type == PF_ADDR_ADDRMASK && 4718 src_host->ifname) || 4719 (dst_host->addr.type == PF_ADDR_ADDRMASK && 4720 dst_host->ifname)) { 4721 yyerror("@if syntax not permitted in from or to"); 4722 error++; 4723 } 4724 /* for link-local IPv6 address, interface must match up */ 4725 if ((r->af && src_host->af && r->af != src_host->af) || 4726 (r->af && dst_host->af && r->af != dst_host->af) || 4727 (src_host->af && dst_host->af && 4728 src_host->af != dst_host->af) || 4729 (src_host->ifindex && dst_host->ifindex && 4730 src_host->ifindex != dst_host->ifindex) || 4731 (src_host->ifindex && *interface->ifname && 4732 src_host->ifindex != ifa_nametoindex(interface->ifname)) || 4733 (dst_host->ifindex && *interface->ifname && 4734 dst_host->ifindex != ifa_nametoindex(interface->ifname))) 4735 continue; 4736 if (!r->af && src_host->af) 4737 r->af = src_host->af; 4738 else if (!r->af && dst_host->af) 4739 r->af = dst_host->af; 4740 4741 if (*interface->ifname) 4742 strlcpy(r->ifname, interface->ifname, 4743 sizeof(r->ifname)); 4744 else if (ifa_indextoname(src_host->ifindex, ifname)) 4745 strlcpy(r->ifname, ifname, sizeof(r->ifname)); 4746 else if (ifa_indextoname(dst_host->ifindex, ifname)) 4747 strlcpy(r->ifname, ifname, sizeof(r->ifname)); 4748 else 4749 memset(r->ifname, '\0', sizeof(r->ifname)); 4750 4751 if (interface->use_rdomain) 4752 r->onrdomain = interface->rdomain; 4753 else 4754 r->onrdomain = -1; 4755 if (strlcpy(r->label, label, sizeof(r->label)) >= 4756 sizeof(r->label)) 4757 errx(1, "expand_rule: strlcpy"); 4758 if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >= 4759 sizeof(r->tagname)) 4760 errx(1, "expand_rule: strlcpy"); 4761 if (strlcpy(r->match_tagname, match_tagname, 4762 sizeof(r->match_tagname)) >= sizeof(r->match_tagname)) 4763 errx(1, "expand_rule: strlcpy"); 4764 expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af, 4765 src_host, src_port, dst_host, dst_port, proto->proto); 4766 expand_label(r->tagname, PF_TAG_NAME_SIZE, r->ifname, r->af, 4767 src_host, src_port, dst_host, dst_port, proto->proto); 4768 expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r->ifname, 4769 r->af, src_host, src_port, dst_host, dst_port, 4770 proto->proto); 4771 4772 osrch = odsth = NULL; 4773 if (src_host->addr.type == PF_ADDR_DYNIFTL) { 4774 osrch = src_host; 4775 if ((src_host = gen_dynnode(src_host, r->af)) == NULL) 4776 err(1, "expand_rule: calloc"); 4777 } 4778 if (dst_host->addr.type == PF_ADDR_DYNIFTL) { 4779 odsth = dst_host; 4780 if ((dst_host = gen_dynnode(dst_host, r->af)) == NULL) 4781 err(1, "expand_rule: calloc"); 4782 } 4783 4784 error += check_netmask(src_host, r->af); 4785 error += check_netmask(dst_host, r->af); 4786 4787 r->ifnot = interface->not; 4788 r->proto = proto->proto; 4789 r->src.addr = src_host->addr; 4790 r->src.neg = src_host->not; 4791 r->src.port[0] = src_port->port[0]; 4792 r->src.port[1] = src_port->port[1]; 4793 r->src.port_op = src_port->op; 4794 r->dst.addr = dst_host->addr; 4795 r->dst.neg = dst_host->not; 4796 r->dst.port[0] = dst_port->port[0]; 4797 r->dst.port[1] = dst_port->port[1]; 4798 r->dst.port_op = dst_port->op; 4799 r->uid.op = uid->op; 4800 r->uid.uid[0] = uid->uid[0]; 4801 r->uid.uid[1] = uid->uid[1]; 4802 r->gid.op = gid->op; 4803 r->gid.gid[0] = gid->gid[0]; 4804 r->gid.gid[1] = gid->gid[1]; 4805 if (rcv) { 4806 strlcpy(r->rcv_ifname, rcv->ifname, 4807 sizeof(r->rcv_ifname)); 4808 r->rcvifnot = rcv->not; 4809 } 4810 r->type = icmp_type->type; 4811 r->code = icmp_type->code; 4812 4813 if ((keep_state == PF_STATE_MODULATE || 4814 keep_state == PF_STATE_SYNPROXY) && 4815 r->proto && r->proto != IPPROTO_TCP) 4816 r->keep_state = PF_STATE_NORMAL; 4817 else 4818 r->keep_state = keep_state; 4819 4820 if (r->proto && r->proto != IPPROTO_TCP) { 4821 r->flags = 0; 4822 r->flagset = 0; 4823 } else { 4824 r->flags = flags; 4825 r->flagset = flagset; 4826 } 4827 if (icmp_type->proto && r->proto != icmp_type->proto) { 4828 yyerror("icmp-type mismatch"); 4829 error++; 4830 } 4831 4832 if (src_os && src_os->os) { 4833 r->os_fingerprint = pfctl_get_fingerprint(src_os->os); 4834 if ((pf->opts & PF_OPT_VERBOSE2) && 4835 r->os_fingerprint == PF_OSFP_NOMATCH) 4836 fprintf(stderr, 4837 "warning: unknown '%s' OS fingerprint\n", 4838 src_os->os); 4839 } else { 4840 r->os_fingerprint = PF_OSFP_ANY; 4841 } 4842 4843 if (nat && nat->rdr && nat->binat) { 4844 if (disallow_table(src_host, "invalid use of table " 4845 "<%s> as the source address of a binat-to rule") || 4846 disallow_alias(src_host, "invalid use of interface " 4847 "(%s) as the source address of a binat-to rule")) { 4848 error++; 4849 } else if ((r->src.addr.type != PF_ADDR_ADDRMASK && 4850 r->src.addr.type != PF_ADDR_DYNIFTL) || 4851 (r->nat.addr.type != PF_ADDR_ADDRMASK && 4852 r->nat.addr.type != PF_ADDR_DYNIFTL)) { 4853 yyerror("binat-to requires a specified " 4854 "source and redirect address"); 4855 error++; 4856 } 4857 if (DYNIF_MULTIADDR(r->src.addr) || 4858 DYNIF_MULTIADDR(r->nat.addr)) { 4859 yyerror ("dynamic interfaces must be used with " 4860 ":0 in a binat-to rule"); 4861 error++; 4862 } 4863 if (PF_AZERO(&r->src.addr.v.a.mask, af) || 4864 PF_AZERO(&r->nat.addr.v.a.mask, af)) { 4865 yyerror ("source and redir addresess must have " 4866 "a matching network mask in binat-rule"); 4867 error++; 4868 } 4869 if (r->nat.addr.type == PF_ADDR_TABLE) { 4870 yyerror ("tables cannot be used as the redirect " 4871 "address of a binat-to rule"); 4872 error++; 4873 } 4874 if (r->direction != PF_INOUT) { 4875 yyerror("binat-to cannot be specified " 4876 "with a direction"); 4877 error++; 4878 } 4879 4880 /* first specify outbound NAT rule */ 4881 r->direction = PF_OUT; 4882 } 4883 4884 error += apply_redirspec(&r->nat, r, nat, 0, dst_port); 4885 error += apply_redirspec(&r->rdr, r, rdr, 1, dst_port); 4886 error += apply_redirspec(&r->route, r, rroute, 2, dst_port); 4887 4888 if (rule_consistent(r, anchor_call[0]) < 0 || error) 4889 yyerror("skipping rule due to errors"); 4890 else { 4891 r->nr = pf->astack[pf->asd]->match++; 4892 pfctl_add_rule(pf, r, anchor_call); 4893 added++; 4894 } 4895 r->direction = dir; 4896 4897 /* Generate binat's matching inbound rule */ 4898 if (!error && nat && nat->rdr && nat->binat) { 4899 bcopy(r, &rb, sizeof(rb)); 4900 4901 /* now specify inbound rdr rule */ 4902 rb.direction = PF_IN; 4903 4904 if ((srch = calloc(1, sizeof(*srch))) == NULL) 4905 err(1, "expand_rule: calloc"); 4906 bcopy(src_host, srch, sizeof(*srch)); 4907 srch->ifname = NULL; 4908 srch->next = NULL; 4909 srch->tail = NULL; 4910 4911 if ((dsth = calloc(1, sizeof(*dsth))) == NULL) 4912 err(1, "expand_rule: calloc"); 4913 bcopy(&rb.nat.addr, &dsth->addr, sizeof(dsth->addr)); 4914 dsth->ifname = NULL; 4915 dsth->next = NULL; 4916 dsth->tail = NULL; 4917 4918 bzero(&binat, sizeof(binat)); 4919 if ((binat.rdr = 4920 calloc(1, sizeof(*binat.rdr))) == NULL) 4921 err(1, "expand_rule: calloc"); 4922 bcopy(nat->rdr, binat.rdr, sizeof(*binat.rdr)); 4923 bcopy(&nat->pool_opts, &binat.pool_opts, 4924 sizeof(binat.pool_opts)); 4925 binat.pool_opts.staticport = 0; 4926 binat.rdr->host = srch; 4927 4928 expand_rule(&rb, 1, interface, NULL, &binat, NULL, 4929 proto, 4930 src_os, dst_host, dst_port, dsth, src_port, 4931 uid, gid, rcv, icmp_type, anchor_call); 4932 } 4933 4934 if (osrch && src_host->addr.type == PF_ADDR_DYNIFTL) { 4935 free(src_host); 4936 src_host = osrch; 4937 } 4938 if (odsth && dst_host->addr.type == PF_ADDR_DYNIFTL) { 4939 free(dst_host); 4940 dst_host = odsth; 4941 } 4942 )))))))))); 4943 4944 if (!keeprule) { 4945 FREE_LIST(struct node_if, interfaces); 4946 FREE_LIST(struct node_proto, protos); 4947 FREE_LIST(struct node_host, src_hosts); 4948 FREE_LIST(struct node_port, src_ports); 4949 FREE_LIST(struct node_os, src_oses); 4950 FREE_LIST(struct node_host, dst_hosts); 4951 FREE_LIST(struct node_port, dst_ports); 4952 FREE_LIST(struct node_uid, uids); 4953 FREE_LIST(struct node_gid, gids); 4954 FREE_LIST(struct node_icmp, icmp_types); 4955 if (nat && nat->rdr) 4956 FREE_LIST(struct node_host, nat->rdr->host); 4957 if (rdr && rdr->rdr) 4958 FREE_LIST(struct node_host, rdr->rdr->host); 4959 4960 } 4961 4962 if (!added) 4963 yyerror("rule expands to no valid combination"); 4964} 4965 4966int 4967expand_skip_interface(struct node_if *interfaces) 4968{ 4969 int errs = 0; 4970 4971 if (!interfaces || (!interfaces->next && !interfaces->not && 4972 !strcmp(interfaces->ifname, "none"))) { 4973 if (pf->opts & PF_OPT_VERBOSE) 4974 printf("set skip on none\n"); 4975 errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0); 4976 return (errs); 4977 } 4978 4979 if (pf->opts & PF_OPT_VERBOSE) 4980 printf("set skip on {"); 4981 LOOP_THROUGH(struct node_if, interface, interfaces, 4982 if (pf->opts & PF_OPT_VERBOSE) 4983 printf(" %s", interface->ifname); 4984 if (interface->not) { 4985 yyerror("skip on ! <interface> is not supported"); 4986 errs++; 4987 } else if (interface->use_rdomain) { 4988 yyerror("skip on rdomain <num> is not supported"); 4989 errs++; 4990 } else 4991 errs += pfctl_set_interface_flags(pf, 4992 interface->ifname, PFI_IFLAG_SKIP, 1); 4993 ); 4994 if (pf->opts & PF_OPT_VERBOSE) 4995 printf(" }\n"); 4996 4997 FREE_LIST(struct node_if, interfaces); 4998 4999 if (errs) 5000 return (1); 5001 else 5002 return (0); 5003} 5004 5005void 5006freehostlist(struct node_host *h) 5007{ 5008 struct node_host *n; 5009 5010 for (n = h; n != NULL; n = n->next) 5011 if (n->ifname) 5012 free(n->ifname); 5013 FREE_LIST(struct node_host, h); 5014} 5015 5016#undef FREE_LIST 5017#undef LOOP_THROUGH 5018 5019int 5020kw_cmp(const void *k, const void *e) 5021{ 5022 return (strcmp(k, ((const struct keywords *)e)->k_name)); 5023} 5024 5025int 5026lookup(char *s) 5027{ 5028 /* this has to be sorted always */ 5029 static const struct keywords keywords[] = { 5030 { "af-to", AFTO}, 5031 { "all", ALL}, 5032 { "allow-opts", ALLOWOPTS}, 5033 { "anchor", ANCHOR}, 5034 { "antispoof", ANTISPOOF}, 5035 { "any", ANY}, 5036 { "bandwidth", BANDWIDTH}, 5037 { "binat-to", BINATTO}, 5038 { "bitmask", BITMASK}, 5039 { "block", BLOCK}, 5040 { "block-policy", BLOCKPOLICY}, 5041 { "burst", BURST}, 5042 { "code", CODE}, 5043 { "debug", DEBUG}, 5044 { "default", DEFAULT}, 5045 { "divert-packet", DIVERTPACKET}, 5046 { "divert-reply", DIVERTREPLY}, 5047 { "divert-to", DIVERTTO}, 5048 { "drop", DROP}, 5049 { "dup-to", DUPTO}, 5050 { "file", FILENAME}, 5051 { "fingerprints", FINGERPRINTS}, 5052 { "flags", FLAGS}, 5053 { "floating", FLOATING}, 5054 { "flows", FLOWS}, 5055 { "flush", FLUSH}, 5056 { "for", FOR}, 5057 { "fragment", FRAGMENT}, 5058 { "from", FROM}, 5059 { "global", GLOBAL}, 5060 { "group", GROUP}, 5061 { "hostid", HOSTID}, 5062 { "icmp-type", ICMPTYPE}, 5063 { "icmp6-type", ICMP6TYPE}, 5064 { "if-bound", IFBOUND}, 5065 { "in", IN}, 5066 { "include", INCLUDE}, 5067 { "inet", INET}, 5068 { "inet6", INET6}, 5069 { "keep", KEEP}, 5070 { "label", LABEL}, 5071 { "least-states", LEASTSTATES}, 5072 { "limit", LIMIT}, 5073 { "load", LOAD}, 5074 { "log", LOG}, 5075 { "loginterface", LOGINTERFACE}, 5076 { "match", MATCH}, 5077 { "matches", MATCHES}, 5078 { "max", MAXIMUM}, 5079 { "max-mss", MAXMSS}, 5080 { "max-pkt-rate", MAXPKTRATE}, 5081 { "max-src-conn", MAXSRCCONN}, 5082 { "max-src-conn-rate", MAXSRCCONNRATE}, 5083 { "max-src-nodes", MAXSRCNODES}, 5084 { "max-src-states", MAXSRCSTATES}, 5085 { "min", MINIMUM}, 5086 { "min-ttl", MINTTL}, 5087 { "modulate", MODULATE}, 5088 { "nat-to", NATTO}, 5089 { "no", NO}, 5090 { "no-df", NODF}, 5091 { "no-route", NOROUTE}, 5092 { "no-sync", NOSYNC}, 5093 { "on", ON}, 5094 { "once", ONCE}, 5095 { "optimization", OPTIMIZATION}, 5096 { "os", OS}, 5097 { "out", OUT}, 5098 { "overload", OVERLOAD}, 5099 { "parent", PARENT}, 5100 { "pass", PASS}, 5101 { "pflow", PFLOW}, 5102 { "port", PORT}, 5103 { "prio", PRIO}, 5104 { "probability", PROBABILITY}, 5105 { "proto", PROTO}, 5106 { "qlimit", QLIMIT}, 5107 { "quantum", QUANTUM}, 5108 { "queue", QUEUE}, 5109 { "quick", QUICK}, 5110 { "random", RANDOM}, 5111 { "random-id", RANDOMID}, 5112 { "rdomain", RDOMAIN}, 5113 { "rdr-to", RDRTO}, 5114 { "reassemble", REASSEMBLE}, 5115 { "received-on", RECEIVEDON}, 5116 { "reply-to", REPLYTO}, 5117 { "return", RETURN}, 5118 { "return-icmp", RETURNICMP}, 5119 { "return-icmp6", RETURNICMP6}, 5120 { "return-rst", RETURNRST}, 5121 { "round-robin", ROUNDROBIN}, 5122 { "route", ROUTE}, 5123 { "route-to", ROUTETO}, 5124 { "rtable", RTABLE}, 5125 { "rule", RULE}, 5126 { "ruleset-optimization", RULESET_OPTIMIZATION}, 5127 { "scrub", SCRUB}, 5128 { "set", SET}, 5129 { "skip", SKIP}, 5130 { "sloppy", SLOPPY}, 5131 { "source-hash", SOURCEHASH}, 5132 { "source-track", SOURCETRACK}, 5133 { "state", STATE}, 5134 { "state-defaults", STATEDEFAULTS}, 5135 { "state-policy", STATEPOLICY}, 5136 { "static-port", STATICPORT}, 5137 { "sticky-address", STICKYADDRESS}, 5138 { "synproxy", SYNPROXY}, 5139 { "table", TABLE}, 5140 { "tag", TAG}, 5141 { "tagged", TAGGED}, 5142 { "timeout", TIMEOUT}, 5143 { "to", TO}, 5144 { "tos", TOS}, 5145 { "ttl", TTL}, 5146 { "urpf-failed", URPFFAILED}, 5147 { "user", USER}, 5148 { "weight", WEIGHT}, 5149 }; 5150 const struct keywords *p; 5151 5152 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 5153 sizeof(keywords[0]), kw_cmp); 5154 5155 if (p) { 5156 if (debug > 1) 5157 fprintf(stderr, "%s: %d\n", s, p->k_val); 5158 return (p->k_val); 5159 } else { 5160 if (debug > 1) 5161 fprintf(stderr, "string: %s\n", s); 5162 return (STRING); 5163 } 5164} 5165 5166#define MAXPUSHBACK 128 5167 5168u_char *parsebuf; 5169int parseindex; 5170u_char pushback_buffer[MAXPUSHBACK]; 5171int pushback_index = 0; 5172 5173int 5174lgetc(int quotec) 5175{ 5176 int c, next; 5177 5178 if (parsebuf) { 5179 /* Read character from the parsebuffer instead of input. */ 5180 if (parseindex >= 0) { 5181 c = parsebuf[parseindex++]; 5182 if (c != '\0') 5183 return (c); 5184 parsebuf = NULL; 5185 } else 5186 parseindex++; 5187 } 5188 5189 if (pushback_index) 5190 return (pushback_buffer[--pushback_index]); 5191 5192 if (quotec) { 5193 if ((c = getc(file->stream)) == EOF) { 5194 yyerror("reached end of file while parsing quoted string"); 5195 if (popfile() == EOF) 5196 return (EOF); 5197 return (quotec); 5198 } 5199 return (c); 5200 } 5201 5202 while ((c = getc(file->stream)) == '\\') { 5203 next = getc(file->stream); 5204 if (next != '\n') { 5205 c = next; 5206 break; 5207 } 5208 yylval.lineno = file->lineno; 5209 file->lineno++; 5210 } 5211 5212 while (c == EOF) { 5213 if (popfile() == EOF) 5214 return (EOF); 5215 c = getc(file->stream); 5216 } 5217 return (c); 5218} 5219 5220int 5221lungetc(int c) 5222{ 5223 if (c == EOF) 5224 return (EOF); 5225 if (parsebuf) { 5226 parseindex--; 5227 if (parseindex >= 0) 5228 return (c); 5229 } 5230 if (pushback_index < MAXPUSHBACK-1) 5231 return (pushback_buffer[pushback_index++] = c); 5232 else 5233 return (EOF); 5234} 5235 5236int 5237findeol(void) 5238{ 5239 int c; 5240 5241 parsebuf = NULL; 5242 5243 /* skip to either EOF or the first real EOL */ 5244 while (1) { 5245 if (pushback_index) 5246 c = pushback_buffer[--pushback_index]; 5247 else 5248 c = lgetc(0); 5249 if (c == '\n') { 5250 file->lineno++; 5251 break; 5252 } 5253 if (c == EOF) 5254 break; 5255 } 5256 return (ERROR); 5257} 5258 5259int 5260yylex(void) 5261{ 5262 u_char buf[8096]; 5263 u_char *p, *val; 5264 int quotec, next, c; 5265 int token; 5266 5267top: 5268 p = buf; 5269 while ((c = lgetc(0)) == ' ' || c == '\t') 5270 ; /* nothing */ 5271 5272 yylval.lineno = file->lineno; 5273 if (c == '#') 5274 while ((c = lgetc(0)) != '\n' && c != EOF) 5275 ; /* nothing */ 5276 if (c == '$' && parsebuf == NULL) { 5277 while (1) { 5278 if ((c = lgetc(0)) == EOF) 5279 return (0); 5280 5281 if (p + 1 >= buf + sizeof(buf) - 1) { 5282 yyerror("string too long"); 5283 return (findeol()); 5284 } 5285 if (isalnum(c) || c == '_') { 5286 *p++ = c; 5287 continue; 5288 } 5289 *p = '\0'; 5290 lungetc(c); 5291 break; 5292 } 5293 val = symget(buf); 5294 if (val == NULL) { 5295 yyerror("macro '%s' not defined", buf); 5296 return (findeol()); 5297 } 5298 parsebuf = val; 5299 parseindex = 0; 5300 goto top; 5301 } 5302 5303 switch (c) { 5304 case '\'': 5305 case '"': 5306 quotec = c; 5307 while (1) { 5308 if ((c = lgetc(quotec)) == EOF) 5309 return (0); 5310 if (c == '\n') { 5311 file->lineno++; 5312 continue; 5313 } else if (c == '\\') { 5314 if ((next = lgetc(quotec)) == EOF) 5315 return (0); 5316 if (next == quotec || c == ' ' || c == '\t') 5317 c = next; 5318 else if (next == '\n') { 5319 file->lineno++; 5320 continue; 5321 } else 5322 lungetc(next); 5323 } else if (c == quotec) { 5324 *p = '\0'; 5325 break; 5326 } else if (c == '\0') { 5327 yyerror("syntax error"); 5328 return (findeol()); 5329 } 5330 if (p + 1 >= buf + sizeof(buf) - 1) { 5331 yyerror("string too long"); 5332 return (findeol()); 5333 } 5334 *p++ = c; 5335 } 5336 yylval.v.string = strdup(buf); 5337 if (yylval.v.string == NULL) 5338 err(1, "yylex: strdup"); 5339 return (STRING); 5340 case '!': 5341 next = lgetc(0); 5342 if (next == '=') 5343 return (NE); 5344 lungetc(next); 5345 break; 5346 case '<': 5347 next = lgetc(0); 5348 if (next == '>') { 5349 yylval.v.i = PF_OP_XRG; 5350 return (PORTBINARY); 5351 } else if (next == '=') 5352 return (LE); 5353 lungetc(next); 5354 break; 5355 case '>': 5356 next = lgetc(0); 5357 if (next == '<') { 5358 yylval.v.i = PF_OP_IRG; 5359 return (PORTBINARY); 5360 } else if (next == '=') 5361 return (GE); 5362 lungetc(next); 5363 break; 5364 } 5365 5366#define allowed_to_end_number(x) \ 5367 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') 5368 5369 if (c == '-' || isdigit(c)) { 5370 do { 5371 *p++ = c; 5372 if ((unsigned)(p-buf) >= sizeof(buf)) { 5373 yyerror("string too long"); 5374 return (findeol()); 5375 } 5376 } while ((c = lgetc(0)) != EOF && isdigit(c)); 5377 lungetc(c); 5378 if (p == buf + 1 && buf[0] == '-') 5379 goto nodigits; 5380 if (c == EOF || allowed_to_end_number(c)) { 5381 const char *errstr = NULL; 5382 5383 *p = '\0'; 5384 yylval.v.number = strtonum(buf, LLONG_MIN, 5385 LLONG_MAX, &errstr); 5386 if (errstr) { 5387 yyerror("\"%s\" invalid number: %s", 5388 buf, errstr); 5389 return (findeol()); 5390 } 5391 return (NUMBER); 5392 } else { 5393nodigits: 5394 while (p > buf + 1) 5395 lungetc(*--p); 5396 c = *--p; 5397 if (c == '-') 5398 return (c); 5399 } 5400 } 5401 5402#define allowed_in_string(x) \ 5403 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 5404 x != '{' && x != '}' && x != '<' && x != '>' && \ 5405 x != '!' && x != '=' && x != '/' && x != '#' && \ 5406 x != ',')) 5407 5408 if (isalnum(c) || c == ':' || c == '_') { 5409 do { 5410 *p++ = c; 5411 if ((unsigned)(p-buf) >= sizeof(buf)) { 5412 yyerror("string too long"); 5413 return (findeol()); 5414 } 5415 } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); 5416 lungetc(c); 5417 *p = '\0'; 5418 if ((token = lookup(buf)) == STRING) 5419 if ((yylval.v.string = strdup(buf)) == NULL) 5420 err(1, "yylex: strdup"); 5421 return (token); 5422 } 5423 if (c == '\n') { 5424 yylval.lineno = file->lineno; 5425 file->lineno++; 5426 } 5427 if (c == EOF) 5428 return (0); 5429 return (c); 5430} 5431 5432int 5433check_file_secrecy(int fd, const char *fname) 5434{ 5435 struct stat st; 5436 5437 if (fstat(fd, &st)) { 5438 warn("cannot stat %s", fname); 5439 return (-1); 5440 } 5441 if (st.st_uid != 0 && st.st_uid != getuid()) { 5442 warnx("%s: owner not root or current user", fname); 5443 return (-1); 5444 } 5445 if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) { 5446 warnx("%s: group writable or world read/writable", fname); 5447 return (-1); 5448 } 5449 return (0); 5450} 5451 5452struct file * 5453pushfile(const char *name, int secret) 5454{ 5455 struct file *nfile; 5456 5457 if ((nfile = calloc(1, sizeof(struct file))) == NULL || 5458 (nfile->name = strdup(name)) == NULL) { 5459 if (nfile) 5460 free(nfile); 5461 warn("malloc"); 5462 return (NULL); 5463 } 5464 if (TAILQ_FIRST(&files) == NULL && strcmp(nfile->name, "-") == 0) { 5465 nfile->stream = stdin; 5466 free(nfile->name); 5467 if ((nfile->name = strdup("stdin")) == NULL) { 5468 warn("strdup"); 5469 free(nfile); 5470 return (NULL); 5471 } 5472 } else if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { 5473 warn("%s", nfile->name); 5474 free(nfile->name); 5475 free(nfile); 5476 return (NULL); 5477 } else if (secret && 5478 check_file_secrecy(fileno(nfile->stream), nfile->name)) { 5479 fclose(nfile->stream); 5480 free(nfile->name); 5481 free(nfile); 5482 return (NULL); 5483 } 5484 nfile->lineno = 1; 5485 TAILQ_INSERT_TAIL(&files, nfile, entry); 5486 return (nfile); 5487} 5488 5489int 5490popfile(void) 5491{ 5492 struct file *prev; 5493 5494 if ((prev = TAILQ_PREV(file, files, entry)) != NULL) { 5495 prev->errors += file->errors; 5496 TAILQ_REMOVE(&files, file, entry); 5497 fclose(file->stream); 5498 free(file->name); 5499 free(file); 5500 file = prev; 5501 return (0); 5502 } 5503 return (EOF); 5504} 5505 5506int 5507parse_config(char *filename, struct pfctl *xpf) 5508{ 5509 int errors = 0; 5510 struct sym *sym; 5511 5512 pf = xpf; 5513 returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 5514 returnicmp6default = 5515 (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT; 5516 blockpolicy = PFRULE_DROP; 5517 5518 if ((file = pushfile(filename, 0)) == NULL) { 5519 warn("cannot open the main config file!"); 5520 return (-1); 5521 } 5522 5523 yyparse(); 5524 errors = file->errors; 5525 popfile(); 5526 5527 /* Free macros and check which have not been used. */ 5528 while ((sym = TAILQ_FIRST(&symhead))) { 5529 if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used) 5530 fprintf(stderr, "warning: macro '%s' not " 5531 "used\n", sym->nam); 5532 free(sym->nam); 5533 free(sym->val); 5534 TAILQ_REMOVE(&symhead, sym, entry); 5535 free(sym); 5536 } 5537 5538 return (errors ? -1 : 0); 5539} 5540 5541int 5542symset(const char *nam, const char *val, int persist) 5543{ 5544 struct sym *sym; 5545 5546 TAILQ_FOREACH(sym, &symhead, entry) { 5547 if (strcmp(nam, sym->nam) == 0) 5548 break; 5549 } 5550 5551 if (sym != NULL) { 5552 if (sym->persist == 1) 5553 return (0); 5554 else { 5555 free(sym->nam); 5556 free(sym->val); 5557 TAILQ_REMOVE(&symhead, sym, entry); 5558 free(sym); 5559 } 5560 } 5561 if ((sym = calloc(1, sizeof(*sym))) == NULL) 5562 return (-1); 5563 5564 sym->nam = strdup(nam); 5565 if (sym->nam == NULL) { 5566 free(sym); 5567 return (-1); 5568 } 5569 sym->val = strdup(val); 5570 if (sym->val == NULL) { 5571 free(sym->nam); 5572 free(sym); 5573 return (-1); 5574 } 5575 sym->used = 0; 5576 sym->persist = persist; 5577 TAILQ_INSERT_TAIL(&symhead, sym, entry); 5578 return (0); 5579} 5580 5581int 5582pfctl_cmdline_symset(char *s) 5583{ 5584 char *sym, *val; 5585 int ret; 5586 5587 if ((val = strrchr(s, '=')) == NULL) 5588 return (-1); 5589 5590 if ((sym = malloc(strlen(s) - strlen(val) + 1)) == NULL) 5591 err(1, "pfctl_cmdline_symset: malloc"); 5592 5593 strlcpy(sym, s, strlen(s) - strlen(val) + 1); 5594 5595 ret = symset(sym, val + 1, 1); 5596 free(sym); 5597 5598 return (ret); 5599} 5600 5601char * 5602symget(const char *nam) 5603{ 5604 struct sym *sym; 5605 5606 TAILQ_FOREACH(sym, &symhead, entry) { 5607 if (strcmp(nam, sym->nam) == 0) { 5608 sym->used = 1; 5609 return (sym->val); 5610 } 5611 } 5612 return (NULL); 5613} 5614 5615void 5616mv_rules(struct pf_ruleset *src, struct pf_ruleset *dst) 5617{ 5618 struct pf_rule *r; 5619 5620 while ((r = TAILQ_FIRST(src->rules.active.ptr)) != NULL) { 5621 TAILQ_REMOVE(src->rules.active.ptr, r, entries); 5622 TAILQ_INSERT_TAIL(dst->rules.active.ptr, r, entries); 5623 dst->anchor->match++; 5624 } 5625 src->anchor->match = 0; 5626 while ((r = TAILQ_FIRST(src->rules.inactive.ptr)) != NULL) { 5627 TAILQ_REMOVE(src->rules.inactive.ptr, r, entries); 5628 TAILQ_INSERT_TAIL(dst->rules.inactive.ptr, r, entries); 5629 } 5630} 5631 5632void 5633decide_address_family(struct node_host *n, sa_family_t *af) 5634{ 5635 if (*af != 0 || n == NULL) 5636 return; 5637 *af = n->af; 5638 while ((n = n->next) != NULL) { 5639 if (n->af != *af) { 5640 *af = 0; 5641 return; 5642 } 5643 } 5644} 5645 5646int 5647invalid_redirect(struct node_host *nh, sa_family_t af) 5648{ 5649 if (!af) { 5650 struct node_host *n; 5651 5652 /* tables and dyniftl are ok without an address family */ 5653 for (n = nh; n != NULL; n = n->next) { 5654 if (n->addr.type != PF_ADDR_TABLE && 5655 n->addr.type != PF_ADDR_DYNIFTL) { 5656 yyerror("address family not given and " 5657 "translation address expands to multiple " 5658 "address families"); 5659 return (1); 5660 } 5661 } 5662 } 5663 if (nh == NULL) { 5664 yyerror("no translation address with matching address family " 5665 "found."); 5666 return (1); 5667 } 5668 return (0); 5669} 5670 5671int 5672atoul(char *s, u_long *ulvalp) 5673{ 5674 u_long ulval; 5675 char *ep; 5676 5677 errno = 0; 5678 ulval = strtoul(s, &ep, 0); 5679 if (s[0] == '\0' || *ep != '\0') 5680 return (-1); 5681 if (errno == ERANGE && ulval == ULONG_MAX) 5682 return (-1); 5683 *ulvalp = ulval; 5684 return (0); 5685} 5686 5687int 5688getservice(char *n) 5689{ 5690 struct servent *s; 5691 u_long ulval; 5692 5693 if (atoul(n, &ulval) == 0) { 5694 if (ulval > 65535) { 5695 yyerror("illegal port value %lu", ulval); 5696 return (-1); 5697 } 5698 return (htons(ulval)); 5699 } else { 5700 s = getservbyname(n, "tcp"); 5701 if (s == NULL) 5702 s = getservbyname(n, "udp"); 5703 if (s == NULL) { 5704 yyerror("unknown port %s", n); 5705 return (-1); 5706 } 5707 return (s->s_port); 5708 } 5709} 5710 5711int 5712rule_label(struct pf_rule *r, char *s) 5713{ 5714 if (s) { 5715 if (strlcpy(r->label, s, sizeof(r->label)) >= 5716 sizeof(r->label)) { 5717 yyerror("rule label too long (max %d chars)", 5718 sizeof(r->label)-1); 5719 return (-1); 5720 } 5721 } 5722 return (0); 5723} 5724 5725u_int16_t 5726parseicmpspec(char *w, sa_family_t af) 5727{ 5728 const struct icmpcodeent *p; 5729 u_long ulval; 5730 u_int8_t icmptype; 5731 5732 if (af == AF_INET) 5733 icmptype = returnicmpdefault >> 8; 5734 else 5735 icmptype = returnicmp6default >> 8; 5736 5737 if (atoul(w, &ulval) == -1) { 5738 if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) { 5739 yyerror("unknown icmp code %s", w); 5740 return (0); 5741 } 5742 ulval = p->code; 5743 } 5744 if (ulval > 255) { 5745 yyerror("invalid icmp code %lu", ulval); 5746 return (0); 5747 } 5748 return (icmptype << 8 | ulval); 5749} 5750 5751int 5752parseport(char *port, struct range *r, int extensions) 5753{ 5754 char *p = strchr(port, ':'); 5755 5756 if (p == NULL) { 5757 if ((r->a = getservice(port)) == -1) 5758 return (-1); 5759 r->b = 0; 5760 r->t = PF_OP_NONE; 5761 return (0); 5762 } 5763 if ((extensions & PPORT_STAR) && !strcmp(p+1, "*")) { 5764 *p = 0; 5765 if ((r->a = getservice(port)) == -1) 5766 return (-1); 5767 r->b = 0; 5768 r->t = PF_OP_IRG; 5769 return (0); 5770 } 5771 if ((extensions & PPORT_RANGE)) { 5772 *p++ = 0; 5773 if ((r->a = getservice(port)) == -1 || 5774 (r->b = getservice(p)) == -1) 5775 return (-1); 5776 if (r->a == r->b) { 5777 r->b = 0; 5778 r->t = PF_OP_NONE; 5779 } else 5780 r->t = PF_OP_RRG; 5781 return (0); 5782 } 5783 return (-1); 5784} 5785 5786int 5787pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans) 5788{ 5789 struct loadanchors *la; 5790 5791 TAILQ_FOREACH(la, &loadanchorshead, entries) { 5792 if (pf->opts & PF_OPT_VERBOSE) 5793 fprintf(stderr, "\nLoading anchor %s from %s\n", 5794 la->anchorname, la->filename); 5795 if (pfctl_rules(dev, la->filename, pf->opts, pf->optimize, 5796 la->anchorname, trans) == -1) 5797 return (-1); 5798 } 5799 5800 return (0); 5801} 5802 5803int 5804kw_casecmp(const void *k, const void *e) 5805{ 5806 return (strcasecmp(k, ((const struct keywords *)e)->k_name)); 5807} 5808 5809int 5810map_tos(char *s, int *val) 5811{ 5812 /* DiffServ Codepoints and other TOS mappings */ 5813 const struct keywords toswords[] = { 5814 { "af11", IPTOS_DSCP_AF11 }, 5815 { "af12", IPTOS_DSCP_AF12 }, 5816 { "af13", IPTOS_DSCP_AF13 }, 5817 { "af21", IPTOS_DSCP_AF21 }, 5818 { "af22", IPTOS_DSCP_AF22 }, 5819 { "af23", IPTOS_DSCP_AF23 }, 5820 { "af31", IPTOS_DSCP_AF31 }, 5821 { "af32", IPTOS_DSCP_AF32 }, 5822 { "af33", IPTOS_DSCP_AF33 }, 5823 { "af41", IPTOS_DSCP_AF41 }, 5824 { "af42", IPTOS_DSCP_AF42 }, 5825 { "af43", IPTOS_DSCP_AF43 }, 5826 { "critical", IPTOS_PREC_CRITIC_ECP }, 5827 { "cs0", IPTOS_DSCP_CS0 }, 5828 { "cs1", IPTOS_DSCP_CS1 }, 5829 { "cs2", IPTOS_DSCP_CS2 }, 5830 { "cs3", IPTOS_DSCP_CS3 }, 5831 { "cs4", IPTOS_DSCP_CS4 }, 5832 { "cs5", IPTOS_DSCP_CS5 }, 5833 { "cs6", IPTOS_DSCP_CS6 }, 5834 { "cs7", IPTOS_DSCP_CS7 }, 5835 { "ef", IPTOS_DSCP_EF }, 5836 { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, 5837 { "lowdelay", IPTOS_LOWDELAY }, 5838 { "netcontrol", IPTOS_PREC_NETCONTROL }, 5839 { "reliability", IPTOS_RELIABILITY }, 5840 { "throughput", IPTOS_THROUGHPUT } 5841 }; 5842 const struct keywords *p; 5843 5844 p = bsearch(s, toswords, sizeof(toswords)/sizeof(toswords[0]), 5845 sizeof(toswords[0]), kw_casecmp); 5846 5847 if (p) { 5848 *val = p->k_val; 5849 return (1); 5850 } 5851 return (0); 5852} 5853