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