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