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