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