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