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