1 /* $OpenBSD: parse.y,v 1.48 2001/12/23 03:50:03 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Markus Friedl. All rights reserved. 5 * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 %{ 28 #include <sys/types.h> 29 #include <sys/socket.h> 30 #include <sys/ioctl.h> 31 #include <net/if.h> 32 #include <netinet/in.h> 33 #include <netinet/in_systm.h> 34 #include <netinet/ip.h> 35 #include <netinet/ip_icmp.h> 36 #include <netinet/icmp6.h> 37 #include <net/pfvar.h> 38 #include <arpa/inet.h> 39 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <ifaddrs.h> 43 #include <netdb.h> 44 #include <stdarg.h> 45 #include <errno.h> 46 #include <string.h> 47 #include <ctype.h> 48 #include <err.h> 49 50 #include "pfctl_parser.h" 51 52 static struct pfctl *pf = NULL; 53 static FILE *fin = NULL; 54 static int debug = 0; 55 static int lineno = 1; 56 static int errors = 0; 57 static int natmode = 0; 58 59 struct node_if { 60 char ifname[IFNAMSIZ]; 61 u_int8_t not; 62 struct node_if *next; 63 }; 64 65 struct node_proto { 66 u_int8_t proto; 67 struct node_proto *next; 68 }; 69 70 struct node_host { 71 struct pf_addr addr; 72 struct pf_addr mask; 73 u_int8_t af; 74 u_int8_t not; 75 struct node_host *next; 76 }; 77 78 struct node_port { 79 u_int16_t port[2]; 80 u_int8_t op; 81 struct node_port *next; 82 }; 83 84 struct node_icmp { 85 u_int8_t code; 86 u_int8_t type; 87 u_int8_t proto; 88 struct node_icmp *next; 89 }; 90 91 struct peer { 92 struct node_host *host; 93 struct node_port *port; 94 }; 95 96 int rule_consistent(struct pf_rule *); 97 int yyparse(void); 98 struct pf_rule_addr *new_addr(void); 99 void ipmask(struct pf_addr *, u_int8_t, int); 100 void expand_rule_hosts(struct pf_rule *, 101 struct node_if *, struct node_proto *, 102 struct node_host *, struct node_port *, 103 struct node_host *, struct node_port *, 104 struct node_icmp *); 105 void expand_rule_protos(struct pf_rule *, 106 struct node_if *, struct node_proto *, 107 struct node_host *, struct node_port *, 108 struct node_host *, struct node_port *, 109 struct node_icmp *); 110 void expand_rule(struct pf_rule *, 111 struct node_if *, struct node_proto *, 112 struct node_host *, struct node_port *, 113 struct node_host *, struct node_port *, 114 struct node_icmp *); 115 116 struct sym { 117 struct sym *next; 118 char *nam; 119 char *val; 120 }; 121 struct sym *symhead = NULL; 122 123 int symset(char *name, char *val); 124 char * symget(char *name); 125 126 struct ifaddrs *ifa0_lookup(char *ifa_name); 127 struct ifaddrs *ifa4_lookup(char *ifa_name); 128 struct ifaddrs *ifa6_lookup(char *ifa_name); 129 130 typedef struct { 131 union { 132 u_int32_t number; 133 int i; 134 char *string; 135 struct { 136 u_int8_t b1; 137 u_int8_t b2; 138 u_int16_t w; 139 } b; 140 struct { 141 int a; 142 int b; 143 int t; 144 } range; 145 struct node_if *interface; 146 struct node_proto *proto; 147 struct node_icmp *icmp; 148 struct node_host *host; 149 struct node_port *port; 150 struct peer peer; 151 struct { 152 struct peer src, dst; 153 } fromto; 154 struct { 155 char *string; 156 struct pf_addr *addr; 157 u_int8_t rt; 158 u_int8_t af; 159 } route; 160 } v; 161 int lineno; 162 } YYSTYPE; 163 164 %} 165 166 %token PASS BLOCK SCRUB RETURN IN OUT LOG LOGALL QUICK ON FROM TO FLAGS 167 %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE 168 %token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF 169 %token MINTTL IPV6ADDR ERROR ALLOWOPTS FASTROUTE ROUTETO DUPTO 170 %token <v.string> STRING 171 %token <v.number> NUMBER 172 %token <v.i> PORTUNARY PORTBINARY 173 %type <v.interface> interface if_list if_item_not if_item 174 %type <v.number> port icmptype icmp6type minttl 175 %type <v.i> dir log quick af keep nodf allowopts 176 %type <v.b> action flag flags blockspec 177 %type <v.range> dport rport 178 %type <v.proto> proto proto_list proto_item 179 %type <v.icmp> icmpspec icmp_list icmp6_list icmp_item icmp6_item 180 %type <v.fromto> fromto 181 %type <v.peer> ipportspec 182 %type <v.host> ipspec xhost host address host_list IPV6ADDR 183 %type <v.port> portspec port_list port_item 184 %type <v.route> route 185 %% 186 187 ruleset : /* empty */ 188 | ruleset '\n' 189 | ruleset pfrule '\n' 190 | ruleset natrule '\n' 191 | ruleset binatrule '\n' 192 | ruleset rdrrule '\n' 193 | ruleset varset '\n' 194 | ruleset error '\n' { errors++; } 195 ; 196 197 varset : STRING PORTUNARY STRING 198 { 199 if (pf->opts & PF_OPT_VERBOSE) 200 printf("%s = %s\n", $1, $3); 201 if (symset($1, $3) == -1) { 202 yyerror("cannot store variable %s", $1); 203 YYERROR; 204 } 205 } 206 ; 207 208 pfrule : action dir log quick interface route af proto fromto flags icmpspec keep nodf minttl allowopts 209 { 210 struct pf_rule r; 211 212 if (natmode) { 213 yyerror("filter rule not permitted in nat mode"); 214 YYERROR; 215 } 216 memset(&r, 0, sizeof(r)); 217 218 r.action = $1.b1; 219 if ($1.b2) 220 r.rule_flag |= PFRULE_RETURNRST; 221 else 222 r.return_icmp = $1.w; 223 r.direction = $2; 224 r.log = $3; 225 r.quick = $4; 226 227 228 r.af = $7; 229 r.flags = $10.b1; 230 r.flagset = $10.b2; 231 232 r.keep_state = $12; 233 234 if ($13) 235 r.rule_flag |= PFRULE_NODF; 236 if ($14) 237 r.min_ttl = $14; 238 r.allow_opts = $15; 239 240 if ($6.rt) { 241 r.rt = $6.rt; 242 if ($6.string) { 243 memcpy(r.rt_ifname, $6.string, 244 sizeof(r.rt_ifname)); 245 free($6.string); 246 } 247 if ($6.addr) { 248 if (!r.af) 249 r.af = $6.af; 250 else if (r.af != $6.af) { 251 yyerror("address family" 252 " mismatch"); 253 YYERROR; 254 } 255 memcpy(&r.rt_addr, $6.addr, 256 sizeof(r.rt_addr)); 257 free($6.addr); 258 } 259 } 260 261 expand_rule(&r, $5, $8, $9.src.host, $9.src.port, 262 $9.dst.host, $9.dst.port, $11); 263 } 264 ; 265 266 action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; } 267 | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } 268 | SCRUB { $$.b1 = PF_SCRUB; $$.b2 = $$.w = 0; } 269 ; 270 271 blockspec : /* empty */ { $$.b2 = 0; $$.w = 0; } 272 | RETURNRST { $$.b2 = 1; $$.w = 0;} 273 | RETURNICMP { 274 $$.b2 = 0; 275 $$.w = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 276 } 277 | RETURNICMP6 { 278 $$.b2 = 0; 279 $$.w = (ICMP6_DST_UNREACH << 8) | 280 ICMP6_DST_UNREACH_NOPORT; 281 } 282 | RETURNICMP '(' NUMBER ')' { 283 $$.w = (ICMP_UNREACH << 8) | $3; 284 $$.b2 = 0; 285 } 286 | RETURNICMP '(' STRING ')' { 287 struct icmpcodeent *p; 288 289 if ((p = geticmpcodebyname(ICMP_UNREACH, $3, 290 AF_INET)) == NULL) { 291 yyerror("unknown icmp code %s", $3); 292 YYERROR; 293 } 294 $$.w = (p->type << 8) | p->code; 295 $$.b2 = 0; 296 } 297 | RETURNICMP6 '(' NUMBER ')' { 298 $$.w = (ICMP6_DST_UNREACH << 8) | $3; 299 $$.b2 = 0; 300 } 301 | RETURNICMP6 '(' STRING ')' { 302 struct icmpcodeent *p; 303 304 if ((p = geticmpcodebyname(ICMP6_DST_UNREACH, $3, 305 AF_INET6)) == NULL) { 306 yyerror("unknown icmp code %s", $3); 307 YYERROR; 308 } 309 $$.w = (p->type << 8) | p->code; 310 $$.b2 = 0; 311 } 312 ; 313 314 dir : IN { $$ = PF_IN; } 315 | OUT { $$ = PF_OUT; } 316 ; 317 318 log : /* empty */ { $$ = 0; } 319 | LOG { $$ = 1; } 320 | LOGALL { $$ = 2; } 321 ; 322 323 quick : /* empty */ { $$ = 0; } 324 | QUICK { $$ = 1; } 325 ; 326 327 interface : /* empty */ { $$ = NULL; } 328 | ON if_item_not { $$ = $2; } 329 | ON '{' if_list '}' { $$ = $3; } 330 ; 331 332 if_list : if_item_not { $$ = $1; } 333 | if_list ',' if_item_not { $3->next = $1; $$ = $3; } 334 ; 335 336 if_item_not : '!' if_item { $$ = $2; $$->not = 1; } 337 | if_item { $$ = $1; } 338 339 if_item : STRING { 340 if (ifa0_lookup($1) == NULL) { 341 yyerror("unknown interface %s", $1); 342 YYERROR; 343 } 344 $$ = malloc(sizeof(struct node_if)); 345 if ($$ == NULL) 346 err(1, "if_item: malloc"); 347 strlcpy($$->ifname, $1, IFNAMSIZ); 348 $$->not = 0; 349 $$->next = NULL; 350 } 351 ; 352 353 af : /* empty */ { $$ = 0; } 354 | INET { $$ = AF_INET; } 355 | INET6 { $$ = AF_INET6; } 356 357 proto : /* empty */ { $$ = NULL; } 358 | PROTO proto_item { $$ = $2; } 359 | PROTO '{' proto_list '}' { $$ = $3; } 360 ; 361 362 proto_list : proto_item { $$ = $1; } 363 | proto_list ',' proto_item { $3->next = $1; $$ = $3; } 364 ; 365 366 proto_item : NUMBER { 367 struct protoent *p; 368 369 if ((p = getprotobynumber($1)) == NULL) { 370 yyerror("unknown protocol %d", $1); 371 YYERROR; 372 } 373 $$ = malloc(sizeof(struct node_proto)); 374 if ($$ == NULL) 375 err(1, "proto_item: malloc"); 376 $$->proto = p->p_proto; 377 $$->next = NULL; 378 } 379 | STRING { 380 struct protoent *p; 381 382 if ((p = getprotobyname($1)) == NULL) { 383 yyerror("unknown protocol %s", $1); 384 YYERROR; 385 } 386 $$ = malloc(sizeof(struct node_proto)); 387 if ($$ == NULL) 388 err(1, "proto_item: malloc"); 389 $$->proto = p->p_proto; 390 $$->next = NULL; 391 } 392 ; 393 394 fromto : ALL { 395 $$.src.host = NULL; 396 $$.src.port = NULL; 397 $$.dst.host = NULL; 398 $$.dst.port = NULL; 399 } 400 | FROM ipportspec TO ipportspec { 401 $$.src = $2; 402 $$.dst = $4; 403 } 404 ; 405 406 ipportspec : ipspec { $$.host = $1; $$.port = NULL; } 407 | ipspec PORT portspec { 408 $$.host = $1; 409 $$.port = $3; 410 } 411 ; 412 413 ipspec : ANY { $$ = NULL; } 414 | xhost { $$ = $1; } 415 | '{' host_list '}' { $$ = $2; } 416 ; 417 418 host_list : xhost { $$ = $1; } 419 | host_list ',' xhost { $3->next = $1; $$ = $3; } 420 ; 421 422 xhost : '!' host { $$ = $2; $$->not = 1; } 423 | host { $$ = $1; } 424 ; 425 426 host : address { 427 $$ = $1; 428 if ($$->af == AF_INET) 429 ipmask(&$$->mask, 32, AF_INET); 430 else 431 ipmask(&$$->mask, 128, AF_INET6); 432 } 433 | address '/' NUMBER { 434 if ($$->af == AF_INET) { 435 if ($3 < 0 || $3 > 32) { 436 yyerror("illegal netmask value %d", $3); 437 YYERROR; 438 } 439 } else { 440 if ($3 < 0 || $3 > 128) { 441 yyerror("illegal netmask value %d", $3); 442 YYERROR; 443 } 444 } 445 $$ = $1; 446 ipmask(&$$->mask, $3, $$->af); 447 } 448 ; 449 450 address : STRING { 451 struct hostent *hp; 452 struct ifaddrs *ifa; 453 454 if (ifa0_lookup($1)) { 455 /* an interface with this name exists */ 456 if ((ifa = ifa4_lookup($1))) { 457 struct sockaddr_in *sin = 458 (struct sockaddr_in *) 459 ifa->ifa_addr; 460 461 $$ = calloc(1, 462 sizeof(struct node_host)); 463 if ($$ == NULL) 464 err(1, "address: calloc"); 465 $$->af = AF_INET; 466 memcpy(&$$->addr, &sin->sin_addr, 467 sizeof(u_int32_t)); 468 } else if ((ifa = ifa6_lookup($1))) { 469 struct sockaddr_in6 *sin6 = 470 (struct sockaddr_in6 *) 471 ifa->ifa_addr; 472 473 $$ = calloc(1, 474 sizeof(struct node_host)); 475 if ($$ == NULL) 476 err(1, "address: calloc"); 477 $$->af = AF_INET6; 478 memcpy(&$$->addr, &sin6->sin6_addr, 479 sizeof(struct pf_addr)); 480 } else { 481 yyerror("interface %s has no IP " 482 "addresses", $1); 483 YYERROR; 484 } 485 } 486 else if ((hp = gethostbyname2($1, AF_INET)) == NULL) { 487 if ((hp = gethostbyname2($1, AF_INET6)) 488 == NULL) { 489 yyerror("cannot resolve %s", $1); 490 YYERROR; 491 } else { 492 $$ = calloc(1, sizeof(struct node_host)); 493 if ($$ == NULL) 494 err(1, "address: calloc"); 495 $$->af = AF_INET6; 496 memcpy(&$$->addr, hp->h_addr, 497 sizeof(struct pf_addr)); 498 } 499 } else { 500 $$ = calloc(1, sizeof(struct node_host)); 501 if ($$ == NULL) 502 err(1, "address: calloc"); 503 $$->af = AF_INET; 504 memcpy(&$$->addr, hp->h_addr, sizeof(u_int32_t)); 505 } 506 } 507 | NUMBER '.' NUMBER '.' NUMBER '.' NUMBER { 508 if ($1 < 0 || $3 < 0 || $5 < 0 || $7 < 0 || 509 $1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 510 yyerror("illegal ip address %d.%d.%d.%d", 511 $1, $3, $5, $7); 512 YYERROR; 513 } 514 $$ = calloc(1, sizeof(struct node_host)); 515 if ($$ == NULL) 516 err(1, "address: calloc"); 517 $$->af = AF_INET; 518 $$->addr.addr32[0] = htonl(($1 << 24) | 519 ($3 << 16) | ($5 << 8) | $7); 520 } 521 | IPV6ADDR { $$ = $1; } 522 ; 523 524 portspec : port_item { $$ = $1; } 525 | '{' port_list '}' { $$ = $2; } 526 ; 527 528 port_list : port_item { $$ = $1; } 529 | port_list ',' port_item { $3->next = $1; $$ = $3; } 530 ; 531 532 port_item : port { 533 $$ = malloc(sizeof(struct node_port)); 534 if ($$ == NULL) 535 err(1, "port_item: malloc"); 536 $$->port[0] = $1; 537 $$->port[1] = $1; 538 $$->op = PF_OP_EQ; 539 $$->next = NULL; 540 } 541 | PORTUNARY port { 542 $$ = malloc(sizeof(struct node_port)); 543 if ($$ == NULL) 544 err(1, "port_item: malloc"); 545 $$->port[0] = $2; 546 $$->port[1] = $2; 547 $$->op = $1; 548 $$->next = NULL; 549 } 550 | port PORTBINARY port { 551 $$ = malloc(sizeof(struct node_port)); 552 if ($$ == NULL) 553 err(1, "port_item: malloc"); 554 $$->port[0] = $1; 555 $$->port[1] = $3; 556 $$->op = $2; 557 $$->next = NULL; 558 } 559 ; 560 561 port : NUMBER { 562 if (0 > $1 || $1 > 65535) { 563 yyerror("illegal port value %d", $1); 564 YYERROR; 565 } 566 $$ = htons($1); 567 } 568 | STRING { 569 struct servent *s = NULL; 570 571 s = getservbyname($1, "tcp"); 572 if (s == NULL) 573 s = getservbyname($1, "udp"); 574 if (s == NULL) { 575 yyerror("unknown protocol %s", $1); 576 YYERROR; 577 } 578 $$ = s->s_port; 579 } 580 ; 581 582 flag : STRING { 583 int f; 584 585 if ((f = parse_flags($1)) < 0) { 586 yyerror("bad flags %s", $1); 587 YYERROR; 588 } 589 $$.b1 = f; 590 } 591 ; 592 593 flags : /* empty */ { $$.b1 = 0; $$.b2 = 0; } 594 | FLAGS flag { $$.b1 = $2.b1; $$.b2 = 63; } 595 | FLAGS flag "/" flag { $$.b1 = $2.b1; $$.b2 = $4.b1; } 596 | FLAGS "/" flag { $$.b1 = 0; $$.b2 = $3.b1; } 597 ; 598 599 icmpspec : /* empty */ { $$ = NULL; } 600 | ICMPTYPE icmp_item { $$ = $2; } 601 | ICMPTYPE '{' icmp_list '}' { $$ = $3; } 602 | ICMP6TYPE icmp6_item { $$ = $2; } 603 | ICMP6TYPE '{' icmp6_list '}' { $$ = $3; } 604 ; 605 606 icmp_list : icmp_item { $$ = $1; } 607 | icmp_list ',' icmp_item { $3->next = $1; $$ = $3; } 608 ; 609 610 icmp6_list : icmp6_item { $$ = $1; } 611 | icmp6_list ',' icmp6_item { $3->next = $1; $$ = $3; } 612 ; 613 614 icmp_item : icmptype { 615 $$ = malloc(sizeof(struct node_icmp)); 616 if ($$ == NULL) 617 err(1, "icmp_item: malloc"); 618 $$->type = $1; 619 $$->code = 0; 620 $$->proto = IPPROTO_ICMP; 621 $$->next = NULL; 622 } 623 | icmptype CODE NUMBER { 624 $$ = malloc(sizeof(struct node_icmp)); 625 if ($$ == NULL) 626 err(1, "icmp_item: malloc"); 627 if ($3 < 0 || $3 > 255) { 628 yyerror("illegal icmp code %d", $3); 629 YYERROR; 630 } 631 $$->type = $1; 632 $$->code = $3 + 1; 633 $$->proto = IPPROTO_ICMP; 634 $$->next = NULL; 635 } 636 | icmptype CODE STRING { 637 struct icmpcodeent *p; 638 639 $$ = malloc(sizeof(struct node_icmp)); 640 if ($$ == NULL) 641 err(1, "icmp_item: malloc"); 642 $$->type = $1; 643 if ((p = geticmpcodebyname($1, $3, 644 AF_INET)) == NULL) { 645 yyerror("unknown icmp-code %s", $3); 646 YYERROR; 647 } 648 $$->code = p->code + 1; 649 $$->proto = IPPROTO_ICMP; 650 $$->next = NULL; 651 } 652 ; 653 654 icmp6_item : icmp6type { 655 $$ = malloc(sizeof(struct node_icmp)); 656 if ($$ == NULL) 657 err(1, "icmp_item: malloc"); 658 $$->type = $1; 659 $$->code = 0; 660 $$->proto = IPPROTO_ICMPV6; 661 $$->next = NULL; 662 } 663 | icmp6type CODE NUMBER { 664 $$ = malloc(sizeof(struct node_icmp)); 665 if ($$ == NULL) 666 err(1, "icmp_item: malloc"); 667 if ($3 < 0 || $3 > 255) { 668 yyerror("illegal icmp6 code %d", $3); 669 YYERROR; 670 } 671 $$->type = $1; 672 $$->code = $3 + 1; 673 $$->proto = IPPROTO_ICMPV6; 674 $$->next = NULL; 675 } 676 | icmp6type CODE STRING { 677 struct icmpcodeent *p; 678 679 $$ = malloc(sizeof(struct node_icmp)); 680 if ($$ == NULL) 681 err(1, "icmp_item: malloc"); 682 $$->type = $1; 683 if ((p = geticmpcodebyname($1, $3, 684 AF_INET6)) == NULL) { 685 yyerror("unknown icmp6-code %s", $3); 686 YYERROR; 687 } 688 $$->code = p->code + 1; 689 $$->proto = IPPROTO_ICMPV6; 690 $$->next = NULL; 691 } 692 ; 693 694 icmptype : STRING { 695 struct icmptypeent *p; 696 697 if ((p = geticmptypebyname($1, AF_INET)) == NULL) { 698 yyerror("unknown icmp-type %s", $1); 699 YYERROR; 700 } 701 $$ = p->type + 1; 702 } 703 | NUMBER { 704 if ($1 < 0 || $1 > 255) { 705 yyerror("illegal icmp type %d", $1); 706 YYERROR; 707 } 708 $$ = $1 + 1; 709 } 710 ; 711 712 icmp6type : STRING { 713 struct icmptypeent *p; 714 715 if ((p = geticmptypebyname($1, AF_INET6)) == NULL) { 716 yyerror("unknown ipv6-icmp-type %s", $1); 717 YYERROR; 718 } 719 $$ = p->type + 1; 720 } 721 | NUMBER { 722 if ($1 < 0 || $1 > 255) { 723 yyerror("illegal icmp6 type %d", $1); 724 YYERROR; 725 } 726 $$ = $1 + 1; 727 } 728 ; 729 730 keep : /* empty */ { $$ = 0; } 731 | KEEP STATE { $$ = PF_STATE_NORMAL; } 732 | MODULATE STATE { $$ = PF_STATE_MODULATE; } 733 ; 734 735 minttl : /* empty */ { $$ = 0; } 736 | MINTTL NUMBER { 737 if ($2 < 0 || $2 > 255) { 738 yyerror("illegal min-ttl value %d", $2); 739 YYERROR; 740 } 741 $$ = $2; 742 } 743 ; 744 745 nodf : /* empty */ { $$ = 0; } 746 | NODF { $$ = 1; } 747 ; 748 749 allowopts : /* empty */ { $$ = 0; } 750 | ALLOWOPTS { $$ = 1; } 751 752 natrule : NAT interface proto FROM ipspec TO ipspec ARROW address 753 { 754 struct pf_nat nat; 755 756 if (!natmode) { 757 yyerror("nat rule not permitted in filter mode"); 758 YYERROR; 759 } 760 memset(&nat, 0, sizeof(nat)); 761 762 if ($2 != NULL) { 763 memcpy(nat.ifname, $2->ifname, 764 sizeof(nat.ifname)); 765 nat.ifnot = $2->not; 766 } 767 if ($3 != NULL) { 768 nat.proto = $3->proto; 769 free($3); 770 } 771 if ($5 != NULL && $7 != NULL && $5->af != $7->af) { 772 yyerror("nat ip versions must match"); 773 YYERROR; 774 } 775 if ($5 != NULL) { 776 nat.af = $5->af; 777 memcpy(&nat.saddr, &$5->addr, 778 sizeof(nat.saddr)); 779 memcpy(&nat.smask, &$5->mask, 780 sizeof(nat.smask)); 781 nat.snot = $5->not; 782 free($5); 783 } 784 if ($7 != NULL) { 785 nat.af = $7->af; 786 memcpy(&nat.daddr, &$7->addr, 787 sizeof(nat.daddr)); 788 memcpy(&nat.dmask, &$7->mask, 789 sizeof(nat.dmask)); 790 nat.dnot = $7->not; 791 free($7); 792 } 793 794 if ($9 == NULL) { 795 yyerror("nat rule requires redirection address"); 796 YYERROR; 797 } 798 /* we don't support IPv4 <-> IPv6 nat... yet */ 799 if (nat.af && $9->af != nat.af) { 800 yyerror("nat ip versions must match"); 801 YYERROR; 802 } 803 nat.af = $9->af; 804 memcpy(&nat.raddr, &$9->addr, sizeof(nat.raddr)); 805 free($9); 806 pfctl_add_nat(pf, &nat); 807 } 808 ; 809 810 binatrule : BINAT interface proto FROM address TO ipspec ARROW address 811 { 812 struct pf_binat binat; 813 814 if (!natmode) { 815 yyerror("binat rule not permitted in filter mode"); 816 YYERROR; 817 } 818 memset(&binat, 0, sizeof(binat)); 819 820 if ($2 != NULL) { 821 memcpy(binat.ifname, $2->ifname, 822 sizeof(binat.ifname)); 823 } 824 if ($3 != NULL) { 825 binat.proto = $3->proto; 826 free($3); 827 } 828 if ($5 != NULL && $7 != NULL && $5->af != $7->af) { 829 yyerror("binat ip versions must match"); 830 YYERROR; 831 } 832 if ($5 != NULL) { 833 binat.af = $5->af; 834 memcpy(&binat.saddr, &$5->addr, 835 sizeof(binat.saddr)); 836 free($5); 837 } 838 if ($7 != NULL) { 839 binat.af = $7->af; 840 memcpy(&binat.daddr, &$7->addr, 841 sizeof(binat.daddr)); 842 memcpy(&binat.dmask, &$7->mask, 843 sizeof(binat.dmask)); 844 binat.dnot = $7->not; 845 free($7); 846 } 847 848 if ($9 == NULL) { 849 yyerror("binat rule requires redirection address"); 850 YYERROR; 851 } 852 /* we don't support IPv4 <-> IPv6 binat... yet */ 853 if (binat.af && $9->af != binat.af) { 854 yyerror("binat ip versions must match"); 855 YYERROR; 856 } 857 binat.af = $9->af; 858 memcpy(&binat.raddr, &$9->addr, sizeof(binat.raddr)); 859 free($9); 860 pfctl_add_binat(pf, &binat); 861 } 862 863 rdrrule : RDR interface proto FROM ipspec TO ipspec dport ARROW address rport 864 { 865 struct pf_rdr rdr; 866 867 if (!natmode) { 868 yyerror("rdr rule not permitted in filter mode"); 869 YYERROR; 870 } 871 memset(&rdr, 0, sizeof(rdr)); 872 873 if ($2 != NULL) { 874 memcpy(rdr.ifname, $2->ifname, 875 sizeof(rdr.ifname)); 876 rdr.ifnot = $2->not; 877 } 878 if ($3 != NULL) { 879 rdr.proto = $3->proto; 880 free($3); 881 } 882 if ($5 != NULL && $7 != NULL && $5->af != $7->af) { 883 yyerror("rdr ip versions must match"); 884 YYERROR; 885 } 886 if ($5 != NULL) { 887 rdr.af = $5->af; 888 memcpy(&rdr.saddr, &$5->addr, 889 sizeof(rdr.saddr)); 890 memcpy(&rdr.smask, &$5->mask, 891 sizeof(rdr.smask)); 892 rdr.snot = $5->not; 893 free($5); 894 } 895 if ($7 != NULL) { 896 rdr.af = $7->af; 897 memcpy(&rdr.daddr, &$7->addr, 898 sizeof(rdr.daddr)); 899 memcpy(&rdr.dmask, &$7->mask, 900 sizeof(rdr.dmask)); 901 rdr.dnot = $7->not; 902 free($7); 903 } 904 905 rdr.dport = $8.a; 906 rdr.dport2 = $8.b; 907 rdr.opts |= $8.t; 908 909 if ($10 == NULL) { 910 yyerror("rdr rule requires redirection address"); 911 YYERROR; 912 } 913 if (rdr.af && $10->af != rdr.af) { 914 yyerror("rdr ip versions must match"); 915 YYERROR; 916 } 917 rdr.af = $10->af; 918 memcpy(&rdr.raddr, &$10->addr, sizeof(rdr.raddr)); 919 free($10); 920 921 rdr.rport = $11.a; 922 rdr.opts |= $11.t; 923 924 if (rdr.proto && rdr.proto != IPPROTO_TCP && 925 rdr.proto != IPPROTO_UDP && 926 (rdr.dport || rdr.dport2 || rdr.rport)) { 927 yyerror("rdr ports are only valid for proto tcp/udp"); 928 YYERROR; 929 } 930 931 pfctl_add_rdr(pf, &rdr); 932 } 933 ; 934 935 dport : /* empty */ { 936 $$.a = $$.b = $$.t = 0; 937 } 938 | PORT port { 939 $$.a = $2; 940 $$.b = $$.t = 0; 941 } 942 | PORT port ':' port { 943 $$.a = $2; 944 $$.b = $4; 945 $$.t = PF_DPORT_RANGE; 946 } 947 ; 948 949 rport : /* empty */ { 950 $$.a = $$.b = $$.t = 0; 951 } 952 | PORT port { 953 $$.a = $2; 954 $$.b = $$.t = 0; 955 } 956 | PORT port ':' '*' { 957 $$.a = $2; 958 $$.b = 0; 959 $$.t = PF_RPORT_RANGE; 960 } 961 ; 962 963 route : /* empty */ { 964 $$.string = NULL; 965 $$.rt = 0; 966 $$.addr = NULL; 967 $$.af = 0; 968 } 969 | FASTROUTE { 970 $$.string = NULL; 971 $$.rt = PF_FASTROUTE; 972 $$.addr = NULL; 973 } 974 | ROUTETO STRING ':' address { 975 $$.string = strdup($2); 976 $$.rt = PF_ROUTETO; 977 $$.addr = &$4->addr; 978 $$.af = $4->af; 979 } 980 | ROUTETO STRING { 981 $$.string = strdup($2); 982 $$.rt = PF_ROUTETO; 983 $$.addr = NULL; 984 } 985 | DUPTO STRING ':' address { 986 $$.string = strdup($2); 987 $$.rt = PF_DUPTO; 988 $$.addr = &$4->addr; 989 $$.af = $4->af; 990 } 991 | DUPTO STRING { 992 $$.string = strdup($2); 993 $$.rt = PF_DUPTO; 994 $$.addr = NULL; 995 } 996 ; 997 %% 998 999 int 1000 yyerror(char *fmt, ...) 1001 { 1002 va_list ap; 1003 extern char *infile; 1004 errors = 1; 1005 1006 va_start(ap, fmt); 1007 fprintf(stderr, "%s:%d: ", infile, yylval.lineno); 1008 vfprintf(stderr, fmt, ap); 1009 fprintf(stderr, "\n"); 1010 va_end(ap); 1011 return (0); 1012 } 1013 1014 int 1015 rule_consistent(struct pf_rule *r) 1016 { 1017 int problems = 0; 1018 1019 if (r->action == PF_SCRUB) { 1020 if (r->quick) { 1021 yyerror("quick does not apply to scrub"); 1022 problems++; 1023 } 1024 if (r->keep_state == PF_STATE_MODULATE) { 1025 yyerror("modulate state does not apply to scrub"); 1026 problems++; 1027 } 1028 if (r->keep_state == PF_STATE_NORMAL) { 1029 yyerror("keep state does not apply to scrub"); 1030 problems++; 1031 } 1032 if (r->src.port_op) { 1033 yyerror("src port does not apply to scrub"); 1034 problems++; 1035 } 1036 if (r->dst.port_op) { 1037 yyerror("dst port does not apply to scrub"); 1038 problems++; 1039 } 1040 if (r->type || r->code) { 1041 yyerror("icmp-type/code does not apply to scrub"); 1042 problems++; 1043 } 1044 } else { 1045 if (r->rule_flag & PFRULE_NODF) { 1046 yyerror("nodf only applies to scrub"); 1047 problems++; 1048 } 1049 if (r->min_ttl) { 1050 yyerror("min-ttl only applies to scrub"); 1051 problems++; 1052 } 1053 } 1054 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 1055 (r->src.port_op || r->dst.port_op)) { 1056 yyerror("port only applies to tcp/udp"); 1057 problems++; 1058 } 1059 if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 && 1060 (r->type || r->code)) { 1061 yyerror("icmp-type/code only applies to icmp"); 1062 problems++; 1063 } 1064 if (!r->af && (r->type || r->code)) { 1065 yyerror("must indicate address family with icmp-type/code"); 1066 problems++; 1067 } 1068 if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) || 1069 (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) { 1070 yyerror("icmp version does not match address family"); 1071 problems++; 1072 } 1073 if (!(r->rule_flag & PFRULE_RETURNRST) && r->return_icmp && 1074 ((r->af != AF_INET6 && (r->return_icmp>>8) != ICMP_UNREACH) || 1075 (r->af == AF_INET6 && (r->return_icmp>>8) != ICMP6_DST_UNREACH))) { 1076 yyerror("return-icmp version does not match address family"); 1077 problems++; 1078 } 1079 if (r->keep_state == PF_STATE_MODULATE && r->proto && 1080 r->proto != IPPROTO_TCP) { 1081 yyerror("modulate state can only be applied to TCP rules"); 1082 problems++; 1083 } 1084 if (r->allow_opts && r->action != PF_PASS) { 1085 yyerror("allow-opts can only be specified for pass rules"); 1086 problems++; 1087 } 1088 return (-problems); 1089 } 1090 1091 #define CHECK_ROOT(T,r) \ 1092 do { \ 1093 if (r == NULL) { \ 1094 r = malloc(sizeof(T)); \ 1095 if (r == NULL) \ 1096 err(1, "malloc"); \ 1097 memset(r, 0, sizeof(T)); \ 1098 } \ 1099 } while (0) 1100 1101 #define FREE_LIST(T,r) \ 1102 do { \ 1103 T *p, *n = r; \ 1104 while (n != NULL) { \ 1105 p = n; \ 1106 n = n->next; \ 1107 free(p); \ 1108 } \ 1109 } while (0) 1110 1111 void expand_rule_hosts(struct pf_rule *r, 1112 struct node_if *interface, struct node_proto *proto, 1113 struct node_host *src_hosts, struct node_port *src_ports, 1114 struct node_host *dst_hosts, struct node_port *dst_ports, 1115 struct node_icmp *icmp_type) 1116 { 1117 struct node_host *src_host, *dst_host; 1118 struct node_port *src_port, *dst_port; 1119 int nomatch = 0; 1120 1121 src_host = src_hosts; 1122 while (src_host != NULL) { 1123 src_port = src_ports; 1124 while (src_port != NULL) { 1125 dst_host = dst_hosts; 1126 while (dst_host != NULL) { 1127 dst_port = dst_ports; 1128 while (dst_port != NULL) { 1129 memcpy(r->ifname, interface->ifname, 1130 sizeof(r->ifname)); 1131 r->proto = proto->proto; 1132 r->src.addr = src_host->addr; 1133 r->src.mask = src_host->mask; 1134 r->src.not = src_host->not; 1135 r->src.port[0] = src_port->port[0]; 1136 r->src.port[1] = src_port->port[1]; 1137 r->src.port_op = src_port->op; 1138 r->dst.addr = dst_host->addr; 1139 r->dst.mask = dst_host->mask; 1140 r->dst.not = dst_host->not; 1141 r->dst.port[0] = dst_port->port[0]; 1142 r->dst.port[1] = dst_port->port[1]; 1143 r->dst.port_op = dst_port->op; 1144 r->type = icmp_type->type; 1145 r->code = icmp_type->code; 1146 1147 if ((src_host->af && dst_host->af && 1148 r->af) && (src_host->af != 1149 dst_host->af || 1150 src_host->af != r->af || 1151 dst_host->af != r->af)) { 1152 yyerror("address family" 1153 " mismatch"); 1154 nomatch++; 1155 } else if ((src_host->af && 1156 dst_host->af) && 1157 (src_host->af != dst_host->af)) { 1158 yyerror("address family" 1159 " mismatch"); 1160 nomatch++; 1161 } else if ((src_host->af && r->af) && 1162 (src_host->af != r->af)) { 1163 yyerror("address family" 1164 " mismatch"); 1165 nomatch++; 1166 } else if ((dst_host->af && r->af) && 1167 (dst_host->af != r->af)) { 1168 yyerror("address family" 1169 " mismatch"); 1170 nomatch++; 1171 } else if (src_host->af && !r->af) { 1172 r->af = src_host->af; 1173 } else if (dst_host->af && !r->af) { 1174 r->af= dst_host->af; 1175 } 1176 1177 if (icmp_type->proto && 1178 r->proto != icmp_type->proto) { 1179 yyerror("icmp-type mismatch"); 1180 nomatch++; 1181 } 1182 1183 if (rule_consistent(r) < 0 || nomatch) 1184 yyerror("skipping rule " 1185 "due to errors"); 1186 else 1187 pfctl_add_rule(pf, r); 1188 dst_port = dst_port->next; 1189 } 1190 dst_host = dst_host->next; 1191 } 1192 src_port = src_port->next; 1193 } 1194 src_host = src_host->next; 1195 } 1196 } 1197 1198 void expand_rule_protos(struct pf_rule *r, 1199 struct node_if *interface, struct node_proto *protos, 1200 struct node_host *src_hosts, struct node_port *src_ports, 1201 struct node_host *dst_hosts, struct node_port *dst_ports, 1202 struct node_icmp *icmp_types) 1203 { 1204 struct node_proto *proto; 1205 struct node_icmp *icmp_type; 1206 1207 proto = protos; 1208 while (proto != NULL) { 1209 icmp_type = icmp_types; 1210 while (icmp_type != NULL) { 1211 expand_rule_hosts(r, interface, proto, src_hosts, 1212 src_ports, dst_hosts, dst_ports, icmp_type); 1213 icmp_type = icmp_type->next; 1214 } 1215 proto = proto->next; 1216 } 1217 } 1218 1219 void 1220 expand_rule(struct pf_rule *r, 1221 struct node_if *interfaces, struct node_proto *protos, 1222 struct node_host *src_hosts, struct node_port *src_ports, 1223 struct node_host *dst_hosts, struct node_port *dst_ports, 1224 struct node_icmp *icmp_types) 1225 { 1226 struct node_if *interface; 1227 1228 CHECK_ROOT(struct node_if, interfaces); 1229 CHECK_ROOT(struct node_proto, protos); 1230 CHECK_ROOT(struct node_host, src_hosts); 1231 CHECK_ROOT(struct node_port, src_ports); 1232 CHECK_ROOT(struct node_host, dst_hosts); 1233 CHECK_ROOT(struct node_port, dst_ports); 1234 CHECK_ROOT(struct node_icmp, icmp_types); 1235 1236 interface = interfaces; 1237 while (interface != NULL) { 1238 expand_rule_protos(r, interface, protos, src_hosts, 1239 src_ports, dst_hosts, dst_ports, icmp_types); 1240 interface = interface->next; 1241 } 1242 1243 FREE_LIST(struct node_if, interfaces); 1244 FREE_LIST(struct node_proto, protos); 1245 FREE_LIST(struct node_host, src_hosts); 1246 FREE_LIST(struct node_port, src_ports); 1247 FREE_LIST(struct node_host, dst_hosts); 1248 FREE_LIST(struct node_port, dst_ports); 1249 FREE_LIST(struct node_icmp, icmp_types); 1250 1251 } 1252 1253 #undef FREE_LIST 1254 #undef CHECK_ROOT 1255 1256 int 1257 lookup(char *s) 1258 { 1259 int i; 1260 struct keywords { 1261 char *k_name; 1262 int k_val; 1263 } keywords[] = { 1264 { "all", ALL}, 1265 { "allow-opts", ALLOWOPTS}, 1266 { "any", ANY}, 1267 { "binat", BINAT}, 1268 { "block", BLOCK}, 1269 { "code", CODE}, 1270 { "dup-to", DUPTO}, 1271 { "flags", FLAGS}, 1272 { "fastroute", FASTROUTE}, 1273 { "from", FROM}, 1274 { "icmp-type", ICMPTYPE}, 1275 { "ipv6-icmp-type", ICMP6TYPE}, 1276 { "in", IN}, 1277 { "inet", INET}, 1278 { "inet6", INET6}, 1279 { "keep", KEEP}, 1280 { "log", LOG}, 1281 { "log-all", LOGALL}, 1282 { "min-ttl", MINTTL}, 1283 { "modulate", MODULATE}, 1284 { "nat", NAT}, 1285 { "no-df", NODF}, 1286 { "on", ON}, 1287 { "out", OUT}, 1288 { "pass", PASS}, 1289 { "port", PORT}, 1290 { "proto", PROTO}, 1291 { "quick", QUICK}, 1292 { "rdr", RDR}, 1293 { "return", RETURN}, 1294 { "return-icmp",RETURNICMP}, 1295 { "return-icmp6",RETURNICMP6}, 1296 { "return-rst", RETURNRST}, 1297 { "route-to", ROUTETO}, 1298 { "scrub", SCRUB}, 1299 { "state", STATE}, 1300 { "to", TO}, 1301 { NULL, 0 }, 1302 }; 1303 1304 for (i = 0; keywords[i].k_name != NULL; i++) { 1305 if (strcmp(s, keywords[i].k_name) == 0) { 1306 if (debug > 1) 1307 fprintf(stderr, "%s: %d\n", s, 1308 keywords[i].k_val); 1309 return (keywords[i].k_val); 1310 } 1311 } 1312 if (debug > 1) 1313 fprintf(stderr, "string: %s\n", s); 1314 return (STRING); 1315 } 1316 1317 char *parsebuf; 1318 int parseindex; 1319 1320 int 1321 lgetc(FILE *fin) 1322 { 1323 int c, next; 1324 1325 restart: 1326 if (parsebuf) { 1327 /* Reading characters from the parse buffer, instead of input */ 1328 c = parsebuf[parseindex++]; 1329 if (c != '\0') 1330 return (c); 1331 free(parsebuf); 1332 parsebuf = NULL; 1333 parseindex = 0; 1334 goto restart; 1335 } 1336 1337 c = getc(fin); 1338 if (c == '\\') { 1339 next = getc(fin); 1340 if (next != '\n') { 1341 ungetc(next, fin); 1342 return (c); 1343 } 1344 yylval.lineno = lineno; 1345 lineno++; 1346 goto restart; 1347 } 1348 return (c); 1349 } 1350 1351 int 1352 lungetc(int c, FILE *fin) 1353 { 1354 if (parsebuf && parseindex) { 1355 /* XXX breaks on index 0 */ 1356 parseindex--; 1357 return (c); 1358 } 1359 return ungetc(c, fin); 1360 } 1361 1362 int 1363 findeol() 1364 { 1365 int c; 1366 1367 if (parsebuf) { 1368 free(parsebuf); 1369 parsebuf = NULL; 1370 parseindex = 0; 1371 } 1372 1373 /* skip to either EOF or the first real EOL */ 1374 while (1) { 1375 c = lgetc(fin); 1376 if (c == '\\') { 1377 c = lgetc(fin); 1378 if (c == '\n') 1379 continue; 1380 } 1381 if (c == EOF || c == '\n') 1382 break; 1383 } 1384 return (ERROR); 1385 } 1386 1387 int 1388 yylex(void) 1389 { 1390 char buf[8096], *p, *val; 1391 int endc, c, next; 1392 int token; 1393 1394 top: 1395 p = buf; 1396 while ((c = lgetc(fin)) == ' ' || c == '\t') 1397 ; 1398 1399 yylval.lineno = lineno; 1400 if (c == '#') 1401 while ((c = lgetc(fin)) != '\n' && c != EOF) 1402 ; 1403 if (c == '$' && parsebuf == NULL) { 1404 while (1) { 1405 if ((c = lgetc(fin)) == EOF) 1406 return (0); 1407 if (p + 1 >= buf + sizeof(buf) - 1) { 1408 yyerror("string too long"); 1409 return (findeol()); 1410 } 1411 if (isalnum(c) || c == '_') { 1412 *p++ = (char)c; 1413 continue; 1414 } 1415 *p = '\0'; 1416 lungetc(c, fin); 1417 break; 1418 } 1419 val = symget(buf); 1420 if (val == NULL) 1421 return (ERROR); 1422 parsebuf = strdup(val); 1423 if (parsebuf == NULL) 1424 err(1, "parsebuf: strdup"); 1425 parseindex = 0; 1426 goto top; 1427 } 1428 1429 switch (c) { 1430 case '\'': 1431 case '"': 1432 endc = c; 1433 while (1) { 1434 if ((c = lgetc(fin)) == EOF) 1435 return (0); 1436 if (c == endc) { 1437 *p = '\0'; 1438 break; 1439 } 1440 if (c == '\n') 1441 continue; 1442 if (p + 1 >= buf + sizeof(buf) - 1) { 1443 yyerror("string too long"); 1444 return (findeol()); 1445 } 1446 *p++ = (char)c; 1447 } 1448 yylval.v.string = strdup(buf); 1449 if (yylval.v.string == NULL) 1450 err(1, "yylex: strdup"); 1451 return (STRING); 1452 case '=': 1453 yylval.v.i = PF_OP_EQ; 1454 return (PORTUNARY); 1455 case '!': 1456 next = lgetc(fin); 1457 if (next == '=') { 1458 yylval.v.i = PF_OP_NE; 1459 return (PORTUNARY); 1460 } 1461 lungetc(next, fin); 1462 break; 1463 case '<': 1464 next = lgetc(fin); 1465 if (next == '>') { 1466 yylval.v.i = PF_OP_XRG; 1467 return (PORTBINARY); 1468 } else if (next == '=') { 1469 yylval.v.i = PF_OP_LE; 1470 } else { 1471 yylval.v.i = PF_OP_LT; 1472 lungetc(next, fin); 1473 } 1474 return (PORTUNARY); 1475 break; 1476 case '>': 1477 next = lgetc(fin); 1478 if (next == '<') { 1479 yylval.v.i = PF_OP_IRG; 1480 return (PORTBINARY); 1481 } else if (next == '=') { 1482 yylval.v.i = PF_OP_GE; 1483 } else { 1484 yylval.v.i = PF_OP_GT; 1485 lungetc(next, fin); 1486 } 1487 return (PORTUNARY); 1488 break; 1489 case '-': 1490 next = lgetc(fin); 1491 if (next == '>') 1492 return (ARROW); 1493 lungetc(next, fin); 1494 break; 1495 } 1496 1497 /* Need to parse v6 addresses before tokenizing numbers. ick */ 1498 if (isxdigit(c) || c == ':') { 1499 struct node_host *node = NULL; 1500 u_int32_t addr[4]; 1501 char lookahead[46]; 1502 int i = 0, notv6addr = 0; 1503 1504 lookahead[i] = c; 1505 1506 while (i < sizeof(lookahead) && 1507 (isxdigit(c) || c == ':' || c == '.')) { 1508 lookahead[++i] = c = lgetc(fin); 1509 } 1510 1511 /* quick check avoids calling inet_pton too often */ 1512 if (isalnum(c)) { 1513 notv6addr++; 1514 } 1515 lungetc(lookahead[i], fin); 1516 lookahead[i] = '\0'; 1517 1518 if(!notv6addr && inet_pton(AF_INET6, lookahead, &addr) == 1) { 1519 node = calloc(1, sizeof(struct node_host)); 1520 node->af = AF_INET6; 1521 memcpy (&node->addr, &addr, sizeof(addr)); 1522 yylval.v.host = node; 1523 return IPV6ADDR; 1524 } else { 1525 free(node); 1526 while (i > 1) { 1527 lungetc(lookahead[--i], fin); 1528 } 1529 c = lookahead[--i]; 1530 } 1531 } 1532 1533 if (isdigit(c)) { 1534 int index = 0, base = 10; 1535 u_int64_t n = 0; 1536 1537 yylval.v.number = 0; 1538 while (1) { 1539 if (base == 10) { 1540 if (!isdigit(c)) 1541 break; 1542 c -= '0'; 1543 } else if (base == 16) { 1544 if (isdigit(c)) 1545 c -= '0'; 1546 else if (c >= 'a' && c <= 'f') 1547 c -= 'a' - 10; 1548 else if (c >= 'A' && c <= 'F') 1549 c -= 'A' - 10; 1550 else 1551 break; 1552 } 1553 n = n * base + c; 1554 1555 if (n > UINT_MAX) { 1556 yyerror("number is too large"); 1557 return (ERROR); 1558 } 1559 c = lgetc(fin); 1560 if (c == EOF) 1561 break; 1562 if (index++ == 0 && n == 0 && c == 'x') { 1563 base = 16; 1564 c = lgetc(fin); 1565 if (c == EOF) 1566 break; 1567 } 1568 } 1569 yylval.v.number = (u_int32_t)n; 1570 1571 if (c != EOF) 1572 lungetc(c, fin); 1573 if (debug > 1) 1574 fprintf(stderr, "number: %d\n", yylval.v.number); 1575 return (NUMBER); 1576 } 1577 1578 #define allowed_in_string(x) \ 1579 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 1580 x != '{' && x != '}' && x != '<' && x != '>' && \ 1581 x != '!' && x != '=' && x != '/' && x != '#' && x != ',' && x != ':')) 1582 1583 if (isalnum(c)) { 1584 do { 1585 *p++ = c; 1586 if (p-buf >= sizeof buf) { 1587 yyerror("string too long"); 1588 return (ERROR); 1589 } 1590 } while ((c = lgetc(fin)) != EOF && (allowed_in_string(c))); 1591 lungetc(c, fin); 1592 *p = '\0'; 1593 token = lookup(buf); 1594 yylval.v.string = strdup(buf); 1595 if (yylval.v.string == NULL) 1596 err(1, "yylex: strdup"); 1597 return (token); 1598 } 1599 if (c == '\n') { 1600 yylval.lineno = lineno; 1601 lineno++; 1602 } 1603 if (c == EOF) 1604 return (0); 1605 return (c); 1606 } 1607 1608 int 1609 parse_rules(FILE *input, struct pfctl *xpf) 1610 { 1611 natmode = 0; 1612 fin = input; 1613 pf = xpf; 1614 errors = 0; 1615 yyparse(); 1616 return (errors ? -1 : 0); 1617 } 1618 1619 int 1620 parse_nat(FILE *input, struct pfctl *xpf) 1621 { 1622 natmode = 1; 1623 fin = input; 1624 pf = xpf; 1625 errors = 0; 1626 yyparse(); 1627 return (errors ? -1 : 0); 1628 } 1629 1630 void 1631 ipmask(struct pf_addr *m, u_int8_t b, int af) 1632 { 1633 int i, j = 0; 1634 1635 while (b >= 32) { 1636 m->addr32[j++] = 0xffffffff; 1637 b -= 32; 1638 } 1639 for (i = 31; i > 31-b; --i) 1640 m->addr32[j] |= (1 << i); 1641 if (b) 1642 m->addr32[j] = htonl(m->addr32[j]); 1643 } 1644 1645 struct pf_rule_addr * 1646 new_addr(void) 1647 { 1648 struct pf_rule_addr *ra; 1649 1650 ra = malloc(sizeof(struct pf_rule_addr)); 1651 if (ra == NULL) 1652 err(1, "new_addr: malloc failed"); 1653 memset(ra, 0, sizeof(*ra)); 1654 return (ra); 1655 } 1656 1657 /* 1658 * Over-designed efficiency is a French and German concept, so how about 1659 * we wait until they discover this ugliness and make it all fancy. 1660 */ 1661 int 1662 symset(char *nam, char *val) 1663 { 1664 struct sym *sym; 1665 1666 sym = calloc(1, sizeof(*sym)); 1667 if (sym == NULL) 1668 return (-1); 1669 sym->nam = strdup(nam); 1670 if (sym->nam == NULL) { 1671 free(sym); 1672 return (-1); 1673 } 1674 sym->val = strdup(val); 1675 if (sym->val == NULL) { 1676 free(sym->nam); 1677 free(sym); 1678 return (-1); 1679 } 1680 sym->next = symhead; 1681 symhead = sym; 1682 return (0); 1683 } 1684 1685 char * 1686 symget(char *nam) 1687 { 1688 struct sym *sym; 1689 1690 for (sym = symhead; sym; sym = sym->next) 1691 if (strcmp(nam, sym->nam) == 0) 1692 return (sym->val); 1693 return (NULL); 1694 } 1695 1696 struct ifaddrs **ifa0tab, **ifa4tab, **ifa6tab; 1697 int ifa0len, ifa4len, ifa6len; 1698 1699 int 1700 ifa_comp(const void *p1, const void *p2) 1701 { 1702 struct ifaddrs *ifa1 = *(struct ifaddrs **)p1; 1703 struct ifaddrs *ifa2 = *(struct ifaddrs **)p2; 1704 1705 return strcmp(ifa1->ifa_name, ifa2->ifa_name); 1706 } 1707 1708 void 1709 ifa_load(void) 1710 { 1711 struct ifaddrs *ifap, *ifa; 1712 int ifalen = 0; 1713 1714 if (getifaddrs(&ifap) < 0) 1715 err(1, "getifaddrs"); 1716 for (ifa = ifap; ifa; ifa = ifa->ifa_next) 1717 ifalen++; 1718 /* (over-)allocate tables */ 1719 ifa0tab = malloc(ifalen * sizeof(void *)); 1720 ifa4tab = malloc(ifalen * sizeof(void *)); 1721 ifa6tab = malloc(ifalen * sizeof(void *)); 1722 if (!ifa0tab || !ifa4tab || !ifa6tab) 1723 err(1, "malloc"); 1724 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 1725 if (ifa->ifa_addr->sa_family == AF_LINK) { 1726 if (bsearch(&ifa, ifa0tab, ifa0len, sizeof(void *), 1727 ifa_comp)) 1728 continue; /* take only the first LINK address */ 1729 ifa0tab[ifa0len++] = ifa; 1730 qsort(ifa0tab, ifa0len, sizeof(void *), ifa_comp); 1731 } 1732 if (ifa->ifa_addr->sa_family == AF_INET) { 1733 if (bsearch(&ifa, ifa4tab, ifa4len, sizeof(void *), 1734 ifa_comp)) 1735 continue; /* take only the first IPv4 address */ 1736 ifa4tab[ifa4len++] = ifa; 1737 qsort(ifa4tab, ifa4len, sizeof(void *), ifa_comp); 1738 } 1739 if (ifa->ifa_addr->sa_family == AF_INET6) { 1740 /* XXX - better address selection required! */ 1741 if (bsearch(&ifa, ifa6tab, ifa6len, sizeof(void *), 1742 ifa_comp)) 1743 continue; /* take only the first IPv6 address */ 1744 ifa6tab[ifa6len++] = ifa; 1745 qsort(ifa6tab, ifa6len, sizeof(void *), ifa_comp); 1746 } 1747 } 1748 /* shrink tables */ 1749 ifa0tab = realloc(ifa0tab, ifa0len * sizeof(void *)); 1750 ifa4tab = realloc(ifa4tab, ifa4len * sizeof(void *)); 1751 ifa6tab = realloc(ifa6tab, ifa6len * sizeof(void *)); 1752 if (!ifa0tab || !ifa4tab || !ifa6tab) 1753 err(1, "realloc"); 1754 } 1755 1756 struct ifaddrs * 1757 ifa0_lookup(char *ifa_name) 1758 { 1759 struct ifaddrs ifa, *ifp = &ifa, **ifpp; 1760 1761 if (!ifa0tab) 1762 ifa_load(); 1763 ifa.ifa_name = ifa_name; 1764 ifpp = bsearch(&ifp, ifa0tab, ifa0len, sizeof(void *), ifa_comp); 1765 return ifpp ? *ifpp : NULL; 1766 } 1767 1768 struct ifaddrs * 1769 ifa4_lookup(char *ifa_name) 1770 { 1771 struct ifaddrs ifa, *ifp = &ifa, **ifpp; 1772 1773 if (!ifa4tab) 1774 ifa_load(); 1775 ifa.ifa_name = ifa_name; 1776 ifpp = bsearch(&ifp, ifa4tab, ifa4len, sizeof(void *), ifa_comp); 1777 return ifpp ? *ifpp : NULL; 1778 } 1779 1780 struct ifaddrs * 1781 ifa6_lookup(char *ifa_name) 1782 { 1783 struct ifaddrs ifa, *ifp = &ifa, **ifpp; 1784 1785 if (!ifa6tab) 1786 ifa_load(); 1787 ifa.ifa_name = ifa_name; 1788 ifpp = bsearch(&ifp, ifa6tab, ifa6len, sizeof(void *), ifa_comp); 1789 return ifpp ? *ifpp : NULL; 1790 } 1791 1792