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