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