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