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