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