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