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