1 /* $OpenBSD: parse.y,v 1.655 2016/08/26 06:06:58 guenther Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Markus Friedl. All rights reserved. 5 * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. 6 * Copyright (c) 2001 Theo de Raadt. All rights reserved. 7 * Copyright (c) 2002 - 2013 Henning Brauer <henning@openbsd.org> 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 %{ 30 #include <sys/types.h> 31 #include <sys/socket.h> 32 #include <sys/stat.h> 33 #include <net/if.h> 34 #include <netinet/in.h> 35 #include <netinet/ip.h> 36 #include <netinet/ip_icmp.h> 37 #include <netinet/icmp6.h> 38 #include <net/pfvar.h> 39 #include <net/hfsc.h> 40 #include <arpa/inet.h> 41 42 #include <stdio.h> 43 #include <unistd.h> 44 #include <stdlib.h> 45 #include <netdb.h> 46 #include <stdarg.h> 47 #include <errno.h> 48 #include <string.h> 49 #include <ctype.h> 50 #include <math.h> 51 #include <err.h> 52 #include <limits.h> 53 #include <pwd.h> 54 #include <grp.h> 55 #include <md5.h> 56 57 #include "pfctl_parser.h" 58 #include "pfctl.h" 59 60 static struct pfctl *pf = NULL; 61 static int debug = 0; 62 static u_int16_t returnicmpdefault = 63 (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 64 static u_int16_t returnicmp6default = 65 (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT; 66 static int blockpolicy = PFRULE_DROP; 67 static int default_statelock; 68 69 TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); 70 static struct file { 71 TAILQ_ENTRY(file) entry; 72 FILE *stream; 73 char *name; 74 int lineno; 75 int errors; 76 } *file; 77 struct file *pushfile(const char *, int); 78 int popfile(void); 79 int check_file_secrecy(int, const char *); 80 int yyparse(void); 81 int yylex(void); 82 int yyerror(const char *, ...); 83 int kw_cmp(const void *, const void *); 84 int lookup(char *); 85 int lgetc(int); 86 int lungetc(int); 87 int findeol(void); 88 89 TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 90 struct sym { 91 TAILQ_ENTRY(sym) entry; 92 int used; 93 int persist; 94 char *nam; 95 char *val; 96 }; 97 int symset(const char *, const char *, int); 98 char *symget(const char *); 99 100 int atoul(char *, u_long *); 101 102 struct node_proto { 103 u_int8_t proto; 104 struct node_proto *next; 105 struct node_proto *tail; 106 }; 107 108 struct node_port { 109 u_int16_t port[2]; 110 u_int8_t op; 111 struct node_port *next; 112 struct node_port *tail; 113 }; 114 115 struct node_uid { 116 uid_t uid[2]; 117 u_int8_t op; 118 struct node_uid *next; 119 struct node_uid *tail; 120 }; 121 122 struct node_gid { 123 gid_t gid[2]; 124 u_int8_t op; 125 struct node_gid *next; 126 struct node_gid *tail; 127 }; 128 129 struct node_icmp { 130 u_int8_t code; 131 u_int8_t type; 132 u_int8_t proto; 133 struct node_icmp *next; 134 struct node_icmp *tail; 135 }; 136 137 enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK, 138 PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN, 139 PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES, 140 PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK, 141 PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY, 142 PF_STATE_OPT_PFLOW }; 143 144 enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE }; 145 146 struct node_state_opt { 147 int type; 148 union { 149 u_int32_t max_states; 150 u_int32_t max_src_states; 151 u_int32_t max_src_conn; 152 struct { 153 u_int32_t limit; 154 u_int32_t seconds; 155 } max_src_conn_rate; 156 struct { 157 u_int8_t flush; 158 char tblname[PF_TABLE_NAME_SIZE]; 159 } overload; 160 u_int32_t max_src_nodes; 161 u_int8_t src_track; 162 u_int32_t statelock; 163 struct { 164 int number; 165 u_int32_t seconds; 166 } timeout; 167 } data; 168 struct node_state_opt *next; 169 struct node_state_opt *tail; 170 }; 171 172 struct peer { 173 struct node_host *host; 174 struct node_port *port; 175 }; 176 177 struct node_queue { 178 char queue[PF_QNAME_SIZE]; 179 char parent[PF_QNAME_SIZE]; 180 char ifname[IFNAMSIZ]; 181 int scheduler; 182 struct node_queue *next; 183 struct node_queue *tail; 184 }; 185 186 struct node_qassign { 187 char *qname; 188 char *pqname; 189 }; 190 191 struct range { 192 int a; 193 int b; 194 int t; 195 }; 196 struct redirection { 197 struct node_host *host; 198 struct range rport; 199 }; 200 201 struct pool_opts { 202 int marker; 203 #define POM_TYPE 0x01 204 #define POM_STICKYADDRESS 0x02 205 u_int8_t opts; 206 int type; 207 int staticport; 208 struct pf_poolhashkey *key; 209 210 } pool_opts; 211 212 struct divertspec { 213 struct node_host *addr; 214 u_int16_t port; 215 }; 216 217 struct redirspec { 218 struct redirection *rdr; 219 struct pool_opts pool_opts; 220 int binat; 221 int af; 222 }; 223 224 struct filter_opts { 225 int marker; 226 #define FOM_FLAGS 0x0001 227 #define FOM_ICMP 0x0002 228 #define FOM_TOS 0x0004 229 #define FOM_KEEP 0x0008 230 #define FOM_SRCTRACK 0x0010 231 #define FOM_MINTTL 0x0020 232 #define FOM_MAXMSS 0x0040 233 #define FOM_AFTO 0x0080 234 #define FOM_SETTOS 0x0100 235 #define FOM_SCRUB_TCP 0x0200 236 #define FOM_SETPRIO 0x0400 237 #define FOM_ONCE 0x1000 238 #define FOM_PRIO 0x2000 239 struct node_uid *uid; 240 struct node_gid *gid; 241 struct node_if *rcv; 242 struct { 243 u_int8_t b1; 244 u_int8_t b2; 245 u_int16_t w; 246 u_int16_t w2; 247 } flags; 248 struct node_icmp *icmpspec; 249 u_int32_t tos; 250 u_int32_t prob; 251 struct { 252 int action; 253 struct node_state_opt *options; 254 } keep; 255 int fragment; 256 int allowopts; 257 char *label; 258 struct node_qassign queues; 259 char *tag; 260 char *match_tag; 261 u_int8_t match_tag_not; 262 u_int rtableid; 263 u_int8_t prio; 264 u_int8_t set_prio[2]; 265 struct divertspec divert; 266 struct divertspec divert_packet; 267 struct redirspec nat; 268 struct redirspec rdr; 269 struct redirspec rroute; 270 271 /* scrub opts */ 272 int nodf; 273 int minttl; 274 int settos; 275 int randomid; 276 int max_mss; 277 278 /* route opts */ 279 struct { 280 struct node_host *host; 281 u_int8_t rt; 282 u_int8_t pool_opts; 283 sa_family_t af; 284 struct pf_poolhashkey *key; 285 } route; 286 } filter_opts; 287 288 struct antispoof_opts { 289 char *label; 290 u_int rtableid; 291 } antispoof_opts; 292 293 struct scrub_opts { 294 int marker; 295 int nodf; 296 int minttl; 297 int maxmss; 298 int settos; 299 int randomid; 300 int reassemble_tcp; 301 } scrub_opts; 302 303 struct node_sc { 304 struct node_queue_bw m1; 305 u_int d; 306 struct node_queue_bw m2; 307 }; 308 309 struct queue_opts { 310 int marker; 311 #define QOM_BWSPEC 0x01 312 #define QOM_PARENT 0x02 313 #define QOM_DEFAULT 0x04 314 #define QOM_QLIMIT 0x08 315 struct node_sc realtime; 316 struct node_sc linkshare; 317 struct node_sc upperlimit; 318 char *parent; 319 int flags; 320 u_int qlimit; 321 } queue_opts; 322 323 struct table_opts { 324 int flags; 325 int init_addr; 326 struct node_tinithead init_nodes; 327 } table_opts; 328 329 struct node_hfsc_opts hfsc_opts; 330 struct node_state_opt *keep_state_defaults = NULL; 331 332 int disallow_table(struct node_host *, const char *); 333 int disallow_urpf_failed(struct node_host *, const char *); 334 int disallow_alias(struct node_host *, const char *); 335 int rule_consistent(struct pf_rule *, int); 336 int process_tabledef(char *, struct table_opts *); 337 void expand_label_str(char *, size_t, const char *, const char *); 338 void expand_label_if(const char *, char *, size_t, const char *); 339 void expand_label_addr(const char *, char *, size_t, u_int8_t, 340 struct node_host *); 341 void expand_label_port(const char *, char *, size_t, 342 struct node_port *); 343 void expand_label_proto(const char *, char *, size_t, u_int8_t); 344 void expand_label_nr(const char *, char *, size_t); 345 void expand_label(char *, size_t, const char *, u_int8_t, 346 struct node_host *, struct node_port *, struct node_host *, 347 struct node_port *, u_int8_t); 348 int expand_divertspec(struct pf_rule *, struct divertspec *); 349 int collapse_redirspec(struct pf_pool *, struct pf_rule *, 350 struct redirspec *rs, u_int8_t); 351 int apply_redirspec(struct pf_pool *, struct pf_rule *, 352 struct redirspec *, int, struct node_port *); 353 void expand_rule(struct pf_rule *, int, struct node_if *, 354 struct redirspec *, struct redirspec *, struct redirspec *, 355 struct node_proto *, 356 struct node_os *, struct node_host *, struct node_port *, 357 struct node_host *, struct node_port *, struct node_uid *, 358 struct node_gid *, struct node_if *, struct node_icmp *, 359 const char *); 360 int expand_queue(char *, struct node_if *, struct queue_opts *); 361 int expand_skip_interface(struct node_if *); 362 363 int getservice(char *); 364 int rule_label(struct pf_rule *, char *); 365 366 void mv_rules(struct pf_ruleset *, struct pf_ruleset *); 367 void decide_address_family(struct node_host *, sa_family_t *); 368 int invalid_redirect(struct node_host *, sa_family_t); 369 u_int16_t parseicmpspec(char *, sa_family_t); 370 int kw_casecmp(const void *, const void *); 371 int map_tos(char *string, int *); 372 373 TAILQ_HEAD(loadanchorshead, loadanchors) 374 loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead); 375 376 struct loadanchors { 377 TAILQ_ENTRY(loadanchors) entries; 378 char *anchorname; 379 char *filename; 380 }; 381 382 typedef struct { 383 union { 384 int64_t number; 385 double probability; 386 int i; 387 char *string; 388 u_int rtableid; 389 u_int16_t weight; 390 struct { 391 u_int8_t b1; 392 u_int8_t b2; 393 u_int16_t w; 394 u_int16_t w2; 395 } b; 396 struct range range; 397 struct node_if *interface; 398 struct node_proto *proto; 399 struct node_icmp *icmp; 400 struct node_host *host; 401 struct node_os *os; 402 struct node_port *port; 403 struct node_uid *uid; 404 struct node_gid *gid; 405 struct node_state_opt *state_opt; 406 struct peer peer; 407 struct { 408 struct peer src, dst; 409 struct node_os *src_os; 410 } fromto; 411 struct redirection *redirection; 412 struct { 413 int action; 414 struct node_state_opt *options; 415 } keep_state; 416 struct { 417 u_int8_t log; 418 u_int8_t logif; 419 u_int8_t quick; 420 } logquick; 421 struct { 422 int neg; 423 char *name; 424 } tagged; 425 struct pf_poolhashkey *hashkey; 426 struct node_queue *queue; 427 struct node_queue_opt queue_options; 428 struct node_queue_bw queue_bwspec; 429 struct node_qassign qassign; 430 struct node_sc sc; 431 struct filter_opts filter_opts; 432 struct antispoof_opts antispoof_opts; 433 struct queue_opts queue_opts; 434 struct scrub_opts scrub_opts; 435 struct table_opts table_opts; 436 struct pool_opts pool_opts; 437 struct node_hfsc_opts hfsc_opts; 438 } v; 439 int lineno; 440 } YYSTYPE; 441 442 #define PPORT_RANGE 1 443 #define PPORT_STAR 2 444 int parseport(char *, struct range *r, int); 445 446 #define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \ 447 (!((addr).iflags & PFI_AFLAG_NOALIAS) || \ 448 !isdigit((unsigned char)(addr).v.ifname[strlen((addr).v.ifname)-1]))) 449 450 %} 451 452 %token PASS BLOCK MATCH SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS 453 %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE 454 %token ICMP6TYPE CODE KEEP MODULATE STATE PORT BINATTO NODF 455 %token MINTTL ERROR ALLOWOPTS FILENAME ROUTETO DUPTO REPLYTO NO LABEL 456 %token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE 457 %token REASSEMBLE ANCHOR 458 %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID 459 %token SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID 460 %token ANTISPOOF FOR INCLUDE MATCHES 461 %token BITMASK RANDOM SOURCEHASH ROUNDROBIN LEASTSTATES STATICPORT PROBABILITY 462 %token WEIGHT BANDWIDTH 463 %token QUEUE PRIORITY QLIMIT RTABLE RDOMAIN MINIMUM BURST PARENT 464 %token LOAD RULESET_OPTIMIZATION RTABLE RDOMAIN PRIO ONCE DEFAULT 465 %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE 466 %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW 467 %token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE 468 %token DIVERTTO DIVERTREPLY DIVERTPACKET NATTO AFTO RDRTO RECEIVEDON NE LE GE 469 %token <v.string> STRING 470 %token <v.number> NUMBER 471 %token <v.i> PORTBINARY 472 %type <v.interface> interface if_list if_item_not if_item 473 %type <v.number> number icmptype icmp6type uid gid 474 %type <v.number> tos not yesno optnodf 475 %type <v.probability> probability 476 %type <v.weight> optweight 477 %type <v.i> dir af optimizer 478 %type <v.i> sourcetrack flush unaryop statelock 479 %type <v.b> action 480 %type <v.b> flags flag blockspec prio 481 %type <v.range> portplain portstar portrange 482 %type <v.hashkey> hashkey 483 %type <v.proto> proto proto_list proto_item 484 %type <v.number> protoval 485 %type <v.icmp> icmpspec 486 %type <v.icmp> icmp_list icmp_item 487 %type <v.icmp> icmp6_list icmp6_item 488 %type <v.number> reticmpspec reticmp6spec 489 %type <v.fromto> fromto 490 %type <v.peer> ipportspec from to 491 %type <v.host> ipspec xhost host dynaddr host_list 492 %type <v.host> table_host_list tablespec 493 %type <v.host> redir_host_list redirspec 494 %type <v.host> route_host route_host_list routespec 495 %type <v.os> os xos os_list 496 %type <v.port> portspec port_list port_item 497 %type <v.uid> uids uid_list uid_item 498 %type <v.gid> gids gid_list gid_item 499 %type <v.redirection> redirpool 500 %type <v.string> label stringall anchorname 501 %type <v.string> string varstring numberstring 502 %type <v.keep_state> keep 503 %type <v.state_opt> state_opt_spec state_opt_list state_opt_item 504 %type <v.logquick> logquick quick log logopts logopt 505 %type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if 506 %type <v.qassign> qname 507 %type <v.queue_bwspec> bandwidth 508 %type <v.filter_opts> filter_opts filter_opt filter_opts_l 509 %type <v.filter_opts> filter_sets filter_set filter_sets_l 510 %type <v.antispoof_opts> antispoof_opts antispoof_opt antispoof_opts_l 511 %type <v.queue_opts> queue_opts queue_opt queue_opts_l optscs 512 %type <v.sc> scspec 513 %type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l 514 %type <v.table_opts> table_opts table_opt table_opts_l 515 %type <v.pool_opts> pool_opts pool_opt pool_opts_l 516 %% 517 518 ruleset : /* empty */ 519 | ruleset include '\n' 520 | ruleset '\n' 521 | ruleset option '\n' 522 | ruleset pfrule '\n' 523 | ruleset anchorrule '\n' 524 | ruleset loadrule '\n' 525 | ruleset queuespec '\n' 526 | ruleset varset '\n' 527 | ruleset antispoof '\n' 528 | ruleset tabledef '\n' 529 | '{' fakeanchor '}' '\n'; 530 | ruleset error '\n' { file->errors++; } 531 ; 532 533 include : INCLUDE STRING { 534 struct file *nfile; 535 536 if ((nfile = pushfile($2, 0)) == NULL) { 537 yyerror("failed to include file %s", $2); 538 free($2); 539 YYERROR; 540 } 541 free($2); 542 543 file = nfile; 544 lungetc('\n'); 545 } 546 ; 547 548 /* 549 * apply to previously specified rule: must be careful to note 550 * what that is: pf or nat or binat or rdr 551 */ 552 fakeanchor : fakeanchor '\n' 553 | fakeanchor anchorrule '\n' 554 | fakeanchor pfrule '\n' 555 | fakeanchor error '\n' 556 ; 557 558 optimizer : string { 559 if (!strcmp($1, "none")) 560 $$ = 0; 561 else if (!strcmp($1, "basic")) 562 $$ = PF_OPTIMIZE_BASIC; 563 else if (!strcmp($1, "profile")) 564 $$ = PF_OPTIMIZE_BASIC | PF_OPTIMIZE_PROFILE; 565 else { 566 yyerror("unknown ruleset-optimization %s", $1); 567 YYERROR; 568 } 569 } 570 ; 571 572 optnodf : /* empty */ { $$ = 0; } 573 | NODF { $$ = 1; } 574 ; 575 576 option : SET REASSEMBLE yesno optnodf { 577 pfctl_set_reassembly(pf, $3, $4); 578 } 579 | SET OPTIMIZATION STRING { 580 if (pfctl_set_optimization(pf, $3) != 0) { 581 yyerror("unknown optimization %s", $3); 582 free($3); 583 YYERROR; 584 } 585 free($3); 586 } 587 | SET RULESET_OPTIMIZATION optimizer { 588 if (!(pf->opts & PF_OPT_OPTIMIZE)) { 589 pf->opts |= PF_OPT_OPTIMIZE; 590 pf->optimize = $3; 591 } 592 } 593 | SET TIMEOUT timeout_spec 594 | SET TIMEOUT '{' optnl timeout_list '}' 595 | SET LIMIT limit_spec 596 | SET LIMIT '{' optnl limit_list '}' 597 | SET LOGINTERFACE stringall { 598 if (pfctl_set_logif(pf, $3) != 0) { 599 yyerror("error setting loginterface %s", $3); 600 free($3); 601 YYERROR; 602 } 603 free($3); 604 } 605 | SET HOSTID number { 606 if ($3 == 0 || $3 > UINT_MAX) { 607 yyerror("hostid must be non-zero"); 608 YYERROR; 609 } 610 pfctl_set_hostid(pf, $3); 611 } 612 | SET BLOCKPOLICY DROP { 613 if (pf->opts & PF_OPT_VERBOSE) 614 printf("set block-policy drop\n"); 615 blockpolicy = PFRULE_DROP; 616 } 617 | SET BLOCKPOLICY RETURN { 618 if (pf->opts & PF_OPT_VERBOSE) 619 printf("set block-policy return\n"); 620 blockpolicy = PFRULE_RETURN; 621 } 622 | SET FINGERPRINTS STRING { 623 if (pf->opts & PF_OPT_VERBOSE) 624 printf("set fingerprints \"%s\"\n", $3); 625 if (!pf->anchor->name[0]) { 626 if (pfctl_file_fingerprints(pf->dev, 627 pf->opts, $3)) { 628 yyerror("error loading " 629 "fingerprints %s", $3); 630 free($3); 631 YYERROR; 632 } 633 } 634 free($3); 635 } 636 | SET STATEPOLICY statelock { 637 if (pf->opts & PF_OPT_VERBOSE) 638 switch ($3) { 639 case 0: 640 printf("set state-policy floating\n"); 641 break; 642 case PFRULE_IFBOUND: 643 printf("set state-policy if-bound\n"); 644 break; 645 } 646 default_statelock = $3; 647 } 648 | SET DEBUG STRING { 649 if (pfctl_set_debug(pf, $3) != 0) { 650 yyerror("error setting debuglevel %s", $3); 651 free($3); 652 YYERROR; 653 } 654 free($3); 655 } 656 | SET DEBUG DEBUG { 657 if (pfctl_set_debug(pf, "debug") != 0) { 658 yyerror("error setting debuglevel %s", "debug"); 659 YYERROR; 660 } 661 } 662 | SET SKIP interface { 663 if (expand_skip_interface($3) != 0) { 664 yyerror("error setting skip interface(s)"); 665 YYERROR; 666 } 667 } 668 | SET STATEDEFAULTS state_opt_list { 669 if (keep_state_defaults != NULL) { 670 yyerror("cannot redefine state-defaults"); 671 YYERROR; 672 } 673 keep_state_defaults = $3; 674 } 675 ; 676 677 stringall : STRING { $$ = $1; } 678 | ALL { 679 if (($$ = strdup("all")) == NULL) { 680 err(1, "stringall: strdup"); 681 } 682 } 683 ; 684 685 string : STRING string { 686 if (asprintf(&$$, "%s %s", $1, $2) == -1) 687 err(1, "string: asprintf"); 688 free($1); 689 free($2); 690 } 691 | STRING 692 ; 693 694 varstring : numberstring varstring { 695 if (asprintf(&$$, "%s %s", $1, $2) == -1) 696 err(1, "string: asprintf"); 697 free($1); 698 free($2); 699 } 700 | numberstring 701 ; 702 703 numberstring : NUMBER { 704 char *s; 705 if (asprintf(&s, "%lld", $1) == -1) { 706 yyerror("string: asprintf"); 707 YYERROR; 708 } 709 $$ = s; 710 } 711 | STRING 712 ; 713 714 varset : STRING '=' varstring { 715 char *s = $1; 716 if (pf->opts & PF_OPT_VERBOSE) 717 printf("%s = \"%s\"\n", $1, $3); 718 while (*s++) { 719 if (isspace((unsigned char)*s)) { 720 yyerror("macro name cannot contain " 721 "whitespace"); 722 YYERROR; 723 } 724 } 725 if (symset($1, $3, 0) == -1) 726 err(1, "cannot store variable %s", $1); 727 free($1); 728 free($3); 729 } 730 ; 731 732 anchorname : STRING { $$ = $1; } 733 | /* empty */ { $$ = NULL; } 734 ; 735 736 pfa_anchorlist : /* empty */ 737 | pfa_anchorlist '\n' 738 | pfa_anchorlist pfrule '\n' 739 | pfa_anchorlist anchorrule '\n' 740 | pfa_anchorlist include '\n' 741 ; 742 743 pfa_anchor : '{' 744 { 745 char ta[PF_ANCHOR_NAME_SIZE]; 746 struct pf_ruleset *rs; 747 748 /* steping into a brace anchor */ 749 pf->asd++; 750 pf->bn++; 751 pf->brace = 1; 752 753 /* 754 * Anchor contents are parsed before the anchor rule 755 * production completes, so we don't know the real 756 * location yet. Create a holding ruleset in the root; 757 * contents will be moved afterwards. 758 */ 759 snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn); 760 rs = pf_find_or_create_ruleset(ta); 761 if (rs == NULL) 762 err(1, "pfa_anchor: pf_find_or_create_ruleset"); 763 pf->astack[pf->asd] = rs->anchor; 764 pf->anchor = rs->anchor; 765 } '\n' pfa_anchorlist '}' 766 { 767 pf->alast = pf->anchor; 768 pf->asd--; 769 pf->anchor = pf->astack[pf->asd]; 770 } 771 | /* empty */ 772 ; 773 774 anchorrule : ANCHOR anchorname dir quick interface af proto fromto 775 filter_opts pfa_anchor 776 { 777 struct pf_rule r; 778 struct node_proto *proto; 779 780 if ($2 && ($2[0] == '_' || strstr($2, "/_") != NULL)) { 781 free($2); 782 yyerror("anchor names beginning with '_' " 783 "are reserved for internal use"); 784 YYERROR; 785 } 786 787 memset(&r, 0, sizeof(r)); 788 if (pf->astack[pf->asd + 1]) { 789 if ($2 && strchr($2, '/') != NULL) { 790 free($2); 791 yyerror("anchor paths containing '/' " 792 "cannot be used for inline anchors."); 793 YYERROR; 794 } 795 796 /* Move inline rules into relative location. */ 797 pf_anchor_setup(&r, 798 &pf->astack[pf->asd]->ruleset, 799 $2 ? $2 : pf->alast->name); 800 801 if (r.anchor == NULL) 802 err(1, "anchorrule: unable to " 803 "create ruleset"); 804 805 if (pf->alast != r.anchor) { 806 if (r.anchor->match) { 807 yyerror("inline anchor '%s' " 808 "already exists", 809 r.anchor->name); 810 YYERROR; 811 } 812 mv_rules(&pf->alast->ruleset, 813 &r.anchor->ruleset); 814 } 815 pf_remove_if_empty_ruleset(&pf->alast->ruleset); 816 pf->alast = r.anchor; 817 } else { 818 if (!$2) { 819 yyerror("anchors without explicit " 820 "rules must specify a name"); 821 YYERROR; 822 } 823 } 824 r.direction = $3; 825 r.quick = $4.quick; 826 r.af = $6; 827 r.prob = $9.prob; 828 r.rtableid = $9.rtableid; 829 830 if ($9.tag) 831 if (strlcpy(r.tagname, $9.tag, 832 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 833 yyerror("tag too long, max %u chars", 834 PF_TAG_NAME_SIZE - 1); 835 YYERROR; 836 } 837 if ($9.match_tag) 838 if (strlcpy(r.match_tagname, $9.match_tag, 839 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 840 yyerror("tag too long, max %u chars", 841 PF_TAG_NAME_SIZE - 1); 842 YYERROR; 843 } 844 r.match_tag_not = $9.match_tag_not; 845 if (rule_label(&r, $9.label)) 846 YYERROR; 847 free($9.label); 848 r.flags = $9.flags.b1; 849 r.flagset = $9.flags.b2; 850 if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) { 851 yyerror("flags always false"); 852 YYERROR; 853 } 854 if ($9.flags.b1 || $9.flags.b2 || $8.src_os) { 855 for (proto = $7; proto != NULL && 856 proto->proto != IPPROTO_TCP; 857 proto = proto->next) 858 ; /* nothing */ 859 if (proto == NULL && $7 != NULL) { 860 if ($9.flags.b1 || $9.flags.b2) 861 yyerror( 862 "flags only apply to tcp"); 863 if ($8.src_os) 864 yyerror( 865 "OS fingerprinting only " 866 "applies to tcp"); 867 YYERROR; 868 } 869 } 870 871 r.tos = $9.tos; 872 873 if ($9.keep.action) { 874 yyerror("cannot specify state handling " 875 "on anchors"); 876 YYERROR; 877 } 878 879 if ($9.route.rt) { 880 yyerror("cannot specify route handling " 881 "on anchors"); 882 YYERROR; 883 } 884 885 if ($9.marker & FOM_ONCE) { 886 yyerror("cannot specify 'once' " 887 "on anchors"); 888 YYERROR; 889 } 890 891 if ($9.match_tag) 892 if (strlcpy(r.match_tagname, $9.match_tag, 893 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 894 yyerror("tag too long, max %u chars", 895 PF_TAG_NAME_SIZE - 1); 896 YYERROR; 897 } 898 r.match_tag_not = $9.match_tag_not; 899 if ($9.marker & FOM_PRIO) { 900 if ($9.prio == 0) 901 r.prio = PF_PRIO_ZERO; 902 else 903 r.prio = $9.prio; 904 } 905 if ($9.marker & FOM_SETPRIO) { 906 r.set_prio[0] = $9.set_prio[0]; 907 r.set_prio[1] = $9.set_prio[1]; 908 r.scrub_flags |= PFSTATE_SETPRIO; 909 } 910 911 decide_address_family($8.src.host, &r.af); 912 decide_address_family($8.dst.host, &r.af); 913 914 expand_rule(&r, 0, $5, NULL, NULL, NULL, $7, $8.src_os, 915 $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, 916 $9.uid, $9.gid, $9.rcv, $9.icmpspec, 917 pf->astack[pf->asd + 1] ? pf->alast->name : $2); 918 free($2); 919 pf->astack[pf->asd + 1] = NULL; 920 } 921 ; 922 923 loadrule : LOAD ANCHOR string FROM string { 924 struct loadanchors *loadanchor; 925 926 if (strlen(pf->anchor->name) + 1 + 927 strlen($3) >= PATH_MAX) { 928 yyerror("anchorname %s too long, max %u\n", 929 $3, PATH_MAX - 1); 930 free($3); 931 YYERROR; 932 } 933 loadanchor = calloc(1, sizeof(struct loadanchors)); 934 if (loadanchor == NULL) 935 err(1, "loadrule: calloc"); 936 if ((loadanchor->anchorname = malloc(PATH_MAX)) == 937 NULL) 938 err(1, "loadrule: malloc"); 939 if (pf->anchor->name[0]) 940 snprintf(loadanchor->anchorname, PATH_MAX, 941 "%s/%s", pf->anchor->name, $3); 942 else 943 strlcpy(loadanchor->anchorname, $3, PATH_MAX); 944 if ((loadanchor->filename = strdup($5)) == NULL) 945 err(1, "loadrule: strdup"); 946 947 TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor, 948 entries); 949 950 free($3); 951 free($5); 952 }; 953 954 scrub_opts : { 955 bzero(&scrub_opts, sizeof scrub_opts); 956 } 957 scrub_opts_l 958 { $$ = scrub_opts; } 959 ; 960 961 scrub_opts_l : scrub_opts_l comma scrub_opt 962 | scrub_opt 963 ; 964 965 scrub_opt : NODF { 966 if (scrub_opts.nodf) { 967 yyerror("no-df cannot be respecified"); 968 YYERROR; 969 } 970 scrub_opts.nodf = 1; 971 } 972 | MINTTL NUMBER { 973 if (scrub_opts.marker & FOM_MINTTL) { 974 yyerror("min-ttl cannot be respecified"); 975 YYERROR; 976 } 977 if ($2 < 0 || $2 > 255) { 978 yyerror("illegal min-ttl value %d", $2); 979 YYERROR; 980 } 981 scrub_opts.marker |= FOM_MINTTL; 982 scrub_opts.minttl = $2; 983 } 984 | MAXMSS NUMBER { 985 if (scrub_opts.marker & FOM_MAXMSS) { 986 yyerror("max-mss cannot be respecified"); 987 YYERROR; 988 } 989 if ($2 < 0 || $2 > 65535) { 990 yyerror("illegal max-mss value %d", $2); 991 YYERROR; 992 } 993 scrub_opts.marker |= FOM_MAXMSS; 994 scrub_opts.maxmss = $2; 995 } 996 | REASSEMBLE STRING { 997 if (strcasecmp($2, "tcp") != 0) { 998 yyerror("scrub reassemble supports only tcp, " 999 "not '%s'", $2); 1000 free($2); 1001 YYERROR; 1002 } 1003 free($2); 1004 if (scrub_opts.reassemble_tcp) { 1005 yyerror("reassemble tcp cannot be respecified"); 1006 YYERROR; 1007 } 1008 scrub_opts.reassemble_tcp = 1; 1009 } 1010 | RANDOMID { 1011 if (scrub_opts.randomid) { 1012 yyerror("random-id cannot be respecified"); 1013 YYERROR; 1014 } 1015 scrub_opts.randomid = 1; 1016 } 1017 ; 1018 1019 antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { 1020 struct pf_rule r; 1021 struct node_host *h = NULL, *hh; 1022 struct node_if *i, *j; 1023 1024 for (i = $3; i; i = i->next) { 1025 bzero(&r, sizeof(r)); 1026 1027 r.action = PF_DROP; 1028 r.direction = PF_IN; 1029 r.log = $2.log; 1030 r.logif = $2.logif; 1031 r.quick = $2.quick; 1032 r.af = $4; 1033 if (rule_label(&r, $5.label)) 1034 YYERROR; 1035 r.rtableid = $5.rtableid; 1036 j = calloc(1, sizeof(struct node_if)); 1037 if (j == NULL) 1038 err(1, "antispoof: calloc"); 1039 if (strlcpy(j->ifname, i->ifname, 1040 sizeof(j->ifname)) >= sizeof(j->ifname)) { 1041 free(j); 1042 yyerror("interface name too long"); 1043 YYERROR; 1044 } 1045 j->not = 1; 1046 if (i->dynamic) { 1047 h = calloc(1, sizeof(*h)); 1048 if (h == NULL) 1049 err(1, "address: calloc"); 1050 h->addr.type = PF_ADDR_DYNIFTL; 1051 set_ipmask(h, 128); 1052 if (strlcpy(h->addr.v.ifname, i->ifname, 1053 sizeof(h->addr.v.ifname)) >= 1054 sizeof(h->addr.v.ifname)) { 1055 free(h); 1056 yyerror( 1057 "interface name too long"); 1058 YYERROR; 1059 } 1060 hh = malloc(sizeof(*hh)); 1061 if (hh == NULL) 1062 err(1, "address: malloc"); 1063 bcopy(h, hh, sizeof(*hh)); 1064 h->addr.iflags = PFI_AFLAG_NETWORK; 1065 } else { 1066 h = ifa_lookup(j->ifname, 1067 PFI_AFLAG_NETWORK); 1068 hh = NULL; 1069 } 1070 1071 if (h != NULL) 1072 expand_rule(&r, 0, j, NULL, NULL, NULL, 1073 NULL, NULL, h, NULL, NULL, NULL, 1074 NULL, NULL, NULL, NULL, ""); 1075 1076 if ((i->ifa_flags & IFF_LOOPBACK) == 0) { 1077 bzero(&r, sizeof(r)); 1078 1079 r.action = PF_DROP; 1080 r.direction = PF_IN; 1081 r.log = $2.log; 1082 r.logif = $2.logif; 1083 r.quick = $2.quick; 1084 r.af = $4; 1085 if (rule_label(&r, $5.label)) 1086 YYERROR; 1087 r.rtableid = $5.rtableid; 1088 if (hh != NULL) 1089 h = hh; 1090 else 1091 h = ifa_lookup(i->ifname, 0); 1092 if (h != NULL) 1093 expand_rule(&r, 0, NULL, NULL, 1094 NULL, NULL, NULL, NULL, h, 1095 NULL, NULL, NULL, NULL, 1096 NULL, NULL, NULL, ""); 1097 } else 1098 free(hh); 1099 } 1100 free($5.label); 1101 } 1102 ; 1103 1104 antispoof_ifspc : FOR antispoof_if { $$ = $2; } 1105 | FOR '{' optnl antispoof_iflst '}' { $$ = $4; } 1106 ; 1107 1108 antispoof_iflst : antispoof_if optnl { $$ = $1; } 1109 | antispoof_iflst comma antispoof_if optnl { 1110 $1->tail->next = $3; 1111 $1->tail = $3; 1112 $$ = $1; 1113 } 1114 ; 1115 1116 antispoof_if : if_item { $$ = $1; } 1117 | '(' if_item ')' { 1118 $2->dynamic = 1; 1119 $$ = $2; 1120 } 1121 ; 1122 1123 antispoof_opts : { 1124 bzero(&antispoof_opts, sizeof antispoof_opts); 1125 antispoof_opts.rtableid = -1; 1126 } 1127 antispoof_opts_l 1128 { $$ = antispoof_opts; } 1129 | /* empty */ { 1130 bzero(&antispoof_opts, sizeof antispoof_opts); 1131 antispoof_opts.rtableid = -1; 1132 $$ = antispoof_opts; 1133 } 1134 ; 1135 1136 antispoof_opts_l : antispoof_opts_l antispoof_opt 1137 | antispoof_opt 1138 ; 1139 1140 antispoof_opt : LABEL label { 1141 if (antispoof_opts.label) { 1142 yyerror("label cannot be redefined"); 1143 YYERROR; 1144 } 1145 antispoof_opts.label = $2; 1146 } 1147 | RTABLE NUMBER { 1148 if ($2 < 0 || $2 > RT_TABLEID_MAX) { 1149 yyerror("invalid rtable id"); 1150 YYERROR; 1151 } 1152 antispoof_opts.rtableid = $2; 1153 } 1154 ; 1155 1156 not : '!' { $$ = 1; } 1157 | /* empty */ { $$ = 0; } 1158 ; 1159 1160 tabledef : TABLE '<' STRING '>' table_opts { 1161 struct node_host *h, *nh; 1162 struct node_tinit *ti, *nti; 1163 1164 if (strlen($3) >= PF_TABLE_NAME_SIZE) { 1165 yyerror("table name too long, max %d chars", 1166 PF_TABLE_NAME_SIZE - 1); 1167 free($3); 1168 YYERROR; 1169 } 1170 if (process_tabledef($3, &$5)) { 1171 free($3); 1172 YYERROR; 1173 } 1174 free($3); 1175 for (ti = SIMPLEQ_FIRST(&$5.init_nodes); ti != NULL; 1176 ti = nti) { 1177 if (ti->file) 1178 free(ti->file); 1179 for (h = ti->host; h != NULL; h = nh) { 1180 nh = h->next; 1181 free(h); 1182 } 1183 nti = SIMPLEQ_NEXT(ti, entries); 1184 free(ti); 1185 } 1186 } 1187 ; 1188 1189 table_opts : { 1190 bzero(&table_opts, sizeof table_opts); 1191 SIMPLEQ_INIT(&table_opts.init_nodes); 1192 } 1193 table_opts_l 1194 { $$ = table_opts; } 1195 | /* empty */ 1196 { 1197 bzero(&table_opts, sizeof table_opts); 1198 SIMPLEQ_INIT(&table_opts.init_nodes); 1199 $$ = table_opts; 1200 } 1201 ; 1202 1203 table_opts_l : table_opts_l table_opt 1204 | table_opt 1205 ; 1206 1207 table_opt : STRING { 1208 if (!strcmp($1, "const")) 1209 table_opts.flags |= PFR_TFLAG_CONST; 1210 else if (!strcmp($1, "persist")) 1211 table_opts.flags |= PFR_TFLAG_PERSIST; 1212 else if (!strcmp($1, "counters")) 1213 table_opts.flags |= PFR_TFLAG_COUNTERS; 1214 else { 1215 yyerror("invalid table option '%s'", $1); 1216 free($1); 1217 YYERROR; 1218 } 1219 free($1); 1220 } 1221 | '{' optnl '}' { table_opts.init_addr = 1; } 1222 | '{' optnl table_host_list '}' { 1223 struct node_host *n; 1224 struct node_tinit *ti; 1225 1226 for (n = $3; n != NULL; n = n->next) { 1227 switch (n->addr.type) { 1228 case PF_ADDR_ADDRMASK: 1229 continue; /* ok */ 1230 case PF_ADDR_RANGE: 1231 yyerror("address ranges are not " 1232 "permitted inside tables"); 1233 break; 1234 case PF_ADDR_DYNIFTL: 1235 yyerror("dynamic addresses are not " 1236 "permitted inside tables"); 1237 break; 1238 case PF_ADDR_TABLE: 1239 yyerror("tables cannot contain tables"); 1240 break; 1241 case PF_ADDR_NOROUTE: 1242 yyerror("\"no-route\" is not permitted " 1243 "inside tables"); 1244 break; 1245 case PF_ADDR_URPFFAILED: 1246 yyerror("\"urpf-failed\" is not " 1247 "permitted inside tables"); 1248 break; 1249 default: 1250 yyerror("unknown address type %d", 1251 n->addr.type); 1252 } 1253 YYERROR; 1254 } 1255 if (!(ti = calloc(1, sizeof(*ti)))) 1256 err(1, "table_opt: calloc"); 1257 ti->host = $3; 1258 SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti, 1259 entries); 1260 table_opts.init_addr = 1; 1261 } 1262 | FILENAME STRING { 1263 struct node_tinit *ti; 1264 1265 if (!(ti = calloc(1, sizeof(*ti)))) 1266 err(1, "table_opt: calloc"); 1267 ti->file = $2; 1268 SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti, 1269 entries); 1270 table_opts.init_addr = 1; 1271 } 1272 ; 1273 1274 tablespec : xhost optweight { 1275 if ($2 > 0) { 1276 struct node_host *n; 1277 for (n = $1; n != NULL; n = n->next) 1278 n->weight = $2; 1279 } 1280 $$ = $1; 1281 } 1282 | '{' optnl table_host_list '}' { $$ = $3; } 1283 ; 1284 1285 table_host_list : tablespec optnl { $$ = $1; } 1286 | table_host_list comma tablespec optnl { 1287 $1->tail->next = $3; 1288 $1->tail = $3->tail; 1289 $$ = $1; 1290 } 1291 ; 1292 1293 queuespec : QUEUE STRING interface queue_opts { 1294 if ($3 == NULL && $4.parent == NULL) { 1295 yyerror("root queue without interface"); 1296 YYERROR; 1297 } 1298 if ($2[0] == '_') { 1299 yyerror("queue names must not start with _"); 1300 YYERROR; 1301 } 1302 expand_queue($2, $3, &$4); 1303 } 1304 ; 1305 1306 queue_opts : { 1307 bzero(&queue_opts, sizeof queue_opts); 1308 } 1309 queue_opts_l 1310 { $$ = queue_opts; } 1311 ; 1312 1313 queue_opts_l : queue_opts_l queue_opt 1314 | queue_opt 1315 ; 1316 1317 queue_opt : BANDWIDTH scspec optscs { 1318 if (queue_opts.marker & QOM_BWSPEC) { 1319 yyerror("bandwidth cannot be respecified"); 1320 YYERROR; 1321 } 1322 queue_opts.marker |= QOM_BWSPEC; 1323 queue_opts.linkshare = $2; 1324 queue_opts.realtime= $3.realtime; 1325 queue_opts.upperlimit = $3.upperlimit; 1326 } 1327 | PARENT STRING { 1328 if (queue_opts.marker & QOM_PARENT) { 1329 yyerror("parent cannot be respecified"); 1330 YYERROR; 1331 } 1332 queue_opts.marker |= QOM_PARENT; 1333 queue_opts.parent = $2; 1334 } 1335 | DEFAULT { 1336 if (queue_opts.marker & QOM_DEFAULT) { 1337 yyerror("default cannot be respecified"); 1338 YYERROR; 1339 } 1340 queue_opts.marker |= QOM_DEFAULT; 1341 queue_opts.flags |= HFSC_DEFAULTCLASS; 1342 } 1343 | QLIMIT NUMBER { 1344 if (queue_opts.marker & QOM_QLIMIT) { 1345 yyerror("qlimit cannot be respecified"); 1346 YYERROR; 1347 } 1348 if ($2 < 0 || $2 > 65535) { 1349 yyerror("qlimit out of range: max 65535"); 1350 YYERROR; 1351 } 1352 queue_opts.marker |= QOM_QLIMIT; 1353 queue_opts.qlimit = $2; 1354 } 1355 ; 1356 1357 optscs : /* nada */ { 1358 1359 } 1360 | comma MINIMUM scspec { 1361 $$.realtime = $3; 1362 } 1363 | comma MAXIMUM scspec { 1364 $$.upperlimit = $3; 1365 } 1366 | comma MINIMUM scspec comma MAXIMUM scspec { 1367 $$.realtime = $3; 1368 $$.upperlimit = $6; 1369 } 1370 | comma MAXIMUM scspec comma MINIMUM scspec { 1371 $$.realtime = $6; 1372 $$.upperlimit = $3; 1373 } 1374 ; 1375 1376 scspec : bandwidth { 1377 $$.m2 = $1; 1378 $$.d = 0; 1379 if ($$.m2.bw_percent) { 1380 yyerror("no bandwidth in %% yet"); 1381 YYERROR; 1382 } 1383 } 1384 | bandwidth BURST bandwidth FOR STRING { 1385 u_long ul; 1386 char *cp; 1387 1388 ul = strtoul($5, &cp, 10); 1389 if (cp == NULL || strcmp(cp, "ms")) { 1390 yyerror("time in scspec must be in ms"); 1391 YYERROR; 1392 } 1393 1394 $$.m1 = $3; 1395 $$.d = ul; 1396 $$.m2 = $1; 1397 1398 if ($$.m1.bw_percent || $$.m2.bw_percent) { 1399 yyerror("no bandwidth in %% yet"); 1400 YYERROR; 1401 } 1402 } 1403 ; 1404 1405 bandwidth : STRING { 1406 double bps; 1407 char *cp; 1408 1409 $$.bw_percent = 0; 1410 1411 bps = strtod($1, &cp); 1412 if (cp != NULL) { 1413 if (strlen(cp) > 1) { 1414 char *cu = cp + 1; 1415 if (!strcmp(cu, "Bit") || 1416 !strcmp(cu, "B") || 1417 !strcmp(cu, "bit") || 1418 !strcmp(cu, "b")) { 1419 *cu = 0; 1420 } 1421 } 1422 if (!strcmp(cp, "b")) 1423 ; /* nothing */ 1424 else if (!strcmp(cp, "K")) 1425 bps *= 1000; 1426 else if (!strcmp(cp, "M")) 1427 bps *= 1000 * 1000; 1428 else if (!strcmp(cp, "G")) 1429 bps *= 1000 * 1000 * 1000; 1430 else if (!strcmp(cp, "%")) { 1431 if (bps < 0 || bps > 100) { 1432 yyerror("bandwidth spec " 1433 "out of range"); 1434 free($1); 1435 YYERROR; 1436 } 1437 $$.bw_percent = bps; 1438 bps = 0; 1439 } else { 1440 yyerror("unknown unit \"%s\"", cp); 1441 free($1); 1442 YYERROR; 1443 } 1444 } 1445 free($1); 1446 $$.bw_absolute = (u_int32_t)bps; 1447 } 1448 | NUMBER { 1449 if ($1 < 0 || $1 > UINT_MAX) { 1450 yyerror("bandwidth number too big"); 1451 YYERROR; 1452 } 1453 $$.bw_percent = 0; 1454 $$.bw_absolute = $1; 1455 } 1456 ; 1457 1458 pfrule : action dir logquick interface af proto fromto 1459 filter_opts 1460 { 1461 struct pf_rule r; 1462 struct node_state_opt *o; 1463 struct node_proto *proto; 1464 int srctrack = 0; 1465 int statelock = 0; 1466 int adaptive = 0; 1467 int defaults = 0; 1468 1469 memset(&r, 0, sizeof(r)); 1470 r.action = $1.b1; 1471 switch ($1.b2) { 1472 case PFRULE_RETURNRST: 1473 r.rule_flag |= PFRULE_RETURNRST; 1474 r.return_ttl = $1.w; 1475 break; 1476 case PFRULE_RETURNICMP: 1477 r.rule_flag |= PFRULE_RETURNICMP; 1478 r.return_icmp = $1.w; 1479 r.return_icmp6 = $1.w2; 1480 break; 1481 case PFRULE_RETURN: 1482 r.rule_flag |= PFRULE_RETURN; 1483 r.return_icmp = $1.w; 1484 r.return_icmp6 = $1.w2; 1485 break; 1486 } 1487 r.direction = $2; 1488 r.log = $3.log; 1489 r.logif = $3.logif; 1490 r.quick = $3.quick; 1491 r.prob = $8.prob; 1492 r.rtableid = $8.rtableid; 1493 1494 if ($8.nodf) 1495 r.scrub_flags |= PFSTATE_NODF; 1496 if ($8.randomid) 1497 r.scrub_flags |= PFSTATE_RANDOMID; 1498 if ($8.minttl) 1499 r.min_ttl = $8.minttl; 1500 if ($8.max_mss) 1501 r.max_mss = $8.max_mss; 1502 if ($8.marker & FOM_SETTOS) { 1503 r.scrub_flags |= PFSTATE_SETTOS; 1504 r.set_tos = $8.settos; 1505 } 1506 if ($8.marker & FOM_SCRUB_TCP) 1507 r.scrub_flags |= PFSTATE_SCRUB_TCP; 1508 if ($8.marker & FOM_PRIO) { 1509 if ($8.prio == 0) 1510 r.prio = PF_PRIO_ZERO; 1511 else 1512 r.prio = $8.prio; 1513 } 1514 if ($8.marker & FOM_SETPRIO) { 1515 r.set_prio[0] = $8.set_prio[0]; 1516 r.set_prio[1] = $8.set_prio[1]; 1517 r.scrub_flags |= PFSTATE_SETPRIO; 1518 } 1519 if ($8.marker & FOM_ONCE) { 1520 if (r.action == PF_MATCH) { 1521 yyerror("can't specify once for " 1522 "match rules"); 1523 YYERROR; 1524 } 1525 r.rule_flag |= PFRULE_ONCE; 1526 } 1527 if ($8.marker & FOM_AFTO) 1528 r.rule_flag |= PFRULE_AFTO; 1529 if (($8.marker & FOM_AFTO) && r.direction != PF_IN) { 1530 yyerror("af-to can only be used with direction in"); 1531 YYERROR; 1532 } 1533 r.af = $5; 1534 1535 if ($8.tag) 1536 if (strlcpy(r.tagname, $8.tag, 1537 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 1538 yyerror("tag too long, max %u chars", 1539 PF_TAG_NAME_SIZE - 1); 1540 YYERROR; 1541 } 1542 if ($8.match_tag) 1543 if (strlcpy(r.match_tagname, $8.match_tag, 1544 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 1545 yyerror("tag too long, max %u chars", 1546 PF_TAG_NAME_SIZE - 1); 1547 YYERROR; 1548 } 1549 r.match_tag_not = $8.match_tag_not; 1550 if (rule_label(&r, $8.label)) 1551 YYERROR; 1552 free($8.label); 1553 r.flags = $8.flags.b1; 1554 r.flagset = $8.flags.b2; 1555 if (($8.flags.b1 & $8.flags.b2) != $8.flags.b1) { 1556 yyerror("flags always false"); 1557 YYERROR; 1558 } 1559 if ($8.flags.b1 || $8.flags.b2 || $7.src_os) { 1560 for (proto = $6; proto != NULL && 1561 proto->proto != IPPROTO_TCP; 1562 proto = proto->next) 1563 ; /* nothing */ 1564 if (proto == NULL && $6 != NULL) { 1565 if ($8.flags.b1 || $8.flags.b2) 1566 yyerror( 1567 "flags only apply to tcp"); 1568 if ($7.src_os) 1569 yyerror( 1570 "OS fingerprinting only " 1571 "apply to tcp"); 1572 YYERROR; 1573 } 1574 #if 0 1575 if (($8.flags.b1 & parse_flags("S")) == 0 && 1576 $7.src_os) { 1577 yyerror("OS fingerprinting requires " 1578 "the SYN TCP flag (flags S/SA)"); 1579 YYERROR; 1580 } 1581 #endif 1582 } 1583 1584 r.tos = $8.tos; 1585 r.keep_state = $8.keep.action; 1586 o = $8.keep.options; 1587 1588 /* 'keep state' by default on pass rules. */ 1589 if (!r.keep_state && !r.action && 1590 !($8.marker & FOM_KEEP)) { 1591 r.keep_state = PF_STATE_NORMAL; 1592 o = keep_state_defaults; 1593 defaults = 1; 1594 } 1595 1596 while (o) { 1597 struct node_state_opt *p = o; 1598 1599 switch (o->type) { 1600 case PF_STATE_OPT_MAX: 1601 if (r.max_states) { 1602 yyerror("state option 'max' " 1603 "multiple definitions"); 1604 YYERROR; 1605 } 1606 r.max_states = o->data.max_states; 1607 break; 1608 case PF_STATE_OPT_NOSYNC: 1609 if (r.rule_flag & PFRULE_NOSYNC) { 1610 yyerror("state option 'sync' " 1611 "multiple definitions"); 1612 YYERROR; 1613 } 1614 r.rule_flag |= PFRULE_NOSYNC; 1615 break; 1616 case PF_STATE_OPT_SRCTRACK: 1617 if (srctrack) { 1618 yyerror("state option " 1619 "'source-track' " 1620 "multiple definitions"); 1621 YYERROR; 1622 } 1623 srctrack = o->data.src_track; 1624 r.rule_flag |= PFRULE_SRCTRACK; 1625 break; 1626 case PF_STATE_OPT_MAX_SRC_STATES: 1627 if (r.max_src_states) { 1628 yyerror("state option " 1629 "'max-src-states' " 1630 "multiple definitions"); 1631 YYERROR; 1632 } 1633 if (o->data.max_src_states == 0) { 1634 yyerror("'max-src-states' must " 1635 "be > 0"); 1636 YYERROR; 1637 } 1638 r.max_src_states = 1639 o->data.max_src_states; 1640 r.rule_flag |= PFRULE_SRCTRACK; 1641 break; 1642 case PF_STATE_OPT_OVERLOAD: 1643 if (r.overload_tblname[0]) { 1644 yyerror("multiple 'overload' " 1645 "table definitions"); 1646 YYERROR; 1647 } 1648 if (strlcpy(r.overload_tblname, 1649 o->data.overload.tblname, 1650 PF_TABLE_NAME_SIZE) >= 1651 PF_TABLE_NAME_SIZE) { 1652 yyerror("state option: " 1653 "strlcpy"); 1654 YYERROR; 1655 } 1656 r.flush = o->data.overload.flush; 1657 break; 1658 case PF_STATE_OPT_MAX_SRC_CONN: 1659 if (r.max_src_conn) { 1660 yyerror("state option " 1661 "'max-src-conn' " 1662 "multiple definitions"); 1663 YYERROR; 1664 } 1665 if (o->data.max_src_conn == 0) { 1666 yyerror("'max-src-conn' " 1667 "must be > 0"); 1668 YYERROR; 1669 } 1670 r.max_src_conn = 1671 o->data.max_src_conn; 1672 r.rule_flag |= PFRULE_SRCTRACK | 1673 PFRULE_RULESRCTRACK; 1674 break; 1675 case PF_STATE_OPT_MAX_SRC_CONN_RATE: 1676 if (r.max_src_conn_rate.limit) { 1677 yyerror("state option " 1678 "'max-src-conn-rate' " 1679 "multiple definitions"); 1680 YYERROR; 1681 } 1682 if (!o->data.max_src_conn_rate.limit || 1683 !o->data.max_src_conn_rate.seconds) { 1684 yyerror("'max-src-conn-rate' " 1685 "values must be > 0"); 1686 YYERROR; 1687 } 1688 if (o->data.max_src_conn_rate.limit > 1689 PF_THRESHOLD_MAX) { 1690 yyerror("'max-src-conn-rate' " 1691 "maximum rate must be < %u", 1692 PF_THRESHOLD_MAX); 1693 YYERROR; 1694 } 1695 r.max_src_conn_rate.limit = 1696 o->data.max_src_conn_rate.limit; 1697 r.max_src_conn_rate.seconds = 1698 o->data.max_src_conn_rate.seconds; 1699 r.rule_flag |= PFRULE_SRCTRACK | 1700 PFRULE_RULESRCTRACK; 1701 break; 1702 case PF_STATE_OPT_MAX_SRC_NODES: 1703 if (r.max_src_nodes) { 1704 yyerror("state option " 1705 "'max-src-nodes' " 1706 "multiple definitions"); 1707 YYERROR; 1708 } 1709 if (o->data.max_src_nodes == 0) { 1710 yyerror("'max-src-nodes' must " 1711 "be > 0"); 1712 YYERROR; 1713 } 1714 r.max_src_nodes = 1715 o->data.max_src_nodes; 1716 r.rule_flag |= PFRULE_SRCTRACK | 1717 PFRULE_RULESRCTRACK; 1718 break; 1719 case PF_STATE_OPT_STATELOCK: 1720 if (statelock) { 1721 yyerror("state locking option: " 1722 "multiple definitions"); 1723 YYERROR; 1724 } 1725 statelock = 1; 1726 r.rule_flag |= o->data.statelock; 1727 break; 1728 case PF_STATE_OPT_SLOPPY: 1729 if (r.rule_flag & PFRULE_STATESLOPPY) { 1730 yyerror("state sloppy option: " 1731 "multiple definitions"); 1732 YYERROR; 1733 } 1734 r.rule_flag |= PFRULE_STATESLOPPY; 1735 break; 1736 case PF_STATE_OPT_PFLOW: 1737 if (r.rule_flag & PFRULE_PFLOW) { 1738 yyerror("state pflow " 1739 "option: multiple " 1740 "definitions"); 1741 YYERROR; 1742 } 1743 r.rule_flag |= PFRULE_PFLOW; 1744 break; 1745 case PF_STATE_OPT_TIMEOUT: 1746 if (o->data.timeout.number == 1747 PFTM_ADAPTIVE_START || 1748 o->data.timeout.number == 1749 PFTM_ADAPTIVE_END) 1750 adaptive = 1; 1751 if (r.timeout[o->data.timeout.number]) { 1752 yyerror("state timeout %s " 1753 "multiple definitions", 1754 pf_timeouts[o->data. 1755 timeout.number].name); 1756 YYERROR; 1757 } 1758 r.timeout[o->data.timeout.number] = 1759 o->data.timeout.seconds; 1760 } 1761 o = o->next; 1762 if (!defaults) 1763 free(p); 1764 } 1765 1766 /* 'flags S/SA' by default on stateful rules */ 1767 if (!r.action && !r.flags && !r.flagset && 1768 !$8.fragment && !($8.marker & FOM_FLAGS) && 1769 r.keep_state) { 1770 r.flags = parse_flags("S"); 1771 r.flagset = parse_flags("SA"); 1772 } 1773 if (!adaptive && r.max_states) { 1774 r.timeout[PFTM_ADAPTIVE_START] = 1775 (r.max_states / 10) * 6; 1776 r.timeout[PFTM_ADAPTIVE_END] = 1777 (r.max_states / 10) * 12; 1778 } 1779 if (r.rule_flag & PFRULE_SRCTRACK) { 1780 if (srctrack == PF_SRCTRACK_GLOBAL && 1781 r.max_src_nodes) { 1782 yyerror("'max-src-nodes' is " 1783 "incompatible with " 1784 "'source-track global'"); 1785 YYERROR; 1786 } 1787 if (srctrack == PF_SRCTRACK_GLOBAL && 1788 r.max_src_conn) { 1789 yyerror("'max-src-conn' is " 1790 "incompatible with " 1791 "'source-track global'"); 1792 YYERROR; 1793 } 1794 if (srctrack == PF_SRCTRACK_GLOBAL && 1795 r.max_src_conn_rate.seconds) { 1796 yyerror("'max-src-conn-rate' is " 1797 "incompatible with " 1798 "'source-track global'"); 1799 YYERROR; 1800 } 1801 if (r.timeout[PFTM_SRC_NODE] < 1802 r.max_src_conn_rate.seconds) 1803 r.timeout[PFTM_SRC_NODE] = 1804 r.max_src_conn_rate.seconds; 1805 r.rule_flag |= PFRULE_SRCTRACK; 1806 if (srctrack == PF_SRCTRACK_RULE) 1807 r.rule_flag |= PFRULE_RULESRCTRACK; 1808 } 1809 if (r.keep_state && !statelock) 1810 r.rule_flag |= default_statelock; 1811 1812 if ($8.fragment) 1813 r.rule_flag |= PFRULE_FRAGMENT; 1814 r.allow_opts = $8.allowopts; 1815 1816 decide_address_family($7.src.host, &r.af); 1817 decide_address_family($7.dst.host, &r.af); 1818 1819 if ($8.route.rt) { 1820 if (!r.direction) { 1821 yyerror("direction must be explicit " 1822 "with rules that specify routing"); 1823 YYERROR; 1824 } 1825 r.rt = $8.route.rt; 1826 r.route.opts = $8.route.pool_opts; 1827 if ($8.route.key != NULL) 1828 memcpy(&r.route.key, $8.route.key, 1829 sizeof(struct pf_poolhashkey)); 1830 } 1831 if (r.rt) { 1832 decide_address_family($8.route.host, &r.af); 1833 if ((r.route.opts & PF_POOL_TYPEMASK) == 1834 PF_POOL_NONE && ($8.route.host->next != NULL || 1835 $8.route.host->addr.type == PF_ADDR_TABLE || 1836 DYNIF_MULTIADDR($8.route.host->addr))) 1837 r.route.opts |= PF_POOL_ROUNDROBIN; 1838 if ($8.route.host->next != NULL) { 1839 if (!PF_POOL_DYNTYPE(r.route.opts)) { 1840 yyerror("address pool option " 1841 "not supported by type"); 1842 YYERROR; 1843 } 1844 } 1845 /* fake redirspec */ 1846 if (($8.rroute.rdr = calloc(1, 1847 sizeof(*$8.rroute.rdr))) == NULL) 1848 err(1, "$8.rroute.rdr"); 1849 $8.rroute.rdr->host = $8.route.host; 1850 } 1851 if ($8.queues.qname != NULL) { 1852 if (strlcpy(r.qname, $8.queues.qname, 1853 sizeof(r.qname)) >= sizeof(r.qname)) { 1854 yyerror("rule qname too long (max " 1855 "%d chars)", sizeof(r.qname)-1); 1856 YYERROR; 1857 } 1858 free($8.queues.qname); 1859 } 1860 if ($8.queues.pqname != NULL) { 1861 if (strlcpy(r.pqname, $8.queues.pqname, 1862 sizeof(r.pqname)) >= sizeof(r.pqname)) { 1863 yyerror("rule pqname too long (max " 1864 "%d chars)", sizeof(r.pqname)-1); 1865 YYERROR; 1866 } 1867 free($8.queues.pqname); 1868 } 1869 if (expand_divertspec(&r, &$8.divert)) 1870 YYERROR; 1871 r.divert_packet.port = $8.divert_packet.port; 1872 1873 expand_rule(&r, 0, $4, &$8.nat, &$8.rdr, &$8.rroute, $6, 1874 $7.src_os, 1875 $7.src.host, $7.src.port, $7.dst.host, $7.dst.port, 1876 $8.uid, $8.gid, $8.rcv, $8.icmpspec, ""); 1877 } 1878 ; 1879 1880 filter_opts : { 1881 bzero(&filter_opts, sizeof filter_opts); 1882 filter_opts.rtableid = -1; 1883 } 1884 filter_opts_l 1885 { $$ = filter_opts; } 1886 | /* empty */ { 1887 bzero(&filter_opts, sizeof filter_opts); 1888 filter_opts.rtableid = -1; 1889 $$ = filter_opts; 1890 } 1891 ; 1892 1893 filter_opts_l : filter_opts_l filter_opt 1894 | filter_opt 1895 ; 1896 1897 filter_opt : USER uids { 1898 if (filter_opts.uid) 1899 $2->tail->next = filter_opts.uid; 1900 filter_opts.uid = $2; 1901 } 1902 | GROUP gids { 1903 if (filter_opts.gid) 1904 $2->tail->next = filter_opts.gid; 1905 filter_opts.gid = $2; 1906 } 1907 | flags { 1908 if (filter_opts.marker & FOM_FLAGS) { 1909 yyerror("flags cannot be redefined"); 1910 YYERROR; 1911 } 1912 filter_opts.marker |= FOM_FLAGS; 1913 filter_opts.flags.b1 |= $1.b1; 1914 filter_opts.flags.b2 |= $1.b2; 1915 filter_opts.flags.w |= $1.w; 1916 filter_opts.flags.w2 |= $1.w2; 1917 } 1918 | icmpspec { 1919 if (filter_opts.marker & FOM_ICMP) { 1920 yyerror("icmp-type cannot be redefined"); 1921 YYERROR; 1922 } 1923 filter_opts.marker |= FOM_ICMP; 1924 filter_opts.icmpspec = $1; 1925 } 1926 | PRIO NUMBER { 1927 if (filter_opts.marker & FOM_PRIO) { 1928 yyerror("prio cannot be redefined"); 1929 YYERROR; 1930 } 1931 if ($2 < 0 || $2 > IFQ_MAXPRIO) { 1932 yyerror("prio must be 0 - %u", IFQ_MAXPRIO); 1933 YYERROR; 1934 } 1935 filter_opts.marker |= FOM_PRIO; 1936 filter_opts.prio = $2; 1937 } 1938 | TOS tos { 1939 if (filter_opts.marker & FOM_TOS) { 1940 yyerror("tos cannot be redefined"); 1941 YYERROR; 1942 } 1943 filter_opts.marker |= FOM_TOS; 1944 filter_opts.tos = $2; 1945 } 1946 | keep { 1947 if (filter_opts.marker & FOM_KEEP) { 1948 yyerror("modulate or keep cannot be redefined"); 1949 YYERROR; 1950 } 1951 filter_opts.marker |= FOM_KEEP; 1952 filter_opts.keep.action = $1.action; 1953 filter_opts.keep.options = $1.options; 1954 } 1955 | FRAGMENT { 1956 filter_opts.fragment = 1; 1957 } 1958 | ALLOWOPTS { 1959 filter_opts.allowopts = 1; 1960 } 1961 | LABEL label { 1962 if (filter_opts.label) { 1963 yyerror("label cannot be redefined"); 1964 YYERROR; 1965 } 1966 filter_opts.label = $2; 1967 } 1968 | QUEUE qname { 1969 if (filter_opts.queues.qname) { 1970 yyerror("queue cannot be redefined"); 1971 YYERROR; 1972 } 1973 filter_opts.queues = $2; 1974 } 1975 | TAG string { 1976 filter_opts.tag = $2; 1977 } 1978 | not TAGGED string { 1979 filter_opts.match_tag = $3; 1980 filter_opts.match_tag_not = $1; 1981 } 1982 | PROBABILITY probability { 1983 double p; 1984 1985 p = floor($2 * UINT_MAX + 0.5); 1986 if (p < 0.0 || p > UINT_MAX) { 1987 yyerror("invalid probability: %g%%", $2 * 100); 1988 YYERROR; 1989 } 1990 filter_opts.prob = (u_int32_t)p; 1991 if (filter_opts.prob == 0) 1992 filter_opts.prob = 1; 1993 } 1994 | RTABLE NUMBER { 1995 if ($2 < 0 || $2 > RT_TABLEID_MAX) { 1996 yyerror("invalid rtable id"); 1997 YYERROR; 1998 } 1999 filter_opts.rtableid = $2; 2000 } 2001 | DIVERTTO STRING PORT portplain { 2002 if ((filter_opts.divert.addr = host($2)) == NULL) { 2003 yyerror("could not parse divert address: %s", 2004 $2); 2005 free($2); 2006 YYERROR; 2007 } 2008 free($2); 2009 filter_opts.divert.port = $4.a; 2010 if (!filter_opts.divert.port) { 2011 yyerror("invalid divert port: %u", ntohs($4.a)); 2012 YYERROR; 2013 } 2014 } 2015 | DIVERTREPLY { 2016 filter_opts.divert.port = 1; /* some random value */ 2017 } 2018 | DIVERTPACKET PORT number { 2019 /* 2020 * If IP reassembly was not turned off, also 2021 * forcibly enable TCP reassembly by default. 2022 */ 2023 if (pf->reassemble & PF_REASS_ENABLED) 2024 filter_opts.marker |= FOM_SCRUB_TCP; 2025 2026 if ($3 < 1 || $3 > 65535) { 2027 yyerror("invalid divert port"); 2028 YYERROR; 2029 } 2030 2031 filter_opts.divert_packet.port = htons($3); 2032 } 2033 | SCRUB '(' scrub_opts ')' { 2034 filter_opts.nodf = $3.nodf; 2035 filter_opts.minttl = $3.minttl; 2036 filter_opts.randomid = $3.randomid; 2037 filter_opts.max_mss = $3.maxmss; 2038 if ($3.reassemble_tcp) 2039 filter_opts.marker |= FOM_SCRUB_TCP; 2040 filter_opts.marker |= $3.marker; 2041 } 2042 | NATTO redirpool pool_opts { 2043 if (filter_opts.nat.rdr) { 2044 yyerror("cannot respecify nat-to/binat-to"); 2045 YYERROR; 2046 } 2047 filter_opts.nat.rdr = $2; 2048 memcpy(&filter_opts.nat.pool_opts, &$3, 2049 sizeof(filter_opts.nat.pool_opts)); 2050 } 2051 | AFTO af FROM redirpool pool_opts { 2052 if (filter_opts.nat.rdr) { 2053 yyerror("cannot respecify af-to"); 2054 YYERROR; 2055 } 2056 if ($2 == 0) { 2057 yyerror("no target address family specified"); 2058 YYERROR; 2059 } 2060 filter_opts.nat.af = $2; 2061 filter_opts.nat.rdr = $4; 2062 memcpy(&filter_opts.nat.pool_opts, &$5, 2063 sizeof(filter_opts.nat.pool_opts)); 2064 filter_opts.rdr.rdr = 2065 calloc(1, sizeof(struct redirection)); 2066 bzero(&filter_opts.rdr.pool_opts, 2067 sizeof(filter_opts.rdr.pool_opts)); 2068 filter_opts.marker |= FOM_AFTO; 2069 } 2070 | AFTO af FROM redirpool pool_opts TO redirpool pool_opts { 2071 if (filter_opts.nat.rdr) { 2072 yyerror("cannot respecify af-to"); 2073 YYERROR; 2074 } 2075 if ($2 == 0) { 2076 yyerror("no address family specified"); 2077 YYERROR; 2078 } 2079 if (($4->host->af && $4->host->af != $2) || 2080 ($7->host->af && $7->host->af != $2)) { 2081 yyerror("af-to addresses must be in the " 2082 "target address family"); 2083 YYERROR; 2084 } 2085 filter_opts.nat.af = $2; 2086 filter_opts.nat.rdr = $4; 2087 memcpy(&filter_opts.nat.pool_opts, &$5, 2088 sizeof(filter_opts.nat.pool_opts)); 2089 filter_opts.rdr.af = $2; 2090 filter_opts.rdr.rdr = $7; 2091 memcpy(&filter_opts.nat.pool_opts, &$8, 2092 sizeof(filter_opts.nat.pool_opts)); 2093 filter_opts.marker |= FOM_AFTO; 2094 } 2095 | RDRTO redirpool pool_opts { 2096 if (filter_opts.rdr.rdr) { 2097 yyerror("cannot respecify rdr-to"); 2098 YYERROR; 2099 } 2100 filter_opts.rdr.rdr = $2; 2101 memcpy(&filter_opts.rdr.pool_opts, &$3, 2102 sizeof(filter_opts.rdr.pool_opts)); 2103 } 2104 | BINATTO redirpool pool_opts { 2105 if (filter_opts.nat.rdr) { 2106 yyerror("cannot respecify nat-to/binat-to"); 2107 YYERROR; 2108 } 2109 filter_opts.nat.rdr = $2; 2110 filter_opts.nat.binat = 1; 2111 memcpy(&filter_opts.nat.pool_opts, &$3, 2112 sizeof(filter_opts.nat.pool_opts)); 2113 filter_opts.nat.pool_opts.staticport = 1; 2114 } 2115 | ROUTETO routespec pool_opts { 2116 filter_opts.route.host = $2; 2117 filter_opts.route.rt = PF_ROUTETO; 2118 filter_opts.route.pool_opts = $3.type | $3.opts; 2119 memcpy(&filter_opts.rroute.pool_opts, &$3, 2120 sizeof(filter_opts.rroute.pool_opts)); 2121 if ($3.key != NULL) 2122 filter_opts.route.key = $3.key; 2123 } 2124 | REPLYTO routespec pool_opts { 2125 filter_opts.route.host = $2; 2126 filter_opts.route.rt = PF_REPLYTO; 2127 filter_opts.route.pool_opts = $3.type | $3.opts; 2128 if ($3.key != NULL) 2129 filter_opts.route.key = $3.key; 2130 } 2131 | DUPTO routespec pool_opts { 2132 filter_opts.route.host = $2; 2133 filter_opts.route.rt = PF_DUPTO; 2134 filter_opts.route.pool_opts = $3.type | $3.opts; 2135 memcpy(&filter_opts.rroute.pool_opts, &$3, 2136 sizeof(filter_opts.rroute.pool_opts)); 2137 if ($3.key != NULL) 2138 filter_opts.route.key = $3.key; 2139 } 2140 | not RECEIVEDON if_item { 2141 if (filter_opts.rcv) { 2142 yyerror("cannot respecify received-on"); 2143 YYERROR; 2144 } 2145 filter_opts.rcv = $3; 2146 filter_opts.rcv->not = $1; 2147 } 2148 | ONCE { 2149 filter_opts.marker |= FOM_ONCE; 2150 } 2151 | filter_sets 2152 ; 2153 2154 filter_sets : SET '(' filter_sets_l ')' { $$ = filter_opts; } 2155 | SET filter_set { $$ = filter_opts; } 2156 ; 2157 2158 filter_sets_l : filter_sets_l comma filter_set 2159 | filter_set 2160 ; 2161 2162 filter_set : prio { 2163 if (filter_opts.marker & FOM_SETPRIO) { 2164 yyerror("prio cannot be redefined"); 2165 YYERROR; 2166 } 2167 filter_opts.marker |= FOM_SETPRIO; 2168 filter_opts.set_prio[0] = $1.b1; 2169 filter_opts.set_prio[1] = $1.b2; 2170 } 2171 | QUEUE qname { 2172 if (filter_opts.queues.qname) { 2173 yyerror("queue cannot be redefined"); 2174 YYERROR; 2175 } 2176 filter_opts.queues = $2; 2177 } 2178 | TOS tos { 2179 if (filter_opts.marker & FOM_SETTOS) { 2180 yyerror("tos cannot be respecified"); 2181 YYERROR; 2182 } 2183 filter_opts.marker |= FOM_SETTOS; 2184 filter_opts.settos = $2; 2185 } 2186 ; 2187 2188 prio : PRIO NUMBER { 2189 if ($2 < 0 || $2 > IFQ_MAXPRIO) { 2190 yyerror("prio must be 0 - %u", IFQ_MAXPRIO); 2191 YYERROR; 2192 } 2193 $$.b1 = $$.b2 = $2; 2194 } 2195 | PRIO '(' NUMBER comma NUMBER ')' { 2196 if ($3 < 0 || $3 > IFQ_MAXPRIO || 2197 $5 < 0 || $5 > IFQ_MAXPRIO) { 2198 yyerror("prio must be 0 - %u", IFQ_MAXPRIO); 2199 YYERROR; 2200 } 2201 $$.b1 = $3; 2202 $$.b2 = $5; 2203 } 2204 ; 2205 2206 probability : STRING { 2207 char *e; 2208 double p = strtod($1, &e); 2209 2210 if (*e == '%') { 2211 p *= 0.01; 2212 e++; 2213 } 2214 if (*e) { 2215 yyerror("invalid probability: %s", $1); 2216 free($1); 2217 YYERROR; 2218 } 2219 free($1); 2220 $$ = p; 2221 } 2222 | NUMBER { 2223 $$ = (double)$1; 2224 } 2225 ; 2226 2227 2228 action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; } 2229 | MATCH { $$.b1 = PF_MATCH; $$.b2 = $$.w = 0; } 2230 | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } 2231 ; 2232 2233 blockspec : /* empty */ { 2234 $$.b2 = blockpolicy; 2235 $$.w = returnicmpdefault; 2236 $$.w2 = returnicmp6default; 2237 } 2238 | DROP { 2239 $$.b2 = PFRULE_DROP; 2240 $$.w = 0; 2241 $$.w2 = 0; 2242 } 2243 | RETURNRST { 2244 $$.b2 = PFRULE_RETURNRST; 2245 $$.w = 0; 2246 $$.w2 = 0; 2247 } 2248 | RETURNRST '(' TTL NUMBER ')' { 2249 if ($4 < 0 || $4 > 255) { 2250 yyerror("illegal ttl value %d", $4); 2251 YYERROR; 2252 } 2253 $$.b2 = PFRULE_RETURNRST; 2254 $$.w = $4; 2255 $$.w2 = 0; 2256 } 2257 | RETURNICMP { 2258 $$.b2 = PFRULE_RETURNICMP; 2259 $$.w = returnicmpdefault; 2260 $$.w2 = returnicmp6default; 2261 } 2262 | RETURNICMP6 { 2263 $$.b2 = PFRULE_RETURNICMP; 2264 $$.w = returnicmpdefault; 2265 $$.w2 = returnicmp6default; 2266 } 2267 | RETURNICMP '(' reticmpspec ')' { 2268 $$.b2 = PFRULE_RETURNICMP; 2269 $$.w = $3; 2270 $$.w2 = returnicmpdefault; 2271 } 2272 | RETURNICMP6 '(' reticmp6spec ')' { 2273 $$.b2 = PFRULE_RETURNICMP; 2274 $$.w = returnicmpdefault; 2275 $$.w2 = $3; 2276 } 2277 | RETURNICMP '(' reticmpspec comma reticmp6spec ')' { 2278 $$.b2 = PFRULE_RETURNICMP; 2279 $$.w = $3; 2280 $$.w2 = $5; 2281 } 2282 | RETURN { 2283 $$.b2 = PFRULE_RETURN; 2284 $$.w = returnicmpdefault; 2285 $$.w2 = returnicmp6default; 2286 } 2287 ; 2288 2289 reticmpspec : STRING { 2290 if (!($$ = parseicmpspec($1, AF_INET))) { 2291 free($1); 2292 YYERROR; 2293 } 2294 free($1); 2295 } 2296 | NUMBER { 2297 u_int8_t icmptype; 2298 2299 if ($1 < 0 || $1 > 255) { 2300 yyerror("invalid icmp code %lu", $1); 2301 YYERROR; 2302 } 2303 icmptype = returnicmpdefault >> 8; 2304 $$ = (icmptype << 8 | $1); 2305 } 2306 ; 2307 2308 reticmp6spec : STRING { 2309 if (!($$ = parseicmpspec($1, AF_INET6))) { 2310 free($1); 2311 YYERROR; 2312 } 2313 free($1); 2314 } 2315 | NUMBER { 2316 u_int8_t icmptype; 2317 2318 if ($1 < 0 || $1 > 255) { 2319 yyerror("invalid icmp code %lu", $1); 2320 YYERROR; 2321 } 2322 icmptype = returnicmp6default >> 8; 2323 $$ = (icmptype << 8 | $1); 2324 } 2325 ; 2326 2327 dir : /* empty */ { $$ = PF_INOUT; } 2328 | IN { $$ = PF_IN; } 2329 | OUT { $$ = PF_OUT; } 2330 ; 2331 2332 quick : /* empty */ { $$.quick = 0; } 2333 | QUICK { $$.quick = 1; } 2334 ; 2335 2336 logquick : /* empty */ { $$.log = 0; $$.quick = 0; $$.logif = 0; } 2337 | log { $$ = $1; $$.quick = 0; } 2338 | QUICK { $$.quick = 1; $$.log = 0; $$.logif = 0; } 2339 | log QUICK { $$ = $1; $$.quick = 1; } 2340 | QUICK log { $$ = $2; $$.quick = 1; } 2341 ; 2342 2343 log : LOG { $$.log = PF_LOG; $$.logif = 0; } 2344 | LOG '(' logopts ')' { 2345 $$.log = PF_LOG | $3.log; 2346 $$.logif = $3.logif; 2347 } 2348 ; 2349 2350 logopts : logopt { $$ = $1; } 2351 | logopts comma logopt { 2352 $$.log = $1.log | $3.log; 2353 $$.logif = $3.logif; 2354 if ($$.logif == 0) 2355 $$.logif = $1.logif; 2356 } 2357 ; 2358 2359 logopt : ALL { $$.log = PF_LOG_ALL; $$.logif = 0; } 2360 | MATCHES { $$.log = PF_LOG_MATCHES; $$.logif = 0; } 2361 | USER { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; } 2362 | GROUP { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; } 2363 | TO string { 2364 const char *errstr; 2365 u_int i; 2366 2367 $$.log = 0; 2368 if (strncmp($2, "pflog", 5)) { 2369 yyerror("%s: should be a pflog interface", $2); 2370 free($2); 2371 YYERROR; 2372 } 2373 i = strtonum($2 + 5, 0, 255, &errstr); 2374 if (errstr) { 2375 yyerror("%s: %s", $2, errstr); 2376 free($2); 2377 YYERROR; 2378 } 2379 free($2); 2380 $$.logif = i; 2381 } 2382 ; 2383 2384 interface : /* empty */ { $$ = NULL; } 2385 | ON if_item_not { $$ = $2; } 2386 | ON '{' optnl if_list '}' { $$ = $4; } 2387 ; 2388 2389 if_list : if_item_not optnl { $$ = $1; } 2390 | if_list comma if_item_not optnl { 2391 $1->tail->next = $3; 2392 $1->tail = $3; 2393 $$ = $1; 2394 } 2395 ; 2396 2397 if_item_not : not if_item { $$ = $2; $$->not = $1; } 2398 ; 2399 2400 if_item : STRING { 2401 struct node_host *n; 2402 2403 $$ = calloc(1, sizeof(struct node_if)); 2404 if ($$ == NULL) 2405 err(1, "if_item: calloc"); 2406 if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >= 2407 sizeof($$->ifname)) { 2408 free($1); 2409 free($$); 2410 yyerror("interface name too long"); 2411 YYERROR; 2412 } 2413 2414 if ((n = ifa_exists($1)) != NULL) 2415 $$->ifa_flags = n->ifa_flags; 2416 2417 free($1); 2418 $$->not = 0; 2419 $$->next = NULL; 2420 $$->tail = $$; 2421 } 2422 | ANY { 2423 $$ = calloc(1, sizeof(struct node_if)); 2424 if ($$ == NULL) 2425 err(1, "if_item: calloc"); 2426 strlcpy($$->ifname, "any", sizeof($$->ifname)); 2427 $$->not = 0; 2428 $$->next = NULL; 2429 $$->tail = $$; 2430 } 2431 | RDOMAIN NUMBER { 2432 if ($2 < 0 || $2 > RT_TABLEID_MAX) { 2433 yyerror("rdomain outside range"); 2434 YYERROR; 2435 } 2436 $$ = calloc(1, sizeof(struct node_if)); 2437 if ($$ == NULL) 2438 err(1, "if_item: calloc"); 2439 $$->not = 0; 2440 $$->use_rdomain = 1; 2441 $$->rdomain = $2; 2442 $$->next = NULL; 2443 $$->tail = $$; 2444 } 2445 ; 2446 2447 af : /* empty */ { $$ = 0; } 2448 | INET { $$ = AF_INET; } 2449 | INET6 { $$ = AF_INET6; } 2450 ; 2451 2452 proto : /* empty */ { $$ = NULL; } 2453 | PROTO proto_item { $$ = $2; } 2454 | PROTO '{' optnl proto_list '}' { $$ = $4; } 2455 ; 2456 2457 proto_list : proto_item optnl { $$ = $1; } 2458 | proto_list comma proto_item optnl { 2459 $1->tail->next = $3; 2460 $1->tail = $3; 2461 $$ = $1; 2462 } 2463 ; 2464 2465 proto_item : protoval { 2466 u_int8_t pr; 2467 2468 pr = (u_int8_t)$1; 2469 if (pr == 0) { 2470 yyerror("proto 0 cannot be used"); 2471 YYERROR; 2472 } 2473 $$ = calloc(1, sizeof(struct node_proto)); 2474 if ($$ == NULL) 2475 err(1, "proto_item: calloc"); 2476 $$->proto = pr; 2477 $$->next = NULL; 2478 $$->tail = $$; 2479 } 2480 ; 2481 2482 protoval : STRING { 2483 struct protoent *p; 2484 2485 p = getprotobyname($1); 2486 if (p == NULL) { 2487 yyerror("unknown protocol %s", $1); 2488 free($1); 2489 YYERROR; 2490 } 2491 $$ = p->p_proto; 2492 free($1); 2493 } 2494 | NUMBER { 2495 if ($1 < 0 || $1 > 255) { 2496 yyerror("protocol outside range"); 2497 YYERROR; 2498 } 2499 } 2500 ; 2501 2502 fromto : ALL { 2503 $$.src.host = NULL; 2504 $$.src.port = NULL; 2505 $$.dst.host = NULL; 2506 $$.dst.port = NULL; 2507 $$.src_os = NULL; 2508 } 2509 | from os to { 2510 $$.src = $1; 2511 $$.src_os = $2; 2512 $$.dst = $3; 2513 } 2514 ; 2515 2516 os : /* empty */ { $$ = NULL; } 2517 | OS xos { $$ = $2; } 2518 | OS '{' optnl os_list '}' { $$ = $4; } 2519 ; 2520 2521 xos : STRING { 2522 $$ = calloc(1, sizeof(struct node_os)); 2523 if ($$ == NULL) 2524 err(1, "os: calloc"); 2525 $$->os = $1; 2526 $$->tail = $$; 2527 } 2528 ; 2529 2530 os_list : xos optnl { $$ = $1; } 2531 | os_list comma xos optnl { 2532 $1->tail->next = $3; 2533 $1->tail = $3; 2534 $$ = $1; 2535 } 2536 ; 2537 2538 from : /* empty */ { 2539 $$.host = NULL; 2540 $$.port = NULL; 2541 } 2542 | FROM ipportspec { 2543 $$ = $2; 2544 } 2545 ; 2546 2547 to : /* empty */ { 2548 $$.host = NULL; 2549 $$.port = NULL; 2550 } 2551 | TO ipportspec { 2552 if (disallow_urpf_failed($2.host, "\"urpf-failed\" is " 2553 "not permitted in a destination address")) 2554 YYERROR; 2555 $$ = $2; 2556 } 2557 ; 2558 2559 ipportspec : ipspec { 2560 $$.host = $1; 2561 $$.port = NULL; 2562 } 2563 | ipspec PORT portspec { 2564 $$.host = $1; 2565 $$.port = $3; 2566 } 2567 | PORT portspec { 2568 $$.host = NULL; 2569 $$.port = $2; 2570 } 2571 ; 2572 2573 optnl : '\n' optnl 2574 | /* empty */ 2575 ; 2576 2577 ipspec : ANY { $$ = NULL; } 2578 | xhost { $$ = $1; } 2579 | '{' optnl host_list '}' { $$ = $3; } 2580 ; 2581 2582 2583 host_list : ipspec optnl { $$ = $1; } 2584 | host_list comma ipspec optnl { 2585 if ($1 == NULL) { 2586 freehostlist($3); 2587 $$ = $1; 2588 } else if ($3 == NULL) { 2589 freehostlist($1); 2590 $$ = $3; 2591 } else { 2592 $1->tail->next = $3; 2593 $1->tail = $3->tail; 2594 $$ = $1; 2595 } 2596 } 2597 ; 2598 2599 xhost : not host { 2600 struct node_host *n; 2601 2602 for (n = $2; n != NULL; n = n->next) 2603 n->not = $1; 2604 $$ = $2; 2605 } 2606 | not NOROUTE { 2607 $$ = calloc(1, sizeof(struct node_host)); 2608 if ($$ == NULL) 2609 err(1, "xhost: calloc"); 2610 $$->addr.type = PF_ADDR_NOROUTE; 2611 $$->next = NULL; 2612 $$->not = $1; 2613 $$->tail = $$; 2614 } 2615 | not URPFFAILED { 2616 $$ = calloc(1, sizeof(struct node_host)); 2617 if ($$ == NULL) 2618 err(1, "xhost: calloc"); 2619 $$->addr.type = PF_ADDR_URPFFAILED; 2620 $$->next = NULL; 2621 $$->not = $1; 2622 $$->tail = $$; 2623 } 2624 ; 2625 2626 optweight : WEIGHT NUMBER { 2627 if ($2 < 1 || $2 > USHRT_MAX) { 2628 yyerror("weight out of range"); 2629 YYERROR; 2630 } 2631 $$ = $2; 2632 } 2633 | /* empty */ { $$ = 0; } 2634 ; 2635 2636 host : STRING { 2637 if (($$ = host($1)) == NULL) { 2638 /* error. "any" is handled elsewhere */ 2639 free($1); 2640 yyerror("could not parse host specification"); 2641 YYERROR; 2642 } 2643 free($1); 2644 2645 } 2646 | STRING '-' STRING { 2647 struct node_host *b, *e; 2648 2649 if ((b = host($1)) == NULL || (e = host($3)) == NULL) { 2650 free($1); 2651 free($3); 2652 yyerror("could not parse host specification"); 2653 YYERROR; 2654 } 2655 if (b->af != e->af || 2656 b->addr.type != PF_ADDR_ADDRMASK || 2657 e->addr.type != PF_ADDR_ADDRMASK || 2658 unmask(&b->addr.v.a.mask, b->af) != 2659 (b->af == AF_INET ? 32 : 128) || 2660 unmask(&e->addr.v.a.mask, e->af) != 2661 (e->af == AF_INET ? 32 : 128) || 2662 b->next != NULL || b->not || 2663 e->next != NULL || e->not) { 2664 free(b); 2665 free(e); 2666 free($1); 2667 free($3); 2668 yyerror("invalid address range"); 2669 YYERROR; 2670 } 2671 memcpy(&b->addr.v.a.mask, &e->addr.v.a.addr, 2672 sizeof(b->addr.v.a.mask)); 2673 b->addr.type = PF_ADDR_RANGE; 2674 $$ = b; 2675 free(e); 2676 free($1); 2677 free($3); 2678 } 2679 | STRING '/' NUMBER { 2680 char *buf; 2681 2682 if (asprintf(&buf, "%s/%lld", $1, $3) == -1) 2683 err(1, "host: asprintf"); 2684 free($1); 2685 if (($$ = host(buf)) == NULL) { 2686 /* error. "any" is handled elsewhere */ 2687 free(buf); 2688 yyerror("could not parse host specification"); 2689 YYERROR; 2690 } 2691 free(buf); 2692 } 2693 | NUMBER '/' NUMBER { 2694 char *buf; 2695 2696 /* ie. for 10/8 parsing */ 2697 if (asprintf(&buf, "%lld/%lld", $1, $3) == -1) 2698 err(1, "host: asprintf"); 2699 if (($$ = host(buf)) == NULL) { 2700 /* error. "any" is handled elsewhere */ 2701 free(buf); 2702 yyerror("could not parse host specification"); 2703 YYERROR; 2704 } 2705 free(buf); 2706 } 2707 | dynaddr 2708 | dynaddr '/' NUMBER { 2709 struct node_host *n; 2710 2711 if ($3 < 0 || $3 > 128) { 2712 yyerror("bit number too big"); 2713 YYERROR; 2714 } 2715 $$ = $1; 2716 for (n = $1; n != NULL; n = n->next) 2717 set_ipmask(n, $3); 2718 } 2719 | '<' STRING '>' { 2720 if (strlen($2) >= PF_TABLE_NAME_SIZE) { 2721 yyerror("table name '%s' too long", $2); 2722 free($2); 2723 YYERROR; 2724 } 2725 $$ = calloc(1, sizeof(struct node_host)); 2726 if ($$ == NULL) 2727 err(1, "host: calloc"); 2728 $$->addr.type = PF_ADDR_TABLE; 2729 if (strlcpy($$->addr.v.tblname, $2, 2730 sizeof($$->addr.v.tblname)) >= 2731 sizeof($$->addr.v.tblname)) 2732 errx(1, "host: strlcpy"); 2733 free($2); 2734 $$->next = NULL; 2735 $$->tail = $$; 2736 } 2737 | ROUTE STRING { 2738 $$ = calloc(1, sizeof(struct node_host)); 2739 if ($$ == NULL) { 2740 free($2); 2741 err(1, "host: calloc"); 2742 } 2743 $$->addr.type = PF_ADDR_RTLABEL; 2744 if (strlcpy($$->addr.v.rtlabelname, $2, 2745 sizeof($$->addr.v.rtlabelname)) >= 2746 sizeof($$->addr.v.rtlabelname)) { 2747 yyerror("route label too long, max %u chars", 2748 sizeof($$->addr.v.rtlabelname) - 1); 2749 free($2); 2750 free($$); 2751 YYERROR; 2752 } 2753 $$->next = NULL; 2754 $$->tail = $$; 2755 free($2); 2756 } 2757 ; 2758 2759 number : NUMBER 2760 | STRING { 2761 u_long ulval; 2762 2763 if (atoul($1, &ulval) == -1) { 2764 yyerror("%s is not a number", $1); 2765 free($1); 2766 YYERROR; 2767 } else 2768 $$ = ulval; 2769 free($1); 2770 } 2771 ; 2772 2773 dynaddr : '(' STRING ')' { 2774 int flags = 0; 2775 char *p, *op; 2776 2777 op = $2; 2778 if (!isalpha((unsigned char)op[0])) { 2779 yyerror("invalid interface name '%s'", op); 2780 free(op); 2781 YYERROR; 2782 } 2783 while ((p = strrchr($2, ':')) != NULL) { 2784 if (!strcmp(p+1, "network")) 2785 flags |= PFI_AFLAG_NETWORK; 2786 else if (!strcmp(p+1, "broadcast")) 2787 flags |= PFI_AFLAG_BROADCAST; 2788 else if (!strcmp(p+1, "peer")) 2789 flags |= PFI_AFLAG_PEER; 2790 else if (!strcmp(p+1, "0")) 2791 flags |= PFI_AFLAG_NOALIAS; 2792 else { 2793 yyerror("interface %s has bad modifier", 2794 $2); 2795 free(op); 2796 YYERROR; 2797 } 2798 *p = '\0'; 2799 } 2800 if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { 2801 free(op); 2802 yyerror("illegal combination of " 2803 "interface modifiers"); 2804 YYERROR; 2805 } 2806 $$ = calloc(1, sizeof(struct node_host)); 2807 if ($$ == NULL) 2808 err(1, "address: calloc"); 2809 $$->af = 0; 2810 set_ipmask($$, 128); 2811 $$->addr.type = PF_ADDR_DYNIFTL; 2812 $$->addr.iflags = flags; 2813 if (strlcpy($$->addr.v.ifname, $2, 2814 sizeof($$->addr.v.ifname)) >= 2815 sizeof($$->addr.v.ifname)) { 2816 free(op); 2817 free($$); 2818 yyerror("interface name too long"); 2819 YYERROR; 2820 } 2821 free(op); 2822 $$->next = NULL; 2823 $$->tail = $$; 2824 } 2825 ; 2826 2827 portspec : port_item { $$ = $1; } 2828 | '{' optnl port_list '}' { $$ = $3; } 2829 ; 2830 2831 port_list : port_item optnl { $$ = $1; } 2832 | port_list comma port_item optnl { 2833 $1->tail->next = $3; 2834 $1->tail = $3; 2835 $$ = $1; 2836 } 2837 ; 2838 2839 port_item : portrange { 2840 $$ = calloc(1, sizeof(struct node_port)); 2841 if ($$ == NULL) 2842 err(1, "port_item: calloc"); 2843 $$->port[0] = $1.a; 2844 $$->port[1] = $1.b; 2845 if ($1.t) 2846 $$->op = PF_OP_RRG; 2847 else 2848 $$->op = PF_OP_EQ; 2849 $$->next = NULL; 2850 $$->tail = $$; 2851 } 2852 | unaryop portrange { 2853 if ($2.t) { 2854 yyerror("':' cannot be used with an other " 2855 "port operator"); 2856 YYERROR; 2857 } 2858 $$ = calloc(1, sizeof(struct node_port)); 2859 if ($$ == NULL) 2860 err(1, "port_item: calloc"); 2861 $$->port[0] = $2.a; 2862 $$->port[1] = $2.b; 2863 $$->op = $1; 2864 $$->next = NULL; 2865 $$->tail = $$; 2866 } 2867 | portrange PORTBINARY portrange { 2868 if ($1.t || $3.t) { 2869 yyerror("':' cannot be used with an other " 2870 "port operator"); 2871 YYERROR; 2872 } 2873 $$ = calloc(1, sizeof(struct node_port)); 2874 if ($$ == NULL) 2875 err(1, "port_item: calloc"); 2876 $$->port[0] = $1.a; 2877 $$->port[1] = $3.a; 2878 $$->op = $2; 2879 $$->next = NULL; 2880 $$->tail = $$; 2881 } 2882 ; 2883 2884 portplain : numberstring { 2885 if (parseport($1, &$$, 0) == -1) { 2886 free($1); 2887 YYERROR; 2888 } 2889 free($1); 2890 } 2891 ; 2892 2893 portrange : numberstring { 2894 if (parseport($1, &$$, PPORT_RANGE) == -1) { 2895 free($1); 2896 YYERROR; 2897 } 2898 free($1); 2899 } 2900 ; 2901 2902 uids : uid_item { $$ = $1; } 2903 | '{' optnl uid_list '}' { $$ = $3; } 2904 ; 2905 2906 uid_list : uid_item optnl { $$ = $1; } 2907 | uid_list comma uid_item optnl { 2908 $1->tail->next = $3; 2909 $1->tail = $3; 2910 $$ = $1; 2911 } 2912 ; 2913 2914 uid_item : uid { 2915 $$ = calloc(1, sizeof(struct node_uid)); 2916 if ($$ == NULL) 2917 err(1, "uid_item: calloc"); 2918 $$->uid[0] = $1; 2919 $$->uid[1] = $1; 2920 $$->op = PF_OP_EQ; 2921 $$->next = NULL; 2922 $$->tail = $$; 2923 } 2924 | unaryop uid { 2925 if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 2926 yyerror("user unknown requires operator = or " 2927 "!="); 2928 YYERROR; 2929 } 2930 $$ = calloc(1, sizeof(struct node_uid)); 2931 if ($$ == NULL) 2932 err(1, "uid_item: calloc"); 2933 $$->uid[0] = $2; 2934 $$->uid[1] = $2; 2935 $$->op = $1; 2936 $$->next = NULL; 2937 $$->tail = $$; 2938 } 2939 | uid PORTBINARY uid { 2940 if ($1 == UID_MAX || $3 == UID_MAX) { 2941 yyerror("user unknown requires operator = or " 2942 "!="); 2943 YYERROR; 2944 } 2945 $$ = calloc(1, sizeof(struct node_uid)); 2946 if ($$ == NULL) 2947 err(1, "uid_item: calloc"); 2948 $$->uid[0] = $1; 2949 $$->uid[1] = $3; 2950 $$->op = $2; 2951 $$->next = NULL; 2952 $$->tail = $$; 2953 } 2954 ; 2955 2956 uid : STRING { 2957 if (!strcmp($1, "unknown")) 2958 $$ = UID_MAX; 2959 else { 2960 struct passwd *pw; 2961 2962 if ((pw = getpwnam($1)) == NULL) { 2963 yyerror("unknown user %s", $1); 2964 free($1); 2965 YYERROR; 2966 } 2967 $$ = pw->pw_uid; 2968 } 2969 free($1); 2970 } 2971 | NUMBER { 2972 if ($1 < 0 || $1 >= UID_MAX) { 2973 yyerror("illegal uid value %lu", $1); 2974 YYERROR; 2975 } 2976 $$ = $1; 2977 } 2978 ; 2979 2980 gids : gid_item { $$ = $1; } 2981 | '{' optnl gid_list '}' { $$ = $3; } 2982 ; 2983 2984 gid_list : gid_item optnl { $$ = $1; } 2985 | gid_list comma gid_item optnl { 2986 $1->tail->next = $3; 2987 $1->tail = $3; 2988 $$ = $1; 2989 } 2990 ; 2991 2992 gid_item : gid { 2993 $$ = calloc(1, sizeof(struct node_gid)); 2994 if ($$ == NULL) 2995 err(1, "gid_item: calloc"); 2996 $$->gid[0] = $1; 2997 $$->gid[1] = $1; 2998 $$->op = PF_OP_EQ; 2999 $$->next = NULL; 3000 $$->tail = $$; 3001 } 3002 | unaryop gid { 3003 if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 3004 yyerror("group unknown requires operator = or " 3005 "!="); 3006 YYERROR; 3007 } 3008 $$ = calloc(1, sizeof(struct node_gid)); 3009 if ($$ == NULL) 3010 err(1, "gid_item: calloc"); 3011 $$->gid[0] = $2; 3012 $$->gid[1] = $2; 3013 $$->op = $1; 3014 $$->next = NULL; 3015 $$->tail = $$; 3016 } 3017 | gid PORTBINARY gid { 3018 if ($1 == GID_MAX || $3 == GID_MAX) { 3019 yyerror("group unknown requires operator = or " 3020 "!="); 3021 YYERROR; 3022 } 3023 $$ = calloc(1, sizeof(struct node_gid)); 3024 if ($$ == NULL) 3025 err(1, "gid_item: calloc"); 3026 $$->gid[0] = $1; 3027 $$->gid[1] = $3; 3028 $$->op = $2; 3029 $$->next = NULL; 3030 $$->tail = $$; 3031 } 3032 ; 3033 3034 gid : STRING { 3035 if (!strcmp($1, "unknown")) 3036 $$ = GID_MAX; 3037 else { 3038 struct group *grp; 3039 3040 if ((grp = getgrnam($1)) == NULL) { 3041 yyerror("unknown group %s", $1); 3042 free($1); 3043 YYERROR; 3044 } 3045 $$ = grp->gr_gid; 3046 } 3047 free($1); 3048 } 3049 | NUMBER { 3050 if ($1 < 0 || $1 >= GID_MAX) { 3051 yyerror("illegal gid value %lu", $1); 3052 YYERROR; 3053 } 3054 $$ = $1; 3055 } 3056 ; 3057 3058 flag : STRING { 3059 int f; 3060 3061 if ((f = parse_flags($1)) < 0) { 3062 yyerror("bad flags %s", $1); 3063 free($1); 3064 YYERROR; 3065 } 3066 free($1); 3067 $$.b1 = f; 3068 } 3069 ; 3070 3071 flags : FLAGS flag '/' flag { $$.b1 = $2.b1; $$.b2 = $4.b1; } 3072 | FLAGS '/' flag { $$.b1 = 0; $$.b2 = $3.b1; } 3073 | FLAGS ANY { $$.b1 = 0; $$.b2 = 0; } 3074 ; 3075 3076 icmpspec : ICMPTYPE icmp_item { $$ = $2; } 3077 | ICMPTYPE '{' optnl icmp_list '}' { $$ = $4; } 3078 | ICMP6TYPE icmp6_item { $$ = $2; } 3079 | ICMP6TYPE '{' optnl icmp6_list '}' { $$ = $4; } 3080 ; 3081 3082 icmp_list : icmp_item optnl { $$ = $1; } 3083 | icmp_list comma icmp_item optnl { 3084 $1->tail->next = $3; 3085 $1->tail = $3; 3086 $$ = $1; 3087 } 3088 ; 3089 3090 icmp6_list : icmp6_item optnl { $$ = $1; } 3091 | icmp6_list comma icmp6_item optnl { 3092 $1->tail->next = $3; 3093 $1->tail = $3; 3094 $$ = $1; 3095 } 3096 ; 3097 3098 icmp_item : icmptype { 3099 $$ = calloc(1, sizeof(struct node_icmp)); 3100 if ($$ == NULL) 3101 err(1, "icmp_item: calloc"); 3102 $$->type = $1; 3103 $$->code = 0; 3104 $$->proto = IPPROTO_ICMP; 3105 $$->next = NULL; 3106 $$->tail = $$; 3107 } 3108 | icmptype CODE STRING { 3109 const struct icmpcodeent *p; 3110 3111 if ((p = geticmpcodebyname($1-1, $3, AF_INET)) == NULL) { 3112 yyerror("unknown icmp-code %s", $3); 3113 free($3); 3114 YYERROR; 3115 } 3116 3117 free($3); 3118 $$ = calloc(1, sizeof(struct node_icmp)); 3119 if ($$ == NULL) 3120 err(1, "icmp_item: calloc"); 3121 $$->type = $1; 3122 $$->code = p->code + 1; 3123 $$->proto = IPPROTO_ICMP; 3124 $$->next = NULL; 3125 $$->tail = $$; 3126 } 3127 | icmptype CODE NUMBER { 3128 if ($3 < 0 || $3 > 255) { 3129 yyerror("illegal icmp-code %lu", $3); 3130 YYERROR; 3131 } 3132 $$ = calloc(1, sizeof(struct node_icmp)); 3133 if ($$ == NULL) 3134 err(1, "icmp_item: calloc"); 3135 $$->type = $1; 3136 $$->code = $3 + 1; 3137 $$->proto = IPPROTO_ICMP; 3138 $$->next = NULL; 3139 $$->tail = $$; 3140 } 3141 ; 3142 3143 icmp6_item : icmp6type { 3144 $$ = calloc(1, sizeof(struct node_icmp)); 3145 if ($$ == NULL) 3146 err(1, "icmp_item: calloc"); 3147 $$->type = $1; 3148 $$->code = 0; 3149 $$->proto = IPPROTO_ICMPV6; 3150 $$->next = NULL; 3151 $$->tail = $$; 3152 } 3153 | icmp6type CODE STRING { 3154 const struct icmpcodeent *p; 3155 3156 if ((p = geticmpcodebyname($1-1, $3, AF_INET6)) == NULL) { 3157 yyerror("unknown icmp6-code %s", $3); 3158 free($3); 3159 YYERROR; 3160 } 3161 free($3); 3162 3163 $$ = calloc(1, sizeof(struct node_icmp)); 3164 if ($$ == NULL) 3165 err(1, "icmp_item: calloc"); 3166 $$->type = $1; 3167 $$->code = p->code + 1; 3168 $$->proto = IPPROTO_ICMPV6; 3169 $$->next = NULL; 3170 $$->tail = $$; 3171 } 3172 | icmp6type CODE NUMBER { 3173 if ($3 < 0 || $3 > 255) { 3174 yyerror("illegal icmp-code %lu", $3); 3175 YYERROR; 3176 } 3177 $$ = calloc(1, sizeof(struct node_icmp)); 3178 if ($$ == NULL) 3179 err(1, "icmp_item: calloc"); 3180 $$->type = $1; 3181 $$->code = $3 + 1; 3182 $$->proto = IPPROTO_ICMPV6; 3183 $$->next = NULL; 3184 $$->tail = $$; 3185 } 3186 ; 3187 3188 icmptype : STRING { 3189 const struct icmptypeent *p; 3190 3191 if ((p = geticmptypebyname($1, AF_INET)) == NULL) { 3192 yyerror("unknown icmp-type %s", $1); 3193 free($1); 3194 YYERROR; 3195 } 3196 $$ = p->type + 1; 3197 free($1); 3198 } 3199 | NUMBER { 3200 if ($1 < 0 || $1 > 255) { 3201 yyerror("illegal icmp-type %lu", $1); 3202 YYERROR; 3203 } 3204 $$ = $1 + 1; 3205 } 3206 ; 3207 3208 icmp6type : STRING { 3209 const struct icmptypeent *p; 3210 3211 if ((p = geticmptypebyname($1, AF_INET6)) == 3212 NULL) { 3213 yyerror("unknown icmp6-type %s", $1); 3214 free($1); 3215 YYERROR; 3216 } 3217 $$ = p->type + 1; 3218 free($1); 3219 } 3220 | NUMBER { 3221 if ($1 < 0 || $1 > 255) { 3222 yyerror("illegal icmp6-type %lu", $1); 3223 YYERROR; 3224 } 3225 $$ = $1 + 1; 3226 } 3227 ; 3228 3229 tos : STRING { 3230 int val; 3231 char *end; 3232 3233 if (map_tos($1, &val)) 3234 $$ = val; 3235 else if ($1[0] == '0' && $1[1] == 'x') { 3236 errno = 0; 3237 $$ = strtoul($1, &end, 16); 3238 if (errno || *end != '\0') 3239 $$ = 256; 3240 } else 3241 $$ = 256; /* flag bad argument */ 3242 if ($$ < 0 || $$ > 255) { 3243 yyerror("illegal tos value %s", $1); 3244 free($1); 3245 YYERROR; 3246 } 3247 free($1); 3248 } 3249 | NUMBER { 3250 $$ = $1; 3251 if ($$ < 0 || $$ > 255) { 3252 yyerror("illegal tos value %lld", $1); 3253 YYERROR; 3254 } 3255 } 3256 ; 3257 3258 sourcetrack : /* empty */ { $$ = PF_SRCTRACK; } 3259 | GLOBAL { $$ = PF_SRCTRACK_GLOBAL; } 3260 | RULE { $$ = PF_SRCTRACK_RULE; } 3261 ; 3262 3263 statelock : IFBOUND { 3264 $$ = PFRULE_IFBOUND; 3265 } 3266 | FLOATING { 3267 $$ = 0; 3268 } 3269 ; 3270 3271 keep : NO STATE { 3272 $$.action = 0; 3273 $$.options = NULL; 3274 } 3275 | KEEP STATE state_opt_spec { 3276 $$.action = PF_STATE_NORMAL; 3277 $$.options = $3; 3278 } 3279 | MODULATE STATE state_opt_spec { 3280 $$.action = PF_STATE_MODULATE; 3281 $$.options = $3; 3282 } 3283 | SYNPROXY STATE state_opt_spec { 3284 $$.action = PF_STATE_SYNPROXY; 3285 $$.options = $3; 3286 } 3287 ; 3288 3289 flush : /* empty */ { $$ = 0; } 3290 | FLUSH { $$ = PF_FLUSH; } 3291 | FLUSH GLOBAL { 3292 $$ = PF_FLUSH | PF_FLUSH_GLOBAL; 3293 } 3294 ; 3295 3296 state_opt_spec : '(' state_opt_list ')' { $$ = $2; } 3297 | /* empty */ { $$ = NULL; } 3298 ; 3299 3300 state_opt_list : state_opt_item { $$ = $1; } 3301 | state_opt_list comma state_opt_item { 3302 $1->tail->next = $3; 3303 $1->tail = $3; 3304 $$ = $1; 3305 } 3306 ; 3307 3308 state_opt_item : MAXIMUM NUMBER { 3309 if ($2 < 0 || $2 > UINT_MAX) { 3310 yyerror("only positive values permitted"); 3311 YYERROR; 3312 } 3313 $$ = calloc(1, sizeof(struct node_state_opt)); 3314 if ($$ == NULL) 3315 err(1, "state_opt_item: calloc"); 3316 $$->type = PF_STATE_OPT_MAX; 3317 $$->data.max_states = $2; 3318 $$->next = NULL; 3319 $$->tail = $$; 3320 } 3321 | NOSYNC { 3322 $$ = calloc(1, sizeof(struct node_state_opt)); 3323 if ($$ == NULL) 3324 err(1, "state_opt_item: calloc"); 3325 $$->type = PF_STATE_OPT_NOSYNC; 3326 $$->next = NULL; 3327 $$->tail = $$; 3328 } 3329 | MAXSRCSTATES NUMBER { 3330 if ($2 < 0 || $2 > UINT_MAX) { 3331 yyerror("only positive values permitted"); 3332 YYERROR; 3333 } 3334 $$ = calloc(1, sizeof(struct node_state_opt)); 3335 if ($$ == NULL) 3336 err(1, "state_opt_item: calloc"); 3337 $$->type = PF_STATE_OPT_MAX_SRC_STATES; 3338 $$->data.max_src_states = $2; 3339 $$->next = NULL; 3340 $$->tail = $$; 3341 } 3342 | MAXSRCCONN NUMBER { 3343 if ($2 < 0 || $2 > UINT_MAX) { 3344 yyerror("only positive values permitted"); 3345 YYERROR; 3346 } 3347 $$ = calloc(1, sizeof(struct node_state_opt)); 3348 if ($$ == NULL) 3349 err(1, "state_opt_item: calloc"); 3350 $$->type = PF_STATE_OPT_MAX_SRC_CONN; 3351 $$->data.max_src_conn = $2; 3352 $$->next = NULL; 3353 $$->tail = $$; 3354 } 3355 | MAXSRCCONNRATE NUMBER '/' NUMBER { 3356 if ($2 < 0 || $2 > UINT_MAX || 3357 $4 < 0 || $4 > UINT_MAX) { 3358 yyerror("only positive values permitted"); 3359 YYERROR; 3360 } 3361 $$ = calloc(1, sizeof(struct node_state_opt)); 3362 if ($$ == NULL) 3363 err(1, "state_opt_item: calloc"); 3364 $$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE; 3365 $$->data.max_src_conn_rate.limit = $2; 3366 $$->data.max_src_conn_rate.seconds = $4; 3367 $$->next = NULL; 3368 $$->tail = $$; 3369 } 3370 | OVERLOAD '<' STRING '>' flush { 3371 if (strlen($3) >= PF_TABLE_NAME_SIZE) { 3372 yyerror("table name '%s' too long", $3); 3373 free($3); 3374 YYERROR; 3375 } 3376 $$ = calloc(1, sizeof(struct node_state_opt)); 3377 if ($$ == NULL) 3378 err(1, "state_opt_item: calloc"); 3379 if (strlcpy($$->data.overload.tblname, $3, 3380 PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE) 3381 errx(1, "state_opt_item: strlcpy"); 3382 free($3); 3383 $$->type = PF_STATE_OPT_OVERLOAD; 3384 $$->data.overload.flush = $5; 3385 $$->next = NULL; 3386 $$->tail = $$; 3387 } 3388 | MAXSRCNODES NUMBER { 3389 if ($2 < 0 || $2 > UINT_MAX) { 3390 yyerror("only positive values permitted"); 3391 YYERROR; 3392 } 3393 $$ = calloc(1, sizeof(struct node_state_opt)); 3394 if ($$ == NULL) 3395 err(1, "state_opt_item: calloc"); 3396 $$->type = PF_STATE_OPT_MAX_SRC_NODES; 3397 $$->data.max_src_nodes = $2; 3398 $$->next = NULL; 3399 $$->tail = $$; 3400 } 3401 | SOURCETRACK sourcetrack { 3402 $$ = calloc(1, sizeof(struct node_state_opt)); 3403 if ($$ == NULL) 3404 err(1, "state_opt_item: calloc"); 3405 $$->type = PF_STATE_OPT_SRCTRACK; 3406 $$->data.src_track = $2; 3407 $$->next = NULL; 3408 $$->tail = $$; 3409 } 3410 | statelock { 3411 $$ = calloc(1, sizeof(struct node_state_opt)); 3412 if ($$ == NULL) 3413 err(1, "state_opt_item: calloc"); 3414 $$->type = PF_STATE_OPT_STATELOCK; 3415 $$->data.statelock = $1; 3416 $$->next = NULL; 3417 $$->tail = $$; 3418 } 3419 | SLOPPY { 3420 $$ = calloc(1, sizeof(struct node_state_opt)); 3421 if ($$ == NULL) 3422 err(1, "state_opt_item: calloc"); 3423 $$->type = PF_STATE_OPT_SLOPPY; 3424 $$->next = NULL; 3425 $$->tail = $$; 3426 } 3427 | PFLOW { 3428 $$ = calloc(1, sizeof(struct node_state_opt)); 3429 if ($$ == NULL) 3430 err(1, "state_opt_item: calloc"); 3431 $$->type = PF_STATE_OPT_PFLOW; 3432 $$->next = NULL; 3433 $$->tail = $$; 3434 } 3435 | STRING NUMBER { 3436 int i; 3437 3438 if ($2 < 0 || $2 > UINT_MAX) { 3439 yyerror("only positive values permitted"); 3440 YYERROR; 3441 } 3442 for (i = 0; pf_timeouts[i].name && 3443 strcmp(pf_timeouts[i].name, $1); ++i) 3444 ; /* nothing */ 3445 if (!pf_timeouts[i].name) { 3446 yyerror("illegal timeout name %s", $1); 3447 free($1); 3448 YYERROR; 3449 } 3450 if (strchr(pf_timeouts[i].name, '.') == NULL) { 3451 yyerror("illegal state timeout %s", $1); 3452 free($1); 3453 YYERROR; 3454 } 3455 free($1); 3456 $$ = calloc(1, sizeof(struct node_state_opt)); 3457 if ($$ == NULL) 3458 err(1, "state_opt_item: calloc"); 3459 $$->type = PF_STATE_OPT_TIMEOUT; 3460 $$->data.timeout.number = pf_timeouts[i].timeout; 3461 $$->data.timeout.seconds = $2; 3462 $$->next = NULL; 3463 $$->tail = $$; 3464 } 3465 ; 3466 3467 label : STRING { 3468 $$ = $1; 3469 } 3470 ; 3471 3472 qname : STRING { 3473 struct pfctl_qsitem *qsi; 3474 3475 if ((qsi = pfctl_find_queue($1, &qspecs)) == NULL) { 3476 yyerror("queue %s is not defined", $1); 3477 YYERROR; 3478 } 3479 $$.qname = $1; 3480 $$.pqname = NULL; 3481 } 3482 | '(' STRING ')' { 3483 struct pfctl_qsitem *qsi; 3484 3485 if ((qsi = pfctl_find_queue($2, &qspecs)) == NULL) { 3486 yyerror("queue %s is not defined", $2); 3487 YYERROR; 3488 } 3489 $$.qname = $2; 3490 $$.pqname = NULL; 3491 } 3492 | '(' STRING comma STRING ')' { 3493 struct pfctl_qsitem *qsi, *pqsi; 3494 3495 if ((qsi = pfctl_find_queue($2, &qspecs)) == NULL) { 3496 yyerror("queue %s is not defined", $2); 3497 YYERROR; 3498 } 3499 if ((pqsi = pfctl_find_queue($4, &qspecs)) == NULL) { 3500 yyerror("queue %s is not defined", $4); 3501 YYERROR; 3502 } 3503 $$.qname = $2; 3504 $$.pqname = $4; 3505 } 3506 ; 3507 3508 portstar : numberstring { 3509 if (parseport($1, &$$, PPORT_RANGE|PPORT_STAR) == -1) { 3510 free($1); 3511 YYERROR; 3512 } 3513 free($1); 3514 } 3515 ; 3516 3517 redirspec : host optweight { 3518 if ($2 > 0) { 3519 struct node_host *n; 3520 for (n = $1; n != NULL; n = n->next) 3521 n->weight = $2; 3522 } 3523 $$ = $1; 3524 } 3525 | '{' optnl redir_host_list '}' { $$ = $3; } 3526 ; 3527 3528 redir_host_list : host optweight optnl { 3529 if ($1->addr.type != PF_ADDR_ADDRMASK) { 3530 free($1); 3531 yyerror("only addresses can be listed for " 3532 "redirection pools "); 3533 YYERROR; 3534 } 3535 if ($2 > 0) { 3536 struct node_host *n; 3537 for (n = $1; n != NULL; n = n->next) 3538 n->weight = $2; 3539 } 3540 $$ = $1; 3541 } 3542 | redir_host_list comma host optweight optnl { 3543 $1->tail->next = $3; 3544 $1->tail = $3->tail; 3545 if ($4 > 0) { 3546 struct node_host *n; 3547 for (n = $3; n != NULL; n = n->next) 3548 n->weight = $4; 3549 } 3550 $$ = $1; 3551 } 3552 ; 3553 3554 redirpool : redirspec { 3555 $$ = calloc(1, sizeof(struct redirection)); 3556 if ($$ == NULL) 3557 err(1, "redirection: calloc"); 3558 $$->host = $1; 3559 $$->rport.a = $$->rport.b = $$->rport.t = 0; 3560 } 3561 | redirspec PORT portstar { 3562 $$ = calloc(1, sizeof(struct redirection)); 3563 if ($$ == NULL) 3564 err(1, "redirection: calloc"); 3565 $$->host = $1; 3566 $$->rport = $3; 3567 } 3568 ; 3569 3570 hashkey : /* empty */ 3571 { 3572 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 3573 if ($$ == NULL) 3574 err(1, "hashkey: calloc"); 3575 $$->key32[0] = arc4random(); 3576 $$->key32[1] = arc4random(); 3577 $$->key32[2] = arc4random(); 3578 $$->key32[3] = arc4random(); 3579 } 3580 | string 3581 { 3582 if (!strncmp($1, "0x", 2)) { 3583 if (strlen($1) != 34) { 3584 free($1); 3585 yyerror("hex key must be 128 bits " 3586 "(32 hex digits) long"); 3587 YYERROR; 3588 } 3589 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 3590 if ($$ == NULL) 3591 err(1, "hashkey: calloc"); 3592 3593 if (sscanf($1, "0x%8x%8x%8x%8x", 3594 &$$->key32[0], &$$->key32[1], 3595 &$$->key32[2], &$$->key32[3]) != 4) { 3596 free($$); 3597 free($1); 3598 yyerror("invalid hex key"); 3599 YYERROR; 3600 } 3601 } else { 3602 MD5_CTX context; 3603 3604 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 3605 if ($$ == NULL) 3606 err(1, "hashkey: calloc"); 3607 MD5Init(&context); 3608 MD5Update(&context, (unsigned char *)$1, 3609 strlen($1)); 3610 MD5Final((unsigned char *)$$, &context); 3611 HTONL($$->key32[0]); 3612 HTONL($$->key32[1]); 3613 HTONL($$->key32[2]); 3614 HTONL($$->key32[3]); 3615 } 3616 free($1); 3617 } 3618 ; 3619 3620 pool_opts : { bzero(&pool_opts, sizeof pool_opts); } 3621 pool_opts_l 3622 { $$ = pool_opts; } 3623 | /* empty */ { 3624 bzero(&pool_opts, sizeof pool_opts); 3625 $$ = pool_opts; 3626 } 3627 ; 3628 3629 pool_opts_l : pool_opts_l pool_opt 3630 | pool_opt 3631 ; 3632 3633 pool_opt : BITMASK { 3634 if (pool_opts.type) { 3635 yyerror("pool type cannot be redefined"); 3636 YYERROR; 3637 } 3638 pool_opts.type = PF_POOL_BITMASK; 3639 } 3640 | RANDOM { 3641 if (pool_opts.type) { 3642 yyerror("pool type cannot be redefined"); 3643 YYERROR; 3644 } 3645 pool_opts.type = PF_POOL_RANDOM; 3646 } 3647 | SOURCEHASH hashkey { 3648 if (pool_opts.type) { 3649 yyerror("pool type cannot be redefined"); 3650 YYERROR; 3651 } 3652 pool_opts.type = PF_POOL_SRCHASH; 3653 pool_opts.key = $2; 3654 } 3655 | ROUNDROBIN { 3656 if (pool_opts.type) { 3657 yyerror("pool type cannot be redefined"); 3658 YYERROR; 3659 } 3660 pool_opts.type = PF_POOL_ROUNDROBIN; 3661 } 3662 | LEASTSTATES { 3663 if (pool_opts.type) { 3664 yyerror("pool type cannot be redefined"); 3665 YYERROR; 3666 } 3667 pool_opts.type = PF_POOL_LEASTSTATES; 3668 } 3669 | STATICPORT { 3670 if (pool_opts.staticport) { 3671 yyerror("static-port cannot be redefined"); 3672 YYERROR; 3673 } 3674 pool_opts.staticport = 1; 3675 } 3676 | STICKYADDRESS { 3677 if (filter_opts.marker & POM_STICKYADDRESS) { 3678 yyerror("sticky-address cannot be redefined"); 3679 YYERROR; 3680 } 3681 pool_opts.marker |= POM_STICKYADDRESS; 3682 pool_opts.opts |= PF_POOL_STICKYADDR; 3683 } 3684 ; 3685 3686 route_host : STRING { 3687 /* try to find @if0 address specs */ 3688 if (strrchr($1, '@') != NULL) { 3689 if (($$ = host($1)) == NULL) { 3690 yyerror("invalid host for route spec"); 3691 YYERROR; 3692 } 3693 free($1); 3694 } else { 3695 $$ = calloc(1, sizeof(struct node_host)); 3696 if ($$ == NULL) 3697 err(1, "route_host: calloc"); 3698 $$->ifname = $1; 3699 $$->addr.type = PF_ADDR_NONE; 3700 set_ipmask($$, 128); 3701 $$->next = NULL; 3702 $$->tail = $$; 3703 } 3704 } 3705 | STRING '/' STRING { 3706 char *buf; 3707 3708 if (asprintf(&buf, "%s/%s", $1, $3) == -1) 3709 err(1, "host: asprintf"); 3710 free($1); 3711 if (($$ = host(buf)) == NULL) { 3712 /* error. "any" is handled elsewhere */ 3713 free(buf); 3714 yyerror("could not parse host specification"); 3715 YYERROR; 3716 } 3717 free(buf); 3718 } 3719 | '<' STRING '>' { 3720 if (strlen($2) >= PF_TABLE_NAME_SIZE) { 3721 yyerror("table name '%s' too long", $2); 3722 free($2); 3723 YYERROR; 3724 } 3725 $$ = calloc(1, sizeof(struct node_host)); 3726 if ($$ == NULL) 3727 err(1, "host: calloc"); 3728 $$->addr.type = PF_ADDR_TABLE; 3729 if (strlcpy($$->addr.v.tblname, $2, 3730 sizeof($$->addr.v.tblname)) >= 3731 sizeof($$->addr.v.tblname)) 3732 errx(1, "host: strlcpy"); 3733 free($2); 3734 $$->next = NULL; 3735 $$->tail = $$; 3736 } 3737 | dynaddr '/' NUMBER { 3738 struct node_host *n; 3739 3740 if ($3 < 0 || $3 > 128) { 3741 yyerror("bit number too big"); 3742 YYERROR; 3743 } 3744 $$ = $1; 3745 for (n = $1; n != NULL; n = n->next) 3746 set_ipmask(n, $3); 3747 } 3748 | '(' STRING host ')' { 3749 struct node_host *n; 3750 3751 $$ = $3; 3752 /* XXX check masks, only full mask should be allowed */ 3753 for (n = $3; n != NULL; n = n->next) { 3754 if ($$->ifname) { 3755 yyerror("cannot specify interface twice " 3756 "in route spec"); 3757 YYERROR; 3758 } 3759 if (($$->ifname = strdup($2)) == NULL) 3760 errx(1, "host: strdup"); 3761 } 3762 free($2); 3763 } 3764 ; 3765 3766 route_host_list : route_host optweight optnl { 3767 if ($2 > 0) { 3768 struct node_host *n; 3769 for (n = $1; n != NULL; n = n->next) 3770 n->weight = $2; 3771 } 3772 $$ = $1; 3773 } 3774 | route_host_list comma route_host optweight optnl { 3775 if ($1->af == 0) 3776 $1->af = $3->af; 3777 if ($1->af != $3->af) { 3778 yyerror("all pool addresses must be in the " 3779 "same address family"); 3780 YYERROR; 3781 } 3782 $1->tail->next = $3; 3783 $1->tail = $3->tail; 3784 if ($4 > 0) { 3785 struct node_host *n; 3786 for (n = $3; n != NULL; n = n->next) 3787 n->weight = $4; 3788 } 3789 $$ = $1; 3790 } 3791 ; 3792 3793 routespec : route_host optweight { 3794 if ($2 > 0) { 3795 struct node_host *n; 3796 for (n = $1; n != NULL; n = n->next) 3797 n->weight = $2; 3798 } 3799 $$ = $1; 3800 } 3801 | '{' optnl route_host_list '}' { $$ = $3; } 3802 ; 3803 3804 timeout_spec : STRING NUMBER 3805 { 3806 if ($2 < 0 || $2 > UINT_MAX) { 3807 yyerror("only positive values permitted"); 3808 YYERROR; 3809 } 3810 if (pfctl_set_timeout(pf, $1, $2, 0) != 0) { 3811 yyerror("unknown timeout %s", $1); 3812 free($1); 3813 YYERROR; 3814 } 3815 free($1); 3816 } 3817 ; 3818 3819 timeout_list : timeout_list comma timeout_spec optnl 3820 | timeout_spec optnl 3821 ; 3822 3823 limit_spec : STRING NUMBER 3824 { 3825 if ($2 < 0 || $2 > UINT_MAX) { 3826 yyerror("only positive values permitted"); 3827 YYERROR; 3828 } 3829 if (pfctl_set_limit(pf, $1, $2) != 0) { 3830 yyerror("unable to set limit %s %u", $1, $2); 3831 free($1); 3832 YYERROR; 3833 } 3834 free($1); 3835 } 3836 ; 3837 3838 limit_list : limit_list comma limit_spec optnl 3839 | limit_spec optnl 3840 ; 3841 3842 comma : ',' 3843 | /* empty */ 3844 ; 3845 3846 yesno : NO { $$ = 0; } 3847 | STRING { 3848 if (!strcmp($1, "yes")) 3849 $$ = 1; 3850 else { 3851 yyerror("invalid value '%s', expected 'yes' " 3852 "or 'no'", $1); 3853 free($1); 3854 YYERROR; 3855 } 3856 free($1); 3857 } 3858 ; 3859 3860 unaryop : '=' { $$ = PF_OP_EQ; } 3861 | NE { $$ = PF_OP_NE; } 3862 | LE { $$ = PF_OP_LE; } 3863 | '<' { $$ = PF_OP_LT; } 3864 | GE { $$ = PF_OP_GE; } 3865 | '>' { $$ = PF_OP_GT; } 3866 ; 3867 3868 %% 3869 3870 int 3871 yyerror(const char *fmt, ...) 3872 { 3873 va_list ap; 3874 3875 file->errors++; 3876 va_start(ap, fmt); 3877 fprintf(stderr, "%s:%d: ", file->name, yylval.lineno); 3878 vfprintf(stderr, fmt, ap); 3879 fprintf(stderr, "\n"); 3880 va_end(ap); 3881 return (0); 3882 } 3883 3884 int 3885 disallow_table(struct node_host *h, const char *fmt) 3886 { 3887 for (; h != NULL; h = h->next) 3888 if (h->addr.type == PF_ADDR_TABLE) { 3889 yyerror(fmt, h->addr.v.tblname); 3890 return (1); 3891 } 3892 return (0); 3893 } 3894 3895 int 3896 disallow_urpf_failed(struct node_host *h, const char *fmt) 3897 { 3898 for (; h != NULL; h = h->next) 3899 if (h->addr.type == PF_ADDR_URPFFAILED) { 3900 yyerror(fmt); 3901 return (1); 3902 } 3903 return (0); 3904 } 3905 3906 int 3907 disallow_alias(struct node_host *h, const char *fmt) 3908 { 3909 for (; h != NULL; h = h->next) 3910 if (DYNIF_MULTIADDR(h->addr)) { 3911 yyerror(fmt, h->addr.v.tblname); 3912 return (1); 3913 } 3914 return (0); 3915 } 3916 3917 int 3918 rule_consistent(struct pf_rule *r, int anchor_call) 3919 { 3920 int problems = 0; 3921 3922 if (r->proto != IPPROTO_TCP && r->os_fingerprint != PF_OSFP_ANY) { 3923 yyerror("os only applies to tcp"); 3924 problems++; 3925 } 3926 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 3927 (r->src.port_op || r->dst.port_op)) { 3928 yyerror("port only applies to tcp/udp"); 3929 problems++; 3930 } 3931 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 3932 r->uid.op) { 3933 yyerror("user only applies to tcp/udp"); 3934 problems++; 3935 } 3936 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 3937 r->gid.op) { 3938 yyerror("group only applies to tcp/udp"); 3939 problems++; 3940 } 3941 if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 && 3942 (r->type || r->code)) { 3943 yyerror("icmp-type/code only applies to icmp"); 3944 problems++; 3945 } 3946 if (!r->af && (r->type || r->code)) { 3947 yyerror("must indicate address family with icmp-type/code"); 3948 problems++; 3949 } 3950 if (r->rule_flag & PFRULE_AFTO && r->af == r->naf) { 3951 yyerror("must indicate different address family with af-to"); 3952 problems++; 3953 } 3954 if (r->overload_tblname[0] && 3955 r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) { 3956 yyerror("'overload' requires 'max-src-conn' " 3957 "or 'max-src-conn-rate'"); 3958 problems++; 3959 } 3960 if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) || 3961 (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) { 3962 yyerror("proto %s doesn't match address family %s", 3963 r->proto == IPPROTO_ICMP ? "icmp" : "icmp6", 3964 r->af == AF_INET ? "inet" : "inet6"); 3965 problems++; 3966 } 3967 if (r->allow_opts && r->action != PF_PASS) { 3968 yyerror("allow-opts can only be specified for pass rules"); 3969 problems++; 3970 } 3971 if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op || 3972 r->dst.port_op || r->flagset || r->type || r->code)) { 3973 yyerror("fragments can be filtered only on IP header fields"); 3974 problems++; 3975 } 3976 if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) { 3977 yyerror("return-rst can only be applied to TCP rules"); 3978 problems++; 3979 } 3980 if (r->max_src_nodes && !(r->rule_flag & PFRULE_RULESRCTRACK)) { 3981 yyerror("max-src-nodes requires 'source-track rule'"); 3982 problems++; 3983 } 3984 if (r->action != PF_PASS && r->keep_state) { 3985 yyerror("keep state is great, but only for pass rules"); 3986 problems++; 3987 } 3988 if (r->rule_flag & PFRULE_STATESLOPPY && 3989 (r->keep_state == PF_STATE_MODULATE || 3990 r->keep_state == PF_STATE_SYNPROXY)) { 3991 yyerror("sloppy state matching cannot be used with " 3992 "synproxy state or modulate state"); 3993 problems++; 3994 } 3995 if ((r->nat.addr.type != PF_ADDR_NONE || 3996 r->rdr.addr.type != PF_ADDR_NONE) && 3997 r->action != PF_MATCH && !r->keep_state) { 3998 yyerror("nat-to and rdr-to require keep state"); 3999 problems++; 4000 } 4001 if (r->direction == PF_INOUT && (r->nat.addr.type != PF_ADDR_NONE || 4002 r->rdr.addr.type != PF_ADDR_NONE)) { 4003 yyerror("nat-to and rdr-to require a direction"); 4004 problems++; 4005 } 4006 if (r->af == AF_INET6 && (r->scrub_flags & 4007 (PFSTATE_NODF|PFSTATE_RANDOMID))) { 4008 yyerror("address family inet6 does not support scrub options " 4009 "no-df, random-id"); 4010 problems++; 4011 } 4012 4013 /* Basic rule sanity check. */ 4014 switch (r->action) { 4015 case PF_MATCH: 4016 if (r->divert.port) { 4017 yyerror("divert is not supported on match rules"); 4018 problems++; 4019 } 4020 if (r->divert_packet.port) { 4021 yyerror("divert is not supported on match rules"); 4022 problems++; 4023 } 4024 if (r->rt) { 4025 yyerror("route-to, reply-to and dup-to " 4026 "are not supported on match rules"); 4027 problems++; 4028 } 4029 if (r->rule_flag & PFRULE_AFTO) { 4030 yyerror("af-to is not supported on match rules"); 4031 problems++; 4032 } 4033 break; 4034 case PF_DROP: 4035 if (r->rt) { 4036 yyerror("route-to, reply-to and dup-to " 4037 "are not supported on block rules"); 4038 problems++; 4039 } 4040 break; 4041 default:; 4042 } 4043 return (-problems); 4044 } 4045 4046 int 4047 process_tabledef(char *name, struct table_opts *opts) 4048 { 4049 struct pfr_buffer ab; 4050 struct node_tinit *ti; 4051 4052 bzero(&ab, sizeof(ab)); 4053 ab.pfrb_type = PFRB_ADDRS; 4054 SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) { 4055 if (ti->file) 4056 if (pfr_buf_load(&ab, ti->file, 0)) { 4057 if (errno) 4058 yyerror("cannot load \"%s\": %s", 4059 ti->file, strerror(errno)); 4060 else 4061 yyerror("file \"%s\" contains bad data", 4062 ti->file); 4063 goto _error; 4064 } 4065 if (ti->host) 4066 if (append_addr_host(&ab, ti->host, 0, 0)) { 4067 yyerror("cannot create address buffer: %s", 4068 strerror(errno)); 4069 goto _error; 4070 } 4071 } 4072 if (pf->opts & PF_OPT_VERBOSE) 4073 print_tabledef(name, opts->flags, opts->init_addr, 4074 &opts->init_nodes); 4075 if (!(pf->opts & PF_OPT_NOACTION) && 4076 pfctl_define_table(name, opts->flags, opts->init_addr, 4077 pf->anchor->name, &ab, pf->anchor->ruleset.tticket)) { 4078 yyerror("cannot define table %s: %s", name, 4079 pfr_strerror(errno)); 4080 goto _error; 4081 } 4082 pf->tdirty = 1; 4083 pfr_buf_clear(&ab); 4084 return (0); 4085 _error: 4086 pfr_buf_clear(&ab); 4087 return (-1); 4088 } 4089 4090 struct keywords { 4091 const char *k_name; 4092 int k_val; 4093 }; 4094 4095 /* macro gore, but you should've seen the prior indentation nightmare... */ 4096 4097 #define FREE_LIST(T,r) \ 4098 do { \ 4099 T *p, *node = r; \ 4100 while (node != NULL) { \ 4101 p = node; \ 4102 node = node->next; \ 4103 free(p); \ 4104 } \ 4105 } while (0) 4106 4107 #define LOOP_THROUGH(T,n,r,C) \ 4108 do { \ 4109 T *n; \ 4110 if (r == NULL) { \ 4111 r = calloc(1, sizeof(T)); \ 4112 if (r == NULL) \ 4113 err(1, "LOOP: calloc"); \ 4114 r->next = NULL; \ 4115 } \ 4116 n = r; \ 4117 while (n != NULL) { \ 4118 do { \ 4119 C; \ 4120 } while (0); \ 4121 n = n->next; \ 4122 } \ 4123 } while (0) 4124 4125 void 4126 expand_label_str(char *label, size_t len, const char *srch, const char *repl) 4127 { 4128 char *tmp; 4129 char *p, *q; 4130 4131 if ((tmp = calloc(1, len)) == NULL) 4132 err(1, "expand_label_str: calloc"); 4133 p = q = label; 4134 while ((q = strstr(p, srch)) != NULL) { 4135 *q = '\0'; 4136 if ((strlcat(tmp, p, len) >= len) || 4137 (strlcat(tmp, repl, len) >= len)) 4138 errx(1, "expand_label: label too long"); 4139 q += strlen(srch); 4140 p = q; 4141 } 4142 if (strlcat(tmp, p, len) >= len) 4143 errx(1, "expand_label: label too long"); 4144 strlcpy(label, tmp, len); /* always fits */ 4145 free(tmp); 4146 } 4147 4148 void 4149 expand_label_if(const char *name, char *label, size_t len, const char *ifname) 4150 { 4151 if (strstr(label, name) != NULL) { 4152 if (!*ifname) 4153 expand_label_str(label, len, name, "any"); 4154 else 4155 expand_label_str(label, len, name, ifname); 4156 } 4157 } 4158 4159 void 4160 expand_label_addr(const char *name, char *label, size_t len, sa_family_t af, 4161 struct node_host *h) 4162 { 4163 char tmp[64], tmp_not[66]; 4164 4165 if (strstr(label, name) != NULL) { 4166 switch (h->addr.type) { 4167 case PF_ADDR_DYNIFTL: 4168 snprintf(tmp, sizeof(tmp), "(%s)", h->addr.v.ifname); 4169 break; 4170 case PF_ADDR_TABLE: 4171 snprintf(tmp, sizeof(tmp), "<%s>", h->addr.v.tblname); 4172 break; 4173 case PF_ADDR_NOROUTE: 4174 snprintf(tmp, sizeof(tmp), "no-route"); 4175 break; 4176 case PF_ADDR_URPFFAILED: 4177 snprintf(tmp, sizeof(tmp), "urpf-failed"); 4178 break; 4179 case PF_ADDR_ADDRMASK: 4180 if (!af || (PF_AZERO(&h->addr.v.a.addr, af) && 4181 PF_AZERO(&h->addr.v.a.mask, af))) 4182 snprintf(tmp, sizeof(tmp), "any"); 4183 else { 4184 char a[48]; 4185 int bits; 4186 4187 if (inet_ntop(af, &h->addr.v.a.addr, a, 4188 sizeof(a)) == NULL) 4189 snprintf(tmp, sizeof(tmp), "?"); 4190 else { 4191 bits = unmask(&h->addr.v.a.mask, af); 4192 if ((af == AF_INET && bits < 32) || 4193 (af == AF_INET6 && bits < 128)) 4194 snprintf(tmp, sizeof(tmp), 4195 "%s/%d", a, bits); 4196 else 4197 snprintf(tmp, sizeof(tmp), 4198 "%s", a); 4199 } 4200 } 4201 break; 4202 default: 4203 snprintf(tmp, sizeof(tmp), "?"); 4204 break; 4205 } 4206 4207 if (h->not) { 4208 snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp); 4209 expand_label_str(label, len, name, tmp_not); 4210 } else 4211 expand_label_str(label, len, name, tmp); 4212 } 4213 } 4214 4215 void 4216 expand_label_port(const char *name, char *label, size_t len, 4217 struct node_port *port) 4218 { 4219 char a1[6], a2[6], op[13] = ""; 4220 4221 if (strstr(label, name) != NULL) { 4222 snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0])); 4223 snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1])); 4224 if (!port->op) 4225 ; 4226 else if (port->op == PF_OP_IRG) 4227 snprintf(op, sizeof(op), "%s><%s", a1, a2); 4228 else if (port->op == PF_OP_XRG) 4229 snprintf(op, sizeof(op), "%s<>%s", a1, a2); 4230 else if (port->op == PF_OP_EQ) 4231 snprintf(op, sizeof(op), "%s", a1); 4232 else if (port->op == PF_OP_NE) 4233 snprintf(op, sizeof(op), "!=%s", a1); 4234 else if (port->op == PF_OP_LT) 4235 snprintf(op, sizeof(op), "<%s", a1); 4236 else if (port->op == PF_OP_LE) 4237 snprintf(op, sizeof(op), "<=%s", a1); 4238 else if (port->op == PF_OP_GT) 4239 snprintf(op, sizeof(op), ">%s", a1); 4240 else if (port->op == PF_OP_GE) 4241 snprintf(op, sizeof(op), ">=%s", a1); 4242 expand_label_str(label, len, name, op); 4243 } 4244 } 4245 4246 void 4247 expand_label_proto(const char *name, char *label, size_t len, u_int8_t proto) 4248 { 4249 struct protoent *pe; 4250 char n[4]; 4251 4252 if (strstr(label, name) != NULL) { 4253 pe = getprotobynumber(proto); 4254 if (pe != NULL) 4255 expand_label_str(label, len, name, pe->p_name); 4256 else { 4257 snprintf(n, sizeof(n), "%u", proto); 4258 expand_label_str(label, len, name, n); 4259 } 4260 } 4261 } 4262 4263 void 4264 expand_label_nr(const char *name, char *label, size_t len) 4265 { 4266 char n[11]; 4267 4268 if (strstr(label, name) != NULL) { 4269 snprintf(n, sizeof(n), "%u", pf->anchor->match); 4270 expand_label_str(label, len, name, n); 4271 } 4272 } 4273 4274 void 4275 expand_label(char *label, size_t len, const char *ifname, sa_family_t af, 4276 struct node_host *src_host, struct node_port *src_port, 4277 struct node_host *dst_host, struct node_port *dst_port, 4278 u_int8_t proto) 4279 { 4280 expand_label_if("$if", label, len, ifname); 4281 expand_label_addr("$srcaddr", label, len, af, src_host); 4282 expand_label_addr("$dstaddr", label, len, af, dst_host); 4283 expand_label_port("$srcport", label, len, src_port); 4284 expand_label_port("$dstport", label, len, dst_port); 4285 expand_label_proto("$proto", label, len, proto); 4286 expand_label_nr("$nr", label, len); 4287 } 4288 4289 int 4290 expand_queue(char *qname, struct node_if *interfaces, struct queue_opts *opts) 4291 { 4292 struct pf_queuespec qspec; 4293 4294 LOOP_THROUGH(struct node_if, interface, interfaces, 4295 bzero(&qspec, sizeof(qspec)); 4296 if (strlcpy(qspec.qname, qname, sizeof(qspec.qname)) >= 4297 sizeof(qspec.qname)) { 4298 yyerror("queuename too long"); 4299 return (1); 4300 } 4301 if (opts->parent && strlcpy(qspec.parent, opts->parent, 4302 sizeof(qspec.parent)) >= sizeof(qspec.parent)) { 4303 yyerror("parent too long"); 4304 return (1); 4305 } 4306 if (strlcpy(qspec.ifname, interface->ifname, 4307 sizeof(qspec.ifname)) >= sizeof(qspec.ifname)) { 4308 yyerror("interface too long"); 4309 return (1); 4310 } 4311 qspec.realtime.m1.absolute = opts->realtime.m1.bw_absolute; 4312 qspec.realtime.m1.percent = opts->realtime.m1.bw_percent; 4313 qspec.realtime.m2.absolute = opts->realtime.m2.bw_absolute; 4314 qspec.realtime.m2.percent = opts->realtime.m2.bw_percent; 4315 qspec.realtime.d = opts->realtime.d; 4316 4317 qspec.linkshare.m1.absolute = opts->linkshare.m1.bw_absolute; 4318 qspec.linkshare.m1.percent = opts->linkshare.m1.bw_percent; 4319 qspec.linkshare.m2.absolute = opts->linkshare.m2.bw_absolute; 4320 qspec.linkshare.m2.percent = opts->linkshare.m2.bw_percent; 4321 qspec.linkshare.d = opts->linkshare.d; 4322 4323 qspec.upperlimit.m1.absolute = opts->upperlimit.m1.bw_absolute; 4324 qspec.upperlimit.m1.percent = opts->upperlimit.m1.bw_percent; 4325 qspec.upperlimit.m2.absolute = opts->upperlimit.m2.bw_absolute; 4326 qspec.upperlimit.m2.percent = opts->upperlimit.m2.bw_percent; 4327 qspec.upperlimit.d = opts->upperlimit.d; 4328 4329 qspec.flags = opts->flags; 4330 qspec.qlimit = opts->qlimit; 4331 4332 if (pfctl_add_queue(pf, &qspec)) { 4333 yyerror("cannot add queue"); 4334 return (1); 4335 } 4336 ); 4337 4338 FREE_LIST(struct node_if, interfaces); 4339 return (0); 4340 } 4341 4342 int 4343 expand_divertspec(struct pf_rule *r, struct divertspec *ds) 4344 { 4345 struct node_host *n; 4346 4347 if (ds->port == 0) 4348 return (0); 4349 4350 r->divert.port = ds->port; 4351 4352 if (r->direction == PF_OUT) { 4353 if (ds->addr) { 4354 yyerror("address specified for outgoing divert"); 4355 return (1); 4356 } 4357 bzero(&r->divert.addr, sizeof(r->divert.addr)); 4358 return (0); 4359 } 4360 4361 if (!ds->addr) { 4362 yyerror("no address specified for incoming divert"); 4363 return (1); 4364 } 4365 if (r->af) { 4366 n = ds->addr; 4367 for (n = ds->addr; n != NULL; n = n->next) 4368 if (n->af == r->af) 4369 break; 4370 if (n == NULL) { 4371 yyerror("address family mismatch for divert"); 4372 return (1); 4373 } 4374 r->divert.addr = n->addr.v.a.addr; 4375 } else { 4376 r->af = ds->addr->af; 4377 r->divert.addr = ds->addr->addr.v.a.addr; 4378 } 4379 return (0); 4380 } 4381 4382 int 4383 collapse_redirspec(struct pf_pool *rpool, struct pf_rule *r, 4384 struct redirspec *rs, u_int8_t allow_if) 4385 { 4386 struct pf_opt_tbl *tbl = NULL; 4387 struct node_host *h, *hprev = NULL; 4388 struct pf_rule_addr ra; 4389 int af = 0, naddr = 0; 4390 4391 if (!rs || !rs->rdr || rs->rdr->host == NULL) { 4392 rpool->addr.type = PF_ADDR_NONE; 4393 return (0); 4394 } 4395 4396 if (r->rule_flag & PFRULE_AFTO) 4397 r->naf = rs->af; 4398 4399 for (h = rs->rdr->host; h != NULL; h = h->next) { 4400 /* set rule address family if redirect spec has one */ 4401 if (rs->af && !r->af && !af) { 4402 /* swap address families for af-to */ 4403 if (r->naf == AF_INET6) 4404 af = AF_INET; 4405 else if (r->naf == AF_INET) 4406 af = AF_INET6; 4407 else 4408 af = rs->af; 4409 } 4410 if (h->af && !r->naf) { /* nat-to/rdr-to case */ 4411 /* skip if the rule af doesn't match redirect af */ 4412 if (r->af && r->af != h->af) 4413 continue; 4414 /* 4415 * fail if the chosen af is not universal for 4416 * all addresses in the redirect address pool 4417 */ 4418 if (!r->af && af && af != h->af) { 4419 yyerror("%s spec contains addresses with " 4420 "different address families", 4421 allow_if ? "routing" : "translation"); 4422 return (1); 4423 } 4424 } else if (h->af) { /* af-to case */ 4425 /* 4426 * fail if the redirect spec af is not universal 4427 * for all addresses in the redirect address pool 4428 */ 4429 if (rs->af && rs->af != h->af) { 4430 yyerror("%s spec contains addresses that " 4431 "don't match target address family", 4432 allow_if ? "routing" : "translation"); 4433 return (1); 4434 } 4435 } 4436 /* else if (!h->af): 4437 * we silently allow any not af-specific host specs, 4438 * e.g. (em0) and let the kernel deal with them 4439 */ 4440 4441 /* if we haven't selected the rule af yet, now it's time */ 4442 if (!r->af && !af) 4443 af = h->af; 4444 4445 if (naddr == 0) { /* the first host */ 4446 rpool->addr = h->addr; 4447 if (!allow_if && h->ifname) { 4448 yyerror("@if not permitted for translation"); 4449 return (1); 4450 } 4451 if (h->ifname && strlcpy(rpool->ifname, h->ifname, 4452 sizeof(rpool->ifname)) >= sizeof(rpool->ifname)) 4453 errx(1, "collapse_redirspec: strlcpy"); 4454 hprev = h; /* in case we need to conver to a table */ 4455 } else { /* multiple hosts */ 4456 if (rs->pool_opts.type && 4457 !PF_POOL_DYNTYPE(rs->pool_opts.type)) { 4458 yyerror("pool type is not valid for multiple " 4459 "translation or routing addresses"); 4460 return (1); 4461 } 4462 if ((hprev && hprev->addr.type != PF_ADDR_ADDRMASK) && 4463 (hprev && hprev->addr.type != PF_ADDR_NONE) && 4464 h->addr.type != PF_ADDR_ADDRMASK && 4465 h->addr.type != PF_ADDR_NONE) { 4466 yyerror("multiple tables or dynamic interfaces " 4467 "not supported for translation or routing"); 4468 return (1); 4469 } 4470 if (!allow_if && h->ifname) { 4471 yyerror("@if not permitted for translation"); 4472 return (1); 4473 } 4474 if (hprev) { 4475 /* 4476 * undo some damage and convert the single 4477 * host pool to the table 4478 */ 4479 memset(&ra, 0, sizeof(ra)); 4480 memset(rpool->ifname, 0, sizeof(rpool->ifname)); 4481 ra.addr = hprev->addr; 4482 ra.weight = hprev->weight; 4483 if (add_opt_table(pf, &tbl, 4484 hprev->af, &ra, hprev->ifname)) 4485 return (1); 4486 hprev = NULL; 4487 } 4488 memset(&ra, 0, sizeof(ra)); 4489 ra.addr = h->addr; 4490 ra.weight = h->weight; 4491 if (add_opt_table(pf, &tbl, 4492 h->af, &ra, h->ifname)) 4493 return (1); 4494 } 4495 naddr++; 4496 } 4497 /* set rule af to the one chosen above */ 4498 if (!r->af && af) 4499 r->af = af; 4500 if (!naddr) { 4501 yyerror("af mismatch in %s spec", 4502 allow_if ? "routing" : "translation"); 4503 return (1); 4504 } 4505 if (tbl) { 4506 if ((pf->opts & PF_OPT_NOACTION) == 0 && 4507 pf_opt_create_table(pf, tbl)) 4508 return (1); 4509 4510 pf->tdirty = 1; 4511 4512 if (pf->opts & PF_OPT_VERBOSE) 4513 print_tabledef(tbl->pt_name, 4514 PFR_TFLAG_CONST | tbl->pt_flags, 4515 1, &tbl->pt_nodes); 4516 4517 memset(&rpool->addr, 0, sizeof(rpool->addr)); 4518 rpool->addr.type = PF_ADDR_TABLE; 4519 strlcpy(rpool->addr.v.tblname, tbl->pt_name, 4520 sizeof(rpool->addr.v.tblname)); 4521 4522 pfr_buf_clear(tbl->pt_buf); 4523 free(tbl->pt_buf); 4524 tbl->pt_buf = NULL; 4525 free(tbl); 4526 } 4527 return (0); 4528 } 4529 4530 4531 int 4532 apply_redirspec(struct pf_pool *rpool, struct pf_rule *r, struct redirspec *rs, 4533 int isrdr, struct node_port *np) 4534 { 4535 if (!rs || !rs->rdr) 4536 return (0); 4537 4538 rpool->proxy_port[0] = ntohs(rs->rdr->rport.a); 4539 4540 if (isrdr) { 4541 if (!rs->rdr->rport.b && rs->rdr->rport.t && np->port != NULL) { 4542 rpool->proxy_port[1] = ntohs(rs->rdr->rport.a) + 4543 (ntohs(np->port[1]) - ntohs(np->port[0])); 4544 } else 4545 rpool->proxy_port[1] = ntohs(rs->rdr->rport.b); 4546 } else { 4547 rpool->proxy_port[1] = ntohs(rs->rdr->rport.b); 4548 if (!rpool->proxy_port[0] && !rpool->proxy_port[1]) { 4549 rpool->proxy_port[0] = PF_NAT_PROXY_PORT_LOW; 4550 rpool->proxy_port[1] = PF_NAT_PROXY_PORT_HIGH; 4551 } else if (!rpool->proxy_port[1]) 4552 rpool->proxy_port[1] = rpool->proxy_port[0]; 4553 } 4554 4555 rpool->opts = rs->pool_opts.type; 4556 if ((rpool->opts & PF_POOL_TYPEMASK) == PF_POOL_NONE && 4557 (rpool->addr.type == PF_ADDR_TABLE || 4558 DYNIF_MULTIADDR(rpool->addr))) 4559 rpool->opts |= PF_POOL_ROUNDROBIN; 4560 4561 if (!PF_POOL_DYNTYPE(rpool->opts) && 4562 (disallow_table(rs->rdr->host, 4563 "tables are not supported by pool type") || 4564 disallow_alias(rs->rdr->host, 4565 "interface (%s) is not supported by pool type"))) 4566 return (1); 4567 4568 if (rs->pool_opts.key != NULL) 4569 memcpy(&rpool->key, rs->pool_opts.key, 4570 sizeof(struct pf_poolhashkey)); 4571 4572 if (rs->pool_opts.opts) 4573 rpool->opts |= rs->pool_opts.opts; 4574 4575 if (rs->pool_opts.staticport) { 4576 if (isrdr) { 4577 yyerror("the 'static-port' option is only valid with " 4578 "nat rules"); 4579 return (1); 4580 } 4581 if (rpool->proxy_port[0] != PF_NAT_PROXY_PORT_LOW && 4582 rpool->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) { 4583 yyerror("the 'static-port' option can't be used when " 4584 "specifying a port range"); 4585 return (1); 4586 } 4587 rpool->proxy_port[0] = 0; 4588 rpool->proxy_port[1] = 0; 4589 } 4590 4591 return (0); 4592 } 4593 4594 4595 void 4596 expand_rule(struct pf_rule *r, int keeprule, struct node_if *interfaces, 4597 struct redirspec *nat, struct redirspec *rdr, struct redirspec *rroute, 4598 struct node_proto *protos, struct node_os *src_oses, 4599 struct node_host *src_hosts, struct node_port *src_ports, 4600 struct node_host *dst_hosts, struct node_port *dst_ports, 4601 struct node_uid *uids, struct node_gid *gids, struct node_if *rcv, 4602 struct node_icmp *icmp_types, const char *anchor_call) 4603 { 4604 sa_family_t af = r->af; 4605 int added = 0, error = 0; 4606 char ifname[IF_NAMESIZE]; 4607 char label[PF_RULE_LABEL_SIZE]; 4608 char tagname[PF_TAG_NAME_SIZE]; 4609 char match_tagname[PF_TAG_NAME_SIZE]; 4610 u_int8_t flags, flagset, keep_state; 4611 struct node_host *srch, *dsth, *osrch, *odsth; 4612 struct redirspec binat; 4613 struct pf_rule rb; 4614 int dir = r->direction; 4615 4616 if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label)) 4617 errx(1, "expand_rule: strlcpy"); 4618 if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname)) 4619 errx(1, "expand_rule: strlcpy"); 4620 if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >= 4621 sizeof(match_tagname)) 4622 errx(1, "expand_rule: strlcpy"); 4623 flags = r->flags; 4624 flagset = r->flagset; 4625 keep_state = r->keep_state; 4626 4627 r->src.addr.type = r->dst.addr.type = PF_ADDR_ADDRMASK; 4628 4629 LOOP_THROUGH(struct node_if, interface, interfaces, 4630 LOOP_THROUGH(struct node_proto, proto, protos, 4631 LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types, 4632 LOOP_THROUGH(struct node_host, src_host, src_hosts, 4633 LOOP_THROUGH(struct node_host, dst_host, dst_hosts, 4634 LOOP_THROUGH(struct node_port, src_port, src_ports, 4635 LOOP_THROUGH(struct node_port, dst_port, dst_ports, 4636 LOOP_THROUGH(struct node_os, src_os, src_oses, 4637 LOOP_THROUGH(struct node_uid, uid, uids, 4638 LOOP_THROUGH(struct node_gid, gid, gids, 4639 4640 r->af = af; 4641 4642 error += collapse_redirspec(&r->rdr, r, rdr, 0); 4643 error += collapse_redirspec(&r->nat, r, nat, 0); 4644 error += collapse_redirspec(&r->route, r, rroute, 1); 4645 4646 /* disallow @if in from or to for the time being */ 4647 if ((src_host->addr.type == PF_ADDR_ADDRMASK && 4648 src_host->ifname) || 4649 (dst_host->addr.type == PF_ADDR_ADDRMASK && 4650 dst_host->ifname)) { 4651 yyerror("@if syntax not permitted in from or to"); 4652 error++; 4653 } 4654 /* for link-local IPv6 address, interface must match up */ 4655 if ((r->af && src_host->af && r->af != src_host->af) || 4656 (r->af && dst_host->af && r->af != dst_host->af) || 4657 (src_host->af && dst_host->af && 4658 src_host->af != dst_host->af) || 4659 (src_host->ifindex && dst_host->ifindex && 4660 src_host->ifindex != dst_host->ifindex) || 4661 (src_host->ifindex && *interface->ifname && 4662 src_host->ifindex != ifa_nametoindex(interface->ifname)) || 4663 (dst_host->ifindex && *interface->ifname && 4664 dst_host->ifindex != ifa_nametoindex(interface->ifname))) 4665 continue; 4666 if (!r->af && src_host->af) 4667 r->af = src_host->af; 4668 else if (!r->af && dst_host->af) 4669 r->af = dst_host->af; 4670 4671 if (*interface->ifname) 4672 strlcpy(r->ifname, interface->ifname, 4673 sizeof(r->ifname)); 4674 else if (ifa_indextoname(src_host->ifindex, ifname)) 4675 strlcpy(r->ifname, ifname, sizeof(r->ifname)); 4676 else if (ifa_indextoname(dst_host->ifindex, ifname)) 4677 strlcpy(r->ifname, ifname, sizeof(r->ifname)); 4678 else 4679 memset(r->ifname, '\0', sizeof(r->ifname)); 4680 4681 if (interface->use_rdomain) 4682 r->onrdomain = interface->rdomain; 4683 else 4684 r->onrdomain = -1; 4685 if (strlcpy(r->label, label, sizeof(r->label)) >= 4686 sizeof(r->label)) 4687 errx(1, "expand_rule: strlcpy"); 4688 if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >= 4689 sizeof(r->tagname)) 4690 errx(1, "expand_rule: strlcpy"); 4691 if (strlcpy(r->match_tagname, match_tagname, 4692 sizeof(r->match_tagname)) >= sizeof(r->match_tagname)) 4693 errx(1, "expand_rule: strlcpy"); 4694 expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af, 4695 src_host, src_port, dst_host, dst_port, proto->proto); 4696 expand_label(r->tagname, PF_TAG_NAME_SIZE, r->ifname, r->af, 4697 src_host, src_port, dst_host, dst_port, proto->proto); 4698 expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r->ifname, 4699 r->af, src_host, src_port, dst_host, dst_port, 4700 proto->proto); 4701 4702 osrch = odsth = NULL; 4703 if (src_host->addr.type == PF_ADDR_DYNIFTL) { 4704 osrch = src_host; 4705 if ((src_host = gen_dynnode(src_host, r->af)) == NULL) 4706 err(1, "expand_rule: calloc"); 4707 } 4708 if (dst_host->addr.type == PF_ADDR_DYNIFTL) { 4709 odsth = dst_host; 4710 if ((dst_host = gen_dynnode(dst_host, r->af)) == NULL) 4711 err(1, "expand_rule: calloc"); 4712 } 4713 4714 error += check_netmask(src_host, r->af); 4715 error += check_netmask(dst_host, r->af); 4716 4717 r->ifnot = interface->not; 4718 r->proto = proto->proto; 4719 r->src.addr = src_host->addr; 4720 r->src.neg = src_host->not; 4721 r->src.port[0] = src_port->port[0]; 4722 r->src.port[1] = src_port->port[1]; 4723 r->src.port_op = src_port->op; 4724 r->dst.addr = dst_host->addr; 4725 r->dst.neg = dst_host->not; 4726 r->dst.port[0] = dst_port->port[0]; 4727 r->dst.port[1] = dst_port->port[1]; 4728 r->dst.port_op = dst_port->op; 4729 r->uid.op = uid->op; 4730 r->uid.uid[0] = uid->uid[0]; 4731 r->uid.uid[1] = uid->uid[1]; 4732 r->gid.op = gid->op; 4733 r->gid.gid[0] = gid->gid[0]; 4734 r->gid.gid[1] = gid->gid[1]; 4735 if (rcv) { 4736 strlcpy(r->rcv_ifname, rcv->ifname, 4737 sizeof(r->rcv_ifname)); 4738 r->rcvifnot = rcv->not; 4739 } 4740 r->type = icmp_type->type; 4741 r->code = icmp_type->code; 4742 4743 if ((keep_state == PF_STATE_MODULATE || 4744 keep_state == PF_STATE_SYNPROXY) && 4745 r->proto && r->proto != IPPROTO_TCP) 4746 r->keep_state = PF_STATE_NORMAL; 4747 else 4748 r->keep_state = keep_state; 4749 4750 if (r->proto && r->proto != IPPROTO_TCP) { 4751 r->flags = 0; 4752 r->flagset = 0; 4753 } else { 4754 r->flags = flags; 4755 r->flagset = flagset; 4756 } 4757 if (icmp_type->proto && r->proto != icmp_type->proto) { 4758 yyerror("icmp-type mismatch"); 4759 error++; 4760 } 4761 4762 if (src_os && src_os->os) { 4763 r->os_fingerprint = pfctl_get_fingerprint(src_os->os); 4764 if ((pf->opts & PF_OPT_VERBOSE2) && 4765 r->os_fingerprint == PF_OSFP_NOMATCH) 4766 fprintf(stderr, 4767 "warning: unknown '%s' OS fingerprint\n", 4768 src_os->os); 4769 } else { 4770 r->os_fingerprint = PF_OSFP_ANY; 4771 } 4772 4773 if (nat && nat->rdr && nat->binat) { 4774 if (disallow_table(src_host, "invalid use of table " 4775 "<%s> as the source address of a binat-to rule") || 4776 disallow_alias(src_host, "invalid use of interface " 4777 "(%s) as the source address of a binat-to rule")) { 4778 error++; 4779 } else if ((r->src.addr.type != PF_ADDR_ADDRMASK && 4780 r->src.addr.type != PF_ADDR_DYNIFTL) || 4781 (r->nat.addr.type != PF_ADDR_ADDRMASK && 4782 r->nat.addr.type != PF_ADDR_DYNIFTL)) { 4783 yyerror("binat-to requires a specified " 4784 "source and redirect address"); 4785 error++; 4786 } 4787 if (DYNIF_MULTIADDR(r->src.addr) || 4788 DYNIF_MULTIADDR(r->nat.addr)) { 4789 yyerror ("dynamic interfaces must be used with " 4790 ":0 in a binat-to rule"); 4791 error++; 4792 } 4793 if (PF_AZERO(&r->src.addr.v.a.mask, af) || 4794 PF_AZERO(&r->nat.addr.v.a.mask, af)) { 4795 yyerror ("source and redir addresess must have " 4796 "a matching network mask in binat-rule"); 4797 error++; 4798 } 4799 if (r->nat.addr.type == PF_ADDR_TABLE) { 4800 yyerror ("tables cannot be used as the redirect " 4801 "address of a binat-to rule"); 4802 error++; 4803 } 4804 if (r->direction != PF_INOUT) { 4805 yyerror("binat-to cannot be specified " 4806 "with a direction"); 4807 error++; 4808 } 4809 4810 /* first specify outbound NAT rule */ 4811 r->direction = PF_OUT; 4812 } 4813 4814 error += apply_redirspec(&r->nat, r, nat, 0, dst_port); 4815 error += apply_redirspec(&r->rdr, r, rdr, 1, dst_port); 4816 error += apply_redirspec(&r->route, r, rroute, 2, dst_port); 4817 4818 if (rule_consistent(r, anchor_call[0]) < 0 || error) 4819 yyerror("skipping rule due to errors"); 4820 else { 4821 r->nr = pf->astack[pf->asd]->match++; 4822 pfctl_add_rule(pf, r, anchor_call); 4823 added++; 4824 } 4825 r->direction = dir; 4826 4827 /* Generate binat's matching inbound rule */ 4828 if (!error && nat && nat->rdr && nat->binat) { 4829 bcopy(r, &rb, sizeof(rb)); 4830 4831 /* now specify inbound rdr rule */ 4832 rb.direction = PF_IN; 4833 4834 if ((srch = calloc(1, sizeof(*srch))) == NULL) 4835 err(1, "expand_rule: calloc"); 4836 bcopy(src_host, srch, sizeof(*srch)); 4837 srch->ifname = NULL; 4838 srch->next = NULL; 4839 srch->tail = NULL; 4840 4841 if ((dsth = calloc(1, sizeof(*dsth))) == NULL) 4842 err(1, "expand_rule: calloc"); 4843 bcopy(&rb.nat.addr, &dsth->addr, sizeof(dsth->addr)); 4844 dsth->ifname = NULL; 4845 dsth->next = NULL; 4846 dsth->tail = NULL; 4847 4848 bzero(&binat, sizeof(binat)); 4849 if ((binat.rdr = 4850 calloc(1, sizeof(*binat.rdr))) == NULL) 4851 err(1, "expand_rule: calloc"); 4852 bcopy(nat->rdr, binat.rdr, sizeof(*binat.rdr)); 4853 bcopy(&nat->pool_opts, &binat.pool_opts, 4854 sizeof(binat.pool_opts)); 4855 binat.pool_opts.staticport = 0; 4856 binat.rdr->host = srch; 4857 4858 expand_rule(&rb, 1, interface, NULL, &binat, NULL, 4859 proto, 4860 src_os, dst_host, dst_port, dsth, src_port, 4861 uid, gid, rcv, icmp_type, anchor_call); 4862 } 4863 4864 if (osrch && src_host->addr.type == PF_ADDR_DYNIFTL) { 4865 free(src_host); 4866 src_host = osrch; 4867 } 4868 if (odsth && dst_host->addr.type == PF_ADDR_DYNIFTL) { 4869 free(dst_host); 4870 dst_host = odsth; 4871 } 4872 )))))))))); 4873 4874 if (!keeprule) { 4875 FREE_LIST(struct node_if, interfaces); 4876 FREE_LIST(struct node_proto, protos); 4877 FREE_LIST(struct node_host, src_hosts); 4878 FREE_LIST(struct node_port, src_ports); 4879 FREE_LIST(struct node_os, src_oses); 4880 FREE_LIST(struct node_host, dst_hosts); 4881 FREE_LIST(struct node_port, dst_ports); 4882 FREE_LIST(struct node_uid, uids); 4883 FREE_LIST(struct node_gid, gids); 4884 FREE_LIST(struct node_icmp, icmp_types); 4885 if (nat && nat->rdr) 4886 FREE_LIST(struct node_host, nat->rdr->host); 4887 if (rdr && rdr->rdr) 4888 FREE_LIST(struct node_host, rdr->rdr->host); 4889 4890 } 4891 4892 if (!added) 4893 yyerror("rule expands to no valid combination"); 4894 } 4895 4896 int 4897 expand_skip_interface(struct node_if *interfaces) 4898 { 4899 int errs = 0; 4900 4901 if (!interfaces || (!interfaces->next && !interfaces->not && 4902 !strcmp(interfaces->ifname, "none"))) { 4903 if (pf->opts & PF_OPT_VERBOSE) 4904 printf("set skip on none\n"); 4905 errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0); 4906 return (errs); 4907 } 4908 4909 if (pf->opts & PF_OPT_VERBOSE) 4910 printf("set skip on {"); 4911 LOOP_THROUGH(struct node_if, interface, interfaces, 4912 if (pf->opts & PF_OPT_VERBOSE) 4913 printf(" %s", interface->ifname); 4914 if (interface->not) { 4915 yyerror("skip on ! <interface> is not supported"); 4916 errs++; 4917 } else if (interface->use_rdomain) { 4918 yyerror("skip on rdomain <num> is not supported"); 4919 errs++; 4920 } else 4921 errs += pfctl_set_interface_flags(pf, 4922 interface->ifname, PFI_IFLAG_SKIP, 1); 4923 ); 4924 if (pf->opts & PF_OPT_VERBOSE) 4925 printf(" }\n"); 4926 4927 FREE_LIST(struct node_if, interfaces); 4928 4929 if (errs) 4930 return (1); 4931 else 4932 return (0); 4933 } 4934 4935 void 4936 freehostlist(struct node_host *h) 4937 { 4938 struct node_host *n; 4939 4940 for (n = h; n != NULL; n = n->next) 4941 if (n->ifname) 4942 free(n->ifname); 4943 FREE_LIST(struct node_host, h); 4944 } 4945 4946 #undef FREE_LIST 4947 #undef LOOP_THROUGH 4948 4949 int 4950 kw_cmp(const void *k, const void *e) 4951 { 4952 return (strcmp(k, ((const struct keywords *)e)->k_name)); 4953 } 4954 4955 int 4956 lookup(char *s) 4957 { 4958 /* this has to be sorted always */ 4959 static const struct keywords keywords[] = { 4960 { "af-to", AFTO}, 4961 { "all", ALL}, 4962 { "allow-opts", ALLOWOPTS}, 4963 { "anchor", ANCHOR}, 4964 { "antispoof", ANTISPOOF}, 4965 { "any", ANY}, 4966 { "bandwidth", BANDWIDTH}, 4967 { "binat-to", BINATTO}, 4968 { "bitmask", BITMASK}, 4969 { "block", BLOCK}, 4970 { "block-policy", BLOCKPOLICY}, 4971 { "burst", BURST}, 4972 { "code", CODE}, 4973 { "debug", DEBUG}, 4974 { "default", DEFAULT}, 4975 { "divert-packet", DIVERTPACKET}, 4976 { "divert-reply", DIVERTREPLY}, 4977 { "divert-to", DIVERTTO}, 4978 { "drop", DROP}, 4979 { "dup-to", DUPTO}, 4980 { "file", FILENAME}, 4981 { "fingerprints", FINGERPRINTS}, 4982 { "flags", FLAGS}, 4983 { "floating", FLOATING}, 4984 { "flush", FLUSH}, 4985 { "for", FOR}, 4986 { "fragment", FRAGMENT}, 4987 { "from", FROM}, 4988 { "global", GLOBAL}, 4989 { "group", GROUP}, 4990 { "hostid", HOSTID}, 4991 { "icmp-type", ICMPTYPE}, 4992 { "icmp6-type", ICMP6TYPE}, 4993 { "if-bound", IFBOUND}, 4994 { "in", IN}, 4995 { "include", INCLUDE}, 4996 { "inet", INET}, 4997 { "inet6", INET6}, 4998 { "keep", KEEP}, 4999 { "label", LABEL}, 5000 { "least-states", LEASTSTATES}, 5001 { "limit", LIMIT}, 5002 { "load", LOAD}, 5003 { "log", LOG}, 5004 { "loginterface", LOGINTERFACE}, 5005 { "match", MATCH}, 5006 { "matches", MATCHES}, 5007 { "max", MAXIMUM}, 5008 { "max-mss", MAXMSS}, 5009 { "max-src-conn", MAXSRCCONN}, 5010 { "max-src-conn-rate", MAXSRCCONNRATE}, 5011 { "max-src-nodes", MAXSRCNODES}, 5012 { "max-src-states", MAXSRCSTATES}, 5013 { "min", MINIMUM}, 5014 { "min-ttl", MINTTL}, 5015 { "modulate", MODULATE}, 5016 { "nat-to", NATTO}, 5017 { "no", NO}, 5018 { "no-df", NODF}, 5019 { "no-route", NOROUTE}, 5020 { "no-sync", NOSYNC}, 5021 { "on", ON}, 5022 { "once", ONCE}, 5023 { "optimization", OPTIMIZATION}, 5024 { "os", OS}, 5025 { "out", OUT}, 5026 { "overload", OVERLOAD}, 5027 { "parent", PARENT}, 5028 { "pass", PASS}, 5029 { "pflow", PFLOW}, 5030 { "port", PORT}, 5031 { "prio", PRIO}, 5032 { "probability", PROBABILITY}, 5033 { "proto", PROTO}, 5034 { "qlimit", QLIMIT}, 5035 { "queue", QUEUE}, 5036 { "quick", QUICK}, 5037 { "random", RANDOM}, 5038 { "random-id", RANDOMID}, 5039 { "rdomain", RDOMAIN}, 5040 { "rdr-to", RDRTO}, 5041 { "reassemble", REASSEMBLE}, 5042 { "received-on", RECEIVEDON}, 5043 { "reply-to", REPLYTO}, 5044 { "return", RETURN}, 5045 { "return-icmp", RETURNICMP}, 5046 { "return-icmp6", RETURNICMP6}, 5047 { "return-rst", RETURNRST}, 5048 { "round-robin", ROUNDROBIN}, 5049 { "route", ROUTE}, 5050 { "route-to", ROUTETO}, 5051 { "rtable", RTABLE}, 5052 { "rule", RULE}, 5053 { "ruleset-optimization", RULESET_OPTIMIZATION}, 5054 { "scrub", SCRUB}, 5055 { "set", SET}, 5056 { "skip", SKIP}, 5057 { "sloppy", SLOPPY}, 5058 { "source-hash", SOURCEHASH}, 5059 { "source-track", SOURCETRACK}, 5060 { "state", STATE}, 5061 { "state-defaults", STATEDEFAULTS}, 5062 { "state-policy", STATEPOLICY}, 5063 { "static-port", STATICPORT}, 5064 { "sticky-address", STICKYADDRESS}, 5065 { "synproxy", SYNPROXY}, 5066 { "table", TABLE}, 5067 { "tag", TAG}, 5068 { "tagged", TAGGED}, 5069 { "timeout", TIMEOUT}, 5070 { "to", TO}, 5071 { "tos", TOS}, 5072 { "ttl", TTL}, 5073 { "urpf-failed", URPFFAILED}, 5074 { "user", USER}, 5075 { "weight", WEIGHT}, 5076 }; 5077 const struct keywords *p; 5078 5079 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 5080 sizeof(keywords[0]), kw_cmp); 5081 5082 if (p) { 5083 if (debug > 1) 5084 fprintf(stderr, "%s: %d\n", s, p->k_val); 5085 return (p->k_val); 5086 } else { 5087 if (debug > 1) 5088 fprintf(stderr, "string: %s\n", s); 5089 return (STRING); 5090 } 5091 } 5092 5093 #define MAXPUSHBACK 128 5094 5095 u_char *parsebuf; 5096 int parseindex; 5097 u_char pushback_buffer[MAXPUSHBACK]; 5098 int pushback_index = 0; 5099 5100 int 5101 lgetc(int quotec) 5102 { 5103 int c, next; 5104 5105 if (parsebuf) { 5106 /* Read character from the parsebuffer instead of input. */ 5107 if (parseindex >= 0) { 5108 c = parsebuf[parseindex++]; 5109 if (c != '\0') 5110 return (c); 5111 parsebuf = NULL; 5112 } else 5113 parseindex++; 5114 } 5115 5116 if (pushback_index) 5117 return (pushback_buffer[--pushback_index]); 5118 5119 if (quotec) { 5120 if ((c = getc(file->stream)) == EOF) { 5121 yyerror("reached end of file while parsing quoted string"); 5122 if (popfile() == EOF) 5123 return (EOF); 5124 return (quotec); 5125 } 5126 return (c); 5127 } 5128 5129 while ((c = getc(file->stream)) == '\\') { 5130 next = getc(file->stream); 5131 if (next != '\n') { 5132 c = next; 5133 break; 5134 } 5135 yylval.lineno = file->lineno; 5136 file->lineno++; 5137 } 5138 5139 while (c == EOF) { 5140 if (popfile() == EOF) 5141 return (EOF); 5142 c = getc(file->stream); 5143 } 5144 return (c); 5145 } 5146 5147 int 5148 lungetc(int c) 5149 { 5150 if (c == EOF) 5151 return (EOF); 5152 if (parsebuf) { 5153 parseindex--; 5154 if (parseindex >= 0) 5155 return (c); 5156 } 5157 if (pushback_index < MAXPUSHBACK-1) 5158 return (pushback_buffer[pushback_index++] = c); 5159 else 5160 return (EOF); 5161 } 5162 5163 int 5164 findeol(void) 5165 { 5166 int c; 5167 5168 parsebuf = NULL; 5169 5170 /* skip to either EOF or the first real EOL */ 5171 while (1) { 5172 if (pushback_index) 5173 c = pushback_buffer[--pushback_index]; 5174 else 5175 c = lgetc(0); 5176 if (c == '\n') { 5177 file->lineno++; 5178 break; 5179 } 5180 if (c == EOF) 5181 break; 5182 } 5183 return (ERROR); 5184 } 5185 5186 int 5187 yylex(void) 5188 { 5189 u_char buf[8096]; 5190 u_char *p, *val; 5191 int quotec, next, c; 5192 int token; 5193 5194 top: 5195 p = buf; 5196 while ((c = lgetc(0)) == ' ' || c == '\t') 5197 ; /* nothing */ 5198 5199 yylval.lineno = file->lineno; 5200 if (c == '#') 5201 while ((c = lgetc(0)) != '\n' && c != EOF) 5202 ; /* nothing */ 5203 if (c == '$' && parsebuf == NULL) { 5204 while (1) { 5205 if ((c = lgetc(0)) == EOF) 5206 return (0); 5207 5208 if (p + 1 >= buf + sizeof(buf) - 1) { 5209 yyerror("string too long"); 5210 return (findeol()); 5211 } 5212 if (isalnum(c) || c == '_') { 5213 *p++ = c; 5214 continue; 5215 } 5216 *p = '\0'; 5217 lungetc(c); 5218 break; 5219 } 5220 val = symget(buf); 5221 if (val == NULL) { 5222 yyerror("macro '%s' not defined", buf); 5223 return (findeol()); 5224 } 5225 parsebuf = val; 5226 parseindex = 0; 5227 goto top; 5228 } 5229 5230 switch (c) { 5231 case '\'': 5232 case '"': 5233 quotec = c; 5234 while (1) { 5235 if ((c = lgetc(quotec)) == EOF) 5236 return (0); 5237 if (c == '\n') { 5238 file->lineno++; 5239 continue; 5240 } else if (c == '\\') { 5241 if ((next = lgetc(quotec)) == EOF) 5242 return (0); 5243 if (next == quotec || c == ' ' || c == '\t') 5244 c = next; 5245 else if (next == '\n') { 5246 file->lineno++; 5247 continue; 5248 } else 5249 lungetc(next); 5250 } else if (c == quotec) { 5251 *p = '\0'; 5252 break; 5253 } else if (c == '\0') { 5254 yyerror("syntax error"); 5255 return (findeol()); 5256 } 5257 if (p + 1 >= buf + sizeof(buf) - 1) { 5258 yyerror("string too long"); 5259 return (findeol()); 5260 } 5261 *p++ = c; 5262 } 5263 yylval.v.string = strdup(buf); 5264 if (yylval.v.string == NULL) 5265 err(1, "yylex: strdup"); 5266 return (STRING); 5267 case '!': 5268 next = lgetc(0); 5269 if (next == '=') 5270 return (NE); 5271 lungetc(next); 5272 break; 5273 case '<': 5274 next = lgetc(0); 5275 if (next == '>') { 5276 yylval.v.i = PF_OP_XRG; 5277 return (PORTBINARY); 5278 } else if (next == '=') 5279 return (LE); 5280 lungetc(next); 5281 break; 5282 case '>': 5283 next = lgetc(0); 5284 if (next == '<') { 5285 yylval.v.i = PF_OP_IRG; 5286 return (PORTBINARY); 5287 } else if (next == '=') 5288 return (GE); 5289 lungetc(next); 5290 break; 5291 } 5292 5293 #define allowed_to_end_number(x) \ 5294 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') 5295 5296 if (c == '-' || isdigit(c)) { 5297 do { 5298 *p++ = c; 5299 if ((unsigned)(p-buf) >= sizeof(buf)) { 5300 yyerror("string too long"); 5301 return (findeol()); 5302 } 5303 } while ((c = lgetc(0)) != EOF && isdigit(c)); 5304 lungetc(c); 5305 if (p == buf + 1 && buf[0] == '-') 5306 goto nodigits; 5307 if (c == EOF || allowed_to_end_number(c)) { 5308 const char *errstr = NULL; 5309 5310 *p = '\0'; 5311 yylval.v.number = strtonum(buf, LLONG_MIN, 5312 LLONG_MAX, &errstr); 5313 if (errstr) { 5314 yyerror("\"%s\" invalid number: %s", 5315 buf, errstr); 5316 return (findeol()); 5317 } 5318 return (NUMBER); 5319 } else { 5320 nodigits: 5321 while (p > buf + 1) 5322 lungetc(*--p); 5323 c = *--p; 5324 if (c == '-') 5325 return (c); 5326 } 5327 } 5328 5329 #define allowed_in_string(x) \ 5330 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 5331 x != '{' && x != '}' && x != '<' && x != '>' && \ 5332 x != '!' && x != '=' && x != '/' && x != '#' && \ 5333 x != ',')) 5334 5335 if (isalnum(c) || c == ':' || c == '_') { 5336 do { 5337 *p++ = c; 5338 if ((unsigned)(p-buf) >= sizeof(buf)) { 5339 yyerror("string too long"); 5340 return (findeol()); 5341 } 5342 } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); 5343 lungetc(c); 5344 *p = '\0'; 5345 if ((token = lookup(buf)) == STRING) 5346 if ((yylval.v.string = strdup(buf)) == NULL) 5347 err(1, "yylex: strdup"); 5348 return (token); 5349 } 5350 if (c == '\n') { 5351 yylval.lineno = file->lineno; 5352 file->lineno++; 5353 } 5354 if (c == EOF) 5355 return (0); 5356 return (c); 5357 } 5358 5359 int 5360 check_file_secrecy(int fd, const char *fname) 5361 { 5362 struct stat st; 5363 5364 if (fstat(fd, &st)) { 5365 warn("cannot stat %s", fname); 5366 return (-1); 5367 } 5368 if (st.st_uid != 0 && st.st_uid != getuid()) { 5369 warnx("%s: owner not root or current user", fname); 5370 return (-1); 5371 } 5372 if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) { 5373 warnx("%s: group writable or world read/writable", fname); 5374 return (-1); 5375 } 5376 return (0); 5377 } 5378 5379 struct file * 5380 pushfile(const char *name, int secret) 5381 { 5382 struct file *nfile; 5383 5384 if ((nfile = calloc(1, sizeof(struct file))) == NULL || 5385 (nfile->name = strdup(name)) == NULL) { 5386 if (nfile) 5387 free(nfile); 5388 warn("malloc"); 5389 return (NULL); 5390 } 5391 if (TAILQ_FIRST(&files) == NULL && strcmp(nfile->name, "-") == 0) { 5392 nfile->stream = stdin; 5393 free(nfile->name); 5394 if ((nfile->name = strdup("stdin")) == NULL) { 5395 warn("strdup"); 5396 free(nfile); 5397 return (NULL); 5398 } 5399 } else if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { 5400 warn("%s", nfile->name); 5401 free(nfile->name); 5402 free(nfile); 5403 return (NULL); 5404 } else if (secret && 5405 check_file_secrecy(fileno(nfile->stream), nfile->name)) { 5406 fclose(nfile->stream); 5407 free(nfile->name); 5408 free(nfile); 5409 return (NULL); 5410 } 5411 nfile->lineno = 1; 5412 TAILQ_INSERT_TAIL(&files, nfile, entry); 5413 return (nfile); 5414 } 5415 5416 int 5417 popfile(void) 5418 { 5419 struct file *prev; 5420 5421 if ((prev = TAILQ_PREV(file, files, entry)) != NULL) { 5422 prev->errors += file->errors; 5423 TAILQ_REMOVE(&files, file, entry); 5424 fclose(file->stream); 5425 free(file->name); 5426 free(file); 5427 file = prev; 5428 return (0); 5429 } 5430 return (EOF); 5431 } 5432 5433 int 5434 parse_config(char *filename, struct pfctl *xpf) 5435 { 5436 int errors = 0; 5437 struct sym *sym; 5438 5439 pf = xpf; 5440 errors = 0; 5441 returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 5442 returnicmp6default = 5443 (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT; 5444 blockpolicy = PFRULE_DROP; 5445 5446 if ((file = pushfile(filename, 0)) == NULL) { 5447 warn("cannot open the main config file!"); 5448 return (-1); 5449 } 5450 5451 yyparse(); 5452 errors = file->errors; 5453 popfile(); 5454 5455 /* Free macros and check which have not been used. */ 5456 while ((sym = TAILQ_FIRST(&symhead))) { 5457 if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used) 5458 fprintf(stderr, "warning: macro '%s' not " 5459 "used\n", sym->nam); 5460 free(sym->nam); 5461 free(sym->val); 5462 TAILQ_REMOVE(&symhead, sym, entry); 5463 free(sym); 5464 } 5465 5466 return (errors ? -1 : 0); 5467 } 5468 5469 int 5470 symset(const char *nam, const char *val, int persist) 5471 { 5472 struct sym *sym; 5473 5474 for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam); 5475 sym = TAILQ_NEXT(sym, entry)) 5476 ; /* nothing */ 5477 5478 if (sym != NULL) { 5479 if (sym->persist == 1) 5480 return (0); 5481 else { 5482 free(sym->nam); 5483 free(sym->val); 5484 TAILQ_REMOVE(&symhead, sym, entry); 5485 free(sym); 5486 } 5487 } 5488 if ((sym = calloc(1, sizeof(*sym))) == NULL) 5489 return (-1); 5490 5491 sym->nam = strdup(nam); 5492 if (sym->nam == NULL) { 5493 free(sym); 5494 return (-1); 5495 } 5496 sym->val = strdup(val); 5497 if (sym->val == NULL) { 5498 free(sym->nam); 5499 free(sym); 5500 return (-1); 5501 } 5502 sym->used = 0; 5503 sym->persist = persist; 5504 TAILQ_INSERT_TAIL(&symhead, sym, entry); 5505 return (0); 5506 } 5507 5508 int 5509 pfctl_cmdline_symset(char *s) 5510 { 5511 char *sym, *val; 5512 int ret; 5513 5514 if ((val = strrchr(s, '=')) == NULL) 5515 return (-1); 5516 5517 if ((sym = malloc(strlen(s) - strlen(val) + 1)) == NULL) 5518 err(1, "pfctl_cmdline_symset: malloc"); 5519 5520 strlcpy(sym, s, strlen(s) - strlen(val) + 1); 5521 5522 ret = symset(sym, val + 1, 1); 5523 free(sym); 5524 5525 return (ret); 5526 } 5527 5528 char * 5529 symget(const char *nam) 5530 { 5531 struct sym *sym; 5532 5533 TAILQ_FOREACH(sym, &symhead, entry) 5534 if (strcmp(nam, sym->nam) == 0) { 5535 sym->used = 1; 5536 return (sym->val); 5537 } 5538 return (NULL); 5539 } 5540 5541 void 5542 mv_rules(struct pf_ruleset *src, struct pf_ruleset *dst) 5543 { 5544 struct pf_rule *r; 5545 5546 while ((r = TAILQ_FIRST(src->rules.active.ptr)) != NULL) { 5547 TAILQ_REMOVE(src->rules.active.ptr, r, entries); 5548 TAILQ_INSERT_TAIL(dst->rules.active.ptr, r, entries); 5549 dst->anchor->match++; 5550 } 5551 src->anchor->match = 0; 5552 while ((r = TAILQ_FIRST(src->rules.inactive.ptr)) != NULL) { 5553 TAILQ_REMOVE(src->rules.inactive.ptr, r, entries); 5554 TAILQ_INSERT_TAIL(dst->rules.inactive.ptr, r, entries); 5555 } 5556 } 5557 5558 void 5559 decide_address_family(struct node_host *n, sa_family_t *af) 5560 { 5561 if (*af != 0 || n == NULL) 5562 return; 5563 *af = n->af; 5564 while ((n = n->next) != NULL) { 5565 if (n->af != *af) { 5566 *af = 0; 5567 return; 5568 } 5569 } 5570 } 5571 5572 int 5573 invalid_redirect(struct node_host *nh, sa_family_t af) 5574 { 5575 if (!af) { 5576 struct node_host *n; 5577 5578 /* tables and dyniftl are ok without an address family */ 5579 for (n = nh; n != NULL; n = n->next) { 5580 if (n->addr.type != PF_ADDR_TABLE && 5581 n->addr.type != PF_ADDR_DYNIFTL) { 5582 yyerror("address family not given and " 5583 "translation address expands to multiple " 5584 "address families"); 5585 return (1); 5586 } 5587 } 5588 } 5589 if (nh == NULL) { 5590 yyerror("no translation address with matching address family " 5591 "found."); 5592 return (1); 5593 } 5594 return (0); 5595 } 5596 5597 int 5598 atoul(char *s, u_long *ulvalp) 5599 { 5600 u_long ulval; 5601 char *ep; 5602 5603 errno = 0; 5604 ulval = strtoul(s, &ep, 0); 5605 if (s[0] == '\0' || *ep != '\0') 5606 return (-1); 5607 if (errno == ERANGE && ulval == ULONG_MAX) 5608 return (-1); 5609 *ulvalp = ulval; 5610 return (0); 5611 } 5612 5613 int 5614 getservice(char *n) 5615 { 5616 struct servent *s; 5617 u_long ulval; 5618 5619 if (atoul(n, &ulval) == 0) { 5620 if (ulval > 65535) { 5621 yyerror("illegal port value %lu", ulval); 5622 return (-1); 5623 } 5624 return (htons(ulval)); 5625 } else { 5626 s = getservbyname(n, "tcp"); 5627 if (s == NULL) 5628 s = getservbyname(n, "udp"); 5629 if (s == NULL) { 5630 yyerror("unknown port %s", n); 5631 return (-1); 5632 } 5633 return (s->s_port); 5634 } 5635 } 5636 5637 int 5638 rule_label(struct pf_rule *r, char *s) 5639 { 5640 if (s) { 5641 if (strlcpy(r->label, s, sizeof(r->label)) >= 5642 sizeof(r->label)) { 5643 yyerror("rule label too long (max %d chars)", 5644 sizeof(r->label)-1); 5645 return (-1); 5646 } 5647 } 5648 return (0); 5649 } 5650 5651 u_int16_t 5652 parseicmpspec(char *w, sa_family_t af) 5653 { 5654 const struct icmpcodeent *p; 5655 u_long ulval; 5656 u_int8_t icmptype; 5657 5658 if (af == AF_INET) 5659 icmptype = returnicmpdefault >> 8; 5660 else 5661 icmptype = returnicmp6default >> 8; 5662 5663 if (atoul(w, &ulval) == -1) { 5664 if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) { 5665 yyerror("unknown icmp code %s", w); 5666 return (0); 5667 } 5668 ulval = p->code; 5669 } 5670 if (ulval > 255) { 5671 yyerror("invalid icmp code %lu", ulval); 5672 return (0); 5673 } 5674 return (icmptype << 8 | ulval); 5675 } 5676 5677 int 5678 parseport(char *port, struct range *r, int extensions) 5679 { 5680 char *p = strchr(port, ':'); 5681 5682 if (p == NULL) { 5683 if ((r->a = getservice(port)) == -1) 5684 return (-1); 5685 r->b = 0; 5686 r->t = PF_OP_NONE; 5687 return (0); 5688 } 5689 if ((extensions & PPORT_STAR) && !strcmp(p+1, "*")) { 5690 *p = 0; 5691 if ((r->a = getservice(port)) == -1) 5692 return (-1); 5693 r->b = 0; 5694 r->t = PF_OP_IRG; 5695 return (0); 5696 } 5697 if ((extensions & PPORT_RANGE)) { 5698 *p++ = 0; 5699 if ((r->a = getservice(port)) == -1 || 5700 (r->b = getservice(p)) == -1) 5701 return (-1); 5702 if (r->a == r->b) { 5703 r->b = 0; 5704 r->t = PF_OP_NONE; 5705 } else 5706 r->t = PF_OP_RRG; 5707 return (0); 5708 } 5709 return (-1); 5710 } 5711 5712 int 5713 pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans) 5714 { 5715 struct loadanchors *la; 5716 5717 TAILQ_FOREACH(la, &loadanchorshead, entries) { 5718 if (pf->opts & PF_OPT_VERBOSE) 5719 fprintf(stderr, "\nLoading anchor %s from %s\n", 5720 la->anchorname, la->filename); 5721 if (pfctl_rules(dev, la->filename, pf->opts, pf->optimize, 5722 la->anchorname, trans) == -1) 5723 return (-1); 5724 } 5725 5726 return (0); 5727 } 5728 5729 int 5730 kw_casecmp(const void *k, const void *e) 5731 { 5732 return (strcasecmp(k, ((const struct keywords *)e)->k_name)); 5733 } 5734 5735 int 5736 map_tos(char *s, int *val) 5737 { 5738 /* DiffServ Codepoints and other TOS mappings */ 5739 const struct keywords toswords[] = { 5740 { "af11", IPTOS_DSCP_AF11 }, 5741 { "af12", IPTOS_DSCP_AF12 }, 5742 { "af13", IPTOS_DSCP_AF13 }, 5743 { "af21", IPTOS_DSCP_AF21 }, 5744 { "af22", IPTOS_DSCP_AF22 }, 5745 { "af23", IPTOS_DSCP_AF23 }, 5746 { "af31", IPTOS_DSCP_AF31 }, 5747 { "af32", IPTOS_DSCP_AF32 }, 5748 { "af33", IPTOS_DSCP_AF33 }, 5749 { "af41", IPTOS_DSCP_AF41 }, 5750 { "af42", IPTOS_DSCP_AF42 }, 5751 { "af43", IPTOS_DSCP_AF43 }, 5752 { "critical", IPTOS_PREC_CRITIC_ECP }, 5753 { "cs0", IPTOS_DSCP_CS0 }, 5754 { "cs1", IPTOS_DSCP_CS1 }, 5755 { "cs2", IPTOS_DSCP_CS2 }, 5756 { "cs3", IPTOS_DSCP_CS3 }, 5757 { "cs4", IPTOS_DSCP_CS4 }, 5758 { "cs5", IPTOS_DSCP_CS5 }, 5759 { "cs6", IPTOS_DSCP_CS6 }, 5760 { "cs7", IPTOS_DSCP_CS7 }, 5761 { "ef", IPTOS_DSCP_EF }, 5762 { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, 5763 { "lowdelay", IPTOS_LOWDELAY }, 5764 { "netcontrol", IPTOS_PREC_NETCONTROL }, 5765 { "reliability", IPTOS_RELIABILITY }, 5766 { "throughput", IPTOS_THROUGHPUT } 5767 }; 5768 const struct keywords *p; 5769 5770 p = bsearch(s, toswords, sizeof(toswords)/sizeof(toswords[0]), 5771 sizeof(toswords[0]), kw_casecmp); 5772 5773 if (p) { 5774 *val = p->k_val; 5775 return (1); 5776 } 5777 return (0); 5778 } 5779