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