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