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