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