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