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