parse.y revision 1.104
1/* $OpenBSD: parse.y,v 1.104 2002/06/20 08:47:58 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 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 51#include "pfctl_parser.h" 52 53static struct pfctl *pf = NULL; 54static FILE *fin = NULL; 55static int debug = 0; 56static int lineno = 1; 57static int errors = 0; 58static int rulestate = 0; 59 60enum {PFCTL_STATE_NONE=0, PFCTL_STATE_SCRUB=1, 61 PFCTL_STATE_NAT=2, PFCTL_STATE_FILTER=3}; 62 63struct node_if { 64 char ifname[IFNAMSIZ]; 65 u_int8_t not; 66 struct node_if *next; 67}; 68 69struct node_proto { 70 u_int8_t proto; 71 struct node_proto *next; 72}; 73 74struct node_host { 75 struct pf_addr_wrap addr; 76 struct pf_addr mask; 77 u_int8_t af; 78 u_int8_t not; 79 u_int8_t noroute; 80 struct node_host *next; 81 u_int32_t ifindex; /* link-local IPv6 addrs */ 82}; 83 84struct node_port { 85 u_int16_t port[2]; 86 u_int8_t op; 87 struct node_port *next; 88}; 89 90struct node_uid { 91 uid_t uid[2]; 92 u_int8_t op; 93 struct node_uid *next; 94}; 95 96struct node_gid { 97 gid_t gid[2]; 98 u_int8_t op; 99 struct node_gid *next; 100}; 101 102struct node_icmp { 103 u_int8_t code; 104 u_int8_t type; 105 u_int8_t proto; 106 struct node_icmp *next; 107}; 108 109enum { PF_STATE_OPT_MAX=0, PF_STATE_OPT_TIMEOUT=1 }; 110struct node_state_opt { 111 int type; 112 union { 113 u_int32_t max_states; 114 struct { 115 int number; 116 u_int32_t seconds; 117 } timeout; 118 } data; 119 struct node_state_opt *next; 120}; 121 122struct peer { 123 struct node_host *host; 124 struct node_port *port; 125}; 126 127int rule_consistent(struct pf_rule *); 128int yyparse(void); 129void ipmask(struct pf_addr *, u_int8_t); 130void expand_rdr(struct pf_rdr *, struct node_if *, struct node_host *, 131 struct node_host *); 132void expand_nat(struct pf_nat *, struct node_host *, struct node_port *, 133 struct node_host *, struct node_port *); 134void expand_label_addr(const char *, char *, u_int8_t, struct node_host *); 135void expand_label_port(const char *, char *, struct node_port *); 136void expand_label_proto(const char *, char *, u_int8_t); 137void expand_label_nr(const char *, char *); 138void expand_label(char *, u_int8_t, struct node_host *, struct node_port *, 139 struct node_host *, struct node_port *, u_int8_t); 140void expand_rule(struct pf_rule *, struct node_if *, struct node_proto *, 141 struct node_host *, struct node_port *, struct node_host *, 142 struct node_port *, struct node_uid *, struct node_gid *, 143 struct node_icmp *); 144 145struct sym { 146 struct sym *next; 147 char *nam; 148 char *val; 149}; 150struct sym *symhead = NULL; 151 152int symset(char *name, char *val); 153char * symget(char *name); 154 155struct ifaddrs *ifa0_lookup(char *ifa_name); 156struct ifaddrs *ifa4_lookup(char *ifa_name); 157struct ifaddrs *ifa6_lookup(char *ifa_name); 158 159typedef struct { 160 union { 161 u_int32_t number; 162 int i; 163 char *string; 164 struct { 165 u_int8_t b1; 166 u_int8_t b2; 167 u_int16_t w; 168 } b; 169 struct range { 170 int a; 171 int b; 172 int t; 173 } range; 174 struct node_if *interface; 175 struct node_proto *proto; 176 struct node_icmp *icmp; 177 struct node_host *host; 178 struct node_port *port; 179 struct node_uid *uid; 180 struct node_gid *gid; 181 struct node_state_opt *state_opt; 182 struct peer peer; 183 struct { 184 struct peer src, dst; 185 } fromto; 186 struct { 187 char *string; 188 struct pf_addr *addr; 189 u_int8_t rt; 190 u_int8_t af; 191 } route; 192 struct redirection { 193 struct node_host *address; 194 struct range rport; 195 } *redirection; 196 struct { 197 int action; 198 struct node_state_opt *options; 199 } keep_state; 200 } v; 201 int lineno; 202} YYSTYPE; 203 204%} 205 206%token PASS BLOCK SCRUB RETURN IN OUT LOG LOGALL QUICK ON FROM TO FLAGS 207%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE 208%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF 209%token MINTTL IPV6ADDR ERROR ALLOWOPTS FASTROUTE ROUTETO DUPTO NO LABEL 210%token NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL 211%token FRAGNORM FRAGDROP FRAGCROP 212%token <v.string> STRING 213%token <v.number> NUMBER 214%token <v.i> PORTUNARY PORTBINARY 215%type <v.interface> interface if_list if_item_not if_item 216%type <v.number> port icmptype icmp6type minttl uid gid maxmss 217%type <v.i> no dir log quick af nodf allowopts fragment fragcache 218%type <v.b> action flag flags blockspec 219%type <v.range> dport rport 220%type <v.proto> proto proto_list proto_item 221%type <v.icmp> icmpspec icmp_list icmp6_list icmp_item icmp6_item 222%type <v.fromto> fromto 223%type <v.peer> ipportspec 224%type <v.host> ipspec xhost host address host_list IPV6ADDR 225%type <v.port> portspec port_list port_item 226%type <v.uid> uids uid_list uid_item 227%type <v.gid> gids gid_list gid_item 228%type <v.route> route 229%type <v.redirection> redirection 230%type <v.string> label 231%type <v.keep_state> keep 232%type <v.state_opt> state_opt_spec state_opt_list state_opt_item 233%% 234 235ruleset : /* empty */ 236 | ruleset '\n' 237 | ruleset scrubrule '\n' 238 | ruleset natrule '\n' 239 | ruleset binatrule '\n' 240 | ruleset rdrrule '\n' 241 | ruleset pfrule '\n' 242 | ruleset varset '\n' 243 | ruleset error '\n' { errors++; } 244 ; 245 246varset : STRING PORTUNARY STRING 247 { 248 if (pf->opts & PF_OPT_VERBOSE) 249 printf("%s = %s\n", $1, $3); 250 if (symset($1, $3) == -1) { 251 yyerror("cannot store variable %s", $1); 252 YYERROR; 253 } 254 } 255 ; 256 257scrubrule : SCRUB dir interface fromto nodf minttl maxmss fragcache 258 { 259 struct pf_rule r; 260 261 if (rulestate > PFCTL_STATE_SCRUB) { 262 yyerror("Rules must be in order: " 263 "scrub, nat, filter"); 264 YYERROR; 265 } 266 rulestate = PFCTL_STATE_SCRUB; 267 268 memset(&r, 0, sizeof(r)); 269 270 r.action = PF_SCRUB; 271 r.direction = $2; 272 273 if ($5) 274 r.rule_flag |= PFRULE_NODF; 275 if ($6) 276 r.min_ttl = $6; 277 if ($7) 278 r.max_mss = $7; 279 280 if ($8) 281 r.rule_flag |= $8; 282 283 r.nr = pf->rule_nr++; 284 pfctl_add_rule(pf, &r); 285 286 } 287 ; 288 289pfrule : action dir log quick interface route af proto fromto 290 uids gids flags icmpspec keep fragment allowopts label 291 { 292 struct pf_rule r; 293 struct node_state_opt *o; 294 295 if (rulestate > PFCTL_STATE_FILTER) { 296 yyerror("Rules must be in order: " 297 "scrub, nat, filter"); 298 YYERROR; 299 } 300 rulestate = PFCTL_STATE_FILTER; 301 302 memset(&r, 0, sizeof(r)); 303 304 r.action = $1.b1; 305 if ($1.b2) { 306 r.rule_flag |= PFRULE_RETURNRST; 307 r.return_ttl = $1.w; 308 } else 309 r.return_icmp = $1.w; 310 r.direction = $2; 311 r.log = $3; 312 r.quick = $4; 313 314 315 r.af = $7; 316 r.flags = $12.b1; 317 r.flagset = $12.b2; 318 319 r.keep_state = $14.action; 320 o = $14.options; 321 while (o) { 322 struct node_state_opt *p = o; 323 324 switch (o->type) { 325 case PF_STATE_OPT_MAX: 326 if (r.max_states) { 327 yyerror("state option 'max' " 328 "multiple definitions"); 329 YYERROR; 330 } 331 r.max_states = o->data.max_states; 332 break; 333 case PF_STATE_OPT_TIMEOUT: 334 if (r.timeout[o->data.timeout.number]) { 335 yyerror("state timeout %s " 336 "multiple definitions", 337 pf_timeouts[o->data. 338 timeout.number].name); 339 YYERROR; 340 } 341 r.timeout[o->data.timeout.number] = 342 o->data.timeout.seconds; 343 } 344 o = o->next; 345 free(p); 346 } 347 348 if ($15) 349 r.rule_flag |= PFRULE_FRAGMENT; 350 r.allow_opts = $16; 351 352 if ($6.rt) { 353 r.rt = $6.rt; 354 if ($6.string) { 355 memcpy(r.rt_ifname, $6.string, 356 sizeof(r.rt_ifname)); 357 free($6.string); 358 } 359 if ($6.addr) { 360 if (!r.af) 361 r.af = $6.af; 362 else if (r.af != $6.af) { 363 yyerror("address family" 364 " mismatch"); 365 YYERROR; 366 } 367 memcpy(&r.rt_addr, $6.addr, 368 sizeof(r.rt_addr)); 369 free($6.addr); 370 } 371 } 372 373 if ($17) { 374 if (strlen($17) >= PF_RULE_LABEL_SIZE) { 375 yyerror("rule label too long (max " 376 "%d chars)", PF_RULE_LABEL_SIZE-1); 377 YYERROR; 378 } 379 strlcpy(r.label, $17, sizeof(r.label)); 380 free($17); 381 } 382 383 expand_rule(&r, $5, $8, $9.src.host, $9.src.port, 384 $9.dst.host, $9.dst.port, $10, $11, $13); 385 } 386 ; 387 388action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; } 389 | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } 390 ; 391 392blockspec : /* empty */ { $$.b2 = 0; $$.w = 0; } 393 | RETURNRST { $$.b2 = 1; $$.w = 0;} 394 | RETURNRST '(' TTL NUMBER ')' { 395 $$.w = $4; 396 $$.b2 = 1; 397 } 398 | RETURNICMP { 399 $$.b2 = 0; 400 $$.w = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 401 } 402 | RETURNICMP6 { 403 $$.b2 = 0; 404 $$.w = (ICMP6_DST_UNREACH << 8) | 405 ICMP6_DST_UNREACH_NOPORT; 406 } 407 | RETURNICMP '(' NUMBER ')' { 408 $$.w = (ICMP_UNREACH << 8) | $3; 409 $$.b2 = 0; 410 } 411 | RETURNICMP '(' STRING ')' { 412 const struct icmpcodeent *p; 413 414 if ((p = geticmpcodebyname(ICMP_UNREACH, $3, 415 AF_INET)) == NULL) { 416 yyerror("unknown icmp code %s", $3); 417 YYERROR; 418 } 419 $$.w = (p->type << 8) | p->code; 420 $$.b2 = 0; 421 } 422 | RETURNICMP6 '(' NUMBER ')' { 423 $$.w = (ICMP6_DST_UNREACH << 8) | $3; 424 $$.b2 = 0; 425 } 426 | RETURNICMP6 '(' STRING ')' { 427 const struct icmpcodeent *p; 428 429 if ((p = geticmpcodebyname(ICMP6_DST_UNREACH, $3, 430 AF_INET6)) == NULL) { 431 yyerror("unknown icmp code %s", $3); 432 YYERROR; 433 } 434 $$.w = (p->type << 8) | p->code; 435 $$.b2 = 0; 436 } 437 ; 438 439fragcache : /* empty */ { $$ = 0; } 440 | fragment FRAGNORM { $$ = 0; /* default */ } 441 | fragment FRAGCROP { $$ = PFRULE_FRAGCROP; } 442 | fragment FRAGDROP { $$ = PFRULE_FRAGDROP; } 443 ; 444 445 446dir : IN { $$ = PF_IN; } 447 | OUT { $$ = PF_OUT; } 448 ; 449 450log : /* empty */ { $$ = 0; } 451 | LOG { $$ = 1; } 452 | LOGALL { $$ = 2; } 453 ; 454 455quick : /* empty */ { $$ = 0; } 456 | QUICK { $$ = 1; } 457 ; 458 459interface : /* empty */ { $$ = NULL; } 460 | ON if_item_not { $$ = $2; } 461 | ON '{' if_list '}' { $$ = $3; } 462 ; 463 464if_list : if_item_not { $$ = $1; } 465 | if_list ',' if_item_not { $3->next = $1; $$ = $3; } 466 ; 467 468if_item_not : '!' if_item { $$ = $2; $$->not = 1; } 469 | if_item { $$ = $1; } 470 471if_item : STRING { 472 if (ifa0_lookup($1) == 0) { 473 yyerror("unknown interface %s", $1); 474 YYERROR; 475 } 476 $$ = malloc(sizeof(struct node_if)); 477 if ($$ == NULL) 478 err(1, "if_item: malloc"); 479 strlcpy($$->ifname, $1, IFNAMSIZ); 480 $$->not = 0; 481 $$->next = NULL; 482 } 483 ; 484 485af : /* empty */ { $$ = 0; } 486 | INET { $$ = AF_INET; } 487 | INET6 { $$ = AF_INET6; } 488 489proto : /* empty */ { $$ = NULL; } 490 | PROTO proto_item { $$ = $2; } 491 | PROTO '{' proto_list '}' { $$ = $3; } 492 ; 493 494proto_list : proto_item { $$ = $1; } 495 | proto_list ',' proto_item { $3->next = $1; $$ = $3; } 496 ; 497 498proto_item : NUMBER { 499 struct protoent *p; 500 501 if ((p = getprotobynumber($1)) == NULL) { 502 yyerror("unknown protocol %d", $1); 503 YYERROR; 504 } 505 $$ = malloc(sizeof(struct node_proto)); 506 if ($$ == NULL) 507 err(1, "proto_item: malloc"); 508 $$->proto = p->p_proto; 509 $$->next = NULL; 510 } 511 | STRING { 512 struct protoent *p; 513 514 if ((p = getprotobyname($1)) == NULL) { 515 yyerror("unknown protocol %s", $1); 516 YYERROR; 517 } 518 $$ = malloc(sizeof(struct node_proto)); 519 if ($$ == NULL) 520 err(1, "proto_item: malloc"); 521 $$->proto = p->p_proto; 522 $$->next = NULL; 523 } 524 ; 525 526fromto : ALL { 527 $$.src.host = NULL; 528 $$.src.port = NULL; 529 $$.dst.host = NULL; 530 $$.dst.port = NULL; 531 } 532 | FROM ipportspec TO ipportspec { 533 $$.src = $2; 534 $$.dst = $4; 535 } 536 ; 537 538ipportspec : ipspec { $$.host = $1; $$.port = NULL; } 539 | ipspec PORT portspec { 540 $$.host = $1; 541 $$.port = $3; 542 } 543 ; 544 545ipspec : ANY { $$ = NULL; } 546 | xhost { $$ = $1; } 547 | '{' host_list '}' { $$ = $2; } 548 ; 549 550host_list : xhost { $$ = $1; } 551 | host_list ',' xhost { 552 /* both $1 and $3 may be lists, so join them */ 553 $$ = $3; 554 while ($3->next) 555 $3 = $3->next; 556 $3->next = $1; 557 } 558 ; 559 560xhost : '!' host { 561 struct node_host *h; 562 for (h = $2; h; h = h->next) 563 h->not = 1; 564 $$ = $2; 565 } 566 | host { $$ = $1; } 567 | NOROUTE { 568 $$ = calloc(1, sizeof(struct node_host)); 569 if ($$ == NULL) 570 err(1, "xhost: calloc"); 571 $$->noroute = 1; 572 } 573 ; 574 575host : address { 576 struct node_host *n; 577 for (n = $1; n; n = n->next) 578 if (n->af == AF_INET) 579 ipmask(&n->mask, 32); 580 else 581 ipmask(&n->mask, 128); 582 $$ = $1; 583 } 584 | address '/' NUMBER { 585 struct node_host *n; 586 for (n = $1; n; n = n->next) { 587 if ($1->af == AF_INET) { 588 if ($3 < 0 || $3 > 32) { 589 yyerror( 590 "illegal netmask value %d", 591 $3); 592 YYERROR; 593 } 594 } else { 595 if ($3 < 0 || $3 > 128) { 596 yyerror( 597 "illegal netmask value %d", 598 $3); 599 YYERROR; 600 } 601 } 602 ipmask(&n->mask, $3); 603 } 604 $$ = $1; 605 } 606 ; 607 608address : '(' STRING ')' { 609 $$ = calloc(1, sizeof(struct node_host)); 610 if ($$ == NULL) 611 err(1, "address: calloc"); 612 $$->af = 0; 613 $$->addr.addr_dyn = (struct pf_addr_dyn *)1; 614 strncpy($$->addr.addr.pfa.ifname, $2, 615 sizeof($$->addr.addr.pfa.ifname)); 616 } 617 | STRING { 618 if (ifa0_lookup($1)) { 619 struct ifaddrs *ifa; 620 621 /* an interface with this name exists */ 622 if ((ifa = ifa4_lookup($1))) { 623 struct sockaddr_in *sin = 624 (struct sockaddr_in *) 625 ifa->ifa_addr; 626 627 $$ = calloc(1, 628 sizeof(struct node_host)); 629 if ($$ == NULL) 630 err(1, "address: calloc"); 631 $$->af = AF_INET; 632 $$->addr.addr_dyn = NULL; 633 memcpy(&$$->addr.addr, &sin->sin_addr, 634 sizeof(u_int32_t)); 635 } else if ((ifa = ifa6_lookup($1))) { 636 struct sockaddr_in6 *sin6 = 637 (struct sockaddr_in6 *) 638 ifa->ifa_addr; 639 640 $$ = calloc(1, 641 sizeof(struct node_host)); 642 if ($$ == NULL) 643 err(1, "address: calloc"); 644 $$->af = AF_INET6; 645 $$->addr.addr_dyn = NULL; 646 memcpy(&$$->addr.addr, &sin6->sin6_addr, 647 sizeof(struct pf_addr)); 648 } else { 649 yyerror("interface %s has no IP " 650 "addresses", $1); 651 YYERROR; 652 } 653 } else { 654 struct node_host *h = NULL, *n; 655 struct addrinfo hints, *res0, *res; 656 int error; 657 658 memset(&hints, 0, sizeof(hints)); 659 hints.ai_family = PF_UNSPEC; 660 hints.ai_socktype = SOCK_STREAM; /* DUMMY */ 661 error = getaddrinfo($1, NULL, &hints, &res0); 662 if (error) { 663 yyerror("cannot resolve %s: %s", 664 $1, gai_strerror(error)); 665 YYERROR; 666 } 667 for (res = res0; res; res = res->ai_next) { 668 if (res->ai_family != AF_INET && 669 res->ai_family != AF_INET6) 670 continue; 671 n = calloc(1, sizeof(struct node_host)); 672 if (n == NULL) 673 err(1, "address: calloc"); 674 n->af = res->ai_family; 675 n->addr.addr_dyn = NULL; 676 if (res->ai_family == AF_INET) 677 memcpy(&n->addr.addr, 678 &((struct sockaddr_in *) 679 res->ai_addr) 680 ->sin_addr.s_addr, 681 sizeof(struct in_addr)); 682 else { 683 memcpy(&n->addr.addr, 684 &((struct sockaddr_in6 *) 685 res->ai_addr) 686 ->sin6_addr.s6_addr, 687 sizeof(struct in6_addr)); 688 n->ifindex = 689 ((struct sockaddr_in6 *) 690 res->ai_addr) 691 ->sin6_scope_id; 692 } 693 n->next = h; 694 h = n; 695 } 696 freeaddrinfo(res0); 697 if (h == NULL) { 698 yyerror("no IP address found for %s", $1); 699 YYERROR; 700 } 701 $$ = h; 702 } 703 } 704 | NUMBER '.' NUMBER '.' NUMBER '.' NUMBER { 705 if ($1 < 0 || $3 < 0 || $5 < 0 || $7 < 0 || 706 $1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 707 yyerror("illegal ip address %d.%d.%d.%d", 708 $1, $3, $5, $7); 709 YYERROR; 710 } 711 $$ = calloc(1, sizeof(struct node_host)); 712 if ($$ == NULL) 713 err(1, "address: calloc"); 714 $$->af = AF_INET; 715 $$->addr.addr_dyn = NULL; 716 $$->addr.addr.addr32[0] = htonl(($1 << 24) | 717 ($3 << 16) | ($5 << 8) | $7); 718 } 719 | IPV6ADDR { $$ = $1; } 720 ; 721 722portspec : port_item { $$ = $1; } 723 | '{' port_list '}' { $$ = $2; } 724 ; 725 726port_list : port_item { $$ = $1; } 727 | port_list ',' port_item { $3->next = $1; $$ = $3; } 728 ; 729 730port_item : port { 731 $$ = malloc(sizeof(struct node_port)); 732 if ($$ == NULL) 733 err(1, "port_item: malloc"); 734 $$->port[0] = $1; 735 $$->port[1] = $1; 736 $$->op = PF_OP_EQ; 737 $$->next = NULL; 738 } 739 | PORTUNARY port { 740 $$ = malloc(sizeof(struct node_port)); 741 if ($$ == NULL) 742 err(1, "port_item: malloc"); 743 $$->port[0] = $2; 744 $$->port[1] = $2; 745 $$->op = $1; 746 $$->next = NULL; 747 } 748 | port PORTBINARY port { 749 $$ = malloc(sizeof(struct node_port)); 750 if ($$ == NULL) 751 err(1, "port_item: malloc"); 752 $$->port[0] = $1; 753 $$->port[1] = $3; 754 $$->op = $2; 755 $$->next = NULL; 756 } 757 ; 758 759port : NUMBER { 760 if ($1 < 0 || $1 > 65535) { 761 yyerror("illegal port value %d", $1); 762 YYERROR; 763 } 764 $$ = htons($1); 765 } 766 | STRING { 767 struct servent *s = NULL; 768 769 s = getservbyname($1, "tcp"); 770 if (s == NULL) 771 s = getservbyname($1, "udp"); 772 if (s == NULL) { 773 yyerror("unknown protocol %s", $1); 774 YYERROR; 775 } 776 $$ = s->s_port; 777 } 778 ; 779 780uids : /* empty */ { $$ = NULL; } 781 | USER uid_item { $$ = $2; } 782 | USER '{' uid_list '}' { $$ = $3; } 783 ; 784 785uid_list : uid_item { $$ = $1; } 786 | uid_list ',' uid_item { $3->next = $1; $$ = $3; } 787 ; 788 789uid_item : uid { 790 $$ = malloc(sizeof(struct node_uid)); 791 if ($$ == NULL) 792 err(1, "uid_item: malloc"); 793 $$->uid[0] = $1; 794 $$->uid[1] = $1; 795 $$->op = PF_OP_EQ; 796 $$->next = NULL; 797 } 798 | PORTUNARY uid { 799 if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 800 yyerror("user unknown requires operator = or !="); 801 YYERROR; 802 } 803 $$ = malloc(sizeof(struct node_uid)); 804 if ($$ == NULL) 805 err(1, "uid_item: malloc"); 806 $$->uid[0] = $2; 807 $$->uid[1] = $2; 808 $$->op = $1; 809 $$->next = NULL; 810 } 811 | uid PORTBINARY uid { 812 if ($1 == UID_MAX || $3 == UID_MAX) { 813 yyerror("user unknown requires operator = or !="); 814 YYERROR; 815 } 816 $$ = malloc(sizeof(struct node_uid)); 817 if ($$ == NULL) 818 err(1, "uid_item: malloc"); 819 $$->uid[0] = $1; 820 $$->uid[1] = $3; 821 $$->op = $2; 822 $$->next = NULL; 823 } 824 ; 825 826uid : NUMBER { 827 if ($1 < 0 || $1 >= UID_MAX) { 828 yyerror("illegal uid value %d", $1); 829 YYERROR; 830 } 831 $$ = $1; 832 } 833 | STRING { 834 if (!strcmp($1, "unknown")) 835 $$ = UID_MAX; 836 else { 837 struct passwd *pw; 838 839 if ((pw = getpwnam($1)) == NULL) { 840 yyerror("unknown user %s", $1); 841 YYERROR; 842 } 843 $$ = pw->pw_uid; 844 } 845 } 846 ; 847 848gids : /* empty */ { $$ = NULL; } 849 | GROUP gid_item { $$ = $2; } 850 | GROUP '{' gid_list '}' { $$ = $3; } 851 ; 852 853gid_list : gid_item { $$ = $1; } 854 | gid_list ',' gid_item { $3->next = $1; $$ = $3; } 855 ; 856 857gid_item : gid { 858 $$ = malloc(sizeof(struct node_gid)); 859 if ($$ == NULL) 860 err(1, "gid_item: malloc"); 861 $$->gid[0] = $1; 862 $$->gid[1] = $1; 863 $$->op = PF_OP_EQ; 864 $$->next = NULL; 865 } 866 | PORTUNARY gid { 867 if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 868 yyerror("group unknown requires operator = or !="); 869 YYERROR; 870 } 871 $$ = malloc(sizeof(struct node_gid)); 872 if ($$ == NULL) 873 err(1, "gid_item: malloc"); 874 $$->gid[0] = $2; 875 $$->gid[1] = $2; 876 $$->op = $1; 877 $$->next = NULL; 878 } 879 | gid PORTBINARY gid { 880 if ($1 == GID_MAX || $3 == GID_MAX) { 881 yyerror("group unknown requires operator = or !="); 882 YYERROR; 883 } 884 $$ = malloc(sizeof(struct node_gid)); 885 if ($$ == NULL) 886 err(1, "gid_item: malloc"); 887 $$->gid[0] = $1; 888 $$->gid[1] = $3; 889 $$->op = $2; 890 $$->next = NULL; 891 } 892 ; 893 894gid : NUMBER { 895 if ($1 < 0 || $1 >= GID_MAX) { 896 yyerror("illegal gid value %d", $1); 897 YYERROR; 898 } 899 $$ = $1; 900 } 901 | STRING { 902 if (!strcmp($1, "unknown")) 903 $$ = GID_MAX; 904 else { 905 struct passwd *pw; 906 907 if ((pw = getpwnam($1)) == NULL) { 908 yyerror("unknown group %s", $1); 909 YYERROR; 910 } 911 $$ = pw->pw_uid; 912 } 913 } 914 ; 915 916flag : STRING { 917 int f; 918 919 if ((f = parse_flags($1)) < 0) { 920 yyerror("bad flags %s", $1); 921 YYERROR; 922 } 923 $$.b1 = f; 924 } 925 ; 926 927flags : /* empty */ { $$.b1 = 0; $$.b2 = 0; } 928 | FLAGS flag { $$.b1 = $2.b1; $$.b2 = PF_TH_ALL; } 929 | FLAGS flag "/" flag { $$.b1 = $2.b1; $$.b2 = $4.b1; } 930 | FLAGS "/" flag { $$.b1 = 0; $$.b2 = $3.b1; } 931 ; 932 933icmpspec : /* empty */ { $$ = NULL; } 934 | ICMPTYPE icmp_item { $$ = $2; } 935 | ICMPTYPE '{' icmp_list '}' { $$ = $3; } 936 | ICMP6TYPE icmp6_item { $$ = $2; } 937 | ICMP6TYPE '{' icmp6_list '}' { $$ = $3; } 938 ; 939 940icmp_list : icmp_item { $$ = $1; } 941 | icmp_list ',' icmp_item { $3->next = $1; $$ = $3; } 942 ; 943 944icmp6_list : icmp6_item { $$ = $1; } 945 | icmp6_list ',' icmp6_item { $3->next = $1; $$ = $3; } 946 ; 947 948icmp_item : icmptype { 949 $$ = malloc(sizeof(struct node_icmp)); 950 if ($$ == NULL) 951 err(1, "icmp_item: malloc"); 952 $$->type = $1; 953 $$->code = 0; 954 $$->proto = IPPROTO_ICMP; 955 $$->next = NULL; 956 } 957 | icmptype CODE NUMBER { 958 $$ = malloc(sizeof(struct node_icmp)); 959 if ($$ == NULL) 960 err(1, "icmp_item: malloc"); 961 if ($3 < 0 || $3 > 255) { 962 yyerror("illegal icmp code %d", $3); 963 YYERROR; 964 } 965 $$->type = $1; 966 $$->code = $3 + 1; 967 $$->proto = IPPROTO_ICMP; 968 $$->next = NULL; 969 } 970 | icmptype CODE STRING { 971 const struct icmpcodeent *p; 972 973 $$ = malloc(sizeof(struct node_icmp)); 974 if ($$ == NULL) 975 err(1, "icmp_item: malloc"); 976 $$->type = $1; 977 if ((p = geticmpcodebyname($1, $3, 978 AF_INET)) == NULL) { 979 yyerror("unknown icmp-code %s", $3); 980 YYERROR; 981 } 982 $$->code = p->code + 1; 983 $$->proto = IPPROTO_ICMP; 984 $$->next = NULL; 985 } 986 ; 987 988icmp6_item : icmp6type { 989 $$ = malloc(sizeof(struct node_icmp)); 990 if ($$ == NULL) 991 err(1, "icmp_item: malloc"); 992 $$->type = $1; 993 $$->code = 0; 994 $$->proto = IPPROTO_ICMPV6; 995 $$->next = NULL; 996 } 997 | icmp6type CODE NUMBER { 998 $$ = malloc(sizeof(struct node_icmp)); 999 if ($$ == NULL) 1000 err(1, "icmp_item: malloc"); 1001 if ($3 < 0 || $3 > 255) { 1002 yyerror("illegal icmp6 code %d", $3); 1003 YYERROR; 1004 } 1005 $$->type = $1; 1006 $$->code = $3 + 1; 1007 $$->proto = IPPROTO_ICMPV6; 1008 $$->next = NULL; 1009 } 1010 | icmp6type CODE STRING { 1011 const struct icmpcodeent *p; 1012 1013 $$ = malloc(sizeof(struct node_icmp)); 1014 if ($$ == NULL) 1015 err(1, "icmp_item: malloc"); 1016 $$->type = $1; 1017 if ((p = geticmpcodebyname($1, $3, 1018 AF_INET6)) == NULL) { 1019 yyerror("unknown icmp6-code %s", $3); 1020 YYERROR; 1021 } 1022 $$->code = p->code + 1; 1023 $$->proto = IPPROTO_ICMPV6; 1024 $$->next = NULL; 1025 } 1026 ; 1027 1028icmptype : STRING { 1029 const struct icmptypeent *p; 1030 1031 if ((p = geticmptypebyname($1, AF_INET)) == NULL) { 1032 yyerror("unknown icmp-type %s", $1); 1033 YYERROR; 1034 } 1035 $$ = p->type + 1; 1036 } 1037 | NUMBER { 1038 if ($1 < 0 || $1 > 255) { 1039 yyerror("illegal icmp type %d", $1); 1040 YYERROR; 1041 } 1042 $$ = $1 + 1; 1043 } 1044 ; 1045 1046icmp6type : STRING { 1047 const struct icmptypeent *p; 1048 1049 if ((p = geticmptypebyname($1, AF_INET6)) == NULL) { 1050 yyerror("unknown ipv6-icmp-type %s", $1); 1051 YYERROR; 1052 } 1053 $$ = p->type + 1; 1054 } 1055 | NUMBER { 1056 if ($1 < 0 || $1 > 255) { 1057 yyerror("illegal icmp6 type %d", $1); 1058 YYERROR; 1059 } 1060 $$ = $1 + 1; 1061 } 1062 ; 1063 1064keep : /* empty */ { 1065 $$.action = 0; 1066 $$.options = NULL; 1067 } 1068 | KEEP STATE state_opt_spec { 1069 $$.action = PF_STATE_NORMAL; 1070 $$.options = $3; 1071 } 1072 | MODULATE STATE state_opt_spec { 1073 $$.action = PF_STATE_MODULATE; 1074 $$.options = $3; 1075 } 1076 ; 1077 1078state_opt_spec : /* empty */ { $$ = NULL; } 1079 | '(' state_opt_list ')' { $$ = $2; } 1080 ; 1081 1082state_opt_list : state_opt_item { $$ = $1; } 1083 | state_opt_list ',' state_opt_item { 1084 $$ = $1; 1085 while ($1->next) 1086 $1 = $1->next; 1087 $1->next = $3; 1088 } 1089 ; 1090 1091state_opt_item : MAXIMUM NUMBER { 1092 if ($2 <= 0) { 1093 yyerror("illegal states max value %d", $2); 1094 YYERROR; 1095 } 1096 $$ = calloc(1, sizeof(struct node_state_opt)); 1097 if ($$ == NULL) 1098 err(1, "state_opt_item: calloc"); 1099 $$->type = PF_STATE_OPT_MAX; 1100 $$->data.max_states = $2; 1101 $$->next = NULL; 1102 } 1103 | STRING NUMBER { 1104 int i; 1105 1106 for (i = 0; pf_timeouts[i].name && 1107 strcmp(pf_timeouts[i].name, $1); ++i); 1108 if (!pf_timeouts[i].name) { 1109 yyerror("illegal timeout name %s", $1); 1110 YYERROR; 1111 } 1112 if (strchr(pf_timeouts[i].name, '.') == NULL) { 1113 yyerror("illegal state timeout %s", $1); 1114 YYERROR; 1115 } 1116 if ($2 < 0) { 1117 yyerror("illegal timeout value %d", $2); 1118 YYERROR; 1119 } 1120 $$ = calloc(1, sizeof(struct node_state_opt)); 1121 if ($$ == NULL) 1122 err(1, "state_opt_item: calloc"); 1123 $$->type = PF_STATE_OPT_TIMEOUT; 1124 $$->data.timeout.number = pf_timeouts[i].timeout; 1125 $$->data.timeout.seconds = $2; 1126 $$->next = NULL; 1127 } 1128 ; 1129 1130fragment : /* empty */ { $$ = 0; } 1131 | FRAGMENT { $$ = 1; } 1132 1133minttl : /* empty */ { $$ = 0; } 1134 | MINTTL NUMBER { 1135 if ($2 < 0 || $2 > 255) { 1136 yyerror("illegal min-ttl value %d", $2); 1137 YYERROR; 1138 } 1139 $$ = $2; 1140 } 1141 ; 1142 1143nodf : /* empty */ { $$ = 0; } 1144 | NODF { $$ = 1; } 1145 ; 1146 1147maxmss : /* empty */ { $$ = 0; } 1148 | MAXMSS NUMBER { 1149 if ($2 < 0) { 1150 yyerror("illegal max-mss value %d", $2); 1151 YYERROR; 1152 } 1153 $$ = $2; 1154 } 1155 ; 1156 1157allowopts : /* empty */ { $$ = 0; } 1158 | ALLOWOPTS { $$ = 1; } 1159 1160label : /* empty */ { $$ = NULL; } 1161 | LABEL STRING { 1162 if (($$ = strdup($2)) == NULL) { 1163 yyerror("rule label strdup() failed"); 1164 YYERROR; 1165 } 1166 } 1167 ; 1168 1169no : /* empty */ { $$ = 0; } 1170 | NO { $$ = 1; } 1171 ; 1172 1173rport : port { 1174 $$.a = $1; 1175 $$.b = $$.t = 0; 1176 } 1177 | port ':' port { 1178 $$.a = $1; 1179 $$.b = $3; 1180 $$.t = PF_RPORT_RANGE; 1181 } 1182 | port ':' '*' { 1183 $$.a = $1; 1184 $$.b = 0; 1185 $$.t = PF_RPORT_RANGE; 1186 } 1187 ; 1188 1189redirection : /* empty */ { $$ = NULL; } 1190 | ARROW address { 1191 $$ = malloc(sizeof(struct redirection)); 1192 if ($$ == NULL) 1193 err(1, "redirection: malloc"); 1194 if ($2->next) { 1195 yyerror("multiple ip addresses"); 1196 YYERROR; 1197 } 1198 $$->address = $2; 1199 $$->rport.a = $$->rport.b = $$->rport.t = 0; 1200 } 1201 | ARROW address PORT rport { 1202 $$ = malloc(sizeof(struct redirection)); 1203 if ($$ == NULL) 1204 err(1, "redirection: malloc"); 1205 if ($2->next) { 1206 yyerror("multiple ip addresses"); 1207 YYERROR; 1208 } 1209 $$->address = $2; 1210 $$->rport = $4; 1211 } 1212 ; 1213 1214natrule : no NAT interface af proto fromto redirection 1215 { 1216 struct pf_nat nat; 1217 1218 if (rulestate > PFCTL_STATE_NAT) { 1219 yyerror("Rules must be in order: " 1220 "scrub, nat, filter"); 1221 YYERROR; 1222 } 1223 rulestate = PFCTL_STATE_NAT; 1224 1225 memset(&nat, 0, sizeof(nat)); 1226 1227 nat.no = $1; 1228 if ($3 != NULL) { 1229 memcpy(nat.ifname, $3->ifname, 1230 sizeof(nat.ifname)); 1231 nat.ifnot = $3->not; 1232 free($3); 1233 } 1234 nat.af = $4; 1235 if ($5 != NULL) { 1236 nat.proto = $5->proto; 1237 free($5); 1238 } 1239 if (nat.no) { 1240 if ($7 != NULL) { 1241 yyerror("'no nat' rule does not need '->'"); 1242 YYERROR; 1243 } 1244 } else { 1245 if ($7 == NULL || $7->address == NULL) { 1246 yyerror("'nat' rule requires '-> address'"); 1247 YYERROR; 1248 } 1249 if ($7->address->addr.addr_dyn != NULL) { 1250 if (!nat.af) { 1251 yyerror("address family (inet/" 1252 "inet6) undefined"); 1253 YYERROR; 1254 } 1255 $7->address->af = nat.af; 1256 } 1257 if (nat.af && $7->address->af != nat.af) { 1258 yyerror("nat ip versions must match"); 1259 YYERROR; 1260 } 1261 nat.af = $7->address->af; 1262 memcpy(&nat.raddr, &$7->address->addr, 1263 sizeof(nat.raddr)); 1264 nat.proxy_port[0] = ntohs($7->rport.a); 1265 nat.proxy_port[1] = ntohs($7->rport.b); 1266 if (!nat.proxy_port[0] && !nat.proxy_port[1]) { 1267 nat.proxy_port[0] = 1268 PF_NAT_PROXY_PORT_LOW; 1269 nat.proxy_port[1] = 1270 PF_NAT_PROXY_PORT_HIGH; 1271 } else if (!nat.proxy_port[1]) 1272 nat.proxy_port[1] = nat.proxy_port[0]; 1273 free($7->address); 1274 free($7); 1275 } 1276 1277 expand_nat(&nat, $6.src.host, $6.src.port, 1278 $6.dst.host, $6.dst.port); 1279 } 1280 ; 1281 1282binatrule : no BINAT interface af proto FROM address TO ipspec redirection 1283 { 1284 struct pf_binat binat; 1285 1286 if (rulestate > PFCTL_STATE_NAT) { 1287 yyerror("Rules must be in order: " 1288 "scrub, nat, filter"); 1289 YYERROR; 1290 } 1291 rulestate = PFCTL_STATE_NAT; 1292 1293 memset(&binat, 0, sizeof(binat)); 1294 1295 binat.no = $1; 1296 if ($3 != NULL) { 1297 memcpy(binat.ifname, $3->ifname, 1298 sizeof(binat.ifname)); 1299 free($3); 1300 } 1301 binat.af = $4; 1302 if ($5 != NULL) { 1303 binat.proto = $5->proto; 1304 free($5); 1305 } 1306 if ($7 != NULL && $9 != NULL && $7->af != $9->af) { 1307 yyerror("binat ip versions must match"); 1308 YYERROR; 1309 } 1310 if ($7 != NULL) { 1311 if ($7->next) { 1312 yyerror("multiple binat ip addresses"); 1313 YYERROR; 1314 } 1315 if ($7->addr.addr_dyn != NULL) { 1316 if (!binat.af) { 1317 yyerror("address family (inet/" 1318 "inet6) undefined"); 1319 YYERROR; 1320 } 1321 $7->af = binat.af; 1322 } 1323 if (binat.af && $7->af != binat.af) { 1324 yyerror("binat ip versions must match"); 1325 YYERROR; 1326 } 1327 binat.af = $7->af; 1328 memcpy(&binat.saddr, &$7->addr, 1329 sizeof(binat.saddr)); 1330 free($7); 1331 } 1332 if ($9 != NULL) { 1333 if ($9->next) { 1334 yyerror("multiple binat ip addresses"); 1335 YYERROR; 1336 } 1337 if ($9->addr.addr_dyn != NULL) { 1338 if (!binat.af) { 1339 yyerror("address family (inet/" 1340 "inet6) undefined"); 1341 YYERROR; 1342 } 1343 $9->af = binat.af; 1344 } 1345 if (binat.af && $9->af != binat.af) { 1346 yyerror("binat ip versions must match"); 1347 YYERROR; 1348 } 1349 binat.af = $9->af; 1350 memcpy(&binat.daddr, &$9->addr, 1351 sizeof(binat.daddr)); 1352 memcpy(&binat.dmask, &$9->mask, 1353 sizeof(binat.dmask)); 1354 binat.dnot = $9->not; 1355 free($9); 1356 } 1357 1358 if (binat.no) { 1359 if ($10 != NULL) { 1360 yyerror("'no binat' rule does not need" 1361 " '->'"); 1362 YYERROR; 1363 } 1364 } else { 1365 if ($10 == NULL || $10->address == NULL) { 1366 yyerror("'binat' rule requires" 1367 " '-> address'"); 1368 YYERROR; 1369 } 1370 if ($10->address->addr.addr_dyn != NULL) { 1371 if (!binat.af) { 1372 yyerror("address family (inet/" 1373 "inet6) undefined"); 1374 YYERROR; 1375 } 1376 $10->address->af = binat.af; 1377 } 1378 if (binat.af && $10->address->af != binat.af) { 1379 yyerror("binat ip versions must match"); 1380 YYERROR; 1381 } 1382 binat.af = $10->address->af; 1383 memcpy(&binat.raddr, &$10->address->addr, 1384 sizeof(binat.raddr)); 1385 free($10->address); 1386 free($10); 1387 } 1388 1389 pfctl_add_binat(pf, &binat); 1390 } 1391 1392rdrrule : no RDR interface af proto FROM ipspec TO ipspec dport redirection 1393 { 1394 struct pf_rdr rdr; 1395 1396 if (rulestate > PFCTL_STATE_NAT) { 1397 yyerror("Rules must be in order: " 1398 "scrub, nat, filter"); 1399 YYERROR; 1400 } 1401 rulestate = PFCTL_STATE_NAT; 1402 1403 memset(&rdr, 0, sizeof(rdr)); 1404 1405 rdr.no = $1; 1406 if ($3 != NULL) { 1407 memcpy(rdr.ifname, $3->ifname, 1408 sizeof(rdr.ifname)); 1409 rdr.ifnot = $3->not; 1410 } 1411 rdr.af = $4; 1412 if ($5 != NULL) { 1413 rdr.proto = $5->proto; 1414 free($5); 1415 } 1416 if ($7 != NULL && $9 != NULL && $7->af != $9->af) { 1417 yyerror("rdr ip versions must match"); 1418 YYERROR; 1419 } 1420 if ($7 != NULL) { 1421 if ($7->addr.addr_dyn != NULL) { 1422 if (!rdr.af) { 1423 yyerror("address family (inet/" 1424 "inet6) undefined"); 1425 YYERROR; 1426 } 1427 $7->af = rdr.af; 1428 } 1429 if (rdr.af && $7->af != rdr.af) { 1430 yyerror("rdr ip versions must match"); 1431 YYERROR; 1432 } 1433 rdr.af = $7->af; 1434 memcpy(&rdr.saddr, &$7->addr, 1435 sizeof(rdr.saddr)); 1436 memcpy(&rdr.smask, &$7->mask, 1437 sizeof(rdr.smask)); 1438 rdr.snot = $7->not; 1439 } 1440 if ($9 != NULL) { 1441 if ($9->addr.addr_dyn != NULL) { 1442 if (!rdr.af) { 1443 yyerror("address family (inet/" 1444 "inet6) undefined"); 1445 YYERROR; 1446 } 1447 $9->af = rdr.af; 1448 } 1449 if (rdr.af && $9->af != rdr.af) { 1450 yyerror("rdr ip versions must match"); 1451 YYERROR; 1452 } 1453 rdr.af = $9->af; 1454 memcpy(&rdr.daddr, &$9->addr, 1455 sizeof(rdr.daddr)); 1456 memcpy(&rdr.dmask, &$9->mask, 1457 sizeof(rdr.dmask)); 1458 rdr.dnot = $9->not; 1459 } 1460 1461 rdr.dport = $10.a; 1462 rdr.dport2 = $10.b; 1463 rdr.opts |= $10.t; 1464 1465 if (rdr.no) { 1466 if ($11 != NULL) { 1467 yyerror("'no rdr' rule does not need '->'"); 1468 YYERROR; 1469 } 1470 } else { 1471 if ($11 == NULL || $11->address == NULL) { 1472 yyerror("'rdr' rule requires '-> address'"); 1473 YYERROR; 1474 } 1475 if ($11->address->addr.addr_dyn != NULL) { 1476 if (!rdr.af) { 1477 yyerror("address family (inet/" 1478 "inet6) undefined"); 1479 YYERROR; 1480 } 1481 $11->address->af = rdr.af; 1482 } 1483 if (rdr.af && $11->address->af != rdr.af) { 1484 yyerror("rdr ip versions must match"); 1485 YYERROR; 1486 } 1487 rdr.af = $11->address->af; 1488 memcpy(&rdr.raddr, &$11->address->addr, 1489 sizeof(rdr.raddr)); 1490 free($11->address); 1491 rdr.rport = $11->rport.a; 1492 rdr.opts |= $11->rport.t; 1493 free($11); 1494 } 1495 1496 if (rdr.proto && rdr.proto != IPPROTO_TCP && 1497 rdr.proto != IPPROTO_UDP && 1498 (rdr.dport || rdr.dport2 || rdr.rport)) { 1499 yyerror("rdr ports are only valid for proto tcp/udp"); 1500 YYERROR; 1501 } 1502 1503 expand_rdr(&rdr, $3, $7, $9); 1504 } 1505 ; 1506 1507dport : /* empty */ { 1508 $$.a = $$.b = $$.t = 0; 1509 } 1510 | PORT port { 1511 $$.a = $2; 1512 $$.b = $$.t = 0; 1513 } 1514 | PORT port ':' port { 1515 $$.a = $2; 1516 $$.b = $4; 1517 $$.t = PF_DPORT_RANGE; 1518 } 1519 ; 1520 1521route : /* empty */ { 1522 $$.string = NULL; 1523 $$.rt = 0; 1524 $$.addr = NULL; 1525 $$.af = 0; 1526 } 1527 | FASTROUTE { 1528 $$.string = NULL; 1529 $$.rt = PF_FASTROUTE; 1530 $$.addr = NULL; 1531 } 1532 | ROUTETO STRING ':' address { 1533 $$.string = strdup($2); 1534 $$.rt = PF_ROUTETO; 1535 if ($4->addr.addr_dyn != NULL) { 1536 yyerror("route-to does not support" 1537 " dynamic addresses"); 1538 YYERROR; 1539 } 1540 if ($4->next) { 1541 yyerror("multiple routeto ip addresses"); 1542 YYERROR; 1543 } 1544 $$.addr = &$4->addr.addr; 1545 $$.af = $4->af; 1546 } 1547 | ROUTETO STRING { 1548 $$.string = strdup($2); 1549 $$.rt = PF_ROUTETO; 1550 $$.addr = NULL; 1551 } 1552 | DUPTO STRING ':' address { 1553 $$.string = strdup($2); 1554 $$.rt = PF_DUPTO; 1555 if ($4->addr.addr_dyn != NULL) { 1556 yyerror("dup-to does not support" 1557 " dynamic addresses"); 1558 YYERROR; 1559 } 1560 if ($4->next) { 1561 yyerror("multiple dupto ip addresses"); 1562 YYERROR; 1563 } 1564 $$.addr = &$4->addr.addr; 1565 $$.af = $4->af; 1566 } 1567 | DUPTO STRING { 1568 $$.string = strdup($2); 1569 $$.rt = PF_DUPTO; 1570 $$.addr = NULL; 1571 } 1572 ; 1573%% 1574 1575int 1576yyerror(char *fmt, ...) 1577{ 1578 va_list ap; 1579 extern char *infile; 1580 errors = 1; 1581 1582 va_start(ap, fmt); 1583 fprintf(stderr, "%s:%d: ", infile, yylval.lineno); 1584 vfprintf(stderr, fmt, ap); 1585 fprintf(stderr, "\n"); 1586 va_end(ap); 1587 return (0); 1588} 1589 1590int 1591rule_consistent(struct pf_rule *r) 1592{ 1593 int problems = 0; 1594 1595 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 1596 (r->src.port_op || r->dst.port_op)) { 1597 yyerror("port only applies to tcp/udp"); 1598 problems++; 1599 } 1600 if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 && 1601 (r->type || r->code)) { 1602 yyerror("icmp-type/code only applies to icmp"); 1603 problems++; 1604 } 1605 if (!r->af && (r->type || r->code)) { 1606 yyerror("must indicate address family with icmp-type/code"); 1607 problems++; 1608 } 1609 if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) || 1610 (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) { 1611 yyerror("icmp version does not match address family"); 1612 problems++; 1613 } 1614 if (!(r->rule_flag & PFRULE_RETURNRST) && r->return_icmp && 1615 ((r->af != AF_INET6 && (r->return_icmp>>8) != ICMP_UNREACH) || 1616 (r->af == AF_INET6 && (r->return_icmp>>8) != ICMP6_DST_UNREACH))) { 1617 yyerror("return-icmp version does not match address family"); 1618 problems++; 1619 } 1620 if (r->keep_state == PF_STATE_MODULATE && r->proto && 1621 r->proto != IPPROTO_TCP) { 1622 yyerror("modulate state can only be applied to TCP rules"); 1623 problems++; 1624 } 1625 if (r->allow_opts && r->action != PF_PASS) { 1626 yyerror("allow-opts can only be specified for pass rules"); 1627 problems++; 1628 } 1629 if (!r->af && (r->src.addr.addr_dyn != NULL || 1630 r->dst.addr.addr_dyn != NULL)) { 1631 yyerror("dynamic addresses require address family (inet/inet6)"); 1632 problems++; 1633 } 1634 if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op || 1635 r->dst.port_op || r->flagset || r->type || r->code)) { 1636 yyerror("fragments can be filtered only on IP header fields"); 1637 problems++; 1638 } 1639 return (-problems); 1640} 1641 1642struct keywords { 1643 const char *k_name; 1644 int k_val; 1645}; 1646 1647/* macro gore, but you should've seen the prior indentation nightmare... */ 1648 1649#define CHECK_ROOT(T,r) \ 1650 do { \ 1651 if (r == NULL) { \ 1652 r = malloc(sizeof(T)); \ 1653 if (r == NULL) \ 1654 err(1, "malloc"); \ 1655 memset(r, 0, sizeof(T)); \ 1656 } \ 1657 } while (0) 1658 1659#define FREE_LIST(T,r) \ 1660 do { \ 1661 T *p, *n = r; \ 1662 while (n != NULL) { \ 1663 p = n; \ 1664 n = n->next; \ 1665 free(p); \ 1666 } \ 1667 } while (0) 1668 1669#define LOOP_THROUGH(T,n,r,C) \ 1670 do { \ 1671 T *n = r; \ 1672 while (n != NULL) { \ 1673 do { \ 1674 C; \ 1675 } while (0); \ 1676 n = n->next; \ 1677 } \ 1678 } while (0) 1679 1680void 1681expand_label_addr(const char *name, char *label, u_int8_t af, 1682 struct node_host *host) 1683{ 1684 char tmp[PF_RULE_LABEL_SIZE]; 1685 char *p; 1686 1687 while ((p = strstr(label, name)) != NULL) { 1688 tmp[0] = 0; 1689 1690 strlcat(tmp, label, p-label+1); 1691 1692 if (host->not) 1693 strlcat(tmp, "! ", PF_RULE_LABEL_SIZE); 1694 if (host->addr.addr_dyn != NULL) { 1695 strlcat(tmp, "(", PF_RULE_LABEL_SIZE); 1696 strlcat(tmp, host->addr.addr.pfa.ifname, 1697 PF_RULE_LABEL_SIZE); 1698 strlcat(tmp, ")", PF_RULE_LABEL_SIZE); 1699 } else if (!af || (PF_AZERO(&host->addr.addr, af) && 1700 PF_AZERO(&host->mask, af))) 1701 strlcat(tmp, "any", PF_RULE_LABEL_SIZE); 1702 else { 1703 char a[48]; 1704 int bits; 1705 1706 if (inet_ntop(af, &host->addr.addr, a, 1707 sizeof(a)) == NULL) 1708 strlcat(a, "?", sizeof(a)); 1709 strlcat(tmp, a, PF_RULE_LABEL_SIZE); 1710 bits = unmask(&host->mask, af); 1711 a[0] = 0; 1712 if ((af == AF_INET && bits < 32) || 1713 (af == AF_INET6 && bits < 128)) 1714 snprintf(a, sizeof(a), "/%u", bits); 1715 strlcat(tmp, a, PF_RULE_LABEL_SIZE); 1716 } 1717 strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE); 1718 strncpy(label, tmp, PF_RULE_LABEL_SIZE); 1719 } 1720} 1721 1722void 1723expand_label_port(const char *name, char *label, struct node_port *port) 1724{ 1725 char tmp[PF_RULE_LABEL_SIZE]; 1726 char *p; 1727 char a1[6], a2[6], op[13]; 1728 1729 while ((p = strstr(label, name)) != NULL) { 1730 tmp[0] = 0; 1731 1732 strlcat(tmp, label, p-label+1); 1733 1734 snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0])); 1735 snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1])); 1736 if (!port->op) 1737 op[0] = 0; 1738 else if (port->op == PF_OP_IRG) 1739 snprintf(op, sizeof(op), "%s><%s", a1, a2); 1740 else if (port->op == PF_OP_XRG) 1741 snprintf(op, sizeof(op), "%s<>%s", a1, a2); 1742 else if (port->op == PF_OP_EQ) 1743 snprintf(op, sizeof(op), "%s", a1); 1744 else if (port->op == PF_OP_NE) 1745 snprintf(op, sizeof(op), "!=%s", a1); 1746 else if (port->op == PF_OP_LT) 1747 snprintf(op, sizeof(op), "<%s", a1); 1748 else if (port->op == PF_OP_LE) 1749 snprintf(op, sizeof(op), "<=%s", a1); 1750 else if (port->op == PF_OP_GT) 1751 snprintf(op, sizeof(op), ">%s", a1); 1752 else if (port->op == PF_OP_GE) 1753 snprintf(op, sizeof(op), ">=%s", a1); 1754 strlcat(tmp, op, PF_RULE_LABEL_SIZE); 1755 strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE); 1756 strncpy(label, tmp, PF_RULE_LABEL_SIZE); 1757 } 1758} 1759 1760void 1761expand_label_proto(const char *name, char *label, u_int8_t proto) 1762{ 1763 char tmp[PF_RULE_LABEL_SIZE]; 1764 char *p; 1765 struct protoent *pe; 1766 1767 while ((p = strstr(label, name)) != NULL) { 1768 tmp[0] = 0; 1769 strlcat(tmp, label, p-label+1); 1770 pe = getprotobynumber(proto); 1771 if (pe != NULL) 1772 strlcat(tmp, pe->p_name, PF_RULE_LABEL_SIZE); 1773 else 1774 snprintf(tmp+strlen(tmp), PF_RULE_LABEL_SIZE-strlen(tmp), 1775 "%u", proto); 1776 strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE); 1777 strncpy(label, tmp, PF_RULE_LABEL_SIZE); 1778 } 1779} 1780 1781void 1782expand_label_nr(const char *name, char *label) 1783{ 1784 char tmp[PF_RULE_LABEL_SIZE]; 1785 char *p; 1786 1787 while ((p = strstr(label, name)) != NULL) { 1788 tmp[0] = 0; 1789 strlcat(tmp, label, p-label+1); 1790 snprintf(tmp+strlen(tmp), PF_RULE_LABEL_SIZE-strlen(tmp), 1791 "%u", pf->rule_nr); 1792 strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE); 1793 strncpy(label, tmp, PF_RULE_LABEL_SIZE); 1794 } 1795} 1796 1797void 1798expand_label(char *label, u_int8_t af, 1799 struct node_host *src_host, struct node_port *src_port, 1800 struct node_host *dst_host, struct node_port *dst_port, 1801 u_int8_t proto) 1802{ 1803 expand_label_addr("$srcaddr", label, af, src_host); 1804 expand_label_addr("$dstaddr", label, af, dst_host); 1805 expand_label_port("$srcport", label, src_port); 1806 expand_label_port("$dstport", label, dst_port); 1807 expand_label_proto("$proto", label, proto); 1808 expand_label_nr("$nr", label); 1809} 1810 1811void 1812expand_rule(struct pf_rule *r, 1813 struct node_if *interfaces, struct node_proto *protos, 1814 struct node_host *src_hosts, struct node_port *src_ports, 1815 struct node_host *dst_hosts, struct node_port *dst_ports, 1816 struct node_uid *uids, struct node_gid *gids, 1817 struct node_icmp *icmp_types) 1818{ 1819 int af = r->af, nomatch = 0, added = 0; 1820 char ifname[IF_NAMESIZE]; 1821 char label[PF_RULE_LABEL_SIZE]; 1822 1823 strlcpy(label, r->label, sizeof(label)); 1824 1825 CHECK_ROOT(struct node_if, interfaces); 1826 CHECK_ROOT(struct node_proto, protos); 1827 CHECK_ROOT(struct node_host, src_hosts); 1828 CHECK_ROOT(struct node_port, src_ports); 1829 CHECK_ROOT(struct node_host, dst_hosts); 1830 CHECK_ROOT(struct node_port, dst_ports); 1831 CHECK_ROOT(struct node_uid, uids); 1832 CHECK_ROOT(struct node_gid, gids); 1833 CHECK_ROOT(struct node_icmp, icmp_types); 1834 1835 LOOP_THROUGH(struct node_if, interface, interfaces, 1836 LOOP_THROUGH(struct node_proto, proto, protos, 1837 LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types, 1838 LOOP_THROUGH(struct node_host, src_host, src_hosts, 1839 LOOP_THROUGH(struct node_port, src_port, src_ports, 1840 LOOP_THROUGH(struct node_host, dst_host, dst_hosts, 1841 LOOP_THROUGH(struct node_port, dst_port, dst_ports, 1842 LOOP_THROUGH(struct node_uid, uid, uids, 1843 LOOP_THROUGH(struct node_gid, gid, gids, 1844 1845 r->af = af; 1846 /* for link-local IPv6 address, interface must match up */ 1847 if ((r->af && src_host->af && r->af != src_host->af) || 1848 (r->af && dst_host->af && r->af != dst_host->af) || 1849 (src_host->af && dst_host->af && 1850 src_host->af != dst_host->af) || 1851 (src_host->ifindex && dst_host->ifindex && 1852 src_host->ifindex != dst_host->ifindex) || 1853 (src_host->ifindex && if_nametoindex(interface->ifname) && 1854 src_host->ifindex != if_nametoindex(interface->ifname)) || 1855 (dst_host->ifindex && if_nametoindex(interface->ifname) && 1856 dst_host->ifindex != if_nametoindex(interface->ifname))) 1857 continue; 1858 if (!r->af && src_host->af) 1859 r->af = src_host->af; 1860 else if (!r->af && dst_host->af) 1861 r->af = dst_host->af; 1862 1863 if (if_indextoname(src_host->ifindex, ifname)) 1864 memcpy(r->ifname, ifname, sizeof(r->ifname)); 1865 else if (if_indextoname(dst_host->ifindex, ifname)) 1866 memcpy(r->ifname, ifname, sizeof(r->ifname)); 1867 else 1868 memcpy(r->ifname, interface->ifname, sizeof(r->ifname)); 1869 1870 strlcpy(r->label, label, PF_RULE_LABEL_SIZE); 1871 expand_label(r->label, r->af, src_host, src_port, 1872 dst_host, dst_port, proto->proto); 1873 r->proto = proto->proto; 1874 r->src.addr = src_host->addr; 1875 r->src.mask = src_host->mask; 1876 r->src.noroute = src_host->noroute; 1877 r->src.not = src_host->not; 1878 r->src.port[0] = src_port->port[0]; 1879 r->src.port[1] = src_port->port[1]; 1880 r->src.port_op = src_port->op; 1881 r->dst.addr = dst_host->addr; 1882 r->dst.mask = dst_host->mask; 1883 r->dst.noroute = dst_host->noroute; 1884 r->dst.not = dst_host->not; 1885 r->dst.port[0] = dst_port->port[0]; 1886 r->dst.port[1] = dst_port->port[1]; 1887 r->dst.port_op = dst_port->op; 1888 r->uid.op = uid->op; 1889 r->uid.uid[0] = uid->uid[0]; 1890 r->uid.uid[1] = uid->uid[1]; 1891 r->gid.op = gid->op; 1892 r->gid.gid[0] = gid->gid[0]; 1893 r->gid.gid[1] = gid->gid[1]; 1894 r->type = icmp_type->type; 1895 r->code = icmp_type->code; 1896 1897 if (icmp_type->proto && r->proto != icmp_type->proto) { 1898 yyerror("icmp-type mismatch"); 1899 nomatch++; 1900 } 1901 1902 if (rule_consistent(r) < 0 || nomatch) 1903 yyerror("skipping rule due to errors"); 1904 else { 1905 r->nr = pf->rule_nr++; 1906 pfctl_add_rule(pf, r); 1907 added++; 1908 } 1909 1910 ))))))))); 1911 1912 FREE_LIST(struct node_if, interfaces); 1913 FREE_LIST(struct node_proto, protos); 1914 FREE_LIST(struct node_host, src_hosts); 1915 FREE_LIST(struct node_port, src_ports); 1916 FREE_LIST(struct node_host, dst_hosts); 1917 FREE_LIST(struct node_port, dst_ports); 1918 FREE_LIST(struct node_uid, uids); 1919 FREE_LIST(struct node_gid, gids); 1920 FREE_LIST(struct node_icmp, icmp_types); 1921 1922 if (!added) 1923 yyerror("rule expands to no valid combination"); 1924} 1925 1926void 1927expand_nat(struct pf_nat *n, struct node_host *src_hosts, 1928 struct node_port *src_ports, struct node_host *dst_hosts, 1929 struct node_port *dst_ports) 1930{ 1931 int af = n->af, added = 0; 1932 1933 CHECK_ROOT(struct node_host, src_hosts); 1934 CHECK_ROOT(struct node_port, src_ports); 1935 CHECK_ROOT(struct node_host, dst_hosts); 1936 CHECK_ROOT(struct node_port, dst_ports); 1937 1938 LOOP_THROUGH(struct node_host, src_host, src_hosts, 1939 LOOP_THROUGH(struct node_port, src_port, src_ports, 1940 LOOP_THROUGH(struct node_host, dst_host, dst_hosts, 1941 LOOP_THROUGH(struct node_port, dst_port, dst_ports, 1942 1943 n->af = af; 1944 if ((n->af && src_host->af && n->af != src_host->af) || 1945 (n->af && dst_host->af && n->af != dst_host->af) || 1946 (src_host->af && dst_host->af && 1947 src_host->af != dst_host->af)) 1948 continue; 1949 if (!n->af && src_host->af) 1950 n->af = src_host->af; 1951 else if (!n->af && dst_host->af) 1952 n->af = dst_host->af; 1953 1954 n->src.addr = src_host->addr; 1955 n->src.mask = src_host->mask; 1956 n->src.noroute = src_host->noroute; 1957 n->src.not = src_host->not; 1958 n->src.port[0] = src_port->port[0]; 1959 n->src.port[1] = src_port->port[1]; 1960 n->src.port_op = src_port->op; 1961 n->dst.addr = dst_host->addr; 1962 n->dst.mask = dst_host->mask; 1963 n->dst.noroute = dst_host->noroute; 1964 n->dst.not = dst_host->not; 1965 n->dst.port[0] = dst_port->port[0]; 1966 n->dst.port[1] = dst_port->port[1]; 1967 n->dst.port_op = dst_port->op; 1968 1969 pfctl_add_nat(pf, n); 1970 added++; 1971 1972 )))); 1973 1974 FREE_LIST(struct node_host, src_hosts); 1975 FREE_LIST(struct node_port, src_ports); 1976 FREE_LIST(struct node_host, dst_hosts); 1977 FREE_LIST(struct node_port, dst_ports); 1978 1979 if (!added) 1980 yyerror("nat rule expands to no valid combinations"); 1981} 1982 1983void 1984expand_rdr(struct pf_rdr *r, struct node_if *interfaces, 1985 struct node_host *src_hosts, 1986 struct node_host *dst_hosts) 1987{ 1988 int af = r->af, added = 0; 1989 char ifname[IF_NAMESIZE]; 1990 1991 CHECK_ROOT(struct node_if, interfaces); 1992 CHECK_ROOT(struct node_host, src_hosts); 1993 CHECK_ROOT(struct node_host, dst_hosts); 1994 1995 LOOP_THROUGH(struct node_if, interface, interfaces, 1996 LOOP_THROUGH(struct node_host, src_host, src_hosts, 1997 LOOP_THROUGH(struct node_host, dst_host, dst_hosts, 1998 1999 r->af = af; 2000 if ((r->af && src_host->af && r->af != src_host->af) || 2001 (r->af && dst_host->af && r->af != dst_host->af) || 2002 (src_host->af && dst_host->af && 2003 src_host->af != dst_host->af) || 2004 (src_host->ifindex && dst_host->ifindex && 2005 src_host->ifindex != dst_host->ifindex) || 2006 (src_host->ifindex && if_nametoindex(interface->ifname) && 2007 src_host->ifindex != if_nametoindex(interface->ifname)) || 2008 (dst_host->ifindex && if_nametoindex(interface->ifname) && 2009 dst_host->ifindex != if_nametoindex(interface->ifname))) 2010 continue; 2011 2012 if (!r->af && src_host->af) 2013 r->af = src_host->af; 2014 else if (!r->af && dst_host->af) 2015 r->af = dst_host->af; 2016 2017 if (if_indextoname(src_host->ifindex, ifname)) 2018 memcpy(r->ifname, ifname, sizeof(r->ifname)); 2019 else if (if_indextoname(dst_host->ifindex, ifname)) 2020 memcpy(r->ifname, ifname, sizeof(r->ifname)); 2021 else 2022 memcpy(r->ifname, interface->ifname, sizeof(r->ifname)); 2023 2024 r->saddr = src_host->addr; 2025 r->smask = src_host->mask; 2026 r->daddr = dst_host->addr; 2027 r->dmask = dst_host->mask; 2028 2029 pfctl_add_rdr(pf, r); 2030 added++; 2031 ))); 2032 2033 FREE_LIST(struct node_if, interfaces); 2034 FREE_LIST(struct node_host, src_hosts); 2035 FREE_LIST(struct node_host, dst_hosts); 2036 2037 if (!added) 2038 yyerror("rdr rule expands to no valid combination"); 2039} 2040 2041#undef FREE_LIST 2042#undef CHECK_ROOT 2043#undef LOOP_THROUGH 2044 2045int 2046kw_cmp(k, e) 2047 const void *k, *e; 2048{ 2049 return (strcmp(k, ((struct keywords *)e)->k_name)); 2050} 2051 2052int 2053lookup(char *s) 2054{ 2055 /* this has to be sorted always */ 2056 static const struct keywords keywords[] = { 2057 { "all", ALL}, 2058 { "allow-opts", ALLOWOPTS}, 2059 { "any", ANY}, 2060 { "binat", BINAT}, 2061 { "block", BLOCK}, 2062 { "code", CODE}, 2063 { "crop", FRAGCROP}, 2064 { "drop-ovl", FRAGDROP}, 2065 { "dup-to", DUPTO}, 2066 { "fastroute", FASTROUTE}, 2067 { "flags", FLAGS}, 2068 { "fragment", FRAGMENT}, 2069 { "from", FROM}, 2070 { "group", GROUP}, 2071 { "icmp-type", ICMPTYPE}, 2072 { "in", IN}, 2073 { "inet", INET}, 2074 { "inet6", INET6}, 2075 { "ipv6-icmp-type", ICMP6TYPE}, 2076 { "keep", KEEP}, 2077 { "label", LABEL}, 2078 { "log", LOG}, 2079 { "log-all", LOGALL}, 2080 { "max", MAXIMUM}, 2081 { "max-mss", MAXMSS}, 2082 { "min-ttl", MINTTL}, 2083 { "modulate", MODULATE}, 2084 { "nat", NAT}, 2085 { "no", NO}, 2086 { "no-df", NODF}, 2087 { "no-route", NOROUTE}, 2088 { "on", ON}, 2089 { "out", OUT}, 2090 { "pass", PASS}, 2091 { "port", PORT}, 2092 { "proto", PROTO}, 2093 { "quick", QUICK}, 2094 { "rdr", RDR}, 2095 { "reassemble", FRAGNORM}, 2096 { "return", RETURN}, 2097 { "return-icmp",RETURNICMP}, 2098 { "return-icmp6",RETURNICMP6}, 2099 { "return-rst", RETURNRST}, 2100 { "route-to", ROUTETO}, 2101 { "scrub", SCRUB}, 2102 { "state", STATE}, 2103 { "to", TO}, 2104 { "ttl", TTL}, 2105 { "user", USER}, 2106 }; 2107 const struct keywords *p; 2108 2109 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 2110 sizeof(keywords[0]), kw_cmp); 2111 2112 if (p) { 2113 if (debug > 1) 2114 fprintf(stderr, "%s: %d\n", s, p->k_val); 2115 return (p->k_val); 2116 } else { 2117 if (debug > 1) 2118 fprintf(stderr, "string: %s\n", s); 2119 return (STRING); 2120 } 2121} 2122 2123char *parsebuf; 2124int parseindex; 2125 2126int 2127lgetc(FILE *fin) 2128{ 2129 int c, next; 2130 2131restart: 2132 if (parsebuf) { 2133 /* Reading characters from the parse buffer, instead of input */ 2134 c = parsebuf[parseindex++]; 2135 if (c != '\0') 2136 return (c); 2137 free(parsebuf); 2138 parsebuf = NULL; 2139 parseindex = 0; 2140 goto restart; 2141 } 2142 2143 c = getc(fin); 2144 if (c == '\\') { 2145 next = getc(fin); 2146 if (next != '\n') { 2147 ungetc(next, fin); 2148 return (c); 2149 } 2150 yylval.lineno = lineno; 2151 lineno++; 2152 goto restart; 2153 } 2154 return (c); 2155} 2156 2157int 2158lungetc(int c, FILE *fin) 2159{ 2160 if (parsebuf && parseindex) { 2161 /* XXX breaks on index 0 */ 2162 parseindex--; 2163 return (c); 2164 } 2165 return ungetc(c, fin); 2166} 2167 2168int 2169findeol() 2170{ 2171 int c; 2172 2173 if (parsebuf) { 2174 free(parsebuf); 2175 parsebuf = NULL; 2176 parseindex = 0; 2177 } 2178 2179 /* skip to either EOF or the first real EOL */ 2180 while (1) { 2181 c = lgetc(fin); 2182 if (c == '\\') { 2183 c = lgetc(fin); 2184 if (c == '\n') 2185 continue; 2186 } 2187 if (c == EOF || c == '\n') 2188 break; 2189 } 2190 return (ERROR); 2191} 2192 2193int 2194yylex(void) 2195{ 2196 char buf[8096], *p, *val; 2197 int endc, c, next; 2198 int token; 2199 2200top: 2201 p = buf; 2202 while ((c = lgetc(fin)) == ' ' || c == '\t') 2203 ; 2204 2205 yylval.lineno = lineno; 2206 if (c == '#') 2207 while ((c = lgetc(fin)) != '\n' && c != EOF) 2208 ; 2209 if (c == '$' && parsebuf == NULL) { 2210 while (1) { 2211 if ((c = lgetc(fin)) == EOF) 2212 return (0); 2213 if (p + 1 >= buf + sizeof(buf) - 1) { 2214 yyerror("string too long"); 2215 return (findeol()); 2216 } 2217 if (isalnum(c) || c == '_') { 2218 *p++ = (char)c; 2219 continue; 2220 } 2221 *p = '\0'; 2222 lungetc(c, fin); 2223 break; 2224 } 2225 val = symget(buf); 2226 if (val == NULL) 2227 return (ERROR); 2228 parsebuf = strdup(val); 2229 if (parsebuf == NULL) 2230 err(1, "parsebuf: strdup"); 2231 parseindex = 0; 2232 goto top; 2233 } 2234 2235 switch (c) { 2236 case '\'': 2237 case '"': 2238 endc = c; 2239 while (1) { 2240 if ((c = lgetc(fin)) == EOF) 2241 return (0); 2242 if (c == endc) { 2243 *p = '\0'; 2244 break; 2245 } 2246 if (c == '\n') 2247 continue; 2248 if (p + 1 >= buf + sizeof(buf) - 1) { 2249 yyerror("string too long"); 2250 return (findeol()); 2251 } 2252 *p++ = (char)c; 2253 } 2254 yylval.v.string = strdup(buf); 2255 if (yylval.v.string == NULL) 2256 err(1, "yylex: strdup"); 2257 return (STRING); 2258 case '=': 2259 yylval.v.i = PF_OP_EQ; 2260 return (PORTUNARY); 2261 case '!': 2262 next = lgetc(fin); 2263 if (next == '=') { 2264 yylval.v.i = PF_OP_NE; 2265 return (PORTUNARY); 2266 } 2267 lungetc(next, fin); 2268 break; 2269 case '<': 2270 next = lgetc(fin); 2271 if (next == '>') { 2272 yylval.v.i = PF_OP_XRG; 2273 return (PORTBINARY); 2274 } else if (next == '=') { 2275 yylval.v.i = PF_OP_LE; 2276 } else { 2277 yylval.v.i = PF_OP_LT; 2278 lungetc(next, fin); 2279 } 2280 return (PORTUNARY); 2281 break; 2282 case '>': 2283 next = lgetc(fin); 2284 if (next == '<') { 2285 yylval.v.i = PF_OP_IRG; 2286 return (PORTBINARY); 2287 } else if (next == '=') { 2288 yylval.v.i = PF_OP_GE; 2289 } else { 2290 yylval.v.i = PF_OP_GT; 2291 lungetc(next, fin); 2292 } 2293 return (PORTUNARY); 2294 break; 2295 case '-': 2296 next = lgetc(fin); 2297 if (next == '>') 2298 return (ARROW); 2299 lungetc(next, fin); 2300 break; 2301 } 2302 2303 /* Need to parse v6 addresses before tokenizing numbers. ick */ 2304 if (isxdigit(c) || c == ':') { 2305 struct node_host *node = NULL; 2306 u_int32_t addr[4]; 2307 char lookahead[46]; 2308 int i = 0; 2309 struct addrinfo hints, *res; 2310 2311 lookahead[i] = c; 2312 2313 while (i < sizeof(lookahead) && 2314 (isalnum(c) || c == ':' || c == '.' || c == '%')) { 2315 lookahead[++i] = c = lgetc(fin); 2316 } 2317 2318 /* quick check avoids calling inet_pton too often */ 2319 lungetc(lookahead[i], fin); 2320 lookahead[i] = '\0'; 2321 2322 memset(&hints, 0, sizeof(hints)); 2323 hints.ai_family = AF_INET6; 2324 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 2325 hints.ai_flags = AI_NUMERICHOST; 2326 if (getaddrinfo(lookahead, "0", &hints, &res) == 0) { 2327 node = calloc(1, sizeof(struct node_host)); 2328 if (node == NULL) 2329 err(1, "yylex: calloc"); 2330 node->af = AF_INET6; 2331 node->addr.addr_dyn = NULL; 2332 memcpy(&node->addr.addr, 2333 &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 2334 sizeof(addr)); 2335 node->ifindex = ((struct sockaddr_in6 *)res->ai_addr) 2336 ->sin6_scope_id; 2337 yylval.v.host = node; 2338 return IPV6ADDR; 2339 freeaddrinfo(res); 2340 } else { 2341 free(node); 2342 while (i > 1) 2343 lungetc(lookahead[--i], fin); 2344 c = lookahead[--i]; 2345 } 2346 } 2347 2348 if (isdigit(c)) { 2349 int index = 0, base = 10; 2350 u_int64_t n = 0; 2351 2352 yylval.v.number = 0; 2353 while (1) { 2354 if (base == 10) { 2355 if (!isdigit(c)) 2356 break; 2357 c -= '0'; 2358 } else if (base == 16) { 2359 if (isdigit(c)) 2360 c -= '0'; 2361 else if (c >= 'a' && c <= 'f') 2362 c -= 'a' - 10; 2363 else if (c >= 'A' && c <= 'F') 2364 c -= 'A' - 10; 2365 else 2366 break; 2367 } 2368 n = n * base + c; 2369 2370 if (n > UINT_MAX) { 2371 yyerror("number is too large"); 2372 return (ERROR); 2373 } 2374 c = lgetc(fin); 2375 if (c == EOF) 2376 break; 2377 if (index++ == 0 && n == 0 && c == 'x') { 2378 base = 16; 2379 c = lgetc(fin); 2380 if (c == EOF) 2381 break; 2382 } 2383 } 2384 yylval.v.number = (u_int32_t)n; 2385 2386 if (c != EOF) 2387 lungetc(c, fin); 2388 if (debug > 1) 2389 fprintf(stderr, "number: %d\n", yylval.v.number); 2390 return (NUMBER); 2391 } 2392 2393#define allowed_in_string(x) \ 2394 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 2395 x != '{' && x != '}' && x != '<' && x != '>' && \ 2396 x != '!' && x != '=' && x != '/' && x != '#' && \ 2397 x != ',' && x != ':' && x != '(' && x != ')')) 2398 2399 if (isalnum(c)) { 2400 do { 2401 *p++ = c; 2402 if (p-buf >= sizeof buf) { 2403 yyerror("string too long"); 2404 return (ERROR); 2405 } 2406 } while ((c = lgetc(fin)) != EOF && (allowed_in_string(c))); 2407 lungetc(c, fin); 2408 *p = '\0'; 2409 token = lookup(buf); 2410 yylval.v.string = strdup(buf); 2411 if (yylval.v.string == NULL) 2412 err(1, "yylex: strdup"); 2413 return (token); 2414 } 2415 if (c == '\n') { 2416 yylval.lineno = lineno; 2417 lineno++; 2418 } 2419 if (c == EOF) 2420 return (0); 2421 return (c); 2422} 2423 2424int 2425parse_rules(FILE *input, struct pfctl *xpf) 2426{ 2427 fin = input; 2428 pf = xpf; 2429 lineno = 1; 2430 errors = 0; 2431 rulestate = PFCTL_STATE_NONE; 2432 yyparse(); 2433 return (errors ? -1 : 0); 2434} 2435 2436void 2437ipmask(struct pf_addr *m, u_int8_t b) 2438{ 2439 int i, j = 0; 2440 2441 while (b >= 32) { 2442 m->addr32[j++] = 0xffffffff; 2443 b -= 32; 2444 } 2445 for (i = 31; i > 31-b; --i) 2446 m->addr32[j] |= (1 << i); 2447 if (b) 2448 m->addr32[j] = htonl(m->addr32[j]); 2449} 2450 2451/* 2452 * Over-designed efficiency is a French and German concept, so how about 2453 * we wait until they discover this ugliness and make it all fancy. 2454 */ 2455int 2456symset(char *nam, char *val) 2457{ 2458 struct sym *sym; 2459 2460 sym = calloc(1, sizeof(*sym)); 2461 if (sym == NULL) 2462 return (-1); 2463 sym->nam = strdup(nam); 2464 if (sym->nam == NULL) { 2465 free(sym); 2466 return (-1); 2467 } 2468 sym->val = strdup(val); 2469 if (sym->val == NULL) { 2470 free(sym->nam); 2471 free(sym); 2472 return (-1); 2473 } 2474 sym->next = symhead; 2475 symhead = sym; 2476 return (0); 2477} 2478 2479char * 2480symget(char *nam) 2481{ 2482 struct sym *sym; 2483 2484 for (sym = symhead; sym; sym = sym->next) 2485 if (strcmp(nam, sym->nam) == 0) 2486 return (sym->val); 2487 return (NULL); 2488} 2489 2490struct ifaddrs **ifa0tab, **ifa4tab, **ifa6tab; 2491int ifa0len, ifa4len, ifa6len; 2492 2493int 2494ifa_comp(const void *p1, const void *p2) 2495{ 2496 struct ifaddrs *ifa1 = *(struct ifaddrs **)p1; 2497 struct ifaddrs *ifa2 = *(struct ifaddrs **)p2; 2498 2499 return strcmp(ifa1->ifa_name, ifa2->ifa_name); 2500} 2501 2502void 2503ifa_load(void) 2504{ 2505 struct ifaddrs *ifap, *ifa; 2506 void *p; 2507 int ifalen = 0; 2508 2509 if (getifaddrs(&ifap) < 0) 2510 err(1, "getifaddrs"); 2511 for (ifa = ifap; ifa; ifa = ifa->ifa_next) 2512 ifalen++; 2513 /* (over-)allocate tables */ 2514 ifa0tab = malloc(ifalen * sizeof(void *)); 2515 ifa4tab = malloc(ifalen * sizeof(void *)); 2516 ifa6tab = malloc(ifalen * sizeof(void *)); 2517 if (!ifa0tab || !ifa4tab || !ifa6tab) 2518 err(1, "malloc"); 2519 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 2520 if (ifa->ifa_addr->sa_family == AF_LINK) { 2521 if (bsearch(&ifa, ifa0tab, ifa0len, sizeof(void *), 2522 ifa_comp)) 2523 continue; /* take only the first LINK address */ 2524 ifa0tab[ifa0len++] = ifa; 2525 qsort(ifa0tab, ifa0len, sizeof(void *), ifa_comp); 2526 } 2527 if (ifa->ifa_addr->sa_family == AF_INET) { 2528 if (bsearch(&ifa, ifa4tab, ifa4len, sizeof(void *), 2529 ifa_comp)) 2530 continue; /* take only the first IPv4 address */ 2531 ifa4tab[ifa4len++] = ifa; 2532 qsort(ifa4tab, ifa4len, sizeof(void *), ifa_comp); 2533 } 2534 if (ifa->ifa_addr->sa_family == AF_INET6) { 2535 /* XXX - better address selection required! */ 2536 if (bsearch(&ifa, ifa6tab, ifa6len, sizeof(void *), 2537 ifa_comp)) 2538 continue; /* take only the first IPv6 address */ 2539 ifa6tab[ifa6len++] = ifa; 2540 qsort(ifa6tab, ifa6len, sizeof(void *), ifa_comp); 2541 } 2542 } 2543 /* shrink tables */ 2544 if ((p = realloc(ifa0tab, ifa0len * sizeof(void *))) == NULL) { 2545 free(ifa0tab); 2546 ifa0tab = NULL; 2547 } else 2548 ifa0tab = p; 2549 if ((p = realloc(ifa4tab, ifa4len * sizeof(void *))) == NULL) { 2550 free(ifa4tab); 2551 ifa4tab = NULL; 2552 } else 2553 ifa4tab = p; 2554 if ((p = realloc(ifa6tab, ifa6len * sizeof(void *))) == NULL) { 2555 free(ifa6tab); 2556 ifa6tab = NULL; 2557 } else 2558 ifa6tab = p; 2559 if (!ifa0tab || !ifa4tab || !ifa6tab) 2560 err(1, "realloc"); 2561} 2562 2563struct ifaddrs * 2564ifa0_lookup(char *ifa_name) 2565{ 2566 struct ifaddrs ifa, *ifp = &ifa, **ifpp; 2567 2568 if (!ifa0tab) 2569 ifa_load(); 2570 ifa.ifa_name = ifa_name; 2571 ifpp = bsearch(&ifp, ifa0tab, ifa0len, sizeof(void *), ifa_comp); 2572 return ifpp ? *ifpp : NULL; 2573} 2574 2575struct ifaddrs * 2576ifa4_lookup(char *ifa_name) 2577{ 2578 struct ifaddrs ifa, *ifp = &ifa, **ifpp; 2579 2580 if (!ifa4tab) 2581 ifa_load(); 2582 ifa.ifa_name = ifa_name; 2583 ifpp = bsearch(&ifp, ifa4tab, ifa4len, sizeof(void *), ifa_comp); 2584 return ifpp ? *ifpp : NULL; 2585} 2586 2587struct ifaddrs * 2588ifa6_lookup(char *ifa_name) 2589{ 2590 struct ifaddrs ifa, *ifp = &ifa, **ifpp; 2591 2592 if (!ifa6tab) 2593 ifa_load(); 2594 ifa.ifa_name = ifa_name; 2595 ifpp = bsearch(&ifp, ifa6tab, ifa6len, sizeof(void *), ifa_comp); 2596 return ifpp ? *ifpp : NULL; 2597} 2598 2599