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