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