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