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 #define PFIOC_USE_LATEST 34 35 #include <sys/types.h> 36 #include <sys/socket.h> 37 #include <sys/stat.h> 38 #ifdef __FreeBSD__ 39 #include <sys/sysctl.h> 40 #endif 41 #include <net/if.h> 42 #include <netinet/in.h> 43 #include <netinet/in_systm.h> 44 #include <netinet/ip.h> 45 #include <netinet/ip_icmp.h> 46 #include <netinet/icmp6.h> 47 #include <net/pfvar.h> 48 #include <arpa/inet.h> 49 #include <net/altq/altq.h> 50 #include <net/altq/altq_cbq.h> 51 #include <net/altq/altq_codel.h> 52 #include <net/altq/altq_priq.h> 53 #include <net/altq/altq_hfsc.h> 54 #include <net/altq/altq_fairq.h> 55 56 #include <assert.h> 57 #include <stdio.h> 58 #include <unistd.h> 59 #include <stdlib.h> 60 #include <netdb.h> 61 #include <stdarg.h> 62 #include <errno.h> 63 #include <string.h> 64 #include <ctype.h> 65 #include <math.h> 66 #include <err.h> 67 #include <limits.h> 68 #include <pwd.h> 69 #include <grp.h> 70 #include <md5.h> 71 72 #include "pfctl_parser.h" 73 #include "pfctl.h" 74 75 #define ISSET(_v, _m) ((_v) & (_m)) 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 size_t ungetpos; 95 size_t ungetsize; 96 u_char *ungetbuf; 97 int eof_reached; 98 int lineno; 99 int errors; 100 } *file, *topfile; 101 struct file *pushfile(const char *, int); 102 int popfile(void); 103 int check_file_secrecy(int, const char *); 104 int yyparse(void); 105 int yylex(void); 106 int yyerror(const char *, ...); 107 int kw_cmp(const void *, const void *); 108 int lookup(char *); 109 int igetc(void); 110 int lgetc(int); 111 void lungetc(int); 112 int findeol(void); 113 114 static TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 115 struct sym { 116 TAILQ_ENTRY(sym) entry; 117 int used; 118 int persist; 119 char *nam; 120 char *val; 121 }; 122 int symset(const char *, const char *, int); 123 char *symget(const char *); 124 125 int atoul(char *, u_long *); 126 127 enum { 128 PFCTL_STATE_NONE, 129 PFCTL_STATE_OPTION, 130 PFCTL_STATE_ETHER, 131 PFCTL_STATE_SCRUB, 132 PFCTL_STATE_QUEUE, 133 PFCTL_STATE_NAT, 134 PFCTL_STATE_FILTER 135 }; 136 137 struct node_etherproto { 138 u_int16_t proto; 139 struct node_etherproto *next; 140 struct node_etherproto *tail; 141 }; 142 143 struct node_proto { 144 u_int8_t proto; 145 struct node_proto *next; 146 struct node_proto *tail; 147 }; 148 149 struct node_port { 150 u_int16_t port[2]; 151 u_int8_t op; 152 struct node_port *next; 153 struct node_port *tail; 154 }; 155 156 struct node_uid { 157 uid_t uid[2]; 158 u_int8_t op; 159 struct node_uid *next; 160 struct node_uid *tail; 161 }; 162 163 struct node_gid { 164 gid_t gid[2]; 165 u_int8_t op; 166 struct node_gid *next; 167 struct node_gid *tail; 168 }; 169 170 struct node_icmp { 171 uint16_t code; 172 uint16_t type; 173 u_int8_t proto; 174 struct node_icmp *next; 175 struct node_icmp *tail; 176 }; 177 178 enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK, 179 PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN, 180 PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES, 181 PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK, 182 PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY, 183 PF_STATE_OPT_PFLOW, PF_STATE_OPT_ALLOW_RELATED, 184 PF_STATE_OPT_STATELIM, PF_STATE_OPT_SOURCELIM }; 185 186 enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE }; 187 188 struct node_state_opt { 189 int type; 190 union { 191 u_int32_t max_states; 192 u_int32_t max_src_states; 193 u_int32_t max_src_conn; 194 struct { 195 u_int32_t limit; 196 u_int32_t seconds; 197 } max_src_conn_rate; 198 struct { 199 u_int8_t flush; 200 char tblname[PF_TABLE_NAME_SIZE]; 201 } overload; 202 u_int32_t max_src_nodes; 203 u_int8_t src_track; 204 u_int32_t statelock; 205 struct { 206 int number; 207 u_int32_t seconds; 208 } timeout; 209 } data; 210 struct node_state_opt *next; 211 struct node_state_opt *tail; 212 }; 213 214 struct peer { 215 struct node_host *host; 216 struct node_port *port; 217 }; 218 219 static struct node_queue { 220 char queue[PF_QNAME_SIZE]; 221 char parent[PF_QNAME_SIZE]; 222 char ifname[IFNAMSIZ]; 223 int scheduler; 224 struct node_queue *next; 225 struct node_queue *tail; 226 } *queues = NULL; 227 228 struct node_qassign { 229 char *qname; 230 char *pqname; 231 }; 232 233 struct range { 234 int a; 235 int b; 236 int t; 237 }; 238 239 static struct pool_opts { 240 int marker; 241 #define POM_TYPE 0x01 242 #define POM_STICKYADDRESS 0x02 243 #define POM_ENDPI 0x04 244 #define POM_IPV6NH 0x08 245 u_int8_t opts; 246 int type; 247 int staticport; 248 struct pf_poolhashkey *key; 249 struct pf_mape_portset mape; 250 } pool_opts; 251 252 struct redirspec { 253 struct node_host *host; 254 struct range rport; 255 struct pool_opts pool_opts; 256 sa_family_t af; 257 bool binat; 258 }; 259 260 struct limiterspec { 261 uint32_t id; 262 int limiter_action; 263 }; 264 265 static struct filter_opts { 266 int marker; 267 #define FOM_FLAGS 0x0001 268 #define FOM_ICMP 0x0002 269 #define FOM_TOS 0x0004 270 #define FOM_KEEP 0x0008 271 #define FOM_SRCTRACK 0x0010 272 #define FOM_MINTTL 0x0020 273 #define FOM_MAXMSS 0x0040 274 #define FOM_AFTO 0x0080 275 #define FOM_SETTOS 0x0100 276 #define FOM_SCRUB_TCP 0x0200 277 #define FOM_SETPRIO 0x0400 278 #define FOM_ONCE 0x1000 279 #define FOM_PRIO 0x2000 280 #define FOM_SETDELAY 0x4000 281 #define FOM_FRAGCACHE 0x8000 /* does not exist in OpenBSD */ 282 struct node_uid *uid; 283 struct node_gid *gid; 284 struct node_if *rcv; 285 struct { 286 u_int8_t b1; 287 u_int8_t b2; 288 u_int16_t w; 289 u_int16_t w2; 290 } flags; 291 struct node_icmp *icmpspec; 292 u_int32_t tos; 293 u_int32_t prob; 294 u_int32_t ridentifier; 295 struct limiterspec statelim; 296 struct limiterspec sourcelim; 297 struct { 298 int action; 299 struct node_state_opt *options; 300 } keep; 301 int fragment; 302 int allowopts; 303 char *label[PF_RULE_MAX_LABEL_COUNT]; 304 int labelcount; 305 struct node_qassign queues; 306 char *tag; 307 char *match_tag; 308 u_int8_t match_tag_not; 309 u_int16_t dnpipe; 310 u_int16_t dnrpipe; 311 u_int32_t free_flags; 312 u_int rtableid; 313 u_int8_t prio; 314 u_int8_t set_prio[2]; 315 struct { 316 struct node_host *addr; 317 u_int16_t port; 318 } divert; 319 struct redirspec *nat; 320 struct redirspec *rdr; 321 /* new-style scrub opts */ 322 int nodf; 323 int minttl; 324 int settos; 325 int randomid; 326 int max_mss; 327 struct { 328 uint32_t limit; 329 uint32_t seconds; 330 } pktrate; 331 int max_pkt_size; 332 } filter_opts; 333 334 static struct antispoof_opts { 335 char *label[PF_RULE_MAX_LABEL_COUNT]; 336 int labelcount; 337 u_int32_t ridentifier; 338 u_int rtableid; 339 } antispoof_opts; 340 341 static struct scrub_opts { 342 int marker; 343 int nodf; 344 int minttl; 345 int maxmss; 346 int settos; 347 int fragcache; 348 int randomid; 349 int reassemble_tcp; 350 char *match_tag; 351 u_int8_t match_tag_not; 352 u_int rtableid; 353 } scrub_opts; 354 355 static struct queue_opts { 356 int marker; 357 #define QOM_BWSPEC 0x01 358 #define QOM_SCHEDULER 0x02 359 #define QOM_PRIORITY 0x04 360 #define QOM_TBRSIZE 0x08 361 #define QOM_QLIMIT 0x10 362 struct node_queue_bw queue_bwspec; 363 struct node_queue_opt scheduler; 364 int priority; 365 unsigned int tbrsize; 366 int qlimit; 367 } queue_opts; 368 369 static struct table_opts { 370 int flags; 371 int init_addr; 372 struct node_tinithead init_nodes; 373 } table_opts; 374 375 struct statelim_opts { 376 unsigned int marker; 377 #define STATELIM_M_ID 0x01 378 #define STATELIM_M_LIMIT 0x02 379 #define STATELIM_M_RATE 0x04 380 381 uint32_t id; 382 char name[PF_STATELIM_NAME_LEN]; 383 unsigned int limit; 384 struct { 385 unsigned int limit; 386 unsigned int seconds; 387 } rate; 388 }; 389 390 static struct statelim_opts statelim_opts; 391 392 struct sourcelim_opts { 393 unsigned int marker; 394 #define SOURCELIM_M_ID 0x01 395 #define SOURCELIM_M_ENTRIES 0x02 396 #define SOURCELIM_M_LIMIT 0x04 397 #define SOURCELIM_M_RATE 0x08 398 #define SOURCELIM_M_TABLE 0x10 399 #define SOURCELIM_M_INET_MASK 0x20 400 #define SOURCELIM_M_INET6_MASK 0x40 401 402 uint32_t id; 403 unsigned int entries; 404 unsigned int limit; 405 struct { 406 unsigned int limit; 407 unsigned int seconds; 408 } rate; 409 struct { 410 char name[PF_TABLE_NAME_SIZE]; 411 unsigned int above; 412 unsigned int below; 413 } table; 414 unsigned int inet_mask; 415 unsigned int inet6_mask; 416 }; 417 418 static struct sourcelim_opts sourcelim_opts; 419 420 static struct codel_opts codel_opts; 421 static struct node_hfsc_opts hfsc_opts; 422 static struct node_fairq_opts fairq_opts; 423 static struct node_state_opt *keep_state_defaults = NULL; 424 static struct pfctl_watermarks syncookie_opts; 425 426 int validate_range(uint8_t, uint16_t, uint16_t); 427 int disallow_table(struct node_host *, const char *); 428 int disallow_urpf_failed(struct node_host *, const char *); 429 int disallow_alias(struct node_host *, const char *); 430 int rule_consistent(struct pfctl_rule *); 431 int filter_consistent(struct pfctl_rule *); 432 int nat_consistent(struct pfctl_rule *); 433 int rdr_consistent(struct pfctl_rule *); 434 int process_tabledef(char *, struct table_opts *, int); 435 void expand_label_str(char *, size_t, const char *, const char *); 436 void expand_label_if(const char *, char *, size_t, const char *); 437 void expand_label_addr(const char *, char *, size_t, sa_family_t, 438 struct pf_rule_addr *); 439 void expand_label_port(const char *, char *, size_t, 440 struct pf_rule_addr *); 441 void expand_label_proto(const char *, char *, size_t, u_int8_t); 442 void expand_label_nr(const char *, char *, size_t, 443 struct pfctl_rule *); 444 void expand_eth_rule(struct pfctl_eth_rule *, 445 struct node_if *, struct node_etherproto *, 446 struct node_mac *, struct node_mac *, 447 struct node_host *, struct node_host *, const char *, 448 const char *); 449 int apply_rdr_ports(struct pfctl_rule *r, struct pfctl_pool *, struct redirspec *); 450 int apply_nat_ports(struct pfctl_pool *, struct redirspec *); 451 int apply_redirspec(struct pfctl_pool *, struct redirspec *); 452 int check_binat_redirspec(struct node_host *, struct pfctl_rule *, sa_family_t); 453 void add_binat_rdr_rule(struct pfctl_rule *, struct redirspec *, 454 struct node_host *, struct pfctl_rule *, struct redirspec **, 455 struct node_host **); 456 void expand_rule(struct pfctl_rule *, bool, struct node_if *, 457 struct redirspec *, struct redirspec *, struct redirspec *, 458 struct node_proto *, struct node_os *, struct node_host *, 459 struct node_port *, struct node_host *, struct node_port *, 460 struct node_uid *, struct node_gid *, struct node_if *, 461 struct node_icmp *); 462 int expand_altq(struct pf_altq *, struct node_if *, 463 struct node_queue *, struct node_queue_bw bwspec, 464 struct node_queue_opt *); 465 int expand_queue(struct pf_altq *, struct node_if *, 466 struct node_queue *, struct node_queue_bw, 467 struct node_queue_opt *); 468 int expand_skip_interface(struct node_if *); 469 470 int check_rulestate(int); 471 int getservice(char *); 472 int rule_label(struct pfctl_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]); 473 int eth_rule_label(struct pfctl_eth_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]); 474 int rt_tableid_max(void); 475 476 void mv_rules(struct pfctl_ruleset *, struct pfctl_ruleset *); 477 void mv_eth_rules(struct pfctl_eth_ruleset *, struct pfctl_eth_ruleset *); 478 void mv_tables(struct pfctl *, struct pfr_ktablehead *, 479 struct pfctl_anchor *, struct pfctl_anchor *); 480 void decide_address_family(struct node_host *, sa_family_t *); 481 void remove_invalid_hosts(struct node_host **, sa_family_t *); 482 int invalid_redirect(struct node_host *, sa_family_t); 483 u_int16_t parseicmpspec(char *, sa_family_t); 484 int kw_casecmp(const void *, const void *); 485 int map_tos(char *string, int *); 486 int filteropts_to_rule(struct pfctl_rule *, struct filter_opts *); 487 struct node_mac* node_mac_from_string(const char *); 488 struct node_mac* node_mac_from_string_masklen(const char *, int); 489 struct node_mac* node_mac_from_string_mask(const char *, const char *); 490 static bool pfctl_setup_anchor(struct pfctl_rule *, struct pfctl *, char *); 491 492 static TAILQ_HEAD(loadanchorshead, loadanchors) 493 loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead); 494 495 struct loadanchors { 496 TAILQ_ENTRY(loadanchors) entries; 497 char *anchorname; 498 char *filename; 499 }; 500 501 typedef struct { 502 union { 503 int64_t number; 504 double probability; 505 int i; 506 char *string; 507 u_int rtableid; 508 struct { 509 u_int8_t b1; 510 u_int8_t b2; 511 u_int16_t w; 512 u_int16_t w2; 513 } b; 514 struct range range; 515 struct node_if *interface; 516 struct node_proto *proto; 517 struct node_etherproto *etherproto; 518 struct node_icmp *icmp; 519 struct node_host *host; 520 struct node_os *os; 521 struct node_port *port; 522 struct node_uid *uid; 523 struct node_gid *gid; 524 struct node_state_opt *state_opt; 525 struct peer peer; 526 struct { 527 struct peer src, dst; 528 struct node_os *src_os; 529 } fromto; 530 struct { 531 struct node_mac *src; 532 struct node_mac *dst; 533 } etherfromto; 534 struct node_mac *mac; 535 struct { 536 struct node_mac *mac; 537 } etheraddr; 538 char *bridge_to; 539 struct { 540 struct redirspec *redirspec; 541 u_int8_t rt; 542 } route; 543 struct redirspec *redirspec; 544 struct { 545 int action; 546 struct node_state_opt *options; 547 } keep_state; 548 struct { 549 u_int8_t log; 550 u_int8_t logif; 551 u_int8_t quick; 552 } logquick; 553 struct { 554 int neg; 555 char *name; 556 } tagged; 557 struct pf_poolhashkey *hashkey; 558 struct node_queue *queue; 559 struct node_queue_opt queue_options; 560 struct node_queue_bw queue_bwspec; 561 struct node_qassign qassign; 562 struct filter_opts filter_opts; 563 struct antispoof_opts antispoof_opts; 564 struct queue_opts queue_opts; 565 struct scrub_opts scrub_opts; 566 struct table_opts table_opts; 567 struct pool_opts pool_opts; 568 struct node_hfsc_opts hfsc_opts; 569 struct node_fairq_opts fairq_opts; 570 struct codel_opts codel_opts; 571 struct statelim_opts *statelim_opts; 572 struct sourcelim_opts *sourcelim_opts; 573 struct pfctl_watermarks *watermarks; 574 struct limiterspec limiterspec; 575 } v; 576 int lineno; 577 } YYSTYPE; 578 579 #define PPORT_RANGE 1 580 #define PPORT_STAR 2 581 int parseport(char *, struct range *r, int); 582 583 #define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \ 584 (!((addr).iflags & PFI_AFLAG_NOALIAS) || \ 585 !isdigit((addr).v.ifname[strlen((addr).v.ifname)-1]))) 586 587 %} 588 589 %token PASS BLOCK MATCH SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS 590 %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE 591 %token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF 592 %token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL 593 %token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE 594 %token REASSEMBLE ANCHOR NATANCHOR RDRANCHOR BINATANCHOR 595 %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY FAILPOLICY 596 %token RANDOMID REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID 597 %token ANTISPOOF FOR INCLUDE KEEPCOUNTERS SYNCOOKIES L3 MATCHES 598 %token ETHER 599 %token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY MAPEPORTSET 600 %token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME 601 %token UPPERLIMIT QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE TARGET INTERVAL 602 %token DNPIPE DNQUEUE RIDENTIFIER 603 %token LOAD RULESET_OPTIMIZATION PRIO ONCE 604 %token STICKYADDRESS ENDPI MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE 605 %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW ALLOW_RELATED 606 %token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS 607 %token DIVERTTO DIVERTREPLY BRIDGE_TO RECEIVEDON NE LE GE AFTO NATTO RDRTO 608 %token BINATTO MAXPKTRATE MAXPKTSIZE IPV6NH 609 %token LIMITER ID RATE SOURCE ENTRIES ABOVE BELOW MASK NOMATCH 610 %token <v.string> STRING 611 %token <v.number> NUMBER 612 %token <v.i> PORTBINARY 613 %type <v.interface> interface if_list if_item_not if_item 614 %type <v.number> number icmptype icmp6type uid gid 615 %type <v.number> tos not yesno optnodf sourcelim_opt_below 616 %type <v.probability> probability 617 %type <v.i> no dir af fragcache optimizer syncookie_val 618 %type <v.i> sourcetrack flush unaryop statelock 619 %type <v.i> etherprotoval 620 %type <v.b> action nataction natpasslog scrubaction 621 %type <v.b> flags flag blockspec prio 622 %type <v.range> portplain portstar portrange 623 %type <v.hashkey> hashkey 624 %type <v.proto> proto proto_list proto_item 625 %type <v.number> protoval 626 %type <v.icmp> icmpspec 627 %type <v.icmp> icmp_list icmp_item 628 %type <v.icmp> icmp6_list icmp6_item 629 %type <v.number> reticmpspec reticmp6spec 630 %type <v.fromto> fromto l3fromto 631 %type <v.peer> ipportspec from to 632 %type <v.host> ipspec toipspec xhost host dynaddr host_list 633 %type <v.host> redir_host redir_host_list routespec 634 %type <v.host> route_host route_host_list 635 %type <v.os> os xos os_list 636 %type <v.port> portspec port_list port_item 637 %type <v.uid> uids uid_list uid_item 638 %type <v.gid> gids gid_list gid_item 639 %type <v.route> route 640 %type <v.redirspec> no_port_redirspec port_redirspec route_redirspec 641 %type <v.redirspec> binat_redirspec nat_redirspec 642 %type <v.string> label stringall tag anchorname 643 %type <v.string> string varstring numberstring 644 %type <v.keep_state> keep 645 %type <v.state_opt> state_opt_spec state_opt_list state_opt_item 646 %type <v.logquick> logquick quick log logopts logopt 647 %type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if 648 %type <v.qassign> qname etherqname 649 %type <v.queue> qassign qassign_list qassign_item 650 %type <v.queue_options> scheduler 651 %type <v.number> cbqflags_list cbqflags_item 652 %type <v.number> priqflags_list priqflags_item 653 %type <v.hfsc_opts> hfscopts_list hfscopts_item hfsc_opts 654 %type <v.fairq_opts> fairqopts_list fairqopts_item fairq_opts 655 %type <v.codel_opts> codelopts_list codelopts_item codel_opts 656 %type <v.queue_bwspec> bandwidth 657 %type <v.filter_opts> filter_opts filter_opt filter_opts_l etherfilter_opts etherfilter_opt etherfilter_opts_l 658 %type <v.filter_opts> filter_sets filter_set filter_sets_l 659 %type <v.antispoof_opts> antispoof_opts antispoof_opt antispoof_opts_l 660 %type <v.queue_opts> queue_opts queue_opt queue_opts_l 661 %type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l 662 %type <v.table_opts> table_opts table_opt table_opts_l 663 %type <v.pool_opts> pool_opts pool_opt pool_opts_l 664 %type <v.tagged> tagged 665 %type <v.rtableid> rtable 666 %type <v.watermarks> syncookie_opts 667 %type <v.etherproto> etherproto etherproto_list etherproto_item 668 %type <v.etherfromto> etherfromto 669 %type <v.etheraddr> etherfrom etherto 670 %type <v.bridge_to> bridge 671 %type <v.mac> xmac mac mac_list macspec 672 %type <v.string> statelim_nm sourcelim_nm 673 %type <v.number> statelim_id sourcelim_id limiter_opt limiter_opt_spec 674 %type <v.limiterspec> statelim_filter_opt sourcelim_filter_opt 675 %type <v.statelim_opts> statelim_opts 676 %type <v.sourcelim_opts> sourcelim_opts 677 %% 678 679 ruleset : /* empty */ 680 | ruleset include '\n' 681 | ruleset '\n' 682 | ruleset option '\n' 683 | ruleset statelim '\n' 684 | ruleset sourcelim '\n' 685 | ruleset etherrule '\n' 686 | ruleset etheranchorrule '\n' 687 | ruleset scrubrule '\n' 688 | ruleset natrule '\n' 689 | ruleset binatrule '\n' 690 | ruleset pfrule '\n' 691 | ruleset anchorrule '\n' 692 | ruleset loadrule '\n' 693 | ruleset altqif '\n' 694 | ruleset queuespec '\n' 695 | ruleset varset '\n' 696 | ruleset antispoof '\n' 697 | ruleset tabledef '\n' 698 | '{' fakeanchor '}' '\n'; 699 | ruleset error '\n' { file->errors++; } 700 ; 701 702 include : INCLUDE STRING { 703 struct file *nfile; 704 705 if ((nfile = pushfile($2, 0)) == NULL) { 706 yyerror("failed to include file %s", $2); 707 free($2); 708 YYERROR; 709 } 710 free($2); 711 712 file = nfile; 713 lungetc('\n'); 714 } 715 ; 716 717 /* 718 * apply to previouslys specified rule: must be careful to note 719 * what that is: pf or nat or binat or rdr 720 */ 721 fakeanchor : fakeanchor '\n' 722 | fakeanchor anchorrule '\n' 723 | fakeanchor binatrule '\n' 724 | fakeanchor natrule '\n' 725 | fakeanchor pfrule '\n' 726 | fakeanchor error '\n' 727 ; 728 729 optimizer : string { 730 if (!strcmp($1, "none")) 731 $$ = 0; 732 else if (!strcmp($1, "basic")) 733 $$ = PF_OPTIMIZE_BASIC; 734 else if (!strcmp($1, "profile")) 735 $$ = PF_OPTIMIZE_BASIC | PF_OPTIMIZE_PROFILE; 736 else { 737 yyerror("unknown ruleset-optimization %s", $1); 738 YYERROR; 739 } 740 } 741 ; 742 743 optnodf : /* empty */ { $$ = 0; } 744 | NODF { $$ = 1; } 745 ; 746 747 option : SET REASSEMBLE yesno optnodf { 748 if (check_rulestate(PFCTL_STATE_OPTION)) 749 YYERROR; 750 pfctl_set_reassembly(pf, $3, $4); 751 } 752 | SET OPTIMIZATION STRING { 753 if (check_rulestate(PFCTL_STATE_OPTION)) { 754 free($3); 755 YYERROR; 756 } 757 if (pfctl_set_optimization(pf, $3) != 0) { 758 yyerror("unknown optimization %s", $3); 759 free($3); 760 YYERROR; 761 } 762 free($3); 763 } 764 | SET RULESET_OPTIMIZATION optimizer { 765 if (!(pf->opts & PF_OPT_OPTIMIZE)) { 766 pf->opts |= PF_OPT_OPTIMIZE; 767 pf->optimize = $3; 768 } 769 } 770 | SET TIMEOUT timeout_spec 771 | SET TIMEOUT '{' optnl timeout_list '}' 772 | SET LIMIT limit_spec 773 | SET LIMIT '{' optnl limit_list '}' 774 | SET LOGINTERFACE stringall { 775 if (check_rulestate(PFCTL_STATE_OPTION)) { 776 free($3); 777 YYERROR; 778 } 779 if (pfctl_set_logif(pf, $3) != 0) { 780 yyerror("error setting loginterface %s", $3); 781 free($3); 782 YYERROR; 783 } 784 free($3); 785 } 786 | SET HOSTID number { 787 if ($3 == 0 || $3 > UINT_MAX) { 788 yyerror("hostid must be non-zero"); 789 YYERROR; 790 } 791 pfctl_set_hostid(pf, $3); 792 } 793 | SET BLOCKPOLICY DROP { 794 if (pf->opts & PF_OPT_VERBOSE) 795 printf("set block-policy drop\n"); 796 if (check_rulestate(PFCTL_STATE_OPTION)) 797 YYERROR; 798 blockpolicy = PFRULE_DROP; 799 } 800 | SET BLOCKPOLICY RETURN { 801 if (pf->opts & PF_OPT_VERBOSE) 802 printf("set block-policy return\n"); 803 if (check_rulestate(PFCTL_STATE_OPTION)) 804 YYERROR; 805 blockpolicy = PFRULE_RETURN; 806 } 807 | SET FAILPOLICY DROP { 808 if (pf->opts & PF_OPT_VERBOSE) 809 printf("set fail-policy drop\n"); 810 if (check_rulestate(PFCTL_STATE_OPTION)) 811 YYERROR; 812 failpolicy = PFRULE_DROP; 813 } 814 | SET FAILPOLICY RETURN { 815 if (pf->opts & PF_OPT_VERBOSE) 816 printf("set fail-policy return\n"); 817 if (check_rulestate(PFCTL_STATE_OPTION)) 818 YYERROR; 819 failpolicy = PFRULE_RETURN; 820 } 821 | SET REQUIREORDER yesno { 822 if (pf->opts & PF_OPT_VERBOSE) 823 printf("set require-order %s\n", 824 $3 == 1 ? "yes" : "no"); 825 require_order = $3; 826 } 827 | SET FINGERPRINTS STRING { 828 if (pf->opts & PF_OPT_VERBOSE) 829 printf("set fingerprints \"%s\"\n", $3); 830 if (check_rulestate(PFCTL_STATE_OPTION)) { 831 free($3); 832 YYERROR; 833 } 834 if (!pf->anchor->name[0]) { 835 if (pfctl_file_fingerprints(pf->dev, 836 pf->opts, $3)) { 837 yyerror("error loading " 838 "fingerprints %s", $3); 839 free($3); 840 YYERROR; 841 } 842 } 843 free($3); 844 } 845 | SET STATEPOLICY statelock { 846 if (pf->opts & PF_OPT_VERBOSE) 847 switch ($3) { 848 case 0: 849 printf("set state-policy floating\n"); 850 break; 851 case PFRULE_IFBOUND: 852 printf("set state-policy if-bound\n"); 853 break; 854 } 855 default_statelock = $3; 856 } 857 | SET DEBUG STRING { 858 if (check_rulestate(PFCTL_STATE_OPTION)) { 859 free($3); 860 YYERROR; 861 } 862 if (pfctl_do_set_debug(pf, $3) != 0) { 863 yyerror("error setting debuglevel %s", $3); 864 free($3); 865 YYERROR; 866 } 867 free($3); 868 } 869 | SET SKIP interface { 870 if (expand_skip_interface($3) != 0) { 871 yyerror("error setting skip interface(s)"); 872 YYERROR; 873 } 874 } 875 | SET STATEDEFAULTS state_opt_list { 876 if (keep_state_defaults != NULL) { 877 yyerror("cannot redefine state-defaults"); 878 YYERROR; 879 } 880 keep_state_defaults = $3; 881 } 882 | SET KEEPCOUNTERS { 883 pf->keep_counters = true; 884 } 885 | SET SYNCOOKIES syncookie_val syncookie_opts { 886 if (pfctl_cfg_syncookies(pf, $3, $4)) { 887 yyerror("error setting syncookies"); 888 YYERROR; 889 } 890 } 891 ; 892 893 syncookie_val : STRING { 894 if (!strcmp($1, "never")) 895 $$ = PFCTL_SYNCOOKIES_NEVER; 896 else if (!strcmp($1, "adaptive")) 897 $$ = PFCTL_SYNCOOKIES_ADAPTIVE; 898 else if (!strcmp($1, "always")) 899 $$ = PFCTL_SYNCOOKIES_ALWAYS; 900 else { 901 yyerror("illegal value for syncookies"); 902 YYERROR; 903 } 904 } 905 ; 906 syncookie_opts : /* empty */ { $$ = NULL; } 907 | { 908 memset(&syncookie_opts, 0, sizeof(syncookie_opts)); 909 } '(' syncookie_opt_l ')' { $$ = &syncookie_opts; } 910 ; 911 912 syncookie_opt_l : syncookie_opt_l comma syncookie_opt 913 | syncookie_opt 914 ; 915 916 syncookie_opt : STRING STRING { 917 double val; 918 char *cp; 919 920 val = strtod($2, &cp); 921 if (cp == NULL || strcmp(cp, "%")) 922 YYERROR; 923 if (val <= 0 || val > 100) { 924 yyerror("illegal percentage value"); 925 YYERROR; 926 } 927 if (!strcmp($1, "start")) { 928 syncookie_opts.hi = val; 929 } else if (!strcmp($1, "end")) { 930 syncookie_opts.lo = val; 931 } else { 932 yyerror("illegal syncookie option"); 933 YYERROR; 934 } 935 } 936 ; 937 938 stringall : STRING { $$ = $1; } 939 | ALL { 940 if (($$ = strdup("all")) == NULL) { 941 err(1, "stringall: strdup"); 942 } 943 } 944 ; 945 946 string : STRING string { 947 if (asprintf(&$$, "%s %s", $1, $2) == -1) 948 err(1, "string: asprintf"); 949 free($1); 950 free($2); 951 } 952 | STRING 953 ; 954 955 varstring : numberstring varstring { 956 if (asprintf(&$$, "%s %s", $1, $2) == -1) 957 err(1, "string: asprintf"); 958 free($1); 959 free($2); 960 } 961 | numberstring 962 ; 963 964 numberstring : NUMBER { 965 char *s; 966 if (asprintf(&s, "%lld", (long long)$1) == -1) { 967 yyerror("string: asprintf"); 968 YYERROR; 969 } 970 $$ = s; 971 } 972 | STRING 973 ; 974 975 varset : STRING '=' varstring { 976 char *s = $1; 977 if (pf->opts & PF_OPT_VERBOSE) 978 printf("%s = \"%s\"\n", $1, $3); 979 while (*s++) { 980 if (isspace((unsigned char)*s)) { 981 yyerror("macro name cannot contain " 982 "whitespace"); 983 free($1); 984 free($3); 985 YYERROR; 986 } 987 } 988 if (symset($1, $3, 0) == -1) 989 err(1, "cannot store variable %s", $1); 990 free($1); 991 free($3); 992 } 993 ; 994 995 anchorname : STRING { 996 if ($1[0] == '\0') { 997 free($1); 998 yyerror("anchor name must not be empty"); 999 YYERROR; 1000 } 1001 if (strlen(pf->anchor->path) + 1 + 1002 strlen($1) >= PATH_MAX) { 1003 free($1); 1004 yyerror("anchor name is longer than %u", 1005 PATH_MAX - 1); 1006 YYERROR; 1007 } 1008 if ($1[0] == '_' || strstr($1, "/_") != NULL) { 1009 free($1); 1010 yyerror("anchor names beginning with '_' " 1011 "are reserved for internal use"); 1012 YYERROR; 1013 } 1014 $$ = $1; 1015 } 1016 | /* empty */ { $$ = NULL; } 1017 ; 1018 1019 pfa_anchorlist : /* empty */ 1020 | pfa_anchorlist '\n' 1021 | pfa_anchorlist tabledef '\n' 1022 | pfa_anchorlist pfrule '\n' 1023 | pfa_anchorlist anchorrule '\n' 1024 | pfa_anchorlist include '\n' 1025 ; 1026 1027 pfa_anchor : '{' 1028 { 1029 char ta[PF_ANCHOR_NAME_SIZE]; 1030 struct pfctl_ruleset *rs; 1031 1032 /* stepping into a brace anchor */ 1033 if (pf->asd >= PFCTL_ANCHOR_STACK_DEPTH) 1034 errx(1, "pfa_anchor: anchors too deep"); 1035 pf->asd++; 1036 pf->bn++; 1037 1038 /* 1039 * Anchor contents are parsed before the anchor rule 1040 * production completes, so we don't know the real 1041 * location yet. Create a holding ruleset in the root; 1042 * contents will be moved afterwards. 1043 */ 1044 snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn); 1045 rs = pf_find_or_create_ruleset(ta); 1046 if (rs == NULL) 1047 err(1, "pfa_anchor: pf_find_or_create_ruleset (%s)", ta); 1048 pf->astack[pf->asd] = rs->anchor; 1049 pf->anchor = rs->anchor; 1050 } '\n' pfa_anchorlist '}' 1051 { 1052 pf->alast = pf->anchor; 1053 pf->asd--; 1054 pf->anchor = pf->astack[pf->asd]; 1055 } 1056 | /* empty */ 1057 ; 1058 1059 anchorrule : ANCHOR anchorname dir quick interface af proto fromto 1060 filter_opts pfa_anchor 1061 { 1062 struct pfctl_rule r; 1063 struct node_proto *proto; 1064 1065 if (check_rulestate(PFCTL_STATE_FILTER)) { 1066 if ($2) 1067 free($2); 1068 YYERROR; 1069 } 1070 1071 pfctl_init_rule(&r); 1072 if (! pfctl_setup_anchor(&r, pf, $2)) 1073 YYERROR; 1074 1075 r.direction = $3; 1076 r.quick = $4.quick; 1077 r.af = $6; 1078 1079 if ($9.flags.b1 || $9.flags.b2 || $8.src_os) { 1080 for (proto = $7; proto != NULL && 1081 proto->proto != IPPROTO_TCP; 1082 proto = proto->next) 1083 ; /* nothing */ 1084 if (proto == NULL && $7 != NULL) { 1085 if ($9.flags.b1 || $9.flags.b2) 1086 yyerror( 1087 "flags only apply to tcp"); 1088 if ($8.src_os) 1089 yyerror( 1090 "OS fingerprinting only " 1091 "applies to tcp"); 1092 YYERROR; 1093 } 1094 } 1095 1096 if (filteropts_to_rule(&r, &$9)) 1097 YYERROR; 1098 1099 if ($9.keep.action) { 1100 yyerror("cannot specify state handling " 1101 "on anchors"); 1102 YYERROR; 1103 } 1104 1105 decide_address_family($8.src.host, &r.af); 1106 decide_address_family($8.dst.host, &r.af); 1107 1108 expand_rule(&r, false, $5, NULL, NULL, NULL, 1109 $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host, 1110 $8.dst.port, $9.uid, $9.gid, $9.rcv, $9.icmpspec); 1111 free($2); 1112 pf->astack[pf->asd + 1] = NULL; 1113 } 1114 | NATANCHOR string interface af proto fromto rtable { 1115 struct pfctl_rule r; 1116 1117 if (check_rulestate(PFCTL_STATE_NAT)) { 1118 free($2); 1119 YYERROR; 1120 } 1121 1122 pfctl_init_rule(&r); 1123 if (! pfctl_setup_anchor(&r, pf, $2)) 1124 YYERROR; 1125 1126 r.action = PF_NAT; 1127 r.af = $4; 1128 r.rtableid = $7; 1129 1130 decide_address_family($6.src.host, &r.af); 1131 decide_address_family($6.dst.host, &r.af); 1132 1133 expand_rule(&r, false, $3, NULL, NULL, NULL, 1134 $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host, 1135 $6.dst.port, 0, 0, 0, 0); 1136 free($2); 1137 } 1138 | RDRANCHOR string interface af proto fromto rtable { 1139 struct pfctl_rule r; 1140 1141 if (check_rulestate(PFCTL_STATE_NAT)) { 1142 free($2); 1143 YYERROR; 1144 } 1145 1146 pfctl_init_rule(&r); 1147 if (! pfctl_setup_anchor(&r, pf, $2)) 1148 YYERROR; 1149 1150 r.action = PF_RDR; 1151 r.af = $4; 1152 r.rtableid = $7; 1153 1154 decide_address_family($6.src.host, &r.af); 1155 decide_address_family($6.dst.host, &r.af); 1156 1157 if ($6.src.port != NULL) { 1158 yyerror("source port parameter not supported" 1159 " in rdr-anchor"); 1160 YYERROR; 1161 } 1162 if ($6.dst.port != NULL) { 1163 if ($6.dst.port->next != NULL) { 1164 yyerror("destination port list " 1165 "expansion not supported in " 1166 "rdr-anchor"); 1167 YYERROR; 1168 } else if ($6.dst.port->op != PF_OP_EQ) { 1169 yyerror("destination port operators" 1170 " not supported in rdr-anchor"); 1171 YYERROR; 1172 } 1173 r.dst.port[0] = $6.dst.port->port[0]; 1174 r.dst.port[1] = $6.dst.port->port[1]; 1175 r.dst.port_op = $6.dst.port->op; 1176 } 1177 1178 expand_rule(&r, false, $3, NULL, NULL, NULL, 1179 $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host, 1180 $6.dst.port, 0, 0, 0, 0); 1181 free($2); 1182 } 1183 | BINATANCHOR string interface af proto fromto rtable { 1184 struct pfctl_rule r; 1185 1186 if (check_rulestate(PFCTL_STATE_NAT)) { 1187 free($2); 1188 YYERROR; 1189 } 1190 1191 pfctl_init_rule(&r); 1192 if (! pfctl_setup_anchor(&r, pf, $2)) 1193 YYERROR; 1194 1195 r.action = PF_BINAT; 1196 r.af = $4; 1197 r.rtableid = $7; 1198 if ($5 != NULL) { 1199 if ($5->next != NULL) { 1200 yyerror("proto list expansion" 1201 " not supported in binat-anchor"); 1202 YYERROR; 1203 } 1204 r.proto = $5->proto; 1205 free($5); 1206 } 1207 1208 if ($6.src.host != NULL || $6.src.port != NULL || 1209 $6.dst.host != NULL || $6.dst.port != NULL) { 1210 yyerror("fromto parameter not supported" 1211 " in binat-anchor"); 1212 YYERROR; 1213 } 1214 1215 decide_address_family($6.src.host, &r.af); 1216 decide_address_family($6.dst.host, &r.af); 1217 1218 pfctl_append_rule(pf, &r); 1219 free($2); 1220 } 1221 ; 1222 1223 loadrule : LOAD ANCHOR anchorname FROM string { 1224 struct loadanchors *loadanchor; 1225 1226 if ($3 == NULL) { 1227 yyerror("anchor name is missing"); 1228 YYERROR; 1229 } 1230 loadanchor = calloc(1, sizeof(struct loadanchors)); 1231 if (loadanchor == NULL) 1232 err(1, "loadrule: calloc"); 1233 if ((loadanchor->anchorname = malloc(MAXPATHLEN)) == 1234 NULL) 1235 err(1, "loadrule: malloc"); 1236 if (pf->anchor->name[0]) 1237 snprintf(loadanchor->anchorname, MAXPATHLEN, 1238 "%s/%s", pf->anchor->path, $3); 1239 else 1240 strlcpy(loadanchor->anchorname, $3, MAXPATHLEN); 1241 if ((loadanchor->filename = strdup($5)) == NULL) 1242 err(1, "loadrule: strdup"); 1243 1244 TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor, 1245 entries); 1246 1247 free($3); 1248 free($5); 1249 }; 1250 1251 scrubaction : no SCRUB { 1252 $$.b2 = $$.w = 0; 1253 if ($1) 1254 $$.b1 = PF_NOSCRUB; 1255 else 1256 $$.b1 = PF_SCRUB; 1257 } 1258 ; 1259 1260 etherrule : ETHER action dir quick interface bridge etherproto etherfromto l3fromto etherfilter_opts 1261 { 1262 struct pfctl_eth_rule r; 1263 1264 bzero(&r, sizeof(r)); 1265 1266 if (check_rulestate(PFCTL_STATE_ETHER)) 1267 YYERROR; 1268 1269 r.action = $2.b1; 1270 r.direction = $3; 1271 r.quick = $4.quick; 1272 if ($10.tag != NULL) 1273 strlcpy(r.tagname, $10.tag, sizeof(r.tagname)); 1274 if ($10.match_tag) 1275 if (strlcpy(r.match_tagname, $10.match_tag, 1276 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 1277 yyerror("tag too long, max %u chars", 1278 PF_TAG_NAME_SIZE - 1); 1279 YYERROR; 1280 } 1281 r.match_tag_not = $10.match_tag_not; 1282 if ($10.queues.qname != NULL) 1283 strlcpy(r.qname, $10.queues.qname, sizeof(r.qname)); 1284 r.dnpipe = $10.dnpipe; 1285 r.dnflags = $10.free_flags; 1286 if (eth_rule_label(&r, $10.label)) 1287 YYERROR; 1288 for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) 1289 free($10.label[i]); 1290 r.ridentifier = $10.ridentifier; 1291 1292 expand_eth_rule(&r, $5, $7, $8.src, $8.dst, 1293 $9.src.host, $9.dst.host, $6, ""); 1294 } 1295 ; 1296 1297 etherpfa_anchorlist : /* empty */ 1298 | etherpfa_anchorlist '\n' 1299 | etherpfa_anchorlist etherrule '\n' 1300 | etherpfa_anchorlist etheranchorrule '\n' 1301 ; 1302 1303 etherpfa_anchor : '{' 1304 { 1305 char ta[PF_ANCHOR_NAME_SIZE]; 1306 struct pfctl_eth_ruleset *rs; 1307 1308 /* steping into a brace anchor */ 1309 if (pf->asd >= PFCTL_ANCHOR_STACK_DEPTH) 1310 errx(1, "pfa_anchor: anchors too deep"); 1311 pf->asd++; 1312 pf->bn++; 1313 1314 /* create a holding ruleset in the root */ 1315 snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn); 1316 rs = pf_find_or_create_eth_ruleset(ta); 1317 if (rs == NULL) 1318 err(1, "etherpfa_anchor: pf_find_or_create_eth_ruleset"); 1319 pf->eastack[pf->asd] = rs->anchor; 1320 pf->eanchor = rs->anchor; 1321 } '\n' etherpfa_anchorlist '}' 1322 { 1323 pf->ealast = pf->eanchor; 1324 pf->asd--; 1325 pf->eanchor = pf->eastack[pf->asd]; 1326 } 1327 | /* empty */ 1328 ; 1329 1330 etheranchorrule : ETHER ANCHOR anchorname dir quick interface etherproto etherfromto l3fromto etherpfa_anchor 1331 { 1332 struct pfctl_eth_rule r; 1333 1334 if (check_rulestate(PFCTL_STATE_ETHER)) { 1335 free($3); 1336 YYERROR; 1337 } 1338 1339 if ($3 && ($3[0] == '_' || strstr($3, "/_") != NULL)) { 1340 free($3); 1341 yyerror("anchor names beginning with '_' " 1342 "are reserved for internal use"); 1343 YYERROR; 1344 } 1345 1346 memset(&r, 0, sizeof(r)); 1347 if (pf->eastack[pf->asd + 1]) { 1348 if ($3 && strchr($3, '/') != NULL) { 1349 free($3); 1350 yyerror("anchor paths containing '/' " 1351 "cannot be used for inline anchors."); 1352 YYERROR; 1353 } 1354 1355 /* Move inline rules into relative location. */ 1356 pfctl_eth_anchor_setup(pf, &r, 1357 &pf->eastack[pf->asd]->ruleset, 1358 $3 ? $3 : pf->ealast->name); 1359 if (r.anchor == NULL) 1360 err(1, "etheranchorrule: unable to " 1361 "create ruleset"); 1362 1363 if (pf->ealast != r.anchor) { 1364 if (r.anchor->match) { 1365 yyerror("inline anchor '%s' " 1366 "already exists", 1367 r.anchor->name); 1368 YYERROR; 1369 } 1370 mv_eth_rules(&pf->ealast->ruleset, 1371 &r.anchor->ruleset); 1372 } 1373 pf_remove_if_empty_eth_ruleset(&pf->ealast->ruleset); 1374 pf->ealast = r.anchor; 1375 } else { 1376 if (!$3) { 1377 yyerror("anchors without explicit " 1378 "rules must specify a name"); 1379 YYERROR; 1380 } 1381 } 1382 1383 r.direction = $4; 1384 r.quick = $5.quick; 1385 1386 expand_eth_rule(&r, $6, $7, $8.src, $8.dst, 1387 $9.src.host, $9.dst.host, NULL, 1388 pf->eastack[pf->asd + 1] ? pf->ealast->name : $3); 1389 1390 free($3); 1391 pf->eastack[pf->asd + 1] = NULL; 1392 } 1393 ; 1394 1395 etherfilter_opts : { 1396 bzero(&filter_opts, sizeof filter_opts); 1397 } 1398 etherfilter_opts_l 1399 { $$ = filter_opts; } 1400 | /* empty */ { 1401 bzero(&filter_opts, sizeof filter_opts); 1402 $$ = filter_opts; 1403 } 1404 ; 1405 1406 etherfilter_opts_l : etherfilter_opts_l etherfilter_opt 1407 | etherfilter_opt 1408 1409 etherfilter_opt : etherqname { 1410 if (filter_opts.queues.qname) { 1411 yyerror("queue cannot be redefined"); 1412 YYERROR; 1413 } 1414 filter_opts.queues = $1; 1415 } 1416 | RIDENTIFIER number { 1417 filter_opts.ridentifier = $2; 1418 } 1419 | label { 1420 if (filter_opts.labelcount >= PF_RULE_MAX_LABEL_COUNT) { 1421 yyerror("label can only be used %d times", PF_RULE_MAX_LABEL_COUNT); 1422 YYERROR; 1423 } 1424 filter_opts.label[filter_opts.labelcount++] = $1; 1425 } 1426 | TAG string { 1427 filter_opts.tag = $2; 1428 } 1429 | not TAGGED string { 1430 filter_opts.match_tag = $3; 1431 filter_opts.match_tag_not = $1; 1432 } 1433 | DNPIPE number { 1434 filter_opts.dnpipe = $2; 1435 filter_opts.free_flags |= PFRULE_DN_IS_PIPE; 1436 } 1437 | DNQUEUE number { 1438 filter_opts.dnpipe = $2; 1439 filter_opts.free_flags |= PFRULE_DN_IS_QUEUE; 1440 } 1441 ; 1442 1443 bridge : /* empty */ { 1444 $$ = NULL; 1445 } 1446 | BRIDGE_TO STRING { 1447 $$ = strdup($2); 1448 } 1449 ; 1450 1451 scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts 1452 { 1453 struct pfctl_rule r; 1454 1455 if (check_rulestate(PFCTL_STATE_SCRUB)) 1456 YYERROR; 1457 1458 pfctl_init_rule(&r); 1459 1460 r.action = $1.b1; 1461 r.direction = $2; 1462 1463 r.log = $3.log; 1464 r.logif = $3.logif; 1465 if ($3.quick) { 1466 yyerror("scrub rules do not support 'quick'"); 1467 YYERROR; 1468 } 1469 1470 r.af = $5; 1471 if ($8.nodf) 1472 r.rule_flag |= PFRULE_NODF; 1473 if ($8.randomid) 1474 r.rule_flag |= PFRULE_RANDOMID; 1475 if ($8.reassemble_tcp) { 1476 if (r.direction != PF_INOUT) { 1477 yyerror("reassemble tcp rules can not " 1478 "specify direction"); 1479 YYERROR; 1480 } 1481 r.rule_flag |= PFRULE_REASSEMBLE_TCP; 1482 } 1483 if ($8.minttl) 1484 r.min_ttl = $8.minttl; 1485 if ($8.maxmss) 1486 r.max_mss = $8.maxmss; 1487 if ($8.marker & FOM_SETTOS) { 1488 r.rule_flag |= PFRULE_SET_TOS; 1489 r.set_tos = $8.settos; 1490 } 1491 if ($8.fragcache) 1492 r.rule_flag |= $8.fragcache; 1493 if ($8.match_tag) 1494 if (strlcpy(r.match_tagname, $8.match_tag, 1495 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 1496 yyerror("tag too long, max %u chars", 1497 PF_TAG_NAME_SIZE - 1); 1498 YYERROR; 1499 } 1500 r.match_tag_not = $8.match_tag_not; 1501 r.rtableid = $8.rtableid; 1502 1503 expand_rule(&r, false, $4, NULL, NULL, NULL, 1504 $6, $7.src_os, $7.src.host, $7.src.port, $7.dst.host, 1505 $7.dst.port, NULL, NULL, NULL, NULL); 1506 } 1507 ; 1508 1509 scrub_opts : { 1510 bzero(&scrub_opts, sizeof scrub_opts); 1511 scrub_opts.rtableid = -1; 1512 } 1513 scrub_opts_l 1514 { $$ = scrub_opts; } 1515 | /* empty */ { 1516 bzero(&scrub_opts, sizeof scrub_opts); 1517 scrub_opts.rtableid = -1; 1518 $$ = scrub_opts; 1519 } 1520 ; 1521 1522 scrub_opts_l : scrub_opts_l comma scrub_opt 1523 | scrub_opt 1524 ; 1525 1526 scrub_opt : NODF { 1527 if (scrub_opts.nodf) { 1528 yyerror("no-df cannot be respecified"); 1529 YYERROR; 1530 } 1531 scrub_opts.nodf = 1; 1532 } 1533 | MINTTL NUMBER { 1534 if (scrub_opts.marker & FOM_MINTTL) { 1535 yyerror("min-ttl cannot be respecified"); 1536 YYERROR; 1537 } 1538 if ($2 < 0 || $2 > 255) { 1539 yyerror("illegal min-ttl value %d", $2); 1540 YYERROR; 1541 } 1542 scrub_opts.marker |= FOM_MINTTL; 1543 scrub_opts.minttl = $2; 1544 } 1545 | MAXMSS NUMBER { 1546 if (scrub_opts.marker & FOM_MAXMSS) { 1547 yyerror("max-mss cannot be respecified"); 1548 YYERROR; 1549 } 1550 if ($2 < 0 || $2 > 65535) { 1551 yyerror("illegal max-mss value %d", $2); 1552 YYERROR; 1553 } 1554 scrub_opts.marker |= FOM_MAXMSS; 1555 scrub_opts.maxmss = $2; 1556 } 1557 | SETTOS tos { 1558 if (scrub_opts.marker & FOM_SETTOS) { 1559 yyerror("set-tos cannot be respecified"); 1560 YYERROR; 1561 } 1562 scrub_opts.marker |= FOM_SETTOS; 1563 scrub_opts.settos = $2; 1564 } 1565 | fragcache { 1566 if (scrub_opts.marker & FOM_FRAGCACHE) { 1567 yyerror("fragcache cannot be respecified"); 1568 YYERROR; 1569 } 1570 scrub_opts.marker |= FOM_FRAGCACHE; 1571 scrub_opts.fragcache = $1; 1572 } 1573 | REASSEMBLE STRING { 1574 if (strcasecmp($2, "tcp") != 0) { 1575 yyerror("scrub reassemble supports only tcp, " 1576 "not '%s'", $2); 1577 free($2); 1578 YYERROR; 1579 } 1580 free($2); 1581 if (scrub_opts.reassemble_tcp) { 1582 yyerror("reassemble tcp cannot be respecified"); 1583 YYERROR; 1584 } 1585 scrub_opts.reassemble_tcp = 1; 1586 } 1587 | RANDOMID { 1588 if (scrub_opts.randomid) { 1589 yyerror("random-id cannot be respecified"); 1590 YYERROR; 1591 } 1592 scrub_opts.randomid = 1; 1593 } 1594 | RTABLE NUMBER { 1595 if ($2 < 0 || $2 > rt_tableid_max()) { 1596 yyerror("invalid rtable id"); 1597 YYERROR; 1598 } 1599 scrub_opts.rtableid = $2; 1600 } 1601 | not TAGGED string { 1602 scrub_opts.match_tag = $3; 1603 scrub_opts.match_tag_not = $1; 1604 } 1605 ; 1606 1607 fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ } 1608 | FRAGMENT NO REASSEMBLE { $$ = PFRULE_FRAGMENT_NOREASS; } 1609 ; 1610 1611 antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { 1612 struct pfctl_rule r; 1613 struct node_host *h = NULL, *hh; 1614 struct node_if *i, *j; 1615 1616 if (check_rulestate(PFCTL_STATE_FILTER)) 1617 YYERROR; 1618 1619 for (i = $3; i; i = i->next) { 1620 pfctl_init_rule(&r); 1621 1622 r.action = PF_DROP; 1623 r.direction = PF_IN; 1624 r.log = $2.log; 1625 r.logif = $2.logif; 1626 r.quick = $2.quick; 1627 r.af = $4; 1628 r.ridentifier = $5.ridentifier; 1629 if (rule_label(&r, $5.label)) 1630 YYERROR; 1631 r.rtableid = $5.rtableid; 1632 j = calloc(1, sizeof(struct node_if)); 1633 if (j == NULL) 1634 err(1, "antispoof: calloc"); 1635 if (strlcpy(j->ifname, i->ifname, 1636 sizeof(j->ifname)) >= sizeof(j->ifname)) { 1637 free(j); 1638 yyerror("interface name too long"); 1639 YYERROR; 1640 } 1641 j->not = 1; 1642 if (i->dynamic) { 1643 h = calloc(1, sizeof(*h)); 1644 if (h == NULL) 1645 err(1, "address: calloc"); 1646 h->addr.type = PF_ADDR_DYNIFTL; 1647 set_ipmask(h, 128); 1648 if (strlcpy(h->addr.v.ifname, i->ifname, 1649 sizeof(h->addr.v.ifname)) >= 1650 sizeof(h->addr.v.ifname)) { 1651 free(h); 1652 yyerror( 1653 "interface name too long"); 1654 YYERROR; 1655 } 1656 hh = malloc(sizeof(*hh)); 1657 if (hh == NULL) 1658 err(1, "address: malloc"); 1659 bcopy(h, hh, sizeof(*hh)); 1660 h->addr.iflags = PFI_AFLAG_NETWORK; 1661 } else { 1662 h = ifa_lookup(j->ifname, 1663 PFI_AFLAG_NETWORK); 1664 hh = NULL; 1665 } 1666 1667 if (h != NULL) 1668 expand_rule(&r, false, j, NULL, NULL, 1669 NULL, NULL, NULL, h, NULL, NULL, 1670 NULL, NULL, NULL, NULL, NULL); 1671 1672 if ((i->ifa_flags & IFF_LOOPBACK) == 0) { 1673 bzero(&r, sizeof(r)); 1674 1675 r.action = PF_DROP; 1676 r.direction = PF_IN; 1677 r.log = $2.log; 1678 r.logif = $2.logif; 1679 r.quick = $2.quick; 1680 r.af = $4; 1681 r.ridentifier = $5.ridentifier; 1682 if (rule_label(&r, $5.label)) 1683 YYERROR; 1684 r.rtableid = $5.rtableid; 1685 if (hh != NULL) 1686 h = hh; 1687 else 1688 h = ifa_lookup(i->ifname, 0); 1689 if (h != NULL) 1690 expand_rule(&r, false, NULL, 1691 NULL, NULL, NULL, NULL, 1692 NULL, h, NULL, NULL, NULL, 1693 NULL, NULL, NULL, NULL); 1694 } else 1695 free(hh); 1696 } 1697 for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) 1698 free($5.label[i]); 1699 } 1700 ; 1701 1702 antispoof_ifspc : FOR antispoof_if { $$ = $2; } 1703 | FOR '{' optnl antispoof_iflst '}' { $$ = $4; } 1704 ; 1705 1706 antispoof_iflst : antispoof_if optnl { $$ = $1; } 1707 | antispoof_iflst comma antispoof_if optnl { 1708 $1->tail->next = $3; 1709 $1->tail = $3; 1710 $$ = $1; 1711 } 1712 ; 1713 1714 antispoof_if : if_item { $$ = $1; } 1715 | '(' if_item ')' { 1716 $2->dynamic = 1; 1717 $$ = $2; 1718 } 1719 ; 1720 1721 antispoof_opts : { 1722 bzero(&antispoof_opts, sizeof antispoof_opts); 1723 antispoof_opts.rtableid = -1; 1724 } 1725 antispoof_opts_l 1726 { $$ = antispoof_opts; } 1727 | /* empty */ { 1728 bzero(&antispoof_opts, sizeof antispoof_opts); 1729 antispoof_opts.rtableid = -1; 1730 $$ = antispoof_opts; 1731 } 1732 ; 1733 1734 antispoof_opts_l : antispoof_opts_l antispoof_opt 1735 | antispoof_opt 1736 ; 1737 1738 antispoof_opt : label { 1739 if (antispoof_opts.labelcount >= PF_RULE_MAX_LABEL_COUNT) { 1740 yyerror("label can only be used %d times", PF_RULE_MAX_LABEL_COUNT); 1741 YYERROR; 1742 } 1743 antispoof_opts.label[antispoof_opts.labelcount++] = $1; 1744 } 1745 | RIDENTIFIER number { 1746 antispoof_opts.ridentifier = $2; 1747 } 1748 | RTABLE NUMBER { 1749 if ($2 < 0 || $2 > rt_tableid_max()) { 1750 yyerror("invalid rtable id"); 1751 YYERROR; 1752 } 1753 antispoof_opts.rtableid = $2; 1754 } 1755 ; 1756 1757 not : '!' { $$ = 1; } 1758 | /* empty */ { $$ = 0; } 1759 ; 1760 1761 tabledef : TABLE '<' STRING '>' table_opts { 1762 struct node_host *h, *nh; 1763 struct node_tinit *ti, *nti; 1764 1765 if (strlen($3) >= PF_TABLE_NAME_SIZE) { 1766 yyerror("table name too long, max %d chars", 1767 PF_TABLE_NAME_SIZE - 1); 1768 free($3); 1769 YYERROR; 1770 } 1771 if (pf->loadopt & PFCTL_FLAG_TABLE) 1772 if (process_tabledef($3, &$5, pf->opts)) { 1773 free($3); 1774 YYERROR; 1775 } 1776 free($3); 1777 for (ti = SIMPLEQ_FIRST(&$5.init_nodes); 1778 ti != SIMPLEQ_END(&$5.init_nodes); ti = nti) { 1779 if (ti->file) 1780 free(ti->file); 1781 for (h = ti->host; h != NULL; h = nh) { 1782 nh = h->next; 1783 free(h); 1784 } 1785 nti = SIMPLEQ_NEXT(ti, entries); 1786 free(ti); 1787 } 1788 } 1789 ; 1790 1791 table_opts : { 1792 bzero(&table_opts, sizeof table_opts); 1793 SIMPLEQ_INIT(&table_opts.init_nodes); 1794 } 1795 table_opts_l 1796 { $$ = table_opts; } 1797 | /* empty */ 1798 { 1799 bzero(&table_opts, sizeof table_opts); 1800 SIMPLEQ_INIT(&table_opts.init_nodes); 1801 $$ = table_opts; 1802 } 1803 ; 1804 1805 table_opts_l : table_opts_l table_opt 1806 | table_opt 1807 ; 1808 1809 table_opt : STRING { 1810 if (!strcmp($1, "const")) 1811 table_opts.flags |= PFR_TFLAG_CONST; 1812 else if (!strcmp($1, "persist")) 1813 table_opts.flags |= PFR_TFLAG_PERSIST; 1814 else if (!strcmp($1, "counters")) 1815 table_opts.flags |= PFR_TFLAG_COUNTERS; 1816 else { 1817 yyerror("invalid table option '%s'", $1); 1818 free($1); 1819 YYERROR; 1820 } 1821 free($1); 1822 } 1823 | '{' optnl '}' { table_opts.init_addr = 1; } 1824 | '{' optnl host_list '}' { 1825 struct node_host *n; 1826 struct node_tinit *ti; 1827 1828 for (n = $3; n != NULL; n = n->next) { 1829 switch (n->addr.type) { 1830 case PF_ADDR_ADDRMASK: 1831 continue; /* ok */ 1832 case PF_ADDR_RANGE: 1833 yyerror("address ranges are not " 1834 "permitted inside tables"); 1835 break; 1836 case PF_ADDR_DYNIFTL: 1837 yyerror("dynamic addresses are not " 1838 "permitted inside tables"); 1839 break; 1840 case PF_ADDR_TABLE: 1841 yyerror("tables cannot contain tables"); 1842 break; 1843 case PF_ADDR_NOROUTE: 1844 yyerror("\"no-route\" is not permitted " 1845 "inside tables"); 1846 break; 1847 case PF_ADDR_URPFFAILED: 1848 yyerror("\"urpf-failed\" is not " 1849 "permitted inside tables"); 1850 break; 1851 default: 1852 yyerror("unknown address type %d", 1853 n->addr.type); 1854 } 1855 YYERROR; 1856 } 1857 if (!(ti = calloc(1, sizeof(*ti)))) 1858 err(1, "table_opt: calloc"); 1859 ti->host = $3; 1860 SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti, 1861 entries); 1862 table_opts.init_addr = 1; 1863 } 1864 | FILENAME STRING { 1865 struct node_tinit *ti; 1866 1867 if (!(ti = calloc(1, sizeof(*ti)))) 1868 err(1, "table_opt: calloc"); 1869 ti->file = $2; 1870 SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti, 1871 entries); 1872 table_opts.init_addr = 1; 1873 } 1874 ; 1875 1876 altqif : ALTQ interface queue_opts QUEUE qassign { 1877 struct pf_altq a; 1878 1879 if (check_rulestate(PFCTL_STATE_QUEUE)) 1880 YYERROR; 1881 1882 memset(&a, 0, sizeof(a)); 1883 if ($3.scheduler.qtype == ALTQT_NONE) { 1884 yyerror("no scheduler specified!"); 1885 YYERROR; 1886 } 1887 a.scheduler = $3.scheduler.qtype; 1888 a.qlimit = $3.qlimit; 1889 a.tbrsize = $3.tbrsize; 1890 if ($5 == NULL && $3.scheduler.qtype != ALTQT_CODEL) { 1891 yyerror("no child queues specified"); 1892 YYERROR; 1893 } 1894 if (expand_altq(&a, $2, $5, $3.queue_bwspec, 1895 &$3.scheduler)) 1896 YYERROR; 1897 } 1898 ; 1899 1900 queuespec : QUEUE STRING interface queue_opts qassign { 1901 struct pf_altq a; 1902 1903 if (check_rulestate(PFCTL_STATE_QUEUE)) { 1904 free($2); 1905 YYERROR; 1906 } 1907 1908 memset(&a, 0, sizeof(a)); 1909 1910 if (strlcpy(a.qname, $2, sizeof(a.qname)) >= 1911 sizeof(a.qname)) { 1912 yyerror("queue name too long (max " 1913 "%d chars)", PF_QNAME_SIZE-1); 1914 free($2); 1915 YYERROR; 1916 } 1917 free($2); 1918 if ($4.tbrsize) { 1919 yyerror("cannot specify tbrsize for queue"); 1920 YYERROR; 1921 } 1922 if ($4.priority > 255) { 1923 yyerror("priority out of range: max 255"); 1924 YYERROR; 1925 } 1926 a.priority = $4.priority; 1927 a.qlimit = $4.qlimit; 1928 a.scheduler = $4.scheduler.qtype; 1929 if (expand_queue(&a, $3, $5, $4.queue_bwspec, 1930 &$4.scheduler)) { 1931 yyerror("errors in queue definition"); 1932 YYERROR; 1933 } 1934 } 1935 ; 1936 1937 queue_opts : { 1938 bzero(&queue_opts, sizeof queue_opts); 1939 queue_opts.priority = DEFAULT_PRIORITY; 1940 queue_opts.qlimit = DEFAULT_QLIMIT; 1941 queue_opts.scheduler.qtype = ALTQT_NONE; 1942 queue_opts.queue_bwspec.bw_percent = 100; 1943 } 1944 queue_opts_l 1945 { $$ = queue_opts; } 1946 | /* empty */ { 1947 bzero(&queue_opts, sizeof queue_opts); 1948 queue_opts.priority = DEFAULT_PRIORITY; 1949 queue_opts.qlimit = DEFAULT_QLIMIT; 1950 queue_opts.scheduler.qtype = ALTQT_NONE; 1951 queue_opts.queue_bwspec.bw_percent = 100; 1952 $$ = queue_opts; 1953 } 1954 ; 1955 1956 queue_opts_l : queue_opts_l queue_opt 1957 | queue_opt 1958 ; 1959 1960 queue_opt : BANDWIDTH bandwidth { 1961 if (queue_opts.marker & QOM_BWSPEC) { 1962 yyerror("bandwidth cannot be respecified"); 1963 YYERROR; 1964 } 1965 queue_opts.marker |= QOM_BWSPEC; 1966 queue_opts.queue_bwspec = $2; 1967 } 1968 | PRIORITY NUMBER { 1969 if (queue_opts.marker & QOM_PRIORITY) { 1970 yyerror("priority cannot be respecified"); 1971 YYERROR; 1972 } 1973 if ($2 < 0 || $2 > 255) { 1974 yyerror("priority out of range: max 255"); 1975 YYERROR; 1976 } 1977 queue_opts.marker |= QOM_PRIORITY; 1978 queue_opts.priority = $2; 1979 } 1980 | QLIMIT NUMBER { 1981 if (queue_opts.marker & QOM_QLIMIT) { 1982 yyerror("qlimit cannot be respecified"); 1983 YYERROR; 1984 } 1985 if ($2 < 0 || $2 > 65535) { 1986 yyerror("qlimit out of range: max 65535"); 1987 YYERROR; 1988 } 1989 queue_opts.marker |= QOM_QLIMIT; 1990 queue_opts.qlimit = $2; 1991 } 1992 | scheduler { 1993 if (queue_opts.marker & QOM_SCHEDULER) { 1994 yyerror("scheduler cannot be respecified"); 1995 YYERROR; 1996 } 1997 queue_opts.marker |= QOM_SCHEDULER; 1998 queue_opts.scheduler = $1; 1999 } 2000 | TBRSIZE NUMBER { 2001 if (queue_opts.marker & QOM_TBRSIZE) { 2002 yyerror("tbrsize cannot be respecified"); 2003 YYERROR; 2004 } 2005 if ($2 < 0 || $2 > UINT_MAX) { 2006 yyerror("tbrsize too big: max %u", UINT_MAX); 2007 YYERROR; 2008 } 2009 queue_opts.marker |= QOM_TBRSIZE; 2010 queue_opts.tbrsize = $2; 2011 } 2012 ; 2013 2014 bandwidth : STRING { 2015 double bps; 2016 char *cp; 2017 2018 $$.bw_percent = 0; 2019 2020 bps = strtod($1, &cp); 2021 if (cp != NULL) { 2022 if (strlen(cp) > 1) { 2023 char *cu = cp + 1; 2024 if (!strcmp(cu, "Bit") || 2025 !strcmp(cu, "B") || 2026 !strcmp(cu, "bit") || 2027 !strcmp(cu, "b")) { 2028 *cu = 0; 2029 } 2030 } 2031 if (!strcmp(cp, "b")) 2032 ; /* nothing */ 2033 else if (!strcmp(cp, "K")) 2034 bps *= 1000; 2035 else if (!strcmp(cp, "M")) 2036 bps *= 1000 * 1000; 2037 else if (!strcmp(cp, "G")) 2038 bps *= 1000 * 1000 * 1000; 2039 else if (!strcmp(cp, "%")) { 2040 if (bps < 0 || bps > 100) { 2041 yyerror("bandwidth spec " 2042 "out of range"); 2043 free($1); 2044 YYERROR; 2045 } 2046 $$.bw_percent = bps; 2047 bps = 0; 2048 } else { 2049 yyerror("unknown unit %s", cp); 2050 free($1); 2051 YYERROR; 2052 } 2053 } 2054 free($1); 2055 $$.bw_absolute = (u_int64_t)bps; 2056 } 2057 | NUMBER { 2058 if ($1 < 0 || $1 >= LLONG_MAX) { 2059 yyerror("bandwidth number too big"); 2060 YYERROR; 2061 } 2062 $$.bw_percent = 0; 2063 $$.bw_absolute = $1; 2064 } 2065 ; 2066 2067 scheduler : CBQ { 2068 $$.qtype = ALTQT_CBQ; 2069 $$.data.cbq_opts.flags = 0; 2070 } 2071 | CBQ '(' cbqflags_list ')' { 2072 $$.qtype = ALTQT_CBQ; 2073 $$.data.cbq_opts.flags = $3; 2074 } 2075 | PRIQ { 2076 $$.qtype = ALTQT_PRIQ; 2077 $$.data.priq_opts.flags = 0; 2078 } 2079 | PRIQ '(' priqflags_list ')' { 2080 $$.qtype = ALTQT_PRIQ; 2081 $$.data.priq_opts.flags = $3; 2082 } 2083 | HFSC { 2084 $$.qtype = ALTQT_HFSC; 2085 bzero(&$$.data.hfsc_opts, 2086 sizeof(struct node_hfsc_opts)); 2087 } 2088 | HFSC '(' hfsc_opts ')' { 2089 $$.qtype = ALTQT_HFSC; 2090 $$.data.hfsc_opts = $3; 2091 } 2092 | FAIRQ { 2093 $$.qtype = ALTQT_FAIRQ; 2094 bzero(&$$.data.fairq_opts, 2095 sizeof(struct node_fairq_opts)); 2096 } 2097 | FAIRQ '(' fairq_opts ')' { 2098 $$.qtype = ALTQT_FAIRQ; 2099 $$.data.fairq_opts = $3; 2100 } 2101 | CODEL { 2102 $$.qtype = ALTQT_CODEL; 2103 bzero(&$$.data.codel_opts, 2104 sizeof(struct codel_opts)); 2105 } 2106 | CODEL '(' codel_opts ')' { 2107 $$.qtype = ALTQT_CODEL; 2108 $$.data.codel_opts = $3; 2109 } 2110 ; 2111 2112 cbqflags_list : cbqflags_item { $$ |= $1; } 2113 | cbqflags_list comma cbqflags_item { $$ |= $3; } 2114 ; 2115 2116 cbqflags_item : STRING { 2117 if (!strcmp($1, "default")) 2118 $$ = CBQCLF_DEFCLASS; 2119 else if (!strcmp($1, "borrow")) 2120 $$ = CBQCLF_BORROW; 2121 else if (!strcmp($1, "red")) 2122 $$ = CBQCLF_RED; 2123 else if (!strcmp($1, "ecn")) 2124 $$ = CBQCLF_RED|CBQCLF_ECN; 2125 else if (!strcmp($1, "rio")) 2126 $$ = CBQCLF_RIO; 2127 else if (!strcmp($1, "codel")) 2128 $$ = CBQCLF_CODEL; 2129 else { 2130 yyerror("unknown cbq flag \"%s\"", $1); 2131 free($1); 2132 YYERROR; 2133 } 2134 free($1); 2135 } 2136 ; 2137 2138 priqflags_list : priqflags_item { $$ |= $1; } 2139 | priqflags_list comma priqflags_item { $$ |= $3; } 2140 ; 2141 2142 priqflags_item : STRING { 2143 if (!strcmp($1, "default")) 2144 $$ = PRCF_DEFAULTCLASS; 2145 else if (!strcmp($1, "red")) 2146 $$ = PRCF_RED; 2147 else if (!strcmp($1, "ecn")) 2148 $$ = PRCF_RED|PRCF_ECN; 2149 else if (!strcmp($1, "rio")) 2150 $$ = PRCF_RIO; 2151 else if (!strcmp($1, "codel")) 2152 $$ = PRCF_CODEL; 2153 else { 2154 yyerror("unknown priq flag \"%s\"", $1); 2155 free($1); 2156 YYERROR; 2157 } 2158 free($1); 2159 } 2160 ; 2161 2162 hfsc_opts : { 2163 bzero(&hfsc_opts, 2164 sizeof(struct node_hfsc_opts)); 2165 } 2166 hfscopts_list { 2167 $$ = hfsc_opts; 2168 } 2169 ; 2170 2171 hfscopts_list : hfscopts_item 2172 | hfscopts_list comma hfscopts_item 2173 ; 2174 2175 hfscopts_item : LINKSHARE bandwidth { 2176 if (hfsc_opts.linkshare.used) { 2177 yyerror("linkshare already specified"); 2178 YYERROR; 2179 } 2180 hfsc_opts.linkshare.m2 = $2; 2181 hfsc_opts.linkshare.used = 1; 2182 } 2183 | LINKSHARE '(' bandwidth comma NUMBER comma bandwidth ')' 2184 { 2185 if ($5 < 0 || $5 > INT_MAX) { 2186 yyerror("timing in curve out of range"); 2187 YYERROR; 2188 } 2189 if (hfsc_opts.linkshare.used) { 2190 yyerror("linkshare already specified"); 2191 YYERROR; 2192 } 2193 hfsc_opts.linkshare.m1 = $3; 2194 hfsc_opts.linkshare.d = $5; 2195 hfsc_opts.linkshare.m2 = $7; 2196 hfsc_opts.linkshare.used = 1; 2197 } 2198 | REALTIME bandwidth { 2199 if (hfsc_opts.realtime.used) { 2200 yyerror("realtime already specified"); 2201 YYERROR; 2202 } 2203 hfsc_opts.realtime.m2 = $2; 2204 hfsc_opts.realtime.used = 1; 2205 } 2206 | REALTIME '(' bandwidth comma NUMBER comma bandwidth ')' 2207 { 2208 if ($5 < 0 || $5 > INT_MAX) { 2209 yyerror("timing in curve out of range"); 2210 YYERROR; 2211 } 2212 if (hfsc_opts.realtime.used) { 2213 yyerror("realtime already specified"); 2214 YYERROR; 2215 } 2216 hfsc_opts.realtime.m1 = $3; 2217 hfsc_opts.realtime.d = $5; 2218 hfsc_opts.realtime.m2 = $7; 2219 hfsc_opts.realtime.used = 1; 2220 } 2221 | UPPERLIMIT bandwidth { 2222 if (hfsc_opts.upperlimit.used) { 2223 yyerror("upperlimit already specified"); 2224 YYERROR; 2225 } 2226 hfsc_opts.upperlimit.m2 = $2; 2227 hfsc_opts.upperlimit.used = 1; 2228 } 2229 | UPPERLIMIT '(' bandwidth comma NUMBER comma bandwidth ')' 2230 { 2231 if ($5 < 0 || $5 > INT_MAX) { 2232 yyerror("timing in curve out of range"); 2233 YYERROR; 2234 } 2235 if (hfsc_opts.upperlimit.used) { 2236 yyerror("upperlimit already specified"); 2237 YYERROR; 2238 } 2239 hfsc_opts.upperlimit.m1 = $3; 2240 hfsc_opts.upperlimit.d = $5; 2241 hfsc_opts.upperlimit.m2 = $7; 2242 hfsc_opts.upperlimit.used = 1; 2243 } 2244 | STRING { 2245 if (!strcmp($1, "default")) 2246 hfsc_opts.flags |= HFCF_DEFAULTCLASS; 2247 else if (!strcmp($1, "red")) 2248 hfsc_opts.flags |= HFCF_RED; 2249 else if (!strcmp($1, "ecn")) 2250 hfsc_opts.flags |= HFCF_RED|HFCF_ECN; 2251 else if (!strcmp($1, "rio")) 2252 hfsc_opts.flags |= HFCF_RIO; 2253 else if (!strcmp($1, "codel")) 2254 hfsc_opts.flags |= HFCF_CODEL; 2255 else { 2256 yyerror("unknown hfsc flag \"%s\"", $1); 2257 free($1); 2258 YYERROR; 2259 } 2260 free($1); 2261 } 2262 ; 2263 2264 fairq_opts : { 2265 bzero(&fairq_opts, 2266 sizeof(struct node_fairq_opts)); 2267 } 2268 fairqopts_list { 2269 $$ = fairq_opts; 2270 } 2271 ; 2272 2273 fairqopts_list : fairqopts_item 2274 | fairqopts_list comma fairqopts_item 2275 ; 2276 2277 fairqopts_item : LINKSHARE bandwidth { 2278 if (fairq_opts.linkshare.used) { 2279 yyerror("linkshare already specified"); 2280 YYERROR; 2281 } 2282 fairq_opts.linkshare.m2 = $2; 2283 fairq_opts.linkshare.used = 1; 2284 } 2285 | LINKSHARE '(' bandwidth number bandwidth ')' { 2286 if (fairq_opts.linkshare.used) { 2287 yyerror("linkshare already specified"); 2288 YYERROR; 2289 } 2290 fairq_opts.linkshare.m1 = $3; 2291 fairq_opts.linkshare.d = $4; 2292 fairq_opts.linkshare.m2 = $5; 2293 fairq_opts.linkshare.used = 1; 2294 } 2295 | HOGS bandwidth { 2296 fairq_opts.hogs_bw = $2; 2297 } 2298 | BUCKETS number { 2299 fairq_opts.nbuckets = $2; 2300 } 2301 | STRING { 2302 if (!strcmp($1, "default")) 2303 fairq_opts.flags |= FARF_DEFAULTCLASS; 2304 else if (!strcmp($1, "red")) 2305 fairq_opts.flags |= FARF_RED; 2306 else if (!strcmp($1, "ecn")) 2307 fairq_opts.flags |= FARF_RED|FARF_ECN; 2308 else if (!strcmp($1, "rio")) 2309 fairq_opts.flags |= FARF_RIO; 2310 else if (!strcmp($1, "codel")) 2311 fairq_opts.flags |= FARF_CODEL; 2312 else { 2313 yyerror("unknown fairq flag \"%s\"", $1); 2314 free($1); 2315 YYERROR; 2316 } 2317 free($1); 2318 } 2319 ; 2320 2321 codel_opts : { 2322 bzero(&codel_opts, 2323 sizeof(struct codel_opts)); 2324 } 2325 codelopts_list { 2326 $$ = codel_opts; 2327 } 2328 ; 2329 2330 codelopts_list : codelopts_item 2331 | codelopts_list comma codelopts_item 2332 ; 2333 2334 codelopts_item : INTERVAL number { 2335 if (codel_opts.interval) { 2336 yyerror("interval already specified"); 2337 YYERROR; 2338 } 2339 codel_opts.interval = $2; 2340 } 2341 | TARGET number { 2342 if (codel_opts.target) { 2343 yyerror("target already specified"); 2344 YYERROR; 2345 } 2346 codel_opts.target = $2; 2347 } 2348 | STRING { 2349 if (!strcmp($1, "ecn")) 2350 codel_opts.ecn = 1; 2351 else { 2352 yyerror("unknown codel option \"%s\"", $1); 2353 free($1); 2354 YYERROR; 2355 } 2356 free($1); 2357 } 2358 ; 2359 2360 qassign : /* empty */ { $$ = NULL; } 2361 | qassign_item { $$ = $1; } 2362 | '{' optnl qassign_list '}' { $$ = $3; } 2363 ; 2364 2365 qassign_list : qassign_item optnl { $$ = $1; } 2366 | qassign_list comma qassign_item optnl { 2367 $1->tail->next = $3; 2368 $1->tail = $3; 2369 $$ = $1; 2370 } 2371 ; 2372 2373 qassign_item : STRING { 2374 $$ = calloc(1, sizeof(struct node_queue)); 2375 if ($$ == NULL) 2376 err(1, "qassign_item: calloc"); 2377 if (strlcpy($$->queue, $1, sizeof($$->queue)) >= 2378 sizeof($$->queue)) { 2379 yyerror("queue name '%s' too long (max " 2380 "%d chars)", $1, sizeof($$->queue)-1); 2381 free($1); 2382 free($$); 2383 YYERROR; 2384 } 2385 free($1); 2386 $$->next = NULL; 2387 $$->tail = $$; 2388 } 2389 ; 2390 2391 statelim : statelim_nm statelim_opts { 2392 struct pfctl_statelim *stlim; 2393 size_t len; 2394 2395 if (!ISSET($2->marker, STATELIM_M_ID)) { 2396 yyerror("id not specified"); 2397 free($1); 2398 YYERROR; 2399 } 2400 if (!ISSET($2->marker, STATELIM_M_LIMIT)) { 2401 yyerror("limit not specified"); 2402 free($1); 2403 YYERROR; 2404 } 2405 2406 stlim = calloc(1, sizeof(*stlim)); 2407 if (stlim == NULL) 2408 err(1, "state limiter: malloc"); 2409 2410 len = strlcpy(stlim->ioc.name, $1, 2411 sizeof(stlim->ioc.name)); 2412 free($1); 2413 if (len >= sizeof(stlim->ioc.name)) { 2414 /* abort? */ 2415 YYERROR; 2416 } 2417 2418 stlim->ioc.id = $2->id; 2419 stlim->ioc.limit = $2->limit; 2420 stlim->ioc.rate.limit = $2->rate.limit; 2421 stlim->ioc.rate.seconds = $2->rate.seconds; 2422 2423 if (pfctl_add_statelim(pf, stlim) != 0) { 2424 yyerror("state limiter %s id %u" 2425 " already exists", 2426 stlim->ioc.name, stlim->ioc.id); 2427 free(stlim); 2428 YYERROR; 2429 } 2430 } 2431 ; 2432 2433 statelim_nm : STATE LIMITER string { 2434 size_t len = strlen($3); 2435 if (len < 1) { 2436 yyerror("state limiter name is too short"); 2437 free($3); 2438 YYERROR; 2439 } 2440 if (len >= PF_STATELIM_NAME_LEN) { 2441 yyerror("state limiter name is too long"); 2442 free($3); 2443 YYERROR; 2444 } 2445 $$ = $3; 2446 } 2447 ; 2448 2449 statelim_id : ID NUMBER { 2450 if ($2 < PF_STATELIM_ID_MIN || 2451 $2 > PF_STATELIM_ID_MAX) { 2452 yyerror("state limiter id %lld: " 2453 "invalid identifier", $2); 2454 YYERROR; 2455 } 2456 2457 $$ = $2; 2458 } 2459 ; 2460 2461 statelim_opts : /* empty */ { 2462 yyerror("state limiter missing options"); 2463 YYERROR; 2464 } 2465 | { 2466 memset(&statelim_opts, 0, sizeof(statelim_opts)); 2467 } statelim_opts_l { 2468 $$ = &statelim_opts; 2469 } 2470 ; 2471 2472 statelim_opts_l : statelim_opts_l statelim_opt 2473 | statelim_opt 2474 ; 2475 2476 statelim_opt : statelim_id { 2477 if (ISSET(statelim_opts.marker, STATELIM_M_ID)) { 2478 yyerror("id cannot be respecified"); 2479 YYERROR; 2480 } 2481 2482 statelim_opts.id = $1; 2483 2484 statelim_opts.marker |= STATELIM_M_ID; 2485 } 2486 | LIMIT NUMBER { 2487 if (ISSET(statelim_opts.marker, STATELIM_M_LIMIT)) { 2488 yyerror("limit cannot be respecified"); 2489 YYERROR; 2490 } 2491 2492 if ($2 < PF_STATELIM_LIMIT_MIN || 2493 $2 > PF_STATELIM_LIMIT_MAX) { 2494 yyerror("invalid state limiter limit"); 2495 YYERROR; 2496 } 2497 2498 statelim_opts.limit = $2; 2499 2500 statelim_opts.marker |= STATELIM_M_LIMIT; 2501 } 2502 | RATE NUMBER '/' NUMBER { 2503 if (ISSET(statelim_opts.marker, STATELIM_M_RATE)) { 2504 yyerror("rate cannot be respecified"); 2505 YYERROR; 2506 } 2507 if ($2 < 1) { 2508 yyerror("invalid rate limit %lld", $2); 2509 YYERROR; 2510 } 2511 if ($4 < 1) { 2512 yyerror("invalid rate seconds %lld", $4); 2513 YYERROR; 2514 } 2515 2516 statelim_opts.rate.limit = $2; 2517 statelim_opts.rate.seconds = $4; 2518 2519 statelim_opts.marker |= STATELIM_M_RATE; 2520 } 2521 ; 2522 2523 statelim_filter_opt 2524 : STATE LIMITER STRING limiter_opt_spec { 2525 struct pfctl_statelim *stlim; 2526 2527 stlim = pfctl_get_statelim_nm(pf, $3); 2528 free($3); 2529 if (stlim == NULL) { 2530 yyerror("state limiter not found"); 2531 YYERROR; 2532 } 2533 2534 $$.id = stlim->ioc.id; 2535 $$.limiter_action = $4; 2536 } 2537 | STATE LIMITER statelim_id limiter_opt_spec { 2538 $$.id = $3; 2539 $$.limiter_action = $4; 2540 } 2541 ; 2542 2543 sourcelim : sourcelim_nm sourcelim_opts { 2544 struct pfctl_sourcelim *srlim; 2545 size_t len; 2546 2547 if (!ISSET($2->marker, SOURCELIM_M_ID)) { 2548 yyerror("id not specified"); 2549 free($1); 2550 YYERROR; 2551 } 2552 if (!ISSET($2->marker, SOURCELIM_M_ENTRIES)) { 2553 yyerror("entries not specified"); 2554 free($1); 2555 YYERROR; 2556 } 2557 if (!ISSET($2->marker, SOURCELIM_M_LIMIT)) { 2558 yyerror("state limit not specified"); 2559 free($1); 2560 YYERROR; 2561 } 2562 2563 srlim = calloc(1, sizeof(*srlim)); 2564 if (srlim == NULL) 2565 err(1, "source limiter: malloc"); 2566 2567 len = strlcpy(srlim->ioc.name, $1, 2568 sizeof(srlim->ioc.name)); 2569 free($1); 2570 if (len >= sizeof(srlim->ioc.name)) { 2571 /* abort? */ 2572 YYERROR; 2573 } 2574 2575 srlim->ioc.id = $2->id; 2576 srlim->ioc.entries = $2->entries; 2577 srlim->ioc.limit = $2->limit; 2578 srlim->ioc.rate.limit = $2->rate.limit; 2579 srlim->ioc.rate.seconds = $2->rate.seconds; 2580 2581 if (ISSET($2->marker, SOURCELIM_M_TABLE)) { 2582 if (strlcpy(srlim->ioc.overload_tblname, 2583 $2->table.name, 2584 sizeof(srlim->ioc.overload_tblname)) >= 2585 sizeof(srlim->ioc.overload_tblname)) { 2586 abort(); 2587 } 2588 srlim->ioc.overload_hwm = $2->table.above; 2589 srlim->ioc.overload_lwm = $2->table.below; 2590 } 2591 2592 srlim->ioc.inet_prefix = $2->inet_mask; 2593 srlim->ioc.inet6_prefix = $2->inet6_mask; 2594 2595 if (pfctl_add_sourcelim(pf, srlim) != 0) { 2596 yyerror("source limiter %s id %u" 2597 " already exists", 2598 srlim->ioc.name, srlim->ioc.id); 2599 free(srlim); 2600 YYERROR; 2601 } 2602 } 2603 ; 2604 2605 sourcelim_nm : SOURCE LIMITER string { 2606 size_t len = strlen($3); 2607 if (len < 1) { 2608 yyerror("source limiter name is too short"); 2609 free($3); 2610 YYERROR; 2611 } 2612 if (len >= PF_SOURCELIM_NAME_LEN) { 2613 yyerror("source limiter name is too long"); 2614 free($3); 2615 YYERROR; 2616 } 2617 $$ = $3; 2618 } 2619 ; 2620 2621 sourcelim_id : ID NUMBER { 2622 if ($2 < PF_SOURCELIM_ID_MIN || 2623 $2 > PF_SOURCELIM_ID_MAX) { 2624 yyerror("source limiter id %lld: " 2625 "invalid identifier", $2); 2626 YYERROR; 2627 } 2628 2629 $$ = $2; 2630 } 2631 ; 2632 2633 sourcelim_opts : /* empty */ { 2634 yyerror("source limiter missing options"); 2635 YYERROR; 2636 } 2637 | { 2638 memset(&sourcelim_opts, 0, sizeof(sourcelim_opts)); 2639 sourcelim_opts.inet_mask = 32; 2640 sourcelim_opts.inet6_mask = 128; 2641 } sourcelim_opts_l { 2642 $$ = &sourcelim_opts; 2643 } 2644 ; 2645 2646 sourcelim_opts_l : sourcelim_opts_l sourcelim_opt 2647 | sourcelim_opt 2648 ; 2649 2650 sourcelim_opt : sourcelim_id { 2651 if (ISSET(sourcelim_opts.marker, SOURCELIM_M_ID)) { 2652 yyerror("entries cannot be respecified"); 2653 YYERROR; 2654 } 2655 2656 sourcelim_opts.id = $1; 2657 2658 sourcelim_opts.marker |= SOURCELIM_M_ID; 2659 } 2660 | ENTRIES NUMBER { 2661 if (ISSET(sourcelim_opts.marker, SOURCELIM_M_ENTRIES)) { 2662 yyerror("entries cannot be respecified"); 2663 YYERROR; 2664 } 2665 2666 sourcelim_opts.entries = $2; 2667 2668 sourcelim_opts.marker |= SOURCELIM_M_ENTRIES; 2669 } 2670 | LIMIT NUMBER { 2671 if (ISSET(sourcelim_opts.marker, SOURCELIM_M_LIMIT)) { 2672 yyerror("state limit cannot be respecified"); 2673 YYERROR; 2674 } 2675 2676 sourcelim_opts.limit = $2; 2677 2678 sourcelim_opts.marker |= SOURCELIM_M_LIMIT; 2679 } 2680 | RATE NUMBER '/' NUMBER { 2681 if (ISSET(sourcelim_opts.marker, SOURCELIM_M_RATE)) { 2682 yyerror("rate cannot be respecified"); 2683 YYERROR; 2684 } 2685 2686 sourcelim_opts.rate.limit = $2; 2687 sourcelim_opts.rate.seconds = $4; 2688 2689 sourcelim_opts.marker |= SOURCELIM_M_RATE; 2690 } 2691 | TABLE '<' STRING '>' ABOVE NUMBER sourcelim_opt_below { 2692 size_t stringlen; 2693 2694 if (ISSET(sourcelim_opts.marker, SOURCELIM_M_TABLE)) { 2695 free($3); 2696 yyerror("rate cannot be respecified"); 2697 YYERROR; 2698 } 2699 2700 stringlen = strlcpy(sourcelim_opts.table.name, 2701 $3, sizeof(sourcelim_opts.table.name)); 2702 free($3); 2703 if (stringlen == 0 || 2704 stringlen >= PF_TABLE_NAME_SIZE) { 2705 yyerror("invalid table name"); 2706 YYERROR; 2707 } 2708 2709 if ($6 < 0) { 2710 yyerror("above limit is invalid"); 2711 YYERROR; 2712 } 2713 if ($7 > $6) { 2714 yyerror("below limit higher than above limit"); 2715 YYERROR; 2716 } 2717 2718 sourcelim_opts.table.above = $6; 2719 sourcelim_opts.table.below = $7; 2720 2721 sourcelim_opts.marker |= SOURCELIM_M_TABLE; 2722 } 2723 | INET MASK NUMBER { 2724 if (ISSET(sourcelim_opts.marker, 2725 SOURCELIM_M_INET_MASK)) { 2726 yyerror("inet mask cannot be respecified"); 2727 YYERROR; 2728 } 2729 2730 if ($3 < 1 || $3 > 32) { 2731 yyerror("inet mask length out of range"); 2732 YYERROR; 2733 } 2734 2735 sourcelim_opts.inet_mask = $3; 2736 2737 sourcelim_opts.marker |= SOURCELIM_M_INET_MASK; 2738 } 2739 | INET6 MASK NUMBER { 2740 if (ISSET(sourcelim_opts.marker, 2741 SOURCELIM_M_INET6_MASK)) { 2742 yyerror("inet6 mask cannot be respecified"); 2743 YYERROR; 2744 } 2745 2746 if ($3 < 1 || $3 > 128) { 2747 yyerror("inet6 mask length out of range"); 2748 YYERROR; 2749 } 2750 2751 sourcelim_opts.inet6_mask = $3; 2752 2753 sourcelim_opts.marker |= SOURCELIM_M_INET6_MASK; 2754 } 2755 ; 2756 2757 sourcelim_opt_below 2758 : /* empty */ { 2759 $$ = 0; 2760 } 2761 | BELOW NUMBER { 2762 if ($2 < 1) { 2763 yyerror("below limit is invalid"); 2764 YYERROR; 2765 } 2766 $$ = $2; 2767 } 2768 ; 2769 2770 sourcelim_filter_opt 2771 : SOURCE LIMITER STRING limiter_opt_spec { 2772 struct pfctl_sourcelim *srlim; 2773 2774 srlim = pfctl_get_sourcelim_nm(pf, $3); 2775 free($3); 2776 if (srlim == NULL) { 2777 yyerror("source limiter not found"); 2778 YYERROR; 2779 } 2780 2781 $$.id = srlim->ioc.id; 2782 $$.limiter_action = $4; 2783 } 2784 | SOURCE LIMITER sourcelim_id limiter_opt_spec { 2785 $$.id = $3; 2786 $$.limiter_action = $4; 2787 } 2788 ; 2789 2790 limiter_opt_spec: /* empty */ { $$ = PF_LIMITER_DEFAULT; } 2791 | '(' limiter_opt ')' { $$ = $2; } 2792 ; 2793 2794 limiter_opt: BLOCK { 2795 $$ = PF_LIMITER_BLOCK; 2796 } 2797 | NOMATCH { 2798 $$ = PF_LIMITER_NOMATCH; 2799 } 2800 ; 2801 2802 pfrule : action dir logquick interface route af proto fromto 2803 filter_opts 2804 { 2805 struct pfctl_rule r; 2806 struct node_state_opt *o; 2807 struct node_proto *proto; 2808 int srctrack = 0; 2809 int statelock = 0; 2810 int adaptive = 0; 2811 int defaults = 0; 2812 2813 if (check_rulestate(PFCTL_STATE_FILTER)) 2814 YYERROR; 2815 2816 pfctl_init_rule(&r); 2817 2818 r.action = $1.b1; 2819 switch ($1.b2) { 2820 case PFRULE_RETURNRST: 2821 r.rule_flag |= PFRULE_RETURNRST; 2822 r.return_ttl = $1.w; 2823 break; 2824 case PFRULE_RETURNICMP: 2825 r.rule_flag |= PFRULE_RETURNICMP; 2826 r.return_icmp = $1.w; 2827 r.return_icmp6 = $1.w2; 2828 break; 2829 case PFRULE_RETURN: 2830 r.rule_flag |= PFRULE_RETURN; 2831 r.return_icmp = $1.w; 2832 r.return_icmp6 = $1.w2; 2833 break; 2834 } 2835 r.direction = $2; 2836 r.log = $3.log; 2837 r.logif = $3.logif; 2838 r.quick = $3.quick; 2839 r.af = $6; 2840 2841 if (filteropts_to_rule(&r, &$9)) 2842 YYERROR; 2843 2844 if ($9.flags.b1 || $9.flags.b2 || $8.src_os) { 2845 for (proto = $7; proto != NULL && 2846 proto->proto != IPPROTO_TCP; 2847 proto = proto->next) 2848 ; /* nothing */ 2849 if (proto == NULL && $7 != NULL) { 2850 if ($9.flags.b1 || $9.flags.b2) 2851 yyerror( 2852 "flags only apply to tcp"); 2853 if ($8.src_os) 2854 yyerror( 2855 "OS fingerprinting only " 2856 "apply to tcp"); 2857 YYERROR; 2858 } 2859 } 2860 2861 o = $9.keep.options; 2862 2863 /* 'keep state' by default on pass rules. */ 2864 if (!r.keep_state && !r.action && 2865 !($9.marker & FOM_KEEP)) { 2866 r.keep_state = PF_STATE_NORMAL; 2867 o = keep_state_defaults; 2868 defaults = 1; 2869 } 2870 2871 while (o) { 2872 struct node_state_opt *p = o; 2873 2874 switch (o->type) { 2875 case PF_STATE_OPT_MAX: 2876 if (r.max_states) { 2877 yyerror("state option 'max' " 2878 "multiple definitions"); 2879 YYERROR; 2880 } 2881 r.max_states = o->data.max_states; 2882 break; 2883 case PF_STATE_OPT_NOSYNC: 2884 if (r.rule_flag & PFRULE_NOSYNC) { 2885 yyerror("state option 'sync' " 2886 "multiple definitions"); 2887 YYERROR; 2888 } 2889 r.rule_flag |= PFRULE_NOSYNC; 2890 break; 2891 case PF_STATE_OPT_SRCTRACK: 2892 if (srctrack) { 2893 yyerror("state option " 2894 "'source-track' " 2895 "multiple definitions"); 2896 YYERROR; 2897 } 2898 srctrack = o->data.src_track; 2899 r.rule_flag |= PFRULE_SRCTRACK; 2900 break; 2901 case PF_STATE_OPT_MAX_SRC_STATES: 2902 if (r.max_src_states) { 2903 yyerror("state option " 2904 "'max-src-states' " 2905 "multiple definitions"); 2906 YYERROR; 2907 } 2908 if (o->data.max_src_states == 0) { 2909 yyerror("'max-src-states' must " 2910 "be > 0"); 2911 YYERROR; 2912 } 2913 r.max_src_states = 2914 o->data.max_src_states; 2915 r.rule_flag |= PFRULE_SRCTRACK; 2916 break; 2917 case PF_STATE_OPT_OVERLOAD: 2918 if (r.overload_tblname[0]) { 2919 yyerror("multiple 'overload' " 2920 "table definitions"); 2921 YYERROR; 2922 } 2923 if (strlcpy(r.overload_tblname, 2924 o->data.overload.tblname, 2925 PF_TABLE_NAME_SIZE) >= 2926 PF_TABLE_NAME_SIZE) { 2927 yyerror("state option: " 2928 "strlcpy"); 2929 YYERROR; 2930 } 2931 r.flush = o->data.overload.flush; 2932 break; 2933 case PF_STATE_OPT_MAX_SRC_CONN: 2934 if (r.max_src_conn) { 2935 yyerror("state option " 2936 "'max-src-conn' " 2937 "multiple definitions"); 2938 YYERROR; 2939 } 2940 if (o->data.max_src_conn == 0) { 2941 yyerror("'max-src-conn' " 2942 "must be > 0"); 2943 YYERROR; 2944 } 2945 r.max_src_conn = 2946 o->data.max_src_conn; 2947 r.rule_flag |= PFRULE_SRCTRACK | 2948 PFRULE_RULESRCTRACK; 2949 break; 2950 case PF_STATE_OPT_MAX_SRC_CONN_RATE: 2951 if (r.max_src_conn_rate.limit) { 2952 yyerror("state option " 2953 "'max-src-conn-rate' " 2954 "multiple definitions"); 2955 YYERROR; 2956 } 2957 if (!o->data.max_src_conn_rate.limit || 2958 !o->data.max_src_conn_rate.seconds) { 2959 yyerror("'max-src-conn-rate' " 2960 "values must be > 0"); 2961 YYERROR; 2962 } 2963 if (o->data.max_src_conn_rate.limit > 2964 PF_THRESHOLD_MAX) { 2965 yyerror("'max-src-conn-rate' " 2966 "maximum rate must be < %u", 2967 PF_THRESHOLD_MAX); 2968 YYERROR; 2969 } 2970 r.max_src_conn_rate.limit = 2971 o->data.max_src_conn_rate.limit; 2972 r.max_src_conn_rate.seconds = 2973 o->data.max_src_conn_rate.seconds; 2974 r.rule_flag |= PFRULE_SRCTRACK | 2975 PFRULE_RULESRCTRACK; 2976 break; 2977 case PF_STATE_OPT_MAX_SRC_NODES: 2978 if (r.max_src_nodes) { 2979 yyerror("state option " 2980 "'max-src-nodes' " 2981 "multiple definitions"); 2982 YYERROR; 2983 } 2984 if (o->data.max_src_nodes == 0) { 2985 yyerror("'max-src-nodes' must " 2986 "be > 0"); 2987 YYERROR; 2988 } 2989 r.max_src_nodes = 2990 o->data.max_src_nodes; 2991 r.rule_flag |= PFRULE_SRCTRACK | 2992 PFRULE_RULESRCTRACK; 2993 break; 2994 case PF_STATE_OPT_STATELOCK: 2995 if (statelock) { 2996 yyerror("state locking option: " 2997 "multiple definitions"); 2998 YYERROR; 2999 } 3000 statelock = 1; 3001 r.rule_flag |= o->data.statelock; 3002 break; 3003 case PF_STATE_OPT_SLOPPY: 3004 if (r.rule_flag & PFRULE_STATESLOPPY) { 3005 yyerror("state sloppy option: " 3006 "multiple definitions"); 3007 YYERROR; 3008 } 3009 r.rule_flag |= PFRULE_STATESLOPPY; 3010 break; 3011 case PF_STATE_OPT_PFLOW: 3012 if (r.rule_flag & PFRULE_PFLOW) { 3013 yyerror("state pflow option: " 3014 "multiple definitions"); 3015 YYERROR; 3016 } 3017 r.rule_flag |= PFRULE_PFLOW; 3018 break; 3019 case PF_STATE_OPT_ALLOW_RELATED: 3020 if (r.rule_flag & PFRULE_ALLOW_RELATED) { 3021 yyerror("state allow-related option: " 3022 "multiple definitions"); 3023 YYERROR; 3024 } 3025 r.rule_flag |= PFRULE_ALLOW_RELATED; 3026 break; 3027 case PF_STATE_OPT_TIMEOUT: 3028 if (o->data.timeout.number == 3029 PFTM_ADAPTIVE_START || 3030 o->data.timeout.number == 3031 PFTM_ADAPTIVE_END) 3032 adaptive = 1; 3033 if (r.timeout[o->data.timeout.number]) { 3034 yyerror("state timeout %s " 3035 "multiple definitions", 3036 pf_timeouts[o->data. 3037 timeout.number].name); 3038 YYERROR; 3039 } 3040 r.timeout[o->data.timeout.number] = 3041 o->data.timeout.seconds; 3042 break; 3043 } 3044 o = o->next; 3045 if (!defaults) 3046 free(p); 3047 } 3048 3049 /* 'flags S/SA' by default on stateful rules */ 3050 if (!r.action && !r.flags && !r.flagset && 3051 !$9.fragment && !($9.marker & FOM_FLAGS) && 3052 r.keep_state) { 3053 r.flags = parse_flags("S"); 3054 r.flagset = parse_flags("SA"); 3055 } 3056 if (!adaptive && r.max_states) { 3057 r.timeout[PFTM_ADAPTIVE_START] = 3058 (r.max_states / 10) * 6; 3059 r.timeout[PFTM_ADAPTIVE_END] = 3060 (r.max_states / 10) * 12; 3061 } 3062 if (r.rule_flag & PFRULE_SRCTRACK) { 3063 if (srctrack == PF_SRCTRACK_GLOBAL && 3064 r.max_src_nodes) { 3065 yyerror("'max-src-nodes' is " 3066 "incompatible with " 3067 "'source-track global'"); 3068 YYERROR; 3069 } 3070 if (srctrack == PF_SRCTRACK_GLOBAL && 3071 r.max_src_conn) { 3072 yyerror("'max-src-conn' is " 3073 "incompatible with " 3074 "'source-track global'"); 3075 YYERROR; 3076 } 3077 if (srctrack == PF_SRCTRACK_GLOBAL && 3078 r.max_src_conn_rate.seconds) { 3079 yyerror("'max-src-conn-rate' is " 3080 "incompatible with " 3081 "'source-track global'"); 3082 YYERROR; 3083 } 3084 if (r.timeout[PFTM_SRC_NODE] < 3085 r.max_src_conn_rate.seconds) 3086 r.timeout[PFTM_SRC_NODE] = 3087 r.max_src_conn_rate.seconds; 3088 r.rule_flag |= PFRULE_SRCTRACK; 3089 if (srctrack == PF_SRCTRACK_RULE) 3090 r.rule_flag |= PFRULE_RULESRCTRACK; 3091 } 3092 if (r.keep_state && !statelock) 3093 r.rule_flag |= default_statelock; 3094 3095 decide_address_family($8.src.host, &r.af); 3096 decide_address_family($8.dst.host, &r.af); 3097 3098 if ($5.rt) { 3099 if (!r.direction) { 3100 yyerror("direction must be explicit " 3101 "with rules that specify routing"); 3102 YYERROR; 3103 } 3104 r.rt = $5.rt; 3105 3106 if (!($5.redirspec->pool_opts.opts & PF_POOL_IPV6NH)) { 3107 decide_address_family($5.redirspec->host, &r.af); 3108 if (!(r.rule_flag & PFRULE_AFTO)) 3109 remove_invalid_hosts(&($5.redirspec->host), &r.af); 3110 if ($5.redirspec->host == NULL) { 3111 yyerror("no routing address with " 3112 "matching address family found."); 3113 YYERROR; 3114 } 3115 } 3116 } 3117 #ifdef __FreeBSD__ 3118 r.divert.port = $9.divert.port; 3119 #else 3120 if ((r.divert.port = $9.divert.port)) { 3121 if (r.direction == PF_OUT) { 3122 if ($9.divert.addr) { 3123 yyerror("address specified " 3124 "for outgoing divert"); 3125 YYERROR; 3126 } 3127 bzero(&r.divert.addr, 3128 sizeof(r.divert.addr)); 3129 } else { 3130 if (!$9.divert.addr) { 3131 yyerror("no address specified " 3132 "for incoming divert"); 3133 YYERROR; 3134 } 3135 if ($9.divert.addr->af != r.af) { 3136 yyerror("address family " 3137 "mismatch for divert"); 3138 YYERROR; 3139 } 3140 r.divert.addr = 3141 $9.divert.addr->addr.v.a.addr; 3142 } 3143 } 3144 #endif 3145 3146 if ($9.dnpipe || $9.dnrpipe) { 3147 r.dnpipe = $9.dnpipe; 3148 r.dnrpipe = $9.dnrpipe; 3149 if ($9.free_flags & PFRULE_DN_IS_PIPE) 3150 r.free_flags |= PFRULE_DN_IS_PIPE; 3151 else 3152 r.free_flags |= PFRULE_DN_IS_QUEUE; 3153 } 3154 3155 if ($9.marker & FOM_AFTO) { 3156 r.naf = $9.nat->af; 3157 } else { 3158 if ($9.nat) { 3159 if (!r.af && ! $9.nat->host->ifindex) 3160 r.af = $9.nat->host->af; 3161 remove_invalid_hosts(&($9.nat->host), &r.af); 3162 if (invalid_redirect($9.nat->host, r.af)) 3163 YYERROR; 3164 if ($9.nat->host->addr.type == PF_ADDR_DYNIFTL) { 3165 if (($9.nat->host = gen_dynnode($9.nat->host, r.af)) == NULL) 3166 err(1, "calloc"); 3167 } 3168 if (check_netmask($9.nat->host, r.af)) 3169 YYERROR; 3170 } 3171 if ($9.rdr) { 3172 if (!r.af && ! $9.rdr->host->ifindex) 3173 r.af = $9.rdr->host->af; 3174 remove_invalid_hosts(&($9.rdr->host), &r.af); 3175 if (invalid_redirect($9.rdr->host, r.af)) 3176 YYERROR; 3177 if ($9.rdr->host->addr.type == PF_ADDR_DYNIFTL) { 3178 if (($9.rdr->host = gen_dynnode($9.rdr->host, r.af)) == NULL) 3179 err(1, "calloc"); 3180 } 3181 if (check_netmask($9.rdr->host, r.af)) 3182 YYERROR; 3183 } 3184 } 3185 3186 expand_rule(&r, false, $4, $9.nat, $9.rdr, $5.redirspec, 3187 $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host, 3188 $8.dst.port, $9.uid, $9.gid, $9.rcv, $9.icmpspec); 3189 } 3190 ; 3191 3192 filter_opts : { 3193 bzero(&filter_opts, sizeof filter_opts); 3194 filter_opts.statelim.id = PF_STATELIM_ID_NONE; 3195 filter_opts.statelim.limiter_action = PF_LIMITER_NOMATCH; 3196 filter_opts.sourcelim.id = PF_SOURCELIM_ID_NONE; 3197 filter_opts.sourcelim.limiter_action = PF_LIMITER_NOMATCH; 3198 filter_opts.rtableid = -1; 3199 } 3200 filter_opts_l 3201 { $$ = filter_opts; } 3202 | /* empty */ { 3203 bzero(&filter_opts, sizeof filter_opts); 3204 filter_opts.statelim.id = PF_STATELIM_ID_NONE; 3205 filter_opts.statelim.limiter_action = PF_LIMITER_NOMATCH; 3206 filter_opts.sourcelim.id = PF_SOURCELIM_ID_NONE; 3207 filter_opts.sourcelim.limiter_action = PF_LIMITER_NOMATCH; 3208 filter_opts.rtableid = -1; 3209 $$ = filter_opts; 3210 } 3211 ; 3212 3213 filter_opts_l : filter_opts_l filter_opt 3214 | filter_opt 3215 ; 3216 3217 filter_opt : USER uids { 3218 if (filter_opts.uid) 3219 $2->tail->next = filter_opts.uid; 3220 filter_opts.uid = $2; 3221 } 3222 | GROUP gids { 3223 if (filter_opts.gid) 3224 $2->tail->next = filter_opts.gid; 3225 filter_opts.gid = $2; 3226 } 3227 | flags { 3228 if (filter_opts.marker & FOM_FLAGS) { 3229 yyerror("flags cannot be redefined"); 3230 YYERROR; 3231 } 3232 filter_opts.marker |= FOM_FLAGS; 3233 filter_opts.flags.b1 |= $1.b1; 3234 filter_opts.flags.b2 |= $1.b2; 3235 filter_opts.flags.w |= $1.w; 3236 filter_opts.flags.w2 |= $1.w2; 3237 } 3238 | icmpspec { 3239 if (filter_opts.marker & FOM_ICMP) { 3240 yyerror("icmp-type cannot be redefined"); 3241 YYERROR; 3242 } 3243 filter_opts.marker |= FOM_ICMP; 3244 filter_opts.icmpspec = $1; 3245 } 3246 | PRIO NUMBER { 3247 if (filter_opts.marker & FOM_PRIO) { 3248 yyerror("prio cannot be redefined"); 3249 YYERROR; 3250 } 3251 if ($2 < 0 || $2 > PF_PRIO_MAX) { 3252 yyerror("prio must be 0 - %u", PF_PRIO_MAX); 3253 YYERROR; 3254 } 3255 filter_opts.marker |= FOM_PRIO; 3256 filter_opts.prio = $2; 3257 } 3258 | TOS tos { 3259 if (filter_opts.marker & FOM_TOS) { 3260 yyerror("tos cannot be redefined"); 3261 YYERROR; 3262 } 3263 filter_opts.marker |= FOM_TOS; 3264 filter_opts.tos = $2; 3265 } 3266 | keep { 3267 if (filter_opts.marker & FOM_KEEP) { 3268 yyerror("modulate or keep cannot be redefined"); 3269 YYERROR; 3270 } 3271 filter_opts.marker |= FOM_KEEP; 3272 filter_opts.keep.action = $1.action; 3273 filter_opts.keep.options = $1.options; 3274 } 3275 | RIDENTIFIER number { 3276 filter_opts.ridentifier = $2; 3277 } 3278 | FRAGMENT { 3279 filter_opts.fragment = 1; 3280 } 3281 | ALLOWOPTS { 3282 filter_opts.allowopts = 1; 3283 } 3284 | label { 3285 if (filter_opts.labelcount >= PF_RULE_MAX_LABEL_COUNT) { 3286 yyerror("label can only be used %d times", PF_RULE_MAX_LABEL_COUNT); 3287 YYERROR; 3288 } 3289 filter_opts.label[filter_opts.labelcount++] = $1; 3290 } 3291 | qname { 3292 if (filter_opts.queues.qname) { 3293 yyerror("queue cannot be redefined"); 3294 YYERROR; 3295 } 3296 filter_opts.queues = $1; 3297 } 3298 | DNPIPE number { 3299 filter_opts.dnpipe = $2; 3300 filter_opts.free_flags |= PFRULE_DN_IS_PIPE; 3301 } 3302 | DNPIPE '(' number ')' { 3303 filter_opts.dnpipe = $3; 3304 filter_opts.free_flags |= PFRULE_DN_IS_PIPE; 3305 } 3306 | DNPIPE '(' number comma number ')' { 3307 filter_opts.dnrpipe = $5; 3308 filter_opts.dnpipe = $3; 3309 filter_opts.free_flags |= PFRULE_DN_IS_PIPE; 3310 } 3311 | DNQUEUE number { 3312 filter_opts.dnpipe = $2; 3313 filter_opts.free_flags |= PFRULE_DN_IS_QUEUE; 3314 } 3315 | DNQUEUE '(' number comma number ')' { 3316 filter_opts.dnrpipe = $5; 3317 filter_opts.dnpipe = $3; 3318 filter_opts.free_flags |= PFRULE_DN_IS_QUEUE; 3319 } 3320 | DNQUEUE '(' number ')' { 3321 filter_opts.dnpipe = $3; 3322 filter_opts.free_flags |= PFRULE_DN_IS_QUEUE; 3323 } 3324 | TAG string { 3325 filter_opts.tag = $2; 3326 } 3327 | not TAGGED string { 3328 filter_opts.match_tag = $3; 3329 filter_opts.match_tag_not = $1; 3330 } 3331 | not RECEIVEDON if_item { 3332 if (filter_opts.rcv) { 3333 yyerror("cannot respecify received-on"); 3334 YYERROR; 3335 } 3336 filter_opts.rcv = $3; 3337 filter_opts.rcv->not = $1; 3338 } 3339 | PROBABILITY probability { 3340 double p; 3341 3342 p = floor($2 * UINT_MAX + 0.5); 3343 if (p < 0.0 || p > UINT_MAX) { 3344 yyerror("invalid probability: %lf", p); 3345 YYERROR; 3346 } 3347 filter_opts.prob = (u_int32_t)p; 3348 if (filter_opts.prob == 0) 3349 filter_opts.prob = 1; 3350 } 3351 | statelim_filter_opt { 3352 if (filter_opts.statelim.id != PF_STATELIM_ID_NONE) { 3353 yyerror("state limiter already specified"); 3354 YYERROR; 3355 } 3356 filter_opts.statelim = $1; 3357 } 3358 | sourcelim_filter_opt { 3359 if (filter_opts.sourcelim.id != PF_SOURCELIM_ID_NONE) { 3360 yyerror("source limiter already specified"); 3361 YYERROR; 3362 } 3363 filter_opts.sourcelim = $1; 3364 } 3365 | RTABLE NUMBER { 3366 if ($2 < 0 || $2 > rt_tableid_max()) { 3367 yyerror("invalid rtable id"); 3368 YYERROR; 3369 } 3370 filter_opts.rtableid = $2; 3371 } 3372 | DIVERTTO portplain { 3373 #ifdef __FreeBSD__ 3374 filter_opts.divert.port = $2.a; 3375 if (!filter_opts.divert.port) { 3376 yyerror("invalid divert port: %u", ntohs($2.a)); 3377 YYERROR; 3378 } 3379 #endif 3380 } 3381 | DIVERTTO STRING PORT portplain { 3382 #ifndef __FreeBSD__ 3383 if ((filter_opts.divert.addr = host($2, pf->opts)) == NULL) { 3384 yyerror("could not parse divert address: %s", 3385 $2); 3386 free($2); 3387 YYERROR; 3388 } 3389 #else 3390 if ($2) 3391 #endif 3392 free($2); 3393 filter_opts.divert.port = $4.a; 3394 if (!filter_opts.divert.port) { 3395 yyerror("invalid divert port: %u", ntohs($4.a)); 3396 YYERROR; 3397 } 3398 } 3399 | DIVERTREPLY { 3400 #ifdef __FreeBSD__ 3401 yyerror("divert-reply has no meaning in FreeBSD pf(4)"); 3402 YYERROR; 3403 #else 3404 filter_opts.divert.port = 1; /* some random value */ 3405 #endif 3406 } 3407 | SCRUB '(' scrub_opts ')' { 3408 filter_opts.nodf = $3.nodf; 3409 filter_opts.minttl = $3.minttl; 3410 if ($3.marker & FOM_SETTOS) { 3411 /* Old style rules are "scrub set-tos 0x42" 3412 * New style are "set tos 0x42 scrub (...)" 3413 * What is in "scrub(...)"" is unfortunately the 3414 * original scrub syntax so it would overwrite 3415 * "set tos" of a pass/match rule. 3416 */ 3417 filter_opts.settos = $3.settos; 3418 } 3419 filter_opts.randomid = $3.randomid; 3420 filter_opts.max_mss = $3.maxmss; 3421 if ($3.reassemble_tcp) 3422 filter_opts.marker |= FOM_SCRUB_TCP; 3423 filter_opts.marker |= $3.marker; 3424 } 3425 | NATTO port_redirspec { 3426 if (filter_opts.nat) { 3427 yyerror("cannot respecify nat-to/binat-to"); 3428 YYERROR; 3429 } 3430 filter_opts.nat = $2; 3431 } 3432 | RDRTO port_redirspec { 3433 if (filter_opts.rdr) { 3434 yyerror("cannot respecify rdr-to"); 3435 YYERROR; 3436 } 3437 filter_opts.rdr = $2; 3438 } 3439 | BINATTO port_redirspec { 3440 if (filter_opts.nat) { 3441 yyerror("cannot respecify nat-to/binat-to"); 3442 YYERROR; 3443 } 3444 filter_opts.nat = $2; 3445 filter_opts.nat->binat = 1; 3446 filter_opts.nat->pool_opts.staticport = 1; 3447 } 3448 | AFTO af FROM port_redirspec { 3449 if (filter_opts.nat) { 3450 yyerror("cannot respecify af-to"); 3451 YYERROR; 3452 } 3453 if ($2 == 0) { 3454 yyerror("no address family specified"); 3455 YYERROR; 3456 } 3457 3458 filter_opts.nat = $4; 3459 filter_opts.nat->af = $2; 3460 remove_invalid_hosts(&($4->host), &(filter_opts.nat->af)); 3461 if ($4->host == NULL) { 3462 yyerror("af-to addresses must be in the " 3463 "target address family"); 3464 YYERROR; 3465 } 3466 filter_opts.marker |= FOM_AFTO; 3467 } 3468 | AFTO af FROM port_redirspec TO port_redirspec { 3469 if (filter_opts.nat) { 3470 yyerror("cannot respecify af-to"); 3471 YYERROR; 3472 } 3473 if ($2 == 0) { 3474 yyerror("no address family specified"); 3475 YYERROR; 3476 } 3477 filter_opts.nat = $4; 3478 filter_opts.nat->af = $2; 3479 filter_opts.rdr = $6; 3480 filter_opts.rdr->af = $2; 3481 remove_invalid_hosts(&($4->host), &(filter_opts.nat->af)); 3482 remove_invalid_hosts(&($6->host), &(filter_opts.rdr->af)); 3483 if ($4->host == NULL || $6->host == NULL) { 3484 yyerror("af-to addresses must be in the " 3485 "target address family"); 3486 YYERROR; 3487 } 3488 filter_opts.marker |= FOM_AFTO; 3489 } 3490 | MAXPKTRATE NUMBER '/' NUMBER { 3491 if ($2 < 0 || $2 > UINT_MAX || 3492 $4 < 0 || $4 > UINT_MAX) { 3493 yyerror("only positive values permitted"); 3494 YYERROR; 3495 } 3496 if (filter_opts.pktrate.limit) { 3497 yyerror("cannot respecify max-pkt-rate"); 3498 YYERROR; 3499 } 3500 filter_opts.pktrate.limit = $2; 3501 filter_opts.pktrate.seconds = $4; 3502 } 3503 | MAXPKTSIZE NUMBER { 3504 if ($2 < 0 || $2 > UINT16_MAX) { 3505 yyerror("only positive values permitted"); 3506 YYERROR; 3507 } 3508 filter_opts.max_pkt_size = $2; 3509 } 3510 | ONCE { 3511 filter_opts.marker |= FOM_ONCE; 3512 } 3513 | filter_sets 3514 ; 3515 3516 filter_sets : SET '(' filter_sets_l ')' { $$ = filter_opts; } 3517 | SET filter_set { $$ = filter_opts; } 3518 ; 3519 3520 filter_sets_l : filter_sets_l comma filter_set 3521 | filter_set 3522 ; 3523 3524 filter_set : prio { 3525 if (filter_opts.marker & FOM_SETPRIO) { 3526 yyerror("prio cannot be redefined"); 3527 YYERROR; 3528 } 3529 filter_opts.marker |= FOM_SETPRIO; 3530 filter_opts.set_prio[0] = $1.b1; 3531 filter_opts.set_prio[1] = $1.b2; 3532 } 3533 | TOS tos { 3534 if (filter_opts.marker & FOM_SETTOS) { 3535 yyerror("tos cannot be respecified"); 3536 YYERROR; 3537 } 3538 filter_opts.marker |= FOM_SETTOS; 3539 filter_opts.settos = $2; 3540 } 3541 prio : PRIO NUMBER { 3542 if ($2 < 0 || $2 > PF_PRIO_MAX) { 3543 yyerror("prio must be 0 - %u", PF_PRIO_MAX); 3544 YYERROR; 3545 } 3546 $$.b1 = $$.b2 = $2; 3547 } 3548 | PRIO '(' NUMBER comma NUMBER ')' { 3549 if ($3 < 0 || $3 > PF_PRIO_MAX || 3550 $5 < 0 || $5 > PF_PRIO_MAX) { 3551 yyerror("prio must be 0 - %u", PF_PRIO_MAX); 3552 YYERROR; 3553 } 3554 $$.b1 = $3; 3555 $$.b2 = $5; 3556 } 3557 ; 3558 3559 probability : STRING { 3560 char *e; 3561 double p = strtod($1, &e); 3562 3563 if (*e == '%') { 3564 p *= 0.01; 3565 e++; 3566 } 3567 if (*e) { 3568 yyerror("invalid probability: %s", $1); 3569 free($1); 3570 YYERROR; 3571 } 3572 free($1); 3573 $$ = p; 3574 } 3575 | NUMBER { 3576 $$ = (double)$1; 3577 } 3578 ; 3579 3580 3581 action : PASS { 3582 $$.b1 = PF_PASS; 3583 $$.b2 = failpolicy; 3584 $$.w = returnicmpdefault; 3585 $$.w2 = returnicmp6default; 3586 } 3587 | MATCH { $$.b1 = PF_MATCH; $$.b2 = $$.w = 0; } 3588 | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } 3589 ; 3590 3591 blockspec : /* empty */ { 3592 $$.b2 = blockpolicy; 3593 $$.w = returnicmpdefault; 3594 $$.w2 = returnicmp6default; 3595 } 3596 | DROP { 3597 $$.b2 = PFRULE_DROP; 3598 $$.w = 0; 3599 $$.w2 = 0; 3600 } 3601 | RETURNRST { 3602 $$.b2 = PFRULE_RETURNRST; 3603 $$.w = 0; 3604 $$.w2 = 0; 3605 } 3606 | RETURNRST '(' TTL NUMBER ')' { 3607 if ($4 < 0 || $4 > 255) { 3608 yyerror("illegal ttl value %d", $4); 3609 YYERROR; 3610 } 3611 $$.b2 = PFRULE_RETURNRST; 3612 $$.w = $4; 3613 $$.w2 = 0; 3614 } 3615 | RETURNICMP { 3616 $$.b2 = PFRULE_RETURNICMP; 3617 $$.w = returnicmpdefault; 3618 $$.w2 = returnicmp6default; 3619 } 3620 | RETURNICMP6 { 3621 $$.b2 = PFRULE_RETURNICMP; 3622 $$.w = returnicmpdefault; 3623 $$.w2 = returnicmp6default; 3624 } 3625 | RETURNICMP '(' reticmpspec ')' { 3626 $$.b2 = PFRULE_RETURNICMP; 3627 $$.w = $3; 3628 $$.w2 = returnicmpdefault; 3629 } 3630 | RETURNICMP6 '(' reticmp6spec ')' { 3631 $$.b2 = PFRULE_RETURNICMP; 3632 $$.w = returnicmpdefault; 3633 $$.w2 = $3; 3634 } 3635 | RETURNICMP '(' reticmpspec comma reticmp6spec ')' { 3636 $$.b2 = PFRULE_RETURNICMP; 3637 $$.w = $3; 3638 $$.w2 = $5; 3639 } 3640 | RETURN { 3641 $$.b2 = PFRULE_RETURN; 3642 $$.w = returnicmpdefault; 3643 $$.w2 = returnicmp6default; 3644 } 3645 ; 3646 3647 reticmpspec : STRING { 3648 if (!($$ = parseicmpspec($1, AF_INET))) { 3649 free($1); 3650 YYERROR; 3651 } 3652 free($1); 3653 } 3654 | NUMBER { 3655 u_int8_t icmptype; 3656 3657 if ($1 < 0 || $1 > 255) { 3658 yyerror("invalid icmp code %lu", $1); 3659 YYERROR; 3660 } 3661 icmptype = returnicmpdefault >> 8; 3662 $$ = (icmptype << 8 | $1); 3663 } 3664 ; 3665 3666 reticmp6spec : STRING { 3667 if (!($$ = parseicmpspec($1, AF_INET6))) { 3668 free($1); 3669 YYERROR; 3670 } 3671 free($1); 3672 } 3673 | NUMBER { 3674 u_int8_t icmptype; 3675 3676 if ($1 < 0 || $1 > 255) { 3677 yyerror("invalid icmp code %lu", $1); 3678 YYERROR; 3679 } 3680 icmptype = returnicmp6default >> 8; 3681 $$ = (icmptype << 8 | $1); 3682 } 3683 ; 3684 3685 dir : /* empty */ { $$ = PF_INOUT; } 3686 | IN { $$ = PF_IN; } 3687 | OUT { $$ = PF_OUT; } 3688 ; 3689 3690 quick : /* empty */ { $$.quick = 0; } 3691 | QUICK { $$.quick = 1; } 3692 ; 3693 3694 logquick : /* empty */ { $$.log = 0; $$.quick = 0; $$.logif = 0; } 3695 | log { $$ = $1; $$.quick = 0; } 3696 | QUICK { $$.quick = 1; $$.log = 0; $$.logif = 0; } 3697 | log QUICK { $$ = $1; $$.quick = 1; } 3698 | QUICK log { $$ = $2; $$.quick = 1; } 3699 ; 3700 3701 log : LOG { $$.log = PF_LOG; $$.logif = 0; } 3702 | LOG '(' logopts ')' { 3703 $$.log = PF_LOG | $3.log; 3704 $$.logif = $3.logif; 3705 } 3706 ; 3707 3708 logopts : logopt { $$ = $1; } 3709 | logopts comma logopt { 3710 $$.log = $1.log | $3.log; 3711 $$.logif = $3.logif; 3712 if ($$.logif == 0) 3713 $$.logif = $1.logif; 3714 } 3715 ; 3716 3717 logopt : ALL { $$.log = PF_LOG_ALL; $$.logif = 0; } 3718 | MATCHES { $$.log = PF_LOG_MATCHES; $$.logif = 0; } 3719 | USER { $$.log = PF_LOG_USER; $$.logif = 0; } 3720 | TO string { 3721 const char *errstr; 3722 u_int i; 3723 3724 $$.log = 0; 3725 if (strncmp($2, "pflog", 5)) { 3726 yyerror("%s: should be a pflog interface", $2); 3727 free($2); 3728 YYERROR; 3729 } 3730 i = strtonum($2 + 5, 0, 255, &errstr); 3731 if (errstr) { 3732 yyerror("%s: %s", $2, errstr); 3733 free($2); 3734 YYERROR; 3735 } 3736 free($2); 3737 $$.logif = i; 3738 } 3739 ; 3740 3741 interface : /* empty */ { $$ = NULL; } 3742 | ON if_item_not { $$ = $2; } 3743 | ON '{' optnl if_list '}' { $$ = $4; } 3744 ; 3745 3746 if_list : if_item_not optnl { $$ = $1; } 3747 | if_list comma if_item_not optnl { 3748 $1->tail->next = $3; 3749 $1->tail = $3; 3750 $$ = $1; 3751 } 3752 ; 3753 3754 if_item_not : not if_item { $$ = $2; $$->not = $1; } 3755 ; 3756 3757 if_item : STRING { 3758 struct node_host *n; 3759 3760 $$ = calloc(1, sizeof(struct node_if)); 3761 if ($$ == NULL) 3762 err(1, "if_item: calloc"); 3763 if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >= 3764 sizeof($$->ifname)) { 3765 free($1); 3766 free($$); 3767 yyerror("interface name too long"); 3768 YYERROR; 3769 } 3770 3771 if ((n = ifa_exists($1)) != NULL) 3772 $$->ifa_flags = n->ifa_flags; 3773 3774 free($1); 3775 $$->not = 0; 3776 $$->next = NULL; 3777 $$->tail = $$; 3778 } 3779 | ANY { 3780 $$ = calloc(1, sizeof(struct node_if)); 3781 if ($$ == NULL) 3782 err(1, "if_item: calloc"); 3783 strlcpy($$->ifname, "any", sizeof($$->ifname)); 3784 $$->not = 0; 3785 $$->next = NULL; 3786 $$->tail = $$; 3787 } 3788 ; 3789 3790 af : /* empty */ { $$ = 0; } 3791 | INET { $$ = AF_INET; } 3792 | INET6 { $$ = AF_INET6; } 3793 ; 3794 3795 etherproto : /* empty */ { $$ = NULL; } 3796 | PROTO etherproto_item { $$ = $2; } 3797 | PROTO '{' optnl etherproto_list '}' { $$ = $4; } 3798 ; 3799 3800 etherproto_list : etherproto_item optnl { $$ = $1; } 3801 | etherproto_list comma etherproto_item optnl { 3802 $1->tail->next = $3; 3803 $1->tail = $3; 3804 $$ = $1; 3805 } 3806 ; 3807 3808 etherproto_item : etherprotoval { 3809 u_int16_t pr; 3810 3811 pr = (u_int16_t)$1; 3812 if (pr == 0) { 3813 yyerror("proto 0 cannot be used"); 3814 YYERROR; 3815 } 3816 $$ = calloc(1, sizeof(struct node_proto)); 3817 if ($$ == NULL) 3818 err(1, "proto_item: calloc"); 3819 $$->proto = pr; 3820 $$->next = NULL; 3821 $$->tail = $$; 3822 } 3823 ; 3824 3825 etherprotoval : NUMBER { 3826 if ($1 < 0 || $1 > 65565) { 3827 yyerror("protocol outside range"); 3828 YYERROR; 3829 } 3830 } 3831 | STRING 3832 { 3833 if (!strncmp($1, "0x", 2)) { 3834 if (sscanf($1, "0x%4x", &$$) != 1) { 3835 free($1); 3836 yyerror("invalid EtherType hex"); 3837 YYERROR; 3838 } 3839 } else { 3840 yyerror("Symbolic EtherType not yet supported"); 3841 } 3842 } 3843 ; 3844 3845 proto : /* empty */ { $$ = NULL; } 3846 | PROTO proto_item { $$ = $2; } 3847 | PROTO '{' optnl proto_list '}' { $$ = $4; } 3848 ; 3849 3850 proto_list : proto_item optnl { $$ = $1; } 3851 | proto_list comma proto_item optnl { 3852 $1->tail->next = $3; 3853 $1->tail = $3; 3854 $$ = $1; 3855 } 3856 ; 3857 3858 proto_item : protoval { 3859 u_int8_t pr; 3860 3861 pr = (u_int8_t)$1; 3862 if (pr == 0) { 3863 yyerror("proto 0 cannot be used"); 3864 YYERROR; 3865 } 3866 $$ = calloc(1, sizeof(struct node_proto)); 3867 if ($$ == NULL) 3868 err(1, "proto_item: calloc"); 3869 $$->proto = pr; 3870 $$->next = NULL; 3871 $$->tail = $$; 3872 } 3873 ; 3874 3875 protoval : STRING { 3876 struct protoent *p; 3877 3878 p = getprotobyname($1); 3879 if (p == NULL) { 3880 yyerror("unknown protocol %s", $1); 3881 free($1); 3882 YYERROR; 3883 } 3884 $$ = p->p_proto; 3885 free($1); 3886 } 3887 | NUMBER { 3888 if ($1 < 0 || $1 > 255) { 3889 yyerror("protocol outside range"); 3890 YYERROR; 3891 } 3892 } 3893 ; 3894 3895 l3fromto : /* empty */ { 3896 bzero(&$$, sizeof($$)); 3897 } 3898 | L3 fromto { 3899 if ($2.src.host != NULL && 3900 $2.src.host->addr.type != PF_ADDR_ADDRMASK && 3901 $2.src.host->addr.type != PF_ADDR_TABLE) { 3902 yyerror("from must be an address or table"); 3903 YYERROR; 3904 } 3905 if ($2.dst.host != NULL && 3906 $2.dst.host->addr.type != PF_ADDR_ADDRMASK && 3907 $2.dst.host->addr.type != PF_ADDR_TABLE) { 3908 yyerror("to must be an address or table"); 3909 YYERROR; 3910 } 3911 $$ = $2; 3912 } 3913 ; 3914 etherfromto : ALL { 3915 $$.src = NULL; 3916 $$.dst = NULL; 3917 } 3918 | etherfrom etherto { 3919 $$.src = $1.mac; 3920 $$.dst = $2.mac; 3921 } 3922 ; 3923 3924 etherfrom : /* emtpy */ { 3925 bzero(&$$, sizeof($$)); 3926 } 3927 | FROM macspec { 3928 $$.mac = $2; 3929 } 3930 ; 3931 3932 etherto : /* empty */ { 3933 bzero(&$$, sizeof($$)); 3934 } 3935 | TO macspec { 3936 $$.mac = $2; 3937 } 3938 ; 3939 3940 mac : string '/' NUMBER { 3941 $$ = node_mac_from_string_masklen($1, $3); 3942 free($1); 3943 if ($$ == NULL) 3944 YYERROR; 3945 } 3946 | string { 3947 if (strchr($1, '&')) { 3948 /* mac&mask */ 3949 char *mac = strtok($1, "&"); 3950 char *mask = strtok(NULL, "&"); 3951 $$ = node_mac_from_string_mask(mac, mask); 3952 } else { 3953 $$ = node_mac_from_string($1); 3954 } 3955 free($1); 3956 if ($$ == NULL) 3957 YYERROR; 3958 3959 } 3960 xmac : not mac { 3961 struct node_mac *n; 3962 3963 for (n = $2; n != NULL; n = n->next) 3964 n->neg = $1; 3965 $$ = $2; 3966 } 3967 ; 3968 macspec : xmac { 3969 $$ = $1; 3970 } 3971 | '{' optnl mac_list '}' 3972 { 3973 $$ = $3; 3974 } 3975 ; 3976 mac_list : xmac optnl { 3977 $$ = $1; 3978 } 3979 | mac_list comma xmac { 3980 if ($3 == NULL) 3981 $$ = $1; 3982 else if ($1 == NULL) 3983 $$ = $3; 3984 else { 3985 $1->tail->next = $3; 3986 $1->tail = $3->tail; 3987 $$ = $1; 3988 } 3989 } 3990 3991 fromto : ALL { 3992 $$.src.host = NULL; 3993 $$.src.port = NULL; 3994 $$.dst.host = NULL; 3995 $$.dst.port = NULL; 3996 $$.src_os = NULL; 3997 } 3998 | from os to { 3999 $$.src = $1; 4000 $$.src_os = $2; 4001 $$.dst = $3; 4002 } 4003 ; 4004 4005 os : /* empty */ { $$ = NULL; } 4006 | OS xos { $$ = $2; } 4007 | OS '{' optnl os_list '}' { $$ = $4; } 4008 ; 4009 4010 xos : STRING { 4011 $$ = calloc(1, sizeof(struct node_os)); 4012 if ($$ == NULL) 4013 err(1, "os: calloc"); 4014 $$->os = $1; 4015 $$->tail = $$; 4016 } 4017 ; 4018 4019 os_list : xos optnl { $$ = $1; } 4020 | os_list comma xos optnl { 4021 $1->tail->next = $3; 4022 $1->tail = $3; 4023 $$ = $1; 4024 } 4025 ; 4026 4027 from : /* empty */ { 4028 $$.host = NULL; 4029 $$.port = NULL; 4030 } 4031 | FROM ipportspec { 4032 $$ = $2; 4033 } 4034 ; 4035 4036 to : /* empty */ { 4037 $$.host = NULL; 4038 $$.port = NULL; 4039 } 4040 | TO ipportspec { 4041 if (disallow_urpf_failed($2.host, "\"urpf-failed\" is " 4042 "not permitted in a destination address")) 4043 YYERROR; 4044 $$ = $2; 4045 } 4046 ; 4047 4048 ipportspec : ipspec { 4049 $$.host = $1; 4050 $$.port = NULL; 4051 } 4052 | ipspec PORT portspec { 4053 $$.host = $1; 4054 $$.port = $3; 4055 } 4056 | PORT portspec { 4057 $$.host = NULL; 4058 $$.port = $2; 4059 } 4060 ; 4061 4062 optnl : '\n' optnl 4063 | 4064 ; 4065 4066 ipspec : ANY { $$ = NULL; } 4067 | xhost { $$ = $1; } 4068 | '{' optnl host_list '}' { $$ = $3; } 4069 ; 4070 4071 toipspec : TO ipspec { $$ = $2; } 4072 | /* empty */ { $$ = NULL; } 4073 ; 4074 4075 host_list : ipspec optnl { $$ = $1; } 4076 | host_list comma ipspec optnl { 4077 if ($1 == NULL) { 4078 freehostlist($3); 4079 $$ = $1; 4080 } else if ($3 == NULL) { 4081 freehostlist($1); 4082 $$ = $3; 4083 } else { 4084 $1->tail->next = $3; 4085 $1->tail = $3->tail; 4086 $$ = $1; 4087 } 4088 } 4089 ; 4090 4091 xhost : not host { 4092 struct node_host *n; 4093 4094 for (n = $2; n != NULL; n = n->next) 4095 n->not = $1; 4096 $$ = $2; 4097 } 4098 | not NOROUTE { 4099 $$ = calloc(1, sizeof(struct node_host)); 4100 if ($$ == NULL) 4101 err(1, "xhost: calloc"); 4102 $$->addr.type = PF_ADDR_NOROUTE; 4103 $$->next = NULL; 4104 $$->not = $1; 4105 $$->tail = $$; 4106 } 4107 | not URPFFAILED { 4108 $$ = calloc(1, sizeof(struct node_host)); 4109 if ($$ == NULL) 4110 err(1, "xhost: calloc"); 4111 $$->addr.type = PF_ADDR_URPFFAILED; 4112 $$->next = NULL; 4113 $$->not = $1; 4114 $$->tail = $$; 4115 } 4116 ; 4117 4118 host : STRING { 4119 if (($$ = host($1, pf->opts)) == NULL) { 4120 /* error. "any" is handled elsewhere */ 4121 free($1); 4122 yyerror("could not parse host specification"); 4123 YYERROR; 4124 } 4125 free($1); 4126 4127 } 4128 | STRING '-' STRING { 4129 struct node_host *b, *e; 4130 4131 if ((b = host($1, pf->opts)) == NULL || 4132 (e = host($3, pf->opts)) == NULL) { 4133 free($1); 4134 free($3); 4135 yyerror("could not parse host specification"); 4136 YYERROR; 4137 } 4138 if (b->af != e->af || 4139 b->addr.type != PF_ADDR_ADDRMASK || 4140 e->addr.type != PF_ADDR_ADDRMASK || 4141 unmask(&b->addr.v.a.mask) != 4142 (b->af == AF_INET ? 32 : 128) || 4143 unmask(&e->addr.v.a.mask) != 4144 (e->af == AF_INET ? 32 : 128) || 4145 b->next != NULL || b->not || 4146 e->next != NULL || e->not) { 4147 free(b); 4148 free(e); 4149 free($1); 4150 free($3); 4151 yyerror("invalid address range"); 4152 YYERROR; 4153 } 4154 memcpy(&b->addr.v.a.mask, &e->addr.v.a.addr, 4155 sizeof(b->addr.v.a.mask)); 4156 b->addr.type = PF_ADDR_RANGE; 4157 $$ = b; 4158 free(e); 4159 free($1); 4160 free($3); 4161 } 4162 | STRING '/' NUMBER { 4163 char *buf; 4164 4165 if (asprintf(&buf, "%s/%lld", $1, (long long)$3) == -1) 4166 err(1, "host: asprintf"); 4167 free($1); 4168 if (($$ = host(buf, pf->opts)) == NULL) { 4169 /* error. "any" is handled elsewhere */ 4170 free(buf); 4171 yyerror("could not parse host specification"); 4172 YYERROR; 4173 } 4174 free(buf); 4175 } 4176 | NUMBER '/' NUMBER { 4177 char *buf; 4178 4179 /* ie. for 10/8 parsing */ 4180 #ifdef __FreeBSD__ 4181 if (asprintf(&buf, "%lld/%lld", (long long)$1, (long long)$3) == -1) 4182 #else 4183 if (asprintf(&buf, "%lld/%lld", $1, $3) == -1) 4184 #endif 4185 err(1, "host: asprintf"); 4186 if (($$ = host(buf, pf->opts)) == NULL) { 4187 /* error. "any" is handled elsewhere */ 4188 free(buf); 4189 yyerror("could not parse host specification"); 4190 YYERROR; 4191 } 4192 free(buf); 4193 } 4194 | dynaddr 4195 | dynaddr '/' NUMBER { 4196 struct node_host *n; 4197 4198 if ($3 < 0 || $3 > 128) { 4199 yyerror("bit number too big"); 4200 YYERROR; 4201 } 4202 $$ = $1; 4203 for (n = $1; n != NULL; n = n->next) 4204 set_ipmask(n, $3); 4205 } 4206 | '<' STRING '>' { 4207 if (strlen($2) >= PF_TABLE_NAME_SIZE) { 4208 yyerror("table name '%s' too long", $2); 4209 free($2); 4210 YYERROR; 4211 } 4212 $$ = calloc(1, sizeof(struct node_host)); 4213 if ($$ == NULL) 4214 err(1, "host: calloc"); 4215 $$->addr.type = PF_ADDR_TABLE; 4216 if (strlcpy($$->addr.v.tblname, $2, 4217 sizeof($$->addr.v.tblname)) >= 4218 sizeof($$->addr.v.tblname)) 4219 errx(1, "host: strlcpy"); 4220 free($2); 4221 $$->next = NULL; 4222 $$->tail = $$; 4223 } 4224 ; 4225 4226 number : NUMBER 4227 | STRING { 4228 u_long ulval; 4229 4230 if (atoul($1, &ulval) == -1) { 4231 yyerror("%s is not a number", $1); 4232 free($1); 4233 YYERROR; 4234 } else 4235 $$ = ulval; 4236 free($1); 4237 } 4238 ; 4239 4240 dynaddr : '(' STRING ')' { 4241 int flags = 0; 4242 char *p, *op; 4243 4244 op = $2; 4245 if (!isalpha(op[0])) { 4246 yyerror("invalid interface name '%s'", op); 4247 free(op); 4248 YYERROR; 4249 } 4250 while ((p = strrchr($2, ':')) != NULL) { 4251 if (!strcmp(p+1, "network")) 4252 flags |= PFI_AFLAG_NETWORK; 4253 else if (!strcmp(p+1, "broadcast")) 4254 flags |= PFI_AFLAG_BROADCAST; 4255 else if (!strcmp(p+1, "peer")) 4256 flags |= PFI_AFLAG_PEER; 4257 else if (!strcmp(p+1, "0")) 4258 flags |= PFI_AFLAG_NOALIAS; 4259 else { 4260 yyerror("interface %s has bad modifier", 4261 $2); 4262 free(op); 4263 YYERROR; 4264 } 4265 *p = '\0'; 4266 } 4267 if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { 4268 free(op); 4269 yyerror("illegal combination of " 4270 "interface modifiers"); 4271 YYERROR; 4272 } 4273 $$ = calloc(1, sizeof(struct node_host)); 4274 if ($$ == NULL) 4275 err(1, "address: calloc"); 4276 $$->af = 0; 4277 set_ipmask($$, 128); 4278 $$->addr.type = PF_ADDR_DYNIFTL; 4279 $$->addr.iflags = flags; 4280 if (strlcpy($$->addr.v.ifname, $2, 4281 sizeof($$->addr.v.ifname)) >= 4282 sizeof($$->addr.v.ifname)) { 4283 free(op); 4284 free($$); 4285 yyerror("interface name too long"); 4286 YYERROR; 4287 } 4288 free(op); 4289 $$->next = NULL; 4290 $$->tail = $$; 4291 } 4292 ; 4293 4294 portspec : port_item { $$ = $1; } 4295 | '{' optnl port_list '}' { $$ = $3; } 4296 ; 4297 4298 port_list : port_item optnl { $$ = $1; } 4299 | port_list comma port_item optnl { 4300 $1->tail->next = $3; 4301 $1->tail = $3; 4302 $$ = $1; 4303 } 4304 ; 4305 4306 port_item : portrange { 4307 $$ = calloc(1, sizeof(struct node_port)); 4308 if ($$ == NULL) 4309 err(1, "port_item: calloc"); 4310 $$->port[0] = $1.a; 4311 $$->port[1] = $1.b; 4312 if ($1.t) { 4313 $$->op = PF_OP_RRG; 4314 if (validate_range($$->op, $$->port[0], 4315 $$->port[1])) { 4316 yyerror("invalid port range"); 4317 YYERROR; 4318 } 4319 } else 4320 $$->op = PF_OP_EQ; 4321 $$->next = NULL; 4322 $$->tail = $$; 4323 } 4324 | unaryop portrange { 4325 if ($2.t) { 4326 yyerror("':' cannot be used with an other " 4327 "port operator"); 4328 YYERROR; 4329 } 4330 $$ = calloc(1, sizeof(struct node_port)); 4331 if ($$ == NULL) 4332 err(1, "port_item: calloc"); 4333 $$->port[0] = $2.a; 4334 $$->port[1] = $2.b; 4335 $$->op = $1; 4336 if (validate_range($$->op, $$->port[0], $$->port[1])) { 4337 yyerror("invalid port range"); 4338 YYERROR; 4339 } 4340 $$->next = NULL; 4341 $$->tail = $$; 4342 } 4343 | portrange PORTBINARY portrange { 4344 if ($1.t || $3.t) { 4345 yyerror("':' cannot be used with an other " 4346 "port operator"); 4347 YYERROR; 4348 } 4349 $$ = calloc(1, sizeof(struct node_port)); 4350 if ($$ == NULL) 4351 err(1, "port_item: calloc"); 4352 $$->port[0] = $1.a; 4353 $$->port[1] = $3.a; 4354 $$->op = $2; 4355 if (validate_range($$->op, $$->port[0], $$->port[1])) { 4356 yyerror("invalid port range"); 4357 YYERROR; 4358 } 4359 $$->next = NULL; 4360 $$->tail = $$; 4361 } 4362 ; 4363 4364 portplain : numberstring { 4365 if (parseport($1, &$$, 0) == -1) { 4366 free($1); 4367 YYERROR; 4368 } 4369 free($1); 4370 } 4371 ; 4372 4373 portrange : numberstring { 4374 if (parseport($1, &$$, PPORT_RANGE) == -1) { 4375 free($1); 4376 YYERROR; 4377 } 4378 free($1); 4379 } 4380 ; 4381 4382 uids : uid_item { $$ = $1; } 4383 | '{' optnl uid_list '}' { $$ = $3; } 4384 ; 4385 4386 uid_list : uid_item optnl { $$ = $1; } 4387 | uid_list comma uid_item optnl { 4388 $1->tail->next = $3; 4389 $1->tail = $3; 4390 $$ = $1; 4391 } 4392 ; 4393 4394 uid_item : uid { 4395 $$ = calloc(1, sizeof(struct node_uid)); 4396 if ($$ == NULL) 4397 err(1, "uid_item: calloc"); 4398 $$->uid[0] = $1; 4399 $$->uid[1] = $1; 4400 $$->op = PF_OP_EQ; 4401 $$->next = NULL; 4402 $$->tail = $$; 4403 } 4404 | unaryop uid { 4405 if ($2 == -1 && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 4406 yyerror("user unknown requires operator = or " 4407 "!="); 4408 YYERROR; 4409 } 4410 $$ = calloc(1, sizeof(struct node_uid)); 4411 if ($$ == NULL) 4412 err(1, "uid_item: calloc"); 4413 $$->uid[0] = $2; 4414 $$->uid[1] = $2; 4415 $$->op = $1; 4416 $$->next = NULL; 4417 $$->tail = $$; 4418 } 4419 | uid PORTBINARY uid { 4420 if ($1 == -1 || $3 == -1) { 4421 yyerror("user unknown requires operator = or " 4422 "!="); 4423 YYERROR; 4424 } 4425 $$ = calloc(1, sizeof(struct node_uid)); 4426 if ($$ == NULL) 4427 err(1, "uid_item: calloc"); 4428 $$->uid[0] = $1; 4429 $$->uid[1] = $3; 4430 $$->op = $2; 4431 $$->next = NULL; 4432 $$->tail = $$; 4433 } 4434 ; 4435 4436 uid : STRING { 4437 if (!strcmp($1, "unknown")) 4438 $$ = -1; 4439 else { 4440 uid_t uid; 4441 4442 if (uid_from_user($1, &uid) == -1) { 4443 yyerror("unknown user %s", $1); 4444 free($1); 4445 YYERROR; 4446 } 4447 $$ = uid; 4448 } 4449 free($1); 4450 } 4451 | NUMBER { 4452 if ($1 < 0 || $1 >= UID_MAX) { 4453 yyerror("illegal uid value %lu", $1); 4454 YYERROR; 4455 } 4456 $$ = $1; 4457 } 4458 ; 4459 4460 gids : gid_item { $$ = $1; } 4461 | '{' optnl gid_list '}' { $$ = $3; } 4462 ; 4463 4464 gid_list : gid_item optnl { $$ = $1; } 4465 | gid_list comma gid_item optnl { 4466 $1->tail->next = $3; 4467 $1->tail = $3; 4468 $$ = $1; 4469 } 4470 ; 4471 4472 gid_item : gid { 4473 $$ = calloc(1, sizeof(struct node_gid)); 4474 if ($$ == NULL) 4475 err(1, "gid_item: calloc"); 4476 $$->gid[0] = $1; 4477 $$->gid[1] = $1; 4478 $$->op = PF_OP_EQ; 4479 $$->next = NULL; 4480 $$->tail = $$; 4481 } 4482 | unaryop gid { 4483 if ($2 == -1 && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 4484 yyerror("group unknown requires operator = or " 4485 "!="); 4486 YYERROR; 4487 } 4488 $$ = calloc(1, sizeof(struct node_gid)); 4489 if ($$ == NULL) 4490 err(1, "gid_item: calloc"); 4491 $$->gid[0] = $2; 4492 $$->gid[1] = $2; 4493 $$->op = $1; 4494 $$->next = NULL; 4495 $$->tail = $$; 4496 } 4497 | gid PORTBINARY gid { 4498 if ($1 == -1 || $3 == -1) { 4499 yyerror("group unknown requires operator = or " 4500 "!="); 4501 YYERROR; 4502 } 4503 $$ = calloc(1, sizeof(struct node_gid)); 4504 if ($$ == NULL) 4505 err(1, "gid_item: calloc"); 4506 $$->gid[0] = $1; 4507 $$->gid[1] = $3; 4508 $$->op = $2; 4509 $$->next = NULL; 4510 $$->tail = $$; 4511 } 4512 ; 4513 4514 gid : STRING { 4515 if (!strcmp($1, "unknown")) 4516 $$ = -1; 4517 else { 4518 gid_t gid; 4519 4520 if (gid_from_group($1, &gid) == -1) { 4521 yyerror("unknown group %s", $1); 4522 free($1); 4523 YYERROR; 4524 } 4525 $$ = gid; 4526 } 4527 free($1); 4528 } 4529 | NUMBER { 4530 if ($1 < 0 || $1 >= GID_MAX) { 4531 yyerror("illegal gid value %lu", $1); 4532 YYERROR; 4533 } 4534 $$ = $1; 4535 } 4536 ; 4537 4538 flag : STRING { 4539 int f; 4540 4541 if ((f = parse_flags($1)) < 0) { 4542 yyerror("bad flags %s", $1); 4543 free($1); 4544 YYERROR; 4545 } 4546 free($1); 4547 $$.b1 = f; 4548 } 4549 ; 4550 4551 flags : FLAGS flag '/' flag { $$.b1 = $2.b1; $$.b2 = $4.b1; } 4552 | FLAGS '/' flag { $$.b1 = 0; $$.b2 = $3.b1; } 4553 | FLAGS ANY { $$.b1 = 0; $$.b2 = 0; } 4554 ; 4555 4556 icmpspec : ICMPTYPE icmp_item { $$ = $2; } 4557 | ICMPTYPE '{' optnl icmp_list '}' { $$ = $4; } 4558 | ICMP6TYPE icmp6_item { $$ = $2; } 4559 | ICMP6TYPE '{' optnl icmp6_list '}' { $$ = $4; } 4560 ; 4561 4562 icmp_list : icmp_item optnl { $$ = $1; } 4563 | icmp_list comma icmp_item optnl { 4564 $1->tail->next = $3; 4565 $1->tail = $3; 4566 $$ = $1; 4567 } 4568 ; 4569 4570 icmp6_list : icmp6_item optnl { $$ = $1; } 4571 | icmp6_list comma icmp6_item optnl { 4572 $1->tail->next = $3; 4573 $1->tail = $3; 4574 $$ = $1; 4575 } 4576 ; 4577 4578 icmp_item : icmptype { 4579 $$ = calloc(1, sizeof(struct node_icmp)); 4580 if ($$ == NULL) 4581 err(1, "icmp_item: calloc"); 4582 $$->type = $1; 4583 $$->code = 0; 4584 $$->proto = IPPROTO_ICMP; 4585 $$->next = NULL; 4586 $$->tail = $$; 4587 } 4588 | icmptype CODE STRING { 4589 const struct icmpcodeent *p; 4590 4591 if ((p = geticmpcodebyname($1-1, $3, AF_INET)) == NULL) { 4592 yyerror("unknown icmp-code %s", $3); 4593 free($3); 4594 YYERROR; 4595 } 4596 4597 free($3); 4598 $$ = calloc(1, sizeof(struct node_icmp)); 4599 if ($$ == NULL) 4600 err(1, "icmp_item: calloc"); 4601 $$->type = $1; 4602 $$->code = p->code + 1; 4603 $$->proto = IPPROTO_ICMP; 4604 $$->next = NULL; 4605 $$->tail = $$; 4606 } 4607 | icmptype CODE NUMBER { 4608 if ($3 < 0 || $3 > 255) { 4609 yyerror("illegal icmp-code %lu", $3); 4610 YYERROR; 4611 } 4612 $$ = calloc(1, sizeof(struct node_icmp)); 4613 if ($$ == NULL) 4614 err(1, "icmp_item: calloc"); 4615 $$->type = $1; 4616 $$->code = $3 + 1; 4617 $$->proto = IPPROTO_ICMP; 4618 $$->next = NULL; 4619 $$->tail = $$; 4620 } 4621 ; 4622 4623 icmp6_item : icmp6type { 4624 $$ = calloc(1, sizeof(struct node_icmp)); 4625 if ($$ == NULL) 4626 err(1, "icmp_item: calloc"); 4627 $$->type = $1; 4628 $$->code = 0; 4629 $$->proto = IPPROTO_ICMPV6; 4630 $$->next = NULL; 4631 $$->tail = $$; 4632 } 4633 | icmp6type CODE STRING { 4634 const struct icmpcodeent *p; 4635 4636 if ((p = geticmpcodebyname($1-1, $3, AF_INET6)) == NULL) { 4637 yyerror("unknown icmp6-code %s", $3); 4638 free($3); 4639 YYERROR; 4640 } 4641 free($3); 4642 4643 $$ = calloc(1, sizeof(struct node_icmp)); 4644 if ($$ == NULL) 4645 err(1, "icmp_item: calloc"); 4646 $$->type = $1; 4647 $$->code = p->code + 1; 4648 $$->proto = IPPROTO_ICMPV6; 4649 $$->next = NULL; 4650 $$->tail = $$; 4651 } 4652 | icmp6type CODE NUMBER { 4653 if ($3 < 0 || $3 > 255) { 4654 yyerror("illegal icmp-code %lu", $3); 4655 YYERROR; 4656 } 4657 $$ = calloc(1, sizeof(struct node_icmp)); 4658 if ($$ == NULL) 4659 err(1, "icmp_item: calloc"); 4660 $$->type = $1; 4661 $$->code = $3 + 1; 4662 $$->proto = IPPROTO_ICMPV6; 4663 $$->next = NULL; 4664 $$->tail = $$; 4665 } 4666 ; 4667 4668 icmptype : STRING { 4669 const struct icmptypeent *p; 4670 4671 if ((p = geticmptypebyname($1, AF_INET)) == NULL) { 4672 yyerror("unknown icmp-type %s", $1); 4673 free($1); 4674 YYERROR; 4675 } 4676 $$ = p->type + 1; 4677 free($1); 4678 } 4679 | NUMBER { 4680 if ($1 < 0 || $1 > 255) { 4681 yyerror("illegal icmp-type %lu", $1); 4682 YYERROR; 4683 } 4684 $$ = $1 + 1; 4685 } 4686 ; 4687 4688 icmp6type : STRING { 4689 const struct icmptypeent *p; 4690 4691 if ((p = geticmptypebyname($1, AF_INET6)) == 4692 NULL) { 4693 yyerror("unknown icmp6-type %s", $1); 4694 free($1); 4695 YYERROR; 4696 } 4697 $$ = p->type + 1; 4698 free($1); 4699 } 4700 | NUMBER { 4701 if ($1 < 0 || $1 > 255) { 4702 yyerror("illegal icmp6-type %lu", $1); 4703 YYERROR; 4704 } 4705 $$ = $1 + 1; 4706 } 4707 ; 4708 4709 tos : STRING { 4710 int val; 4711 char *end; 4712 4713 if (map_tos($1, &val)) 4714 $$ = val; 4715 else if ($1[0] == '0' && $1[1] == 'x') { 4716 errno = 0; 4717 $$ = strtoul($1, &end, 16); 4718 if (errno || *end != '\0') 4719 $$ = 256; 4720 } else 4721 $$ = 256; /* flag bad argument */ 4722 if ($$ < 0 || $$ > 255) { 4723 yyerror("illegal tos value %s", $1); 4724 free($1); 4725 YYERROR; 4726 } 4727 free($1); 4728 } 4729 | NUMBER { 4730 $$ = $1; 4731 if ($$ < 0 || $$ > 255) { 4732 yyerror("illegal tos value %lu", $1); 4733 YYERROR; 4734 } 4735 } 4736 ; 4737 4738 sourcetrack : SOURCETRACK { $$ = PF_SRCTRACK; } 4739 | SOURCETRACK GLOBAL { $$ = PF_SRCTRACK_GLOBAL; } 4740 | SOURCETRACK RULE { $$ = PF_SRCTRACK_RULE; } 4741 ; 4742 4743 statelock : IFBOUND { 4744 $$ = PFRULE_IFBOUND; 4745 } 4746 | FLOATING { 4747 $$ = 0; 4748 } 4749 ; 4750 4751 keep : NO STATE { 4752 $$.action = 0; 4753 $$.options = NULL; 4754 } 4755 | KEEP STATE state_opt_spec { 4756 $$.action = PF_STATE_NORMAL; 4757 $$.options = $3; 4758 } 4759 | MODULATE STATE state_opt_spec { 4760 $$.action = PF_STATE_MODULATE; 4761 $$.options = $3; 4762 } 4763 | SYNPROXY STATE state_opt_spec { 4764 $$.action = PF_STATE_SYNPROXY; 4765 $$.options = $3; 4766 } 4767 ; 4768 4769 flush : /* empty */ { $$ = 0; } 4770 | FLUSH { $$ = PF_FLUSH; } 4771 | FLUSH GLOBAL { 4772 $$ = PF_FLUSH | PF_FLUSH_GLOBAL; 4773 } 4774 ; 4775 4776 state_opt_spec : '(' state_opt_list ')' { $$ = $2; } 4777 | /* empty */ { $$ = NULL; } 4778 ; 4779 4780 state_opt_list : state_opt_item { $$ = $1; } 4781 | state_opt_list comma state_opt_item { 4782 $1->tail->next = $3; 4783 $1->tail = $3; 4784 $$ = $1; 4785 } 4786 ; 4787 4788 state_opt_item : MAXIMUM NUMBER { 4789 if ($2 < 0 || $2 > UINT_MAX) { 4790 yyerror("only positive values permitted"); 4791 YYERROR; 4792 } 4793 $$ = calloc(1, sizeof(struct node_state_opt)); 4794 if ($$ == NULL) 4795 err(1, "state_opt_item: calloc"); 4796 $$->type = PF_STATE_OPT_MAX; 4797 $$->data.max_states = $2; 4798 $$->next = NULL; 4799 $$->tail = $$; 4800 } 4801 | NOSYNC { 4802 $$ = calloc(1, sizeof(struct node_state_opt)); 4803 if ($$ == NULL) 4804 err(1, "state_opt_item: calloc"); 4805 $$->type = PF_STATE_OPT_NOSYNC; 4806 $$->next = NULL; 4807 $$->tail = $$; 4808 } 4809 | MAXSRCSTATES NUMBER { 4810 if ($2 < 0 || $2 > UINT_MAX) { 4811 yyerror("only positive values permitted"); 4812 YYERROR; 4813 } 4814 $$ = calloc(1, sizeof(struct node_state_opt)); 4815 if ($$ == NULL) 4816 err(1, "state_opt_item: calloc"); 4817 $$->type = PF_STATE_OPT_MAX_SRC_STATES; 4818 $$->data.max_src_states = $2; 4819 $$->next = NULL; 4820 $$->tail = $$; 4821 } 4822 | MAXSRCCONN NUMBER { 4823 if ($2 < 0 || $2 > UINT_MAX) { 4824 yyerror("only positive values permitted"); 4825 YYERROR; 4826 } 4827 $$ = calloc(1, sizeof(struct node_state_opt)); 4828 if ($$ == NULL) 4829 err(1, "state_opt_item: calloc"); 4830 $$->type = PF_STATE_OPT_MAX_SRC_CONN; 4831 $$->data.max_src_conn = $2; 4832 $$->next = NULL; 4833 $$->tail = $$; 4834 } 4835 | MAXSRCCONNRATE NUMBER '/' NUMBER { 4836 if ($2 < 0 || $2 > UINT_MAX || 4837 $4 < 0 || $4 > UINT_MAX) { 4838 yyerror("only positive values permitted"); 4839 YYERROR; 4840 } 4841 $$ = calloc(1, sizeof(struct node_state_opt)); 4842 if ($$ == NULL) 4843 err(1, "state_opt_item: calloc"); 4844 $$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE; 4845 $$->data.max_src_conn_rate.limit = $2; 4846 $$->data.max_src_conn_rate.seconds = $4; 4847 $$->next = NULL; 4848 $$->tail = $$; 4849 } 4850 | OVERLOAD '<' STRING '>' flush { 4851 if (strlen($3) >= PF_TABLE_NAME_SIZE) { 4852 yyerror("table name '%s' too long", $3); 4853 free($3); 4854 YYERROR; 4855 } 4856 $$ = calloc(1, sizeof(struct node_state_opt)); 4857 if ($$ == NULL) 4858 err(1, "state_opt_item: calloc"); 4859 if (strlcpy($$->data.overload.tblname, $3, 4860 PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE) 4861 errx(1, "state_opt_item: strlcpy"); 4862 free($3); 4863 $$->type = PF_STATE_OPT_OVERLOAD; 4864 $$->data.overload.flush = $5; 4865 $$->next = NULL; 4866 $$->tail = $$; 4867 } 4868 | MAXSRCNODES NUMBER { 4869 if ($2 < 0 || $2 > UINT_MAX) { 4870 yyerror("only positive values permitted"); 4871 YYERROR; 4872 } 4873 $$ = calloc(1, sizeof(struct node_state_opt)); 4874 if ($$ == NULL) 4875 err(1, "state_opt_item: calloc"); 4876 $$->type = PF_STATE_OPT_MAX_SRC_NODES; 4877 $$->data.max_src_nodes = $2; 4878 $$->next = NULL; 4879 $$->tail = $$; 4880 } 4881 | sourcetrack { 4882 $$ = calloc(1, sizeof(struct node_state_opt)); 4883 if ($$ == NULL) 4884 err(1, "state_opt_item: calloc"); 4885 $$->type = PF_STATE_OPT_SRCTRACK; 4886 $$->data.src_track = $1; 4887 $$->next = NULL; 4888 $$->tail = $$; 4889 } 4890 | statelock { 4891 $$ = calloc(1, sizeof(struct node_state_opt)); 4892 if ($$ == NULL) 4893 err(1, "state_opt_item: calloc"); 4894 $$->type = PF_STATE_OPT_STATELOCK; 4895 $$->data.statelock = $1; 4896 $$->next = NULL; 4897 $$->tail = $$; 4898 } 4899 | SLOPPY { 4900 $$ = calloc(1, sizeof(struct node_state_opt)); 4901 if ($$ == NULL) 4902 err(1, "state_opt_item: calloc"); 4903 $$->type = PF_STATE_OPT_SLOPPY; 4904 $$->next = NULL; 4905 $$->tail = $$; 4906 } 4907 | PFLOW { 4908 $$ = calloc(1, sizeof(struct node_state_opt)); 4909 if ($$ == NULL) 4910 err(1, "state_opt_item: calloc"); 4911 $$->type = PF_STATE_OPT_PFLOW; 4912 $$->next = NULL; 4913 $$->tail = $$; 4914 } 4915 | ALLOW_RELATED { 4916 $$ = calloc(1, sizeof(struct node_state_opt)); 4917 if ($$ == NULL) 4918 err(1, "state_opt_item: calloc"); 4919 $$->type = PF_STATE_OPT_ALLOW_RELATED; 4920 $$->next = NULL; 4921 $$->tail = $$; 4922 } 4923 | STRING NUMBER { 4924 int i; 4925 4926 if ($2 < 0 || $2 > UINT_MAX) { 4927 yyerror("only positive values permitted"); 4928 YYERROR; 4929 } 4930 for (i = 0; pf_timeouts[i].name && 4931 strcmp(pf_timeouts[i].name, $1); ++i) 4932 ; /* nothing */ 4933 if (!pf_timeouts[i].name) { 4934 yyerror("illegal timeout name %s", $1); 4935 free($1); 4936 YYERROR; 4937 } 4938 if (strchr(pf_timeouts[i].name, '.') == NULL) { 4939 yyerror("illegal state timeout %s", $1); 4940 free($1); 4941 YYERROR; 4942 } 4943 free($1); 4944 $$ = calloc(1, sizeof(struct node_state_opt)); 4945 if ($$ == NULL) 4946 err(1, "state_opt_item: calloc"); 4947 $$->type = PF_STATE_OPT_TIMEOUT; 4948 $$->data.timeout.number = pf_timeouts[i].timeout; 4949 $$->data.timeout.seconds = $2; 4950 $$->next = NULL; 4951 $$->tail = $$; 4952 } 4953 ; 4954 4955 label : LABEL STRING { 4956 $$ = $2; 4957 } 4958 ; 4959 4960 etherqname : QUEUE STRING { 4961 $$.qname = $2; 4962 } 4963 | QUEUE '(' STRING ')' { 4964 $$.qname = $3; 4965 } 4966 ; 4967 4968 qname : QUEUE STRING { 4969 $$.qname = $2; 4970 $$.pqname = NULL; 4971 } 4972 | QUEUE '(' STRING ')' { 4973 $$.qname = $3; 4974 $$.pqname = NULL; 4975 } 4976 | QUEUE '(' STRING comma STRING ')' { 4977 $$.qname = $3; 4978 $$.pqname = $5; 4979 } 4980 ; 4981 4982 no : /* empty */ { $$ = 0; } 4983 | NO { $$ = 1; } 4984 ; 4985 4986 portstar : numberstring { 4987 if (parseport($1, &$$, PPORT_RANGE|PPORT_STAR) == -1) { 4988 free($1); 4989 YYERROR; 4990 } 4991 free($1); 4992 } 4993 ; 4994 4995 redir_host : host { $$ = $1; } 4996 | '{' optnl redir_host_list '}' { $$ = $3; } 4997 ; 4998 4999 redir_host_list : host optnl { $$ = $1; } 5000 | redir_host_list comma host optnl { 5001 $1->tail->next = $3; 5002 $1->tail = $3->tail; 5003 $$ = $1; 5004 } 5005 ; 5006 5007 /* Redirection without port */ 5008 no_port_redirspec: redir_host pool_opts { 5009 $$ = calloc(1, sizeof(struct redirspec)); 5010 if ($$ == NULL) 5011 err(1, "redirspec: calloc"); 5012 $$->host = $1; 5013 $$->pool_opts = $2; 5014 $$->rport.a = $$->rport.b = $$->rport.t = 0; 5015 } 5016 ; 5017 5018 /* Redirection with optional port */ 5019 port_redirspec : no_port_redirspec; 5020 | redir_host PORT portstar pool_opts { 5021 $$ = calloc(1, sizeof(struct redirspec)); 5022 if ($$ == NULL) 5023 err(1, "redirspec: calloc"); 5024 $$->host = $1; 5025 $$->rport = $3; 5026 $$->pool_opts = $4; 5027 } 5028 5029 /* Redirection with an arrow and an optional port: FreeBSD NAT rules */ 5030 nat_redirspec : /* empty */ { $$ = NULL; } 5031 | ARROW port_redirspec { 5032 $$ = $2; 5033 } 5034 ; 5035 5036 /* Redirection with interfaces and without ports: route-to rules */ 5037 route_redirspec : routespec pool_opts { 5038 $$ = calloc(1, sizeof(struct redirspec)); 5039 if ($$ == NULL) 5040 err(1, "redirspec: calloc"); 5041 $$->host = $1; 5042 $$->pool_opts = $2; 5043 } 5044 ; 5045 5046 hashkey : /* empty */ 5047 { 5048 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 5049 if ($$ == NULL) 5050 err(1, "hashkey: calloc"); 5051 $$->key32[0] = arc4random(); 5052 $$->key32[1] = arc4random(); 5053 $$->key32[2] = arc4random(); 5054 $$->key32[3] = arc4random(); 5055 } 5056 | string 5057 { 5058 if (!strncmp($1, "0x", 2)) { 5059 if (strlen($1) != 34) { 5060 free($1); 5061 yyerror("hex key must be 128 bits " 5062 "(32 hex digits) long"); 5063 YYERROR; 5064 } 5065 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 5066 if ($$ == NULL) 5067 err(1, "hashkey: calloc"); 5068 5069 if (sscanf($1, "0x%8x%8x%8x%8x", 5070 &$$->key32[0], &$$->key32[1], 5071 &$$->key32[2], &$$->key32[3]) != 4) { 5072 free($$); 5073 free($1); 5074 yyerror("invalid hex key"); 5075 YYERROR; 5076 } 5077 } else { 5078 MD5_CTX context; 5079 5080 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 5081 if ($$ == NULL) 5082 err(1, "hashkey: calloc"); 5083 MD5Init(&context); 5084 MD5Update(&context, (unsigned char *)$1, 5085 strlen($1)); 5086 MD5Final((unsigned char *)$$, &context); 5087 HTONL($$->key32[0]); 5088 HTONL($$->key32[1]); 5089 HTONL($$->key32[2]); 5090 HTONL($$->key32[3]); 5091 } 5092 free($1); 5093 } 5094 ; 5095 5096 pool_opts : { bzero(&pool_opts, sizeof pool_opts); } 5097 pool_opts_l 5098 { $$ = pool_opts; } 5099 | /* empty */ { 5100 bzero(&pool_opts, sizeof pool_opts); 5101 $$ = pool_opts; 5102 } 5103 ; 5104 5105 pool_opts_l : pool_opts_l pool_opt 5106 | pool_opt 5107 ; 5108 5109 pool_opt : BITMASK { 5110 if (pool_opts.type) { 5111 yyerror("pool type cannot be redefined"); 5112 YYERROR; 5113 } 5114 pool_opts.type = PF_POOL_BITMASK; 5115 } 5116 | RANDOM { 5117 if (pool_opts.type) { 5118 yyerror("pool type cannot be redefined"); 5119 YYERROR; 5120 } 5121 pool_opts.type = PF_POOL_RANDOM; 5122 } 5123 | SOURCEHASH hashkey { 5124 if (pool_opts.type) { 5125 yyerror("pool type cannot be redefined"); 5126 YYERROR; 5127 } 5128 pool_opts.type = PF_POOL_SRCHASH; 5129 pool_opts.key = $2; 5130 } 5131 | ROUNDROBIN { 5132 if (pool_opts.type) { 5133 yyerror("pool type cannot be redefined"); 5134 YYERROR; 5135 } 5136 pool_opts.type = PF_POOL_ROUNDROBIN; 5137 } 5138 | STATICPORT { 5139 if (pool_opts.staticport) { 5140 yyerror("static-port cannot be redefined"); 5141 YYERROR; 5142 } 5143 pool_opts.staticport = 1; 5144 } 5145 | STICKYADDRESS { 5146 if (pool_opts.marker & POM_STICKYADDRESS) { 5147 yyerror("sticky-address cannot be redefined"); 5148 YYERROR; 5149 } 5150 pool_opts.marker |= POM_STICKYADDRESS; 5151 pool_opts.opts |= PF_POOL_STICKYADDR; 5152 } 5153 | ENDPI { 5154 if (pool_opts.marker & POM_ENDPI) { 5155 yyerror("endpoint-independent cannot be redefined"); 5156 YYERROR; 5157 } 5158 pool_opts.marker |= POM_ENDPI; 5159 pool_opts.opts |= PF_POOL_ENDPI; 5160 } 5161 | IPV6NH { 5162 if (pool_opts.marker & POM_IPV6NH) { 5163 yyerror("prefer-ipv6-nexthop cannot be redefined"); 5164 YYERROR; 5165 } 5166 pool_opts.marker |= POM_IPV6NH; 5167 pool_opts.opts |= PF_POOL_IPV6NH; 5168 } 5169 | MAPEPORTSET number '/' number '/' number { 5170 if (pool_opts.mape.offset) { 5171 yyerror("map-e-portset cannot be redefined"); 5172 YYERROR; 5173 } 5174 if (pool_opts.type) { 5175 yyerror("map-e-portset cannot be used with " 5176 "address pools"); 5177 YYERROR; 5178 } 5179 if ($2 <= 0 || $2 >= 16) { 5180 yyerror("MAP-E PSID offset must be 1-15"); 5181 YYERROR; 5182 } 5183 if ($4 < 0 || $4 >= 16 || $2 + $4 > 16) { 5184 yyerror("Invalid MAP-E PSID length"); 5185 YYERROR; 5186 } else if ($4 == 0) { 5187 yyerror("PSID Length = 0: this means" 5188 " you do not need MAP-E"); 5189 YYERROR; 5190 } 5191 if ($6 < 0 || $6 > 65535) { 5192 yyerror("Invalid MAP-E PSID"); 5193 YYERROR; 5194 } 5195 pool_opts.mape.offset = $2; 5196 pool_opts.mape.psidlen = $4; 5197 pool_opts.mape.psid = $6; 5198 } 5199 ; 5200 5201 binat_redirspec : /* empty */ { $$ = NULL; } 5202 | ARROW host { 5203 $$ = calloc(1, sizeof(struct redirspec)); 5204 if ($$ == NULL) 5205 err(1, "redirspec: calloc"); 5206 $$->host = $2; 5207 $$->rport.a = $$->rport.b = $$->rport.t = 0; 5208 } 5209 | ARROW host PORT portstar { 5210 $$ = calloc(1, sizeof(struct redirspec)); 5211 if ($$ == NULL) 5212 err(1, "redirspec: calloc"); 5213 $$->host = $2; 5214 $$->rport = $4; 5215 } 5216 ; 5217 5218 natpasslog : /* empty */ { $$.b1 = $$.b2 = 0; $$.w2 = 0; } 5219 | PASS { $$.b1 = 1; $$.b2 = 0; $$.w2 = 0; } 5220 | PASS log { $$.b1 = 1; $$.b2 = $2.log; $$.w2 = $2.logif; } 5221 | log { $$.b1 = 0; $$.b2 = $1.log; $$.w2 = $1.logif; } 5222 ; 5223 5224 nataction : no NAT natpasslog { 5225 if ($1 && $3.b1) { 5226 yyerror("\"pass\" not valid with \"no\""); 5227 YYERROR; 5228 } 5229 if ($1) 5230 $$.b1 = PF_NONAT; 5231 else 5232 $$.b1 = PF_NAT; 5233 $$.b2 = $3.b1; 5234 $$.w = $3.b2; 5235 $$.w2 = $3.w2; 5236 } 5237 | no RDR natpasslog { 5238 if ($1 && $3.b1) { 5239 yyerror("\"pass\" not valid with \"no\""); 5240 YYERROR; 5241 } 5242 if ($1) 5243 $$.b1 = PF_NORDR; 5244 else 5245 $$.b1 = PF_RDR; 5246 $$.b2 = $3.b1; 5247 $$.w = $3.b2; 5248 $$.w2 = $3.w2; 5249 } 5250 ; 5251 5252 natrule : nataction interface af proto fromto tag tagged rtable 5253 nat_redirspec 5254 { 5255 struct pfctl_rule r; 5256 struct node_state_opt *o; 5257 5258 if (check_rulestate(PFCTL_STATE_NAT)) 5259 YYERROR; 5260 5261 pfctl_init_rule(&r); 5262 5263 r.action = $1.b1; 5264 r.natpass = $1.b2; 5265 r.log = $1.w; 5266 r.logif = $1.w2; 5267 r.af = $3; 5268 5269 if (!r.af) { 5270 if ($5.src.host && $5.src.host->af && 5271 !$5.src.host->ifindex) 5272 r.af = $5.src.host->af; 5273 else if ($5.dst.host && $5.dst.host->af && 5274 !$5.dst.host->ifindex) 5275 r.af = $5.dst.host->af; 5276 } 5277 5278 if ($6 != NULL) 5279 if (strlcpy(r.tagname, $6, PF_TAG_NAME_SIZE) >= 5280 PF_TAG_NAME_SIZE) { 5281 yyerror("tag too long, max %u chars", 5282 PF_TAG_NAME_SIZE - 1); 5283 YYERROR; 5284 } 5285 5286 if ($7.name) 5287 if (strlcpy(r.match_tagname, $7.name, 5288 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 5289 yyerror("tag too long, max %u chars", 5290 PF_TAG_NAME_SIZE - 1); 5291 YYERROR; 5292 } 5293 r.match_tag_not = $7.neg; 5294 r.rtableid = $8; 5295 5296 if (r.action == PF_NONAT || r.action == PF_NORDR) { 5297 if ($9 != NULL) { 5298 yyerror("translation rule with 'no' " 5299 "does not need '->'"); 5300 YYERROR; 5301 } 5302 } else { 5303 if ($9 == NULL || $9->host == NULL) { 5304 yyerror("translation rule requires '-> " 5305 "address'"); 5306 YYERROR; 5307 } 5308 if ($9->pool_opts.opts & PF_POOL_IPV6NH) { 5309 yyerror("The prefer-ipv6-nexthop option " 5310 "can't be used for nat/rdr/binat pools" 5311 ); 5312 YYERROR; 5313 } 5314 if (!r.af && ! $9->host->ifindex) 5315 r.af = $9->host->af; 5316 5317 remove_invalid_hosts(&$9->host, &r.af); 5318 if (invalid_redirect($9->host, r.af)) 5319 YYERROR; 5320 if ($9->host->addr.type == PF_ADDR_DYNIFTL) { 5321 if (($9->host = gen_dynnode($9->host, r.af)) == NULL) 5322 err(1, "calloc"); 5323 } 5324 if (check_netmask($9->host, r.af)) 5325 YYERROR; 5326 } 5327 5328 o = keep_state_defaults; 5329 while (o) { 5330 switch (o->type) { 5331 case PF_STATE_OPT_PFLOW: 5332 if (r.rule_flag & PFRULE_PFLOW) { 5333 yyerror("state pflow option: " 5334 "multiple definitions"); 5335 YYERROR; 5336 } 5337 r.rule_flag |= PFRULE_PFLOW; 5338 break; 5339 } 5340 o = o->next; 5341 } 5342 5343 expand_rule(&r, false, $2, NULL, $9, NULL, $4, 5344 $5.src_os, $5.src.host, $5.src.port, $5.dst.host, 5345 $5.dst.port, 0, 0, 0, 0); 5346 } 5347 ; 5348 5349 binatrule : no BINAT natpasslog interface af proto FROM ipspec toipspec tag 5350 tagged rtable binat_redirspec 5351 { 5352 struct pfctl_rule binat; 5353 struct pfctl_pooladdr *pa; 5354 5355 if (check_rulestate(PFCTL_STATE_NAT)) 5356 YYERROR; 5357 if (disallow_urpf_failed($9, "\"urpf-failed\" is not " 5358 "permitted as a binat destination")) 5359 YYERROR; 5360 5361 pfctl_init_rule(&binat); 5362 5363 if ($1 && $3.b1) { 5364 yyerror("\"pass\" not valid with \"no\""); 5365 YYERROR; 5366 } 5367 if ($1) 5368 binat.action = PF_NOBINAT; 5369 else 5370 binat.action = PF_BINAT; 5371 binat.natpass = $3.b1; 5372 binat.log = $3.b2; 5373 binat.logif = $3.w2; 5374 binat.af = $5; 5375 if (!binat.af && $8 != NULL && $8->af) 5376 binat.af = $8->af; 5377 if (!binat.af && $9 != NULL && $9->af) 5378 binat.af = $9->af; 5379 5380 if (!binat.af && $13 != NULL && $13->host) 5381 binat.af = $13->host->af; 5382 if (!binat.af) { 5383 yyerror("address family (inet/inet6) " 5384 "undefined"); 5385 YYERROR; 5386 } 5387 5388 if ($4 != NULL) { 5389 memcpy(binat.ifname, $4->ifname, 5390 sizeof(binat.ifname)); 5391 binat.ifnot = $4->not; 5392 free($4); 5393 } 5394 5395 if ($10 != NULL) 5396 if (strlcpy(binat.tagname, $10, 5397 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 5398 yyerror("tag too long, max %u chars", 5399 PF_TAG_NAME_SIZE - 1); 5400 YYERROR; 5401 } 5402 if ($11.name) 5403 if (strlcpy(binat.match_tagname, $11.name, 5404 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 5405 yyerror("tag too long, max %u chars", 5406 PF_TAG_NAME_SIZE - 1); 5407 YYERROR; 5408 } 5409 binat.match_tag_not = $11.neg; 5410 binat.rtableid = $12; 5411 5412 if ($6 != NULL) { 5413 binat.proto = $6->proto; 5414 free($6); 5415 } 5416 5417 if ($8 != NULL && disallow_table($8, "invalid use of " 5418 "table <%s> as the source address of a binat rule")) 5419 YYERROR; 5420 if ($8 != NULL && disallow_alias($8, "invalid use of " 5421 "interface (%s) as the source address of a binat " 5422 "rule")) 5423 YYERROR; 5424 if ($13 != NULL && $13->host != NULL && disallow_table( 5425 $13->host, "invalid use of table <%s> as the " 5426 "redirect address of a binat rule")) 5427 YYERROR; 5428 if ($13 != NULL && $13->host != NULL && disallow_alias( 5429 $13->host, "invalid use of interface (%s) as the " 5430 "redirect address of a binat rule")) 5431 YYERROR; 5432 5433 if ($8 != NULL) { 5434 if ($8->next) { 5435 yyerror("multiple binat ip addresses"); 5436 YYERROR; 5437 } 5438 if ($8->addr.type == PF_ADDR_DYNIFTL) 5439 $8->af = binat.af; 5440 if ($8->af != binat.af) { 5441 yyerror("binat ip versions must match"); 5442 YYERROR; 5443 } 5444 if ($8->addr.type == PF_ADDR_DYNIFTL) { 5445 if (($8 = gen_dynnode($8, binat.af)) == NULL) 5446 err(1, "calloc"); 5447 } 5448 if (check_netmask($8, binat.af)) 5449 YYERROR; 5450 memcpy(&binat.src.addr, &$8->addr, 5451 sizeof(binat.src.addr)); 5452 free($8); 5453 } 5454 if ($9 != NULL) { 5455 if ($9->next) { 5456 yyerror("multiple binat ip addresses"); 5457 YYERROR; 5458 } 5459 if ($9->af != binat.af && $9->af) { 5460 yyerror("binat ip versions must match"); 5461 YYERROR; 5462 } 5463 if ($9->addr.type == PF_ADDR_DYNIFTL) { 5464 if (($9 = gen_dynnode($9, binat.af)) == NULL) 5465 err(1, "calloc"); 5466 } 5467 if (check_netmask($9, binat.af)) 5468 YYERROR; 5469 memcpy(&binat.dst.addr, &$9->addr, 5470 sizeof(binat.dst.addr)); 5471 binat.dst.neg = $9->not; 5472 free($9); 5473 } 5474 5475 if (binat.action == PF_NOBINAT) { 5476 if ($13 != NULL) { 5477 yyerror("'no binat' rule does not need" 5478 " '->'"); 5479 YYERROR; 5480 } 5481 } else { 5482 if ($13 == NULL || $13->host == NULL) { 5483 yyerror("'binat' rule requires" 5484 " '-> address'"); 5485 YYERROR; 5486 } 5487 5488 remove_invalid_hosts(&$13->host, &binat.af); 5489 if (invalid_redirect($13->host, binat.af)) 5490 YYERROR; 5491 if ($13->host->next != NULL) { 5492 yyerror("binat rule must redirect to " 5493 "a single address"); 5494 YYERROR; 5495 } 5496 if ($13->host->addr.type == PF_ADDR_DYNIFTL) { 5497 if (($13->host = gen_dynnode($13->host, binat.af)) == NULL) 5498 err(1, "calloc"); 5499 } 5500 if (check_netmask($13->host, binat.af)) 5501 YYERROR; 5502 5503 if (!PF_AZERO(&binat.src.addr.v.a.mask, 5504 binat.af) && 5505 !PF_AEQ(&binat.src.addr.v.a.mask, 5506 &$13->host->addr.v.a.mask, binat.af)) { 5507 yyerror("'binat' source mask and " 5508 "redirect mask must be the same"); 5509 YYERROR; 5510 } 5511 5512 pa = calloc(1, sizeof(struct pfctl_pooladdr)); 5513 if (pa == NULL) 5514 err(1, "binat: calloc"); 5515 pa->addr = $13->host->addr; 5516 pa->ifname[0] = 0; 5517 pa->af = $13->host->af; 5518 TAILQ_INSERT_TAIL(&binat.rdr.list, 5519 pa, entries); 5520 5521 free($13); 5522 } 5523 5524 pfctl_append_rule(pf, &binat); 5525 } 5526 ; 5527 5528 tag : /* empty */ { $$ = NULL; } 5529 | TAG STRING { $$ = $2; } 5530 ; 5531 5532 tagged : /* empty */ { $$.neg = 0; $$.name = NULL; } 5533 | not TAGGED string { $$.neg = $1; $$.name = $3; } 5534 ; 5535 5536 rtable : /* empty */ { $$ = -1; } 5537 | RTABLE NUMBER { 5538 if ($2 < 0 || $2 > rt_tableid_max()) { 5539 yyerror("invalid rtable id"); 5540 YYERROR; 5541 } 5542 $$ = $2; 5543 } 5544 ; 5545 5546 route_host : STRING { 5547 $$ = calloc(1, sizeof(struct node_host)); 5548 if ($$ == NULL) 5549 err(1, "route_host: calloc"); 5550 if (strlen($1) >= IFNAMSIZ) { 5551 yyerror("interface name too long"); 5552 YYERROR; 5553 } 5554 $$->ifname = strdup($1); 5555 set_ipmask($$, 128); 5556 $$->next = NULL; 5557 $$->tail = $$; 5558 } 5559 | '(' STRING host ')' { 5560 struct node_host *n; 5561 5562 $$ = $3; 5563 for (n = $3; n != NULL; n = n->next) { 5564 if (strlen($2) >= IFNAMSIZ) { 5565 yyerror("interface name too long"); 5566 YYERROR; 5567 } 5568 n->ifname = strdup($2); 5569 } 5570 } 5571 ; 5572 5573 route_host_list : route_host optnl { $$ = $1; } 5574 | route_host_list comma route_host optnl { 5575 $1->tail->next = $3; 5576 $1->tail = $3->tail; 5577 $$ = $1; 5578 } 5579 ; 5580 5581 routespec : route_host { $$ = $1; } 5582 | '{' optnl route_host_list '}' { $$ = $3; } 5583 ; 5584 5585 route : /* empty */ { 5586 $$.rt = PF_NOPFROUTE; 5587 } 5588 | FASTROUTE { 5589 /* backwards-compat */ 5590 $$.rt = PF_NOPFROUTE; 5591 } 5592 | ROUTETO route_redirspec { 5593 $$.rt = PF_ROUTETO; 5594 $$.redirspec = $2; 5595 } 5596 | REPLYTO route_redirspec { 5597 $$.rt = PF_REPLYTO; 5598 $$.redirspec = $2; 5599 } 5600 | DUPTO route_redirspec { 5601 $$.rt = PF_DUPTO; 5602 $$.redirspec = $2; 5603 } 5604 ; 5605 5606 timeout_spec : STRING NUMBER 5607 { 5608 if (check_rulestate(PFCTL_STATE_OPTION)) { 5609 free($1); 5610 YYERROR; 5611 } 5612 if ($2 < 0 || $2 > UINT_MAX) { 5613 yyerror("only positive values permitted"); 5614 YYERROR; 5615 } 5616 if (pfctl_apply_timeout(pf, $1, $2, 0) != 0) { 5617 yyerror("unknown timeout %s", $1); 5618 free($1); 5619 YYERROR; 5620 } 5621 free($1); 5622 } 5623 | INTERVAL NUMBER { 5624 if (check_rulestate(PFCTL_STATE_OPTION)) 5625 YYERROR; 5626 if ($2 < 0 || $2 > UINT_MAX) { 5627 yyerror("only positive values permitted"); 5628 YYERROR; 5629 } 5630 if (pfctl_apply_timeout(pf, "interval", $2, 0) != 0) 5631 YYERROR; 5632 } 5633 ; 5634 5635 timeout_list : timeout_list comma timeout_spec optnl 5636 | timeout_spec optnl 5637 ; 5638 5639 limit_spec : STRING NUMBER 5640 { 5641 if (check_rulestate(PFCTL_STATE_OPTION)) { 5642 free($1); 5643 YYERROR; 5644 } 5645 if ($2 < 0 || $2 > UINT_MAX) { 5646 yyerror("only positive values permitted"); 5647 YYERROR; 5648 } 5649 if (pfctl_apply_limit(pf, $1, $2) != 0) { 5650 yyerror("unable to set limit %s %u", $1, $2); 5651 free($1); 5652 YYERROR; 5653 } 5654 free($1); 5655 } 5656 ; 5657 5658 limit_list : limit_list comma limit_spec optnl 5659 | limit_spec optnl 5660 ; 5661 5662 comma : ',' 5663 | /* empty */ 5664 ; 5665 5666 yesno : NO { $$ = 0; } 5667 | STRING { 5668 if (!strcmp($1, "yes")) 5669 $$ = 1; 5670 else { 5671 yyerror("invalid value '%s', expected 'yes' " 5672 "or 'no'", $1); 5673 free($1); 5674 YYERROR; 5675 } 5676 free($1); 5677 } 5678 ; 5679 5680 unaryop : '=' { $$ = PF_OP_EQ; } 5681 | NE { $$ = PF_OP_NE; } 5682 | LE { $$ = PF_OP_LE; } 5683 | '<' { $$ = PF_OP_LT; } 5684 | GE { $$ = PF_OP_GE; } 5685 | '>' { $$ = PF_OP_GT; } 5686 ; 5687 5688 %% 5689 5690 int 5691 yyerror(const char *fmt, ...) 5692 { 5693 va_list ap; 5694 5695 file->errors++; 5696 va_start(ap, fmt); 5697 fprintf(stderr, "%s:%d: ", file->name, yylval.lineno); 5698 vfprintf(stderr, fmt, ap); 5699 fprintf(stderr, "\n"); 5700 va_end(ap); 5701 return (0); 5702 } 5703 5704 int 5705 validate_range(uint8_t op, uint16_t p1, uint16_t p2) 5706 { 5707 uint16_t a = ntohs(p1); 5708 uint16_t b = ntohs(p2); 5709 5710 if ((op == PF_OP_RRG && a > b) || /* 34:12, i.e. none */ 5711 (op == PF_OP_IRG && a >= b) || /* 34><12, i.e. none */ 5712 (op == PF_OP_XRG && a > b)) /* 34<>22, i.e. all */ 5713 return 1; 5714 return 0; 5715 } 5716 5717 int 5718 disallow_table(struct node_host *h, const char *fmt) 5719 { 5720 for (; h != NULL; h = h->next) 5721 if (h->addr.type == PF_ADDR_TABLE) { 5722 yyerror(fmt, h->addr.v.tblname); 5723 return (1); 5724 } 5725 return (0); 5726 } 5727 5728 int 5729 disallow_urpf_failed(struct node_host *h, const char *fmt) 5730 { 5731 for (; h != NULL; h = h->next) 5732 if (h->addr.type == PF_ADDR_URPFFAILED) { 5733 yyerror(fmt); 5734 return (1); 5735 } 5736 return (0); 5737 } 5738 5739 int 5740 disallow_alias(struct node_host *h, const char *fmt) 5741 { 5742 for (; h != NULL; h = h->next) 5743 if (DYNIF_MULTIADDR(h->addr)) { 5744 yyerror(fmt, h->addr.v.tblname); 5745 return (1); 5746 } 5747 return (0); 5748 } 5749 5750 int 5751 rule_consistent(struct pfctl_rule *r) 5752 { 5753 int problems = 0; 5754 5755 switch (r->action) { 5756 case PF_PASS: 5757 case PF_MATCH: 5758 case PF_DROP: 5759 case PF_SCRUB: 5760 case PF_NOSCRUB: 5761 problems = filter_consistent(r); 5762 break; 5763 case PF_NAT: 5764 case PF_NONAT: 5765 problems = nat_consistent(r); 5766 break; 5767 case PF_RDR: 5768 case PF_NORDR: 5769 problems = rdr_consistent(r); 5770 break; 5771 case PF_BINAT: 5772 case PF_NOBINAT: 5773 default: 5774 break; 5775 } 5776 return (problems); 5777 } 5778 5779 int 5780 filter_consistent(struct pfctl_rule *r) 5781 { 5782 int problems = 0; 5783 5784 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 5785 r->proto != IPPROTO_SCTP && 5786 (r->src.port_op || r->dst.port_op)) { 5787 yyerror("port only applies to tcp/udp/sctp"); 5788 problems++; 5789 } 5790 if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 && 5791 (r->type || r->code)) { 5792 yyerror("icmp-type/code only applies to icmp"); 5793 problems++; 5794 } 5795 if (!r->af && (r->type || r->code)) { 5796 yyerror("must indicate address family with icmp-type/code"); 5797 problems++; 5798 } 5799 if (r->rule_flag & PFRULE_AFTO && r->af == r->naf) { 5800 yyerror("must indicate different address family with af-to"); 5801 problems++; 5802 } 5803 if (r->overload_tblname[0] && 5804 r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) { 5805 yyerror("'overload' requires 'max-src-conn' " 5806 "or 'max-src-conn-rate'"); 5807 problems++; 5808 } 5809 if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) || 5810 (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) { 5811 yyerror("proto %s doesn't match address family %s", 5812 r->proto == IPPROTO_ICMP ? "icmp" : "icmp6", 5813 r->af == AF_INET ? "inet" : "inet6"); 5814 problems++; 5815 } 5816 if (r->allow_opts && r->action != PF_PASS && r->action != PF_MATCH) { 5817 yyerror("allow-opts can only be specified for pass or " 5818 "match rules"); 5819 problems++; 5820 } 5821 if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op || 5822 r->dst.port_op || r->flagset || r->type || r->code)) { 5823 yyerror("fragments can be filtered only on IP header fields"); 5824 problems++; 5825 } 5826 if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) { 5827 yyerror("return-rst can only be applied to TCP rules"); 5828 problems++; 5829 } 5830 if (r->max_src_nodes && !(r->rule_flag & PFRULE_RULESRCTRACK)) { 5831 yyerror("max-src-nodes requires 'source-track rule'"); 5832 problems++; 5833 } 5834 if (r->action != PF_PASS && r->keep_state) { 5835 yyerror("keep state is great, but only for pass rules"); 5836 problems++; 5837 } 5838 if (r->rule_flag & PFRULE_STATESLOPPY && 5839 (r->keep_state == PF_STATE_MODULATE || 5840 r->keep_state == PF_STATE_SYNPROXY)) { 5841 yyerror("sloppy state matching cannot be used with " 5842 "synproxy state or modulate state"); 5843 problems++; 5844 } 5845 if ((r->keep_state == PF_STATE_SYNPROXY) && (r->direction != PF_IN)) 5846 fprintf(stderr, "%s:%d: warning: " 5847 "synproxy used for inbound rules only, " 5848 "ignored for outbound\n", file->name, yylval.lineno); 5849 if (r->rule_flag & PFRULE_AFTO && r->rt) { 5850 if (r->rt != PF_ROUTETO && r->rt != PF_REPLYTO) { 5851 yyerror("dup-to " 5852 "must not be used on af-to rules"); 5853 problems++; 5854 } 5855 } 5856 /* Basic rule sanity check. */ 5857 switch (r->action) { 5858 case PF_MATCH: 5859 if (r->divert.port) { 5860 yyerror("divert is not supported on match rules"); 5861 problems++; 5862 } 5863 if (r->rt) { 5864 yyerror("route-to, reply-to, dup-to and fastroute " 5865 "must not be used on match rules"); 5866 problems++; 5867 } 5868 if (r->rule_flag & PFRULE_AFTO) { 5869 yyerror("af-to is not supported on match rules"); 5870 problems++; 5871 } 5872 break; 5873 case PF_DROP: 5874 if (r->rt) { 5875 yyerror("route-to, reply-to and dup-to " 5876 "are not supported on block rules"); 5877 problems++; 5878 } 5879 break; 5880 default:; 5881 } 5882 if (!TAILQ_EMPTY(&(r->nat.list)) || !TAILQ_EMPTY(&(r->rdr.list))) { 5883 if (r->action != PF_MATCH && !r->keep_state) { 5884 yyerror("nat-to and rdr-to require keep state"); 5885 problems++; 5886 } 5887 if (r->direction == PF_INOUT) { 5888 yyerror("nat-to and rdr-to require a direction"); 5889 problems++; 5890 } 5891 } 5892 if (r->route.opts & PF_POOL_STICKYADDR && !r->keep_state) { 5893 yyerror("'sticky-address' requires 'keep state'"); 5894 } 5895 return (-problems); 5896 } 5897 5898 int 5899 nat_consistent(struct pfctl_rule *r) 5900 { 5901 return (0); /* yeah! */ 5902 } 5903 5904 int 5905 rdr_consistent(struct pfctl_rule *r) 5906 { 5907 int problems = 0; 5908 5909 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 5910 r->proto != IPPROTO_SCTP) { 5911 if (r->src.port_op) { 5912 yyerror("src port only applies to tcp/udp/sctp"); 5913 problems++; 5914 } 5915 if (r->dst.port_op) { 5916 yyerror("dst port only applies to tcp/udp/sctp"); 5917 problems++; 5918 } 5919 if (r->rdr.proxy_port[0]) { 5920 yyerror("rdr port only applies to tcp/udp/sctp"); 5921 problems++; 5922 } 5923 } 5924 if (r->dst.port_op && 5925 r->dst.port_op != PF_OP_EQ && r->dst.port_op != PF_OP_RRG) { 5926 yyerror("invalid port operator for rdr destination port"); 5927 problems++; 5928 } 5929 return (-problems); 5930 } 5931 5932 int 5933 process_tabledef(char *name, struct table_opts *opts, int popts) 5934 { 5935 struct pfr_buffer ab; 5936 struct node_tinit *ti; 5937 struct pfr_uktable *ukt; 5938 unsigned long maxcount; 5939 size_t s = sizeof(maxcount); 5940 5941 bzero(&ab, sizeof(ab)); 5942 ab.pfrb_type = PFRB_ADDRS; 5943 SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) { 5944 if (ti->file) 5945 if (pfr_buf_load(&ab, ti->file, 0, append_addr, popts)) { 5946 if (errno) 5947 yyerror("cannot load \"%s\": %s", 5948 ti->file, strerror(errno)); 5949 else 5950 yyerror("file \"%s\" contains bad data", 5951 ti->file); 5952 goto _error; 5953 } 5954 if (ti->host) 5955 if (append_addr_host(&ab, ti->host, 0, 0)) { 5956 yyerror("cannot create address buffer: %s", 5957 strerror(errno)); 5958 goto _error; 5959 } 5960 } 5961 if (pf->opts & PF_OPT_VERBOSE) 5962 print_tabledef(name, opts->flags, opts->init_addr, 5963 &opts->init_nodes); 5964 if (!(pf->opts & PF_OPT_NOACTION) || 5965 (pf->opts & PF_OPT_DUMMYACTION)) 5966 warn_duplicate_tables(name, pf->anchor->path); 5967 else if (pf->opts & PF_OPT_VERBOSE) 5968 fprintf(stderr, "%s:%d: skipping duplicate table checks" 5969 " for <%s>\n", file->name, yylval.lineno, name); 5970 /* 5971 * postpone definition of non-root tables to moment 5972 * when path is fully resolved. 5973 */ 5974 if (pf->asd > 0) { 5975 ukt = calloc(1, sizeof(struct pfr_uktable)); 5976 if (ukt == NULL) { 5977 DBGPRINT( 5978 "%s:%d: not enough memory for <%s>\n", file->name, 5979 yylval.lineno, name); 5980 goto _error; 5981 } 5982 } else 5983 ukt = NULL; 5984 if (!(pf->opts & PF_OPT_NOACTION) && 5985 pfctl_define_table(name, opts->flags, opts->init_addr, 5986 pf->anchor->path, &ab, pf->anchor->ruleset.tticket, ukt)) { 5987 5988 if (sysctlbyname("net.pf.request_maxcount", &maxcount, &s, 5989 NULL, 0) == -1) 5990 maxcount = 65535; 5991 5992 if (ab.pfrb_size > maxcount) 5993 yyerror("cannot define table %s: too many elements.\n" 5994 "Consider increasing net.pf.request_maxcount.", 5995 name); 5996 else 5997 yyerror("cannot define table %s: %s", name, 5998 pf_strerror(errno)); 5999 6000 goto _error; 6001 } 6002 6003 if (ukt != NULL) { 6004 ukt->pfrukt_init_addr = opts->init_addr; 6005 if (RB_INSERT(pfr_ktablehead, &pfr_ktables, 6006 &ukt->pfrukt_kt) != NULL) { 6007 /* 6008 * I think this should not happen, because 6009 * pfctl_define_table() above does the same check 6010 * effectively. 6011 */ 6012 DBGPRINT( 6013 "%s:%d table %s already exists in %s\n", 6014 file->name, yylval.lineno, 6015 ukt->pfrukt_name, pf->anchor->path); 6016 free(ukt); 6017 goto _error; 6018 } 6019 DBGPRINT("%s %s@%s inserted to tree\n", 6020 __func__, ukt->pfrukt_name, pf->anchor->path); 6021 } else 6022 DBGPRINT("%s ukt is null\n", __func__); 6023 6024 pf->tdirty = 1; 6025 pfr_buf_clear(&ab); 6026 return (0); 6027 _error: 6028 pfr_buf_clear(&ab); 6029 return (-1); 6030 } 6031 6032 struct keywords { 6033 const char *k_name; 6034 int k_val; 6035 }; 6036 6037 /* macro gore, but you should've seen the prior indentation nightmare... */ 6038 6039 #define FREE_LIST(T,r) \ 6040 do { \ 6041 T *p, *node = r; \ 6042 while (node != NULL) { \ 6043 p = node; \ 6044 node = node->next; \ 6045 free(p); \ 6046 } \ 6047 } while (0) 6048 6049 #define LOOP_THROUGH(T,n,r,C) \ 6050 do { \ 6051 T *n; \ 6052 if (r == NULL) { \ 6053 r = calloc(1, sizeof(T)); \ 6054 if (r == NULL) \ 6055 err(1, "LOOP: calloc"); \ 6056 r->next = NULL; \ 6057 } \ 6058 n = r; \ 6059 while (n != NULL) { \ 6060 do { \ 6061 C; \ 6062 } while (0); \ 6063 n = n->next; \ 6064 } \ 6065 } while (0) 6066 6067 void 6068 expand_label_str(char *label, size_t len, const char *srch, const char *repl) 6069 { 6070 char *tmp; 6071 char *p, *q; 6072 6073 if ((tmp = calloc(1, len)) == NULL) 6074 err(1, "%s: calloc", __func__); 6075 p = q = label; 6076 while ((q = strstr(p, srch)) != NULL) { 6077 *q = '\0'; 6078 if ((strlcat(tmp, p, len) >= len) || 6079 (strlcat(tmp, repl, len) >= len)) 6080 errx(1, "%s: label too long", __func__); 6081 q += strlen(srch); 6082 p = q; 6083 } 6084 if (strlcat(tmp, p, len) >= len) 6085 errx(1, "%s: label too long", __func__); 6086 strlcpy(label, tmp, len); /* always fits */ 6087 free(tmp); 6088 } 6089 6090 void 6091 expand_label_if(const char *name, char *label, size_t len, const char *ifname) 6092 { 6093 if (strstr(label, name) != NULL) { 6094 if (!*ifname) 6095 expand_label_str(label, len, name, "any"); 6096 else 6097 expand_label_str(label, len, name, ifname); 6098 } 6099 } 6100 6101 void 6102 expand_label_addr(const char *name, char *label, size_t len, sa_family_t af, 6103 struct pf_rule_addr *addr) 6104 { 6105 char tmp[64], tmp_not[66]; 6106 6107 if (strstr(label, name) != NULL) { 6108 switch (addr->addr.type) { 6109 case PF_ADDR_DYNIFTL: 6110 snprintf(tmp, sizeof(tmp), "(%s)", addr->addr.v.ifname); 6111 break; 6112 case PF_ADDR_TABLE: 6113 snprintf(tmp, sizeof(tmp), "<%s>", addr->addr.v.tblname); 6114 break; 6115 case PF_ADDR_NOROUTE: 6116 snprintf(tmp, sizeof(tmp), "no-route"); 6117 break; 6118 case PF_ADDR_URPFFAILED: 6119 snprintf(tmp, sizeof(tmp), "urpf-failed"); 6120 break; 6121 case PF_ADDR_ADDRMASK: 6122 if (!af || (PF_AZERO(&addr->addr.v.a.addr, af) && 6123 PF_AZERO(&addr->addr.v.a.mask, af))) 6124 snprintf(tmp, sizeof(tmp), "any"); 6125 else { 6126 char a[48]; 6127 int bits; 6128 6129 if (inet_ntop(af, &addr->addr.v.a.addr, a, 6130 sizeof(a)) == NULL) 6131 snprintf(tmp, sizeof(tmp), "?"); 6132 else { 6133 bits = unmask(&addr->addr.v.a.mask); 6134 if ((af == AF_INET && bits < 32) || 6135 (af == AF_INET6 && bits < 128)) 6136 snprintf(tmp, sizeof(tmp), 6137 "%s/%d", a, bits); 6138 else 6139 snprintf(tmp, sizeof(tmp), 6140 "%s", a); 6141 } 6142 } 6143 break; 6144 default: 6145 snprintf(tmp, sizeof(tmp), "?"); 6146 break; 6147 } 6148 6149 if (addr->neg) { 6150 snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp); 6151 expand_label_str(label, len, name, tmp_not); 6152 } else 6153 expand_label_str(label, len, name, tmp); 6154 } 6155 } 6156 6157 void 6158 expand_label_port(const char *name, char *label, size_t len, 6159 struct pf_rule_addr *addr) 6160 { 6161 char a1[6], a2[6], op[13] = ""; 6162 6163 if (strstr(label, name) != NULL) { 6164 snprintf(a1, sizeof(a1), "%u", ntohs(addr->port[0])); 6165 snprintf(a2, sizeof(a2), "%u", ntohs(addr->port[1])); 6166 if (!addr->port_op) 6167 ; 6168 else if (addr->port_op == PF_OP_IRG) 6169 snprintf(op, sizeof(op), "%s><%s", a1, a2); 6170 else if (addr->port_op == PF_OP_XRG) 6171 snprintf(op, sizeof(op), "%s<>%s", a1, a2); 6172 else if (addr->port_op == PF_OP_EQ) 6173 snprintf(op, sizeof(op), "%s", a1); 6174 else if (addr->port_op == PF_OP_NE) 6175 snprintf(op, sizeof(op), "!=%s", a1); 6176 else if (addr->port_op == PF_OP_LT) 6177 snprintf(op, sizeof(op), "<%s", a1); 6178 else if (addr->port_op == PF_OP_LE) 6179 snprintf(op, sizeof(op), "<=%s", a1); 6180 else if (addr->port_op == PF_OP_GT) 6181 snprintf(op, sizeof(op), ">%s", a1); 6182 else if (addr->port_op == PF_OP_GE) 6183 snprintf(op, sizeof(op), ">=%s", a1); 6184 expand_label_str(label, len, name, op); 6185 } 6186 } 6187 6188 void 6189 expand_label_proto(const char *name, char *label, size_t len, u_int8_t proto) 6190 { 6191 const char *protoname; 6192 char n[4]; 6193 6194 if (strstr(label, name) != NULL) { 6195 protoname = pfctl_proto2name(proto); 6196 if (protoname != NULL) 6197 expand_label_str(label, len, name, protoname); 6198 else { 6199 snprintf(n, sizeof(n), "%u", proto); 6200 expand_label_str(label, len, name, n); 6201 } 6202 } 6203 } 6204 6205 void 6206 expand_label_nr(const char *name, char *label, size_t len, 6207 struct pfctl_rule *r) 6208 { 6209 char n[11]; 6210 6211 if (strstr(label, name) != NULL) { 6212 snprintf(n, sizeof(n), "%u", r->nr); 6213 expand_label_str(label, len, name, n); 6214 } 6215 } 6216 6217 void 6218 expand_label(char *label, size_t len, struct pfctl_rule *r) 6219 { 6220 expand_label_if("$if", label, len, r->ifname); 6221 expand_label_addr("$srcaddr", label, len, r->af, &r->src); 6222 expand_label_addr("$dstaddr", label, len, r->af, &r->dst); 6223 expand_label_port("$srcport", label, len, &r->src); 6224 expand_label_port("$dstport", label, len, &r->dst); 6225 expand_label_proto("$proto", label, len, r->proto); 6226 expand_label_nr("$nr", label, len, r); 6227 } 6228 6229 int 6230 expand_altq(struct pf_altq *a, struct node_if *interfaces, 6231 struct node_queue *nqueues, struct node_queue_bw bwspec, 6232 struct node_queue_opt *opts) 6233 { 6234 struct pf_altq pa, pb; 6235 char qname[PF_QNAME_SIZE]; 6236 struct node_queue *n; 6237 struct node_queue_bw bw; 6238 int errs = 0; 6239 6240 if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) { 6241 FREE_LIST(struct node_if, interfaces); 6242 if (nqueues) 6243 FREE_LIST(struct node_queue, nqueues); 6244 return (0); 6245 } 6246 6247 LOOP_THROUGH(struct node_if, interface, interfaces, 6248 memcpy(&pa, a, sizeof(struct pf_altq)); 6249 if (strlcpy(pa.ifname, interface->ifname, 6250 sizeof(pa.ifname)) >= sizeof(pa.ifname)) 6251 errx(1, "%s: strlcpy", __func__); 6252 6253 if (interface->not) { 6254 yyerror("altq on ! <interface> is not supported"); 6255 errs++; 6256 } else { 6257 if (eval_pfaltq(pf, &pa, &bwspec, opts)) 6258 errs++; 6259 else 6260 if (pfctl_add_altq(pf, &pa)) 6261 errs++; 6262 6263 if (pf->opts & PF_OPT_VERBOSE) { 6264 print_altq(&pf->paltq->altq, 0, 6265 &bwspec, opts); 6266 if (nqueues && nqueues->tail) { 6267 printf("queue { "); 6268 LOOP_THROUGH(struct node_queue, queue, 6269 nqueues, 6270 printf("%s ", 6271 queue->queue); 6272 ); 6273 printf("}"); 6274 } 6275 printf("\n"); 6276 } 6277 6278 if (pa.scheduler == ALTQT_CBQ || 6279 pa.scheduler == ALTQT_HFSC || 6280 pa.scheduler == ALTQT_FAIRQ) { 6281 /* now create a root queue */ 6282 memset(&pb, 0, sizeof(struct pf_altq)); 6283 if (strlcpy(qname, "root_", sizeof(qname)) >= 6284 sizeof(qname)) 6285 errx(1, "%s: strlcpy", __func__); 6286 if (strlcat(qname, interface->ifname, 6287 sizeof(qname)) >= sizeof(qname)) 6288 errx(1, "%s: strlcat", __func__); 6289 if (strlcpy(pb.qname, qname, 6290 sizeof(pb.qname)) >= sizeof(pb.qname)) 6291 errx(1, "%s: strlcpy", __func__); 6292 if (strlcpy(pb.ifname, interface->ifname, 6293 sizeof(pb.ifname)) >= sizeof(pb.ifname)) 6294 errx(1, "%s: strlcpy", __func__); 6295 pb.qlimit = pa.qlimit; 6296 pb.scheduler = pa.scheduler; 6297 bw.bw_absolute = pa.ifbandwidth; 6298 bw.bw_percent = 0; 6299 if (eval_pfqueue(pf, &pb, &bw, opts)) 6300 errs++; 6301 else 6302 if (pfctl_add_altq(pf, &pb)) 6303 errs++; 6304 } 6305 6306 LOOP_THROUGH(struct node_queue, queue, nqueues, 6307 n = calloc(1, sizeof(struct node_queue)); 6308 if (n == NULL) 6309 err(1, "%s: calloc", __func__); 6310 if (pa.scheduler == ALTQT_CBQ || 6311 pa.scheduler == ALTQT_HFSC || 6312 pa.scheduler == ALTQT_FAIRQ) 6313 if (strlcpy(n->parent, qname, 6314 sizeof(n->parent)) >= 6315 sizeof(n->parent)) 6316 errx(1, "%s: strlcpy", __func__); 6317 if (strlcpy(n->queue, queue->queue, 6318 sizeof(n->queue)) >= sizeof(n->queue)) 6319 errx(1, "%s: strlcpy", __func__); 6320 if (strlcpy(n->ifname, interface->ifname, 6321 sizeof(n->ifname)) >= sizeof(n->ifname)) 6322 errx(1, "%s: strlcpy", __func__); 6323 n->scheduler = pa.scheduler; 6324 n->next = NULL; 6325 n->tail = n; 6326 if (queues == NULL) 6327 queues = n; 6328 else { 6329 queues->tail->next = n; 6330 queues->tail = n; 6331 } 6332 ); 6333 } 6334 ); 6335 FREE_LIST(struct node_if, interfaces); 6336 if (nqueues) 6337 FREE_LIST(struct node_queue, nqueues); 6338 6339 return (errs); 6340 } 6341 6342 int 6343 expand_queue(struct pf_altq *a, struct node_if *interfaces, 6344 struct node_queue *nqueues, struct node_queue_bw bwspec, 6345 struct node_queue_opt *opts) 6346 { 6347 struct node_queue *n, *nq; 6348 struct pf_altq pa; 6349 u_int8_t found = 0; 6350 u_int8_t errs = 0; 6351 6352 if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) { 6353 FREE_LIST(struct node_queue, nqueues); 6354 return (0); 6355 } 6356 6357 if (queues == NULL) { 6358 yyerror("queue %s has no parent", a->qname); 6359 FREE_LIST(struct node_queue, nqueues); 6360 return (1); 6361 } 6362 6363 LOOP_THROUGH(struct node_if, interface, interfaces, 6364 LOOP_THROUGH(struct node_queue, tqueue, queues, 6365 if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE) && 6366 (interface->ifname[0] == 0 || 6367 (!interface->not && !strncmp(interface->ifname, 6368 tqueue->ifname, IFNAMSIZ)) || 6369 (interface->not && strncmp(interface->ifname, 6370 tqueue->ifname, IFNAMSIZ)))) { 6371 /* found ourself in queues */ 6372 found++; 6373 6374 memcpy(&pa, a, sizeof(struct pf_altq)); 6375 6376 if (pa.scheduler != ALTQT_NONE && 6377 pa.scheduler != tqueue->scheduler) { 6378 yyerror("exactly one scheduler type " 6379 "per interface allowed"); 6380 return (1); 6381 } 6382 pa.scheduler = tqueue->scheduler; 6383 6384 /* scheduler dependent error checking */ 6385 switch (pa.scheduler) { 6386 case ALTQT_PRIQ: 6387 if (nqueues != NULL) { 6388 yyerror("priq queues cannot " 6389 "have child queues"); 6390 return (1); 6391 } 6392 if (bwspec.bw_absolute > 0 || 6393 bwspec.bw_percent < 100) { 6394 yyerror("priq doesn't take " 6395 "bandwidth"); 6396 return (1); 6397 } 6398 break; 6399 default: 6400 break; 6401 } 6402 6403 if (strlcpy(pa.ifname, tqueue->ifname, 6404 sizeof(pa.ifname)) >= sizeof(pa.ifname)) 6405 errx(1, "%s: strlcpy", __func__); 6406 if (strlcpy(pa.parent, tqueue->parent, 6407 sizeof(pa.parent)) >= sizeof(pa.parent)) 6408 errx(1, "%s: strlcpy", __func__); 6409 6410 if (eval_pfqueue(pf, &pa, &bwspec, opts)) 6411 errs++; 6412 else 6413 if (pfctl_add_altq(pf, &pa)) 6414 errs++; 6415 6416 for (nq = nqueues; nq != NULL; nq = nq->next) { 6417 if (!strcmp(a->qname, nq->queue)) { 6418 yyerror("queue cannot have " 6419 "itself as child"); 6420 errs++; 6421 continue; 6422 } 6423 n = calloc(1, 6424 sizeof(struct node_queue)); 6425 if (n == NULL) 6426 err(1, "%s: calloc", __func__); 6427 if (strlcpy(n->parent, a->qname, 6428 sizeof(n->parent)) >= 6429 sizeof(n->parent)) 6430 errx(1, "%s strlcpy", __func__); 6431 if (strlcpy(n->queue, nq->queue, 6432 sizeof(n->queue)) >= 6433 sizeof(n->queue)) 6434 errx(1, "%s strlcpy", __func__); 6435 if (strlcpy(n->ifname, tqueue->ifname, 6436 sizeof(n->ifname)) >= 6437 sizeof(n->ifname)) 6438 errx(1, "%s strlcpy", __func__); 6439 n->scheduler = tqueue->scheduler; 6440 n->next = NULL; 6441 n->tail = n; 6442 if (queues == NULL) 6443 queues = n; 6444 else { 6445 queues->tail->next = n; 6446 queues->tail = n; 6447 } 6448 } 6449 if ((pf->opts & PF_OPT_VERBOSE) && ( 6450 (found == 1 && interface->ifname[0] == 0) || 6451 (found > 0 && interface->ifname[0] != 0))) { 6452 print_queue(&pf->paltq->altq, 0, 6453 &bwspec, interface->ifname[0] != 0, 6454 opts); 6455 if (nqueues && nqueues->tail) { 6456 printf("{ "); 6457 LOOP_THROUGH(struct node_queue, 6458 queue, nqueues, 6459 printf("%s ", 6460 queue->queue); 6461 ); 6462 printf("}"); 6463 } 6464 printf("\n"); 6465 } 6466 } 6467 ); 6468 ); 6469 6470 FREE_LIST(struct node_queue, nqueues); 6471 FREE_LIST(struct node_if, interfaces); 6472 6473 if (!found) { 6474 yyerror("queue %s has no parent", a->qname); 6475 errs++; 6476 } 6477 6478 if (errs) 6479 return (1); 6480 else 6481 return (0); 6482 } 6483 6484 static int 6485 pf_af_to_proto(sa_family_t af) 6486 { 6487 if (af == AF_INET) 6488 return (ETHERTYPE_IP); 6489 if (af == AF_INET6) 6490 return (ETHERTYPE_IPV6); 6491 6492 return (0); 6493 } 6494 6495 void 6496 expand_eth_rule(struct pfctl_eth_rule *r, 6497 struct node_if *interfaces, struct node_etherproto *protos, 6498 struct node_mac *srcs, struct node_mac *dsts, 6499 struct node_host *ipsrcs, struct node_host *ipdsts, 6500 const char *bridge_to, const char *anchor_call) 6501 { 6502 char tagname[PF_TAG_NAME_SIZE]; 6503 char match_tagname[PF_TAG_NAME_SIZE]; 6504 char qname[PF_QNAME_SIZE]; 6505 6506 if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname)) 6507 errx(1, "%s: tagname", __func__); 6508 if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >= 6509 sizeof(match_tagname)) 6510 errx(1, "%s: match_tagname", __func__); 6511 if (strlcpy(qname, r->qname, sizeof(qname)) >= sizeof(qname)) 6512 errx(1, "%s: qname", __func__); 6513 6514 LOOP_THROUGH(struct node_if, interface, interfaces, 6515 LOOP_THROUGH(struct node_etherproto, proto, protos, 6516 LOOP_THROUGH(struct node_mac, src, srcs, 6517 LOOP_THROUGH(struct node_mac, dst, dsts, 6518 LOOP_THROUGH(struct node_host, ipsrc, ipsrcs, 6519 LOOP_THROUGH(struct node_host, ipdst, ipdsts, 6520 strlcpy(r->ifname, interface->ifname, 6521 sizeof(r->ifname)); 6522 r->ifnot = interface->not; 6523 r->proto = proto->proto; 6524 if (!r->proto && ipsrc->af) 6525 r->proto = pf_af_to_proto(ipsrc->af); 6526 else if (!r->proto && ipdst->af) 6527 r->proto = pf_af_to_proto(ipdst->af); 6528 bcopy(src->mac, r->src.addr, ETHER_ADDR_LEN); 6529 bcopy(src->mask, r->src.mask, ETHER_ADDR_LEN); 6530 r->src.neg = src->neg; 6531 r->src.isset = src->isset; 6532 r->ipsrc.addr = ipsrc->addr; 6533 r->ipsrc.neg = ipsrc->not; 6534 r->ipdst.addr = ipdst->addr; 6535 r->ipdst.neg = ipdst->not; 6536 bcopy(dst->mac, r->dst.addr, ETHER_ADDR_LEN); 6537 bcopy(dst->mask, r->dst.mask, ETHER_ADDR_LEN); 6538 r->dst.neg = dst->neg; 6539 r->dst.isset = dst->isset; 6540 r->nr = pf->eastack[pf->asd]->match++; 6541 6542 if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >= 6543 sizeof(r->tagname)) 6544 errx(1, "%s: r->tagname", __func__); 6545 if (strlcpy(r->match_tagname, match_tagname, 6546 sizeof(r->match_tagname)) >= sizeof(r->match_tagname)) 6547 errx(1, "%s: r->match_tagname", __func__); 6548 if (strlcpy(r->qname, qname, sizeof(r->qname)) >= sizeof(r->qname)) 6549 errx(1, "%s: r->qname", __func__); 6550 6551 if (bridge_to) 6552 strlcpy(r->bridge_to, bridge_to, sizeof(r->bridge_to)); 6553 6554 pfctl_append_eth_rule(pf, r, anchor_call); 6555 )))))); 6556 6557 FREE_LIST(struct node_if, interfaces); 6558 FREE_LIST(struct node_etherproto, protos); 6559 FREE_LIST(struct node_mac, srcs); 6560 FREE_LIST(struct node_mac, dsts); 6561 FREE_LIST(struct node_host, ipsrcs); 6562 FREE_LIST(struct node_host, ipdsts); 6563 } 6564 6565 int 6566 apply_rdr_ports(struct pfctl_rule *r, struct pfctl_pool *rpool, struct redirspec *rs) 6567 { 6568 if (rs == NULL) 6569 return 0; 6570 6571 rpool->proxy_port[0] = ntohs(rs->rport.a); 6572 6573 if (!rs->rport.b && rs->rport.t) { 6574 rpool->proxy_port[1] = ntohs(rs->rport.a) + 6575 (ntohs(r->dst.port[1]) - ntohs(r->dst.port[0])); 6576 } else { 6577 if (validate_range(rs->rport.t, rs->rport.a, 6578 rs->rport.b)) { 6579 yyerror("invalid rdr-to port range"); 6580 return (1); 6581 } 6582 r->rdr.proxy_port[1] = ntohs(rs->rport.b); 6583 } 6584 6585 if (rs->pool_opts.staticport) { 6586 yyerror("the 'static-port' option is only valid with nat rules"); 6587 return 1; 6588 } 6589 6590 if (rs->pool_opts.mape.offset) { 6591 yyerror("the 'map-e-portset' option is only valid with nat rules"); 6592 return 1; 6593 } 6594 6595 return 0; 6596 } 6597 6598 int 6599 apply_nat_ports(struct pfctl_pool *rpool, struct redirspec *rs) 6600 { 6601 if (rs == NULL) 6602 return 0; 6603 6604 rpool->proxy_port[0] = ntohs(rs->rport.a); 6605 rpool->proxy_port[1] = ntohs(rs->rport.b); 6606 if (!rpool->proxy_port[0] && !rpool->proxy_port[1]) { 6607 rpool->proxy_port[0] = PF_NAT_PROXY_PORT_LOW; 6608 rpool->proxy_port[1] = PF_NAT_PROXY_PORT_HIGH; 6609 } else if (!rpool->proxy_port[1]) 6610 rpool->proxy_port[1] = rpool->proxy_port[0]; 6611 6612 if (rs->pool_opts.staticport) { 6613 if (rpool->proxy_port[0] != PF_NAT_PROXY_PORT_LOW && 6614 rpool->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) { 6615 yyerror("the 'static-port' option can't" 6616 " be used when specifying a port" 6617 " range"); 6618 return 1; 6619 } 6620 rpool->proxy_port[0] = 0; 6621 rpool->proxy_port[1] = 0; 6622 } 6623 6624 if (rs->pool_opts.mape.offset) { 6625 if (rs->pool_opts.staticport) { 6626 yyerror("the 'map-e-portset' option" 6627 " can't be used 'static-port'"); 6628 return 1; 6629 } 6630 if (rpool->proxy_port[0] != PF_NAT_PROXY_PORT_LOW && 6631 rpool->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) { 6632 yyerror("the 'map-e-portset' option" 6633 " can't be used when specifying" 6634 " a port range"); 6635 return 1; 6636 } 6637 rpool->mape = rs->pool_opts.mape; 6638 } 6639 6640 return 0; 6641 } 6642 6643 int 6644 apply_redirspec(struct pfctl_pool *rpool, struct redirspec *rs) 6645 { 6646 struct node_host *h; 6647 struct pfctl_pooladdr *pa; 6648 6649 if (rs == NULL) 6650 return 0; 6651 6652 rpool->opts = rs->pool_opts.type; 6653 6654 if ((rpool->opts & PF_POOL_TYPEMASK) == PF_POOL_NONE && 6655 (rs->host->next != NULL || 6656 rs->host->addr.type == PF_ADDR_TABLE || 6657 DYNIF_MULTIADDR(rs->host->addr))) 6658 rpool->opts = PF_POOL_ROUNDROBIN; 6659 6660 if (!PF_POOL_DYNTYPE(rpool->opts) && 6661 (disallow_table(rs->host, "tables are not supported by pool type") || 6662 disallow_alias(rs->host, "interface (%s) is not supported by pool type"))) 6663 return 1; 6664 6665 if (rs->host->next != NULL && 6666 ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN)) { 6667 yyerror("r.route.opts must be PF_POOL_ROUNDROBIN"); 6668 return 1; 6669 } 6670 6671 if (rs->host->next != NULL) { 6672 if ((rpool->opts & PF_POOL_TYPEMASK) != 6673 PF_POOL_ROUNDROBIN) { 6674 yyerror("only round-robin valid for multiple " 6675 "redirection addresses"); 6676 return 1; 6677 } 6678 } 6679 6680 rpool->opts |= rs->pool_opts.opts; 6681 6682 if (rs->pool_opts.key != NULL) 6683 memcpy(&(rpool->key), rs->pool_opts.key, 6684 sizeof(struct pf_poolhashkey)); 6685 6686 for (h = rs->host; h != NULL; h = h->next) { 6687 pa = calloc(1, sizeof(struct pfctl_pooladdr)); 6688 if (pa == NULL) 6689 err(1, "%s: calloc", __func__); 6690 pa->addr = h->addr; 6691 pa->af = h->af; 6692 if (h->ifname != NULL) { 6693 if (strlcpy(pa->ifname, h->ifname, 6694 sizeof(pa->ifname)) >= sizeof(pa->ifname)) 6695 errx(1, "%s: strlcpy", __func__); 6696 } else 6697 pa->ifname[0] = 0; 6698 TAILQ_INSERT_TAIL(&(rpool->list), pa, entries); 6699 } 6700 6701 return 0; 6702 } 6703 6704 int 6705 check_binat_redirspec(struct node_host *src_host, struct pfctl_rule *r, 6706 sa_family_t af) 6707 { 6708 struct pfctl_pooladdr *nat_pool = TAILQ_FIRST(&(r->nat.list)); 6709 int error = 0; 6710 6711 /* XXX: FreeBSD allows syntax like "{ host1 host2 }" for redirection 6712 * pools but does not covert them to tables automatically, because 6713 * syntax "{ (iface1 host1), (iface2 iface2) }" is allowed for route-to 6714 * redirection. Add a FreeBSD-specific guard against using multiple 6715 * hosts for source and redirection. 6716 */ 6717 if (src_host->next) { 6718 yyerror("invalid use of table as the source address " 6719 "of a binat-to rule"); 6720 error++; 6721 } 6722 if (TAILQ_NEXT(nat_pool, entries)) { 6723 yyerror ("tables cannot be used as the redirect " 6724 "address of a binat-to rule"); 6725 error++; 6726 } 6727 6728 if (disallow_table(src_host, "invalid use of table " 6729 "<%s> as the source address of a binat-to rule") || 6730 disallow_alias(src_host, "invalid use of interface " 6731 "(%s) as the source address of a binat-to rule")) { 6732 error++; 6733 } else if ((r->src.addr.type != PF_ADDR_ADDRMASK && 6734 r->src.addr.type != PF_ADDR_DYNIFTL) || 6735 (nat_pool->addr.type != PF_ADDR_ADDRMASK && 6736 nat_pool->addr.type != PF_ADDR_DYNIFTL)) { 6737 yyerror("binat-to requires a specified " 6738 "source and redirect address"); 6739 error++; 6740 } 6741 if (DYNIF_MULTIADDR(r->src.addr) || 6742 DYNIF_MULTIADDR(nat_pool->addr)) { 6743 yyerror ("dynamic interfaces must be " 6744 "used with:0 in a binat-to rule"); 6745 error++; 6746 } 6747 if (PF_AZERO(&r->src.addr.v.a.mask, af) || 6748 PF_AZERO(&(nat_pool->addr.v.a.mask), af)) { 6749 yyerror ("source and redir addresses must have " 6750 "a matching network mask in binat-rule"); 6751 error++; 6752 } 6753 if (nat_pool->addr.type == PF_ADDR_TABLE) { 6754 yyerror ("tables cannot be used as the redirect " 6755 "address of a binat-to rule"); 6756 error++; 6757 } 6758 if (r->direction != PF_INOUT) { 6759 yyerror("binat-to cannot be specified " 6760 "with a direction"); 6761 error++; 6762 } 6763 6764 /* first specify outbound NAT rule */ 6765 r->direction = PF_OUT; 6766 6767 return (error); 6768 } 6769 6770 void 6771 add_binat_rdr_rule( 6772 struct pfctl_rule *binat_rule, 6773 struct redirspec *binat_nat_redirspec, struct node_host *binat_src_host, 6774 struct pfctl_rule *rdr_rule, struct redirspec **rdr_redirspec, 6775 struct node_host **rdr_dst_host) 6776 { 6777 struct node_host *rdr_src_host; 6778 6779 /* 6780 * We're copying the whole rule, but we must re-init redir pools. 6781 * FreeBSD uses lists of pfctl_pooladdr, we can't just overwrite them. 6782 */ 6783 bcopy(binat_rule, rdr_rule, sizeof(struct pfctl_rule)); 6784 TAILQ_INIT(&(rdr_rule->rdr.list)); 6785 TAILQ_INIT(&(rdr_rule->nat.list)); 6786 6787 /* now specify inbound rdr rule */ 6788 rdr_rule->direction = PF_IN; 6789 6790 if ((rdr_src_host = calloc(1, sizeof(*rdr_src_host))) == NULL) 6791 err(1, "%s", __func__); 6792 bcopy(binat_src_host, rdr_src_host, sizeof(*rdr_src_host)); 6793 rdr_src_host->ifname = NULL; 6794 rdr_src_host->next = NULL; 6795 rdr_src_host->tail = NULL; 6796 6797 if (((*rdr_dst_host) = calloc(1, sizeof(**rdr_dst_host))) == NULL) 6798 err(1, "%s", __func__); 6799 bcopy(&(binat_nat_redirspec->host->addr), &((*rdr_dst_host)->addr), 6800 sizeof((*rdr_dst_host)->addr)); 6801 (*rdr_dst_host)->ifname = NULL; 6802 (*rdr_dst_host)->next = NULL; 6803 (*rdr_dst_host)->tail = NULL; 6804 6805 if (((*rdr_redirspec) = calloc(1, sizeof(**rdr_redirspec))) == NULL) 6806 err(1, "%s", __func__); 6807 bcopy(binat_nat_redirspec, (*rdr_redirspec), sizeof(**rdr_redirspec)); 6808 (*rdr_redirspec)->pool_opts.staticport = 0; 6809 (*rdr_redirspec)->host = rdr_src_host; 6810 } 6811 6812 void 6813 expand_rule(struct pfctl_rule *r, bool keeprule, 6814 struct node_if *interfaces, struct redirspec *nat, 6815 struct redirspec *rdr, struct redirspec *route, 6816 struct node_proto *protos, 6817 struct node_os *src_oses, struct node_host *src_hosts, 6818 struct node_port *src_ports, struct node_host *dst_hosts, 6819 struct node_port *dst_ports, struct node_uid *uids, struct node_gid *gids, 6820 struct node_if *rcv, struct node_icmp *icmp_types) 6821 { 6822 sa_family_t af = r->af; 6823 int added = 0, error = 0; 6824 char ifname[IF_NAMESIZE]; 6825 char label[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE]; 6826 char tagname[PF_TAG_NAME_SIZE]; 6827 char match_tagname[PF_TAG_NAME_SIZE]; 6828 struct node_host *osrch, *odsth; 6829 u_int8_t flags, flagset, keep_state; 6830 6831 memcpy(label, r->label, sizeof(r->label)); 6832 assert(sizeof(r->label) == sizeof(label)); 6833 if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname)) 6834 errx(1, "%s: strlcpy", __func__); 6835 if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >= 6836 sizeof(match_tagname)) 6837 errx(1, "%s: strlcpy", __func__); 6838 flags = r->flags; 6839 flagset = r->flagset; 6840 keep_state = r->keep_state; 6841 6842 LOOP_THROUGH(struct node_if, interface, interfaces, 6843 LOOP_THROUGH(struct node_proto, proto, protos, 6844 LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types, 6845 LOOP_THROUGH(struct node_host, src_host, src_hosts, 6846 LOOP_THROUGH(struct node_host, dst_host, dst_hosts, 6847 LOOP_THROUGH(struct node_port, src_port, src_ports, 6848 LOOP_THROUGH(struct node_port, dst_port, dst_ports, 6849 LOOP_THROUGH(struct node_os, src_os, src_oses, 6850 LOOP_THROUGH(struct node_uid, uid, uids, 6851 LOOP_THROUGH(struct node_gid, gid, gids, 6852 6853 r->af = af; 6854 6855 if (r->rule_flag & PFRULE_AFTO) { 6856 assert(nat != NULL); 6857 r->naf = nat->af; 6858 } 6859 6860 /* for link-local IPv6 address, interface must match up */ 6861 if ((r->af && src_host->af && r->af != src_host->af) || 6862 (r->af && dst_host->af && r->af != dst_host->af) || 6863 (src_host->af && dst_host->af && 6864 src_host->af != dst_host->af) || 6865 (src_host->ifindex && dst_host->ifindex && 6866 src_host->ifindex != dst_host->ifindex) || 6867 (src_host->ifindex && *interface->ifname && 6868 src_host->ifindex != ifa_nametoindex(interface->ifname)) || 6869 (dst_host->ifindex && *interface->ifname && 6870 dst_host->ifindex != ifa_nametoindex(interface->ifname))) 6871 continue; 6872 if (!r->af && src_host->af) 6873 r->af = src_host->af; 6874 else if (!r->af && dst_host->af) 6875 r->af = dst_host->af; 6876 6877 if (*interface->ifname) 6878 strlcpy(r->ifname, interface->ifname, 6879 sizeof(r->ifname)); 6880 else if (ifa_indextoname(src_host->ifindex, ifname)) 6881 strlcpy(r->ifname, ifname, sizeof(r->ifname)); 6882 else if (ifa_indextoname(dst_host->ifindex, ifname)) 6883 strlcpy(r->ifname, ifname, sizeof(r->ifname)); 6884 else 6885 memset(r->ifname, '\0', sizeof(r->ifname)); 6886 6887 memcpy(r->label, label, sizeof(r->label)); 6888 if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >= 6889 sizeof(r->tagname)) 6890 errx(1, "%s: strlcpy", __func__); 6891 if (strlcpy(r->match_tagname, match_tagname, 6892 sizeof(r->match_tagname)) >= sizeof(r->match_tagname)) 6893 errx(1, "%s: strlcpy", __func__); 6894 6895 osrch = odsth = NULL; 6896 if (src_host->addr.type == PF_ADDR_DYNIFTL) { 6897 osrch = src_host; 6898 if ((src_host = gen_dynnode(src_host, r->af)) == NULL) 6899 err(1, "%s: calloc", __func__); 6900 } 6901 if (dst_host->addr.type == PF_ADDR_DYNIFTL) { 6902 odsth = dst_host; 6903 if ((dst_host = gen_dynnode(dst_host, r->af)) == NULL) 6904 err(1, "%s: calloc", __func__); 6905 } 6906 6907 error += check_netmask(src_host, r->af); 6908 error += check_netmask(dst_host, r->af); 6909 6910 r->ifnot = interface->not; 6911 r->proto = proto->proto; 6912 r->src.addr = src_host->addr; 6913 r->src.neg = src_host->not; 6914 r->src.port[0] = src_port->port[0]; 6915 r->src.port[1] = src_port->port[1]; 6916 r->src.port_op = src_port->op; 6917 r->dst.addr = dst_host->addr; 6918 r->dst.neg = dst_host->not; 6919 r->dst.port[0] = dst_port->port[0]; 6920 r->dst.port[1] = dst_port->port[1]; 6921 r->dst.port_op = dst_port->op; 6922 r->uid.op = uid->op; 6923 r->uid.uid[0] = uid->uid[0]; 6924 r->uid.uid[1] = uid->uid[1]; 6925 r->gid.op = gid->op; 6926 r->gid.gid[0] = gid->gid[0]; 6927 r->gid.gid[1] = gid->gid[1]; 6928 if (rcv) { 6929 strlcpy(r->rcv_ifname, rcv->ifname, 6930 sizeof(r->rcv_ifname)); 6931 r->rcvifnot = rcv->not; 6932 } 6933 r->type = icmp_type->type; 6934 r->code = icmp_type->code; 6935 6936 if ((keep_state == PF_STATE_MODULATE || 6937 keep_state == PF_STATE_SYNPROXY) && 6938 r->proto && r->proto != IPPROTO_TCP) 6939 r->keep_state = PF_STATE_NORMAL; 6940 else 6941 r->keep_state = keep_state; 6942 6943 if (r->proto && r->proto != IPPROTO_TCP) { 6944 r->flags = 0; 6945 r->flagset = 0; 6946 } else { 6947 r->flags = flags; 6948 r->flagset = flagset; 6949 } 6950 if (icmp_type->proto && r->proto != icmp_type->proto) { 6951 yyerror("icmp-type mismatch"); 6952 error++; 6953 } 6954 6955 if (src_os && src_os->os) { 6956 r->os_fingerprint = pfctl_get_fingerprint(src_os->os); 6957 if ((pf->opts & PF_OPT_VERBOSE2) && 6958 r->os_fingerprint == PF_OSFP_NOMATCH) 6959 fprintf(stderr, 6960 "warning: unknown '%s' OS fingerprint\n", 6961 src_os->os); 6962 } else { 6963 r->os_fingerprint = PF_OSFP_ANY; 6964 } 6965 6966 if (r->action == PF_RDR) { 6967 /* Pre-FreeBSD 15 "rdr" rule */ 6968 error += apply_rdr_ports(r, &(r->rdr), rdr); 6969 error += apply_redirspec(&(r->rdr), rdr); 6970 } else if (r->action == PF_NAT) { 6971 /* Pre-FreeBSD 15 "nat" rule */ 6972 error += apply_nat_ports(&(r->rdr), rdr); 6973 error += apply_redirspec(&(r->rdr), rdr); 6974 } else { 6975 /* Modern rule with optional NAT, BINAT, RDR or ROUTE*/ 6976 error += apply_redirspec(&(r->route), route); 6977 6978 error += apply_nat_ports(&(r->nat), nat); 6979 error += apply_redirspec(&(r->nat), nat); 6980 error += apply_rdr_ports(r, &(r->rdr), rdr); 6981 error += apply_redirspec(&(r->rdr), rdr); 6982 6983 if (nat && nat->binat) 6984 error += check_binat_redirspec(src_host, r, af); 6985 } 6986 6987 if (rule_consistent(r) < 0 || error) 6988 yyerror("skipping rule due to errors"); 6989 else { 6990 r->nr = pf->astack[pf->asd]->match++; 6991 pfctl_append_rule(pf, r); 6992 added++; 6993 } 6994 6995 /* Generate binat's matching inbound rule */ 6996 if (!error && nat && nat->binat) { 6997 struct pfctl_rule rdr_rule; 6998 struct redirspec *rdr_redirspec; 6999 struct node_host *rdr_dst_host; 7000 7001 add_binat_rdr_rule( 7002 r, nat, src_hosts, 7003 &rdr_rule, &rdr_redirspec, &rdr_dst_host); 7004 7005 expand_rule(&rdr_rule, true, interface, NULL, rdr_redirspec, 7006 NULL, proto, src_os, dst_host, dst_port, 7007 rdr_dst_host, src_port, uid, gid, rcv, icmp_type); 7008 } 7009 7010 if (osrch && src_host->addr.type == PF_ADDR_DYNIFTL) { 7011 free(src_host); 7012 src_host = osrch; 7013 } 7014 if (odsth && dst_host->addr.type == PF_ADDR_DYNIFTL) { 7015 free(dst_host); 7016 dst_host = odsth; 7017 } 7018 7019 )))))))))); 7020 7021 if (!keeprule) { 7022 FREE_LIST(struct node_if, interfaces); 7023 FREE_LIST(struct node_proto, protos); 7024 FREE_LIST(struct node_host, src_hosts); 7025 FREE_LIST(struct node_port, src_ports); 7026 FREE_LIST(struct node_os, src_oses); 7027 FREE_LIST(struct node_host, dst_hosts); 7028 FREE_LIST(struct node_port, dst_ports); 7029 FREE_LIST(struct node_uid, uids); 7030 FREE_LIST(struct node_gid, gids); 7031 FREE_LIST(struct node_icmp, icmp_types); 7032 if (nat) { 7033 FREE_LIST(struct node_host, nat->host); 7034 free(nat); 7035 } 7036 if (rdr) { 7037 FREE_LIST(struct node_host, rdr->host); 7038 free(rdr); 7039 } 7040 if (route) { 7041 FREE_LIST(struct node_host, route->host); 7042 free(route); 7043 } 7044 } 7045 7046 if (!added) 7047 yyerror("rule expands to no valid combination"); 7048 } 7049 7050 int 7051 expand_skip_interface(struct node_if *interfaces) 7052 { 7053 int errs = 0; 7054 7055 if (!interfaces || (!interfaces->next && !interfaces->not && 7056 !strcmp(interfaces->ifname, "none"))) { 7057 if (pf->opts & PF_OPT_VERBOSE) 7058 printf("set skip on none\n"); 7059 errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0); 7060 return (errs); 7061 } 7062 7063 if (pf->opts & PF_OPT_VERBOSE) 7064 printf("set skip on {"); 7065 LOOP_THROUGH(struct node_if, interface, interfaces, 7066 if (pf->opts & PF_OPT_VERBOSE) 7067 printf(" %s", interface->ifname); 7068 if (interface->not) { 7069 yyerror("skip on ! <interface> is not supported"); 7070 errs++; 7071 } else 7072 errs += pfctl_set_interface_flags(pf, 7073 interface->ifname, PFI_IFLAG_SKIP, 1); 7074 ); 7075 if (pf->opts & PF_OPT_VERBOSE) 7076 printf(" }\n"); 7077 7078 FREE_LIST(struct node_if, interfaces); 7079 7080 if (errs) 7081 return (1); 7082 else 7083 return (0); 7084 } 7085 7086 void 7087 freehostlist(struct node_host *h) 7088 { 7089 FREE_LIST(struct node_host, h); 7090 } 7091 7092 #undef FREE_LIST 7093 #undef LOOP_THROUGH 7094 7095 int 7096 check_rulestate(int desired_state) 7097 { 7098 if (require_order && (rulestate > desired_state)) { 7099 yyerror("Rules must be in order: options, ethernet, " 7100 "normalization, queueing, translation, filtering"); 7101 return (1); 7102 } 7103 rulestate = desired_state; 7104 return (0); 7105 } 7106 7107 int 7108 kw_cmp(const void *k, const void *e) 7109 { 7110 return (strcmp(k, ((const struct keywords *)e)->k_name)); 7111 } 7112 7113 int 7114 lookup(char *s) 7115 { 7116 /* this has to be sorted always */ 7117 static const struct keywords keywords[] = { 7118 { "above", ABOVE}, 7119 { "af-to", AFTO}, 7120 { "all", ALL}, 7121 { "allow-opts", ALLOWOPTS}, 7122 { "allow-related", ALLOW_RELATED}, 7123 { "altq", ALTQ}, 7124 { "anchor", ANCHOR}, 7125 { "antispoof", ANTISPOOF}, 7126 { "any", ANY}, 7127 { "bandwidth", BANDWIDTH}, 7128 { "below", BELOW}, 7129 { "binat", BINAT}, 7130 { "binat-anchor", BINATANCHOR}, 7131 { "binat-to", BINATTO}, 7132 { "bitmask", BITMASK}, 7133 { "block", BLOCK}, 7134 { "block-policy", BLOCKPOLICY}, 7135 { "bridge-to", BRIDGE_TO}, 7136 { "buckets", BUCKETS}, 7137 { "cbq", CBQ}, 7138 { "code", CODE}, 7139 { "codelq", CODEL}, 7140 { "debug", DEBUG}, 7141 { "divert-reply", DIVERTREPLY}, 7142 { "divert-to", DIVERTTO}, 7143 { "dnpipe", DNPIPE}, 7144 { "dnqueue", DNQUEUE}, 7145 { "drop", DROP}, 7146 { "dup-to", DUPTO}, 7147 { "endpoint-independent", ENDPI}, 7148 { "entries", ENTRIES}, 7149 { "ether", ETHER}, 7150 { "fail-policy", FAILPOLICY}, 7151 { "fairq", FAIRQ}, 7152 { "fastroute", FASTROUTE}, 7153 { "file", FILENAME}, 7154 { "fingerprints", FINGERPRINTS}, 7155 { "flags", FLAGS}, 7156 { "floating", FLOATING}, 7157 { "flush", FLUSH}, 7158 { "for", FOR}, 7159 { "fragment", FRAGMENT}, 7160 { "from", FROM}, 7161 { "global", GLOBAL}, 7162 { "group", GROUP}, 7163 { "hfsc", HFSC}, 7164 { "hogs", HOGS}, 7165 { "hostid", HOSTID}, 7166 { "icmp-type", ICMPTYPE}, 7167 { "icmp6-type", ICMP6TYPE}, 7168 { "id", ID}, 7169 { "if-bound", IFBOUND}, 7170 { "in", IN}, 7171 { "include", INCLUDE}, 7172 { "inet", INET}, 7173 { "inet6", INET6}, 7174 { "interval", INTERVAL}, 7175 { "keep", KEEP}, 7176 { "keepcounters", KEEPCOUNTERS}, 7177 { "l3", L3}, 7178 { "label", LABEL}, 7179 { "limit", LIMIT}, 7180 { "limiter", LIMITER}, 7181 { "linkshare", LINKSHARE}, 7182 { "load", LOAD}, 7183 { "log", LOG}, 7184 { "loginterface", LOGINTERFACE}, 7185 { "map-e-portset", MAPEPORTSET}, 7186 { "mask", MASK}, 7187 { "match", MATCH}, 7188 { "matches", MATCHES}, 7189 { "max", MAXIMUM}, 7190 { "max-mss", MAXMSS}, 7191 { "max-pkt-rate", MAXPKTRATE}, 7192 { "max-pkt-size", MAXPKTSIZE}, 7193 { "max-src-conn", MAXSRCCONN}, 7194 { "max-src-conn-rate", MAXSRCCONNRATE}, 7195 { "max-src-nodes", MAXSRCNODES}, 7196 { "max-src-states", MAXSRCSTATES}, 7197 { "min-ttl", MINTTL}, 7198 { "modulate", MODULATE}, 7199 { "nat", NAT}, 7200 { "nat-anchor", NATANCHOR}, 7201 { "nat-to", NATTO}, 7202 { "no", NO}, 7203 { "no-df", NODF}, 7204 { "no-match", NOMATCH}, 7205 { "no-route", NOROUTE}, 7206 { "no-sync", NOSYNC}, 7207 { "on", ON}, 7208 { "once", ONCE}, 7209 { "optimization", OPTIMIZATION}, 7210 { "os", OS}, 7211 { "out", OUT}, 7212 { "overload", OVERLOAD}, 7213 { "pass", PASS}, 7214 { "pflow", PFLOW}, 7215 { "port", PORT}, 7216 { "prefer-ipv6-nexthop", IPV6NH}, 7217 { "prio", PRIO}, 7218 { "priority", PRIORITY}, 7219 { "priq", PRIQ}, 7220 { "probability", PROBABILITY}, 7221 { "proto", PROTO}, 7222 { "qlimit", QLIMIT}, 7223 { "queue", QUEUE}, 7224 { "quick", QUICK}, 7225 { "random", RANDOM}, 7226 { "random-id", RANDOMID}, 7227 { "rate", RATE}, 7228 { "rdr", RDR}, 7229 { "rdr-anchor", RDRANCHOR}, 7230 { "rdr-to", RDRTO}, 7231 { "realtime", REALTIME}, 7232 { "reassemble", REASSEMBLE}, 7233 { "received-on", RECEIVEDON}, 7234 { "reply-to", REPLYTO}, 7235 { "require-order", REQUIREORDER}, 7236 { "return", RETURN}, 7237 { "return-icmp", RETURNICMP}, 7238 { "return-icmp6", RETURNICMP6}, 7239 { "return-rst", RETURNRST}, 7240 { "ridentifier", RIDENTIFIER}, 7241 { "round-robin", ROUNDROBIN}, 7242 { "route", ROUTE}, 7243 { "route-to", ROUTETO}, 7244 { "rtable", RTABLE}, 7245 { "rule", RULE}, 7246 { "ruleset-optimization", RULESET_OPTIMIZATION}, 7247 { "scrub", SCRUB}, 7248 { "set", SET}, 7249 { "set-tos", SETTOS}, 7250 { "skip", SKIP}, 7251 { "sloppy", SLOPPY}, 7252 { "source", SOURCE}, 7253 { "source-hash", SOURCEHASH}, 7254 { "source-track", SOURCETRACK}, 7255 { "state", STATE}, 7256 { "state-defaults", STATEDEFAULTS}, 7257 { "state-policy", STATEPOLICY}, 7258 { "static-port", STATICPORT}, 7259 { "sticky-address", STICKYADDRESS}, 7260 { "syncookies", SYNCOOKIES}, 7261 { "synproxy", SYNPROXY}, 7262 { "table", TABLE}, 7263 { "tag", TAG}, 7264 { "tagged", TAGGED}, 7265 { "target", TARGET}, 7266 { "tbrsize", TBRSIZE}, 7267 { "timeout", TIMEOUT}, 7268 { "to", TO}, 7269 { "tos", TOS}, 7270 { "ttl", TTL}, 7271 { "upperlimit", UPPERLIMIT}, 7272 { "urpf-failed", URPFFAILED}, 7273 { "user", USER}, 7274 }; 7275 const struct keywords *p; 7276 7277 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 7278 sizeof(keywords[0]), kw_cmp); 7279 7280 if (p) { 7281 if (debug > 1) 7282 fprintf(stderr, "%s: %d\n", s, p->k_val); 7283 return (p->k_val); 7284 } else { 7285 if (debug > 1) 7286 fprintf(stderr, "string: %s\n", s); 7287 return (STRING); 7288 } 7289 } 7290 7291 #define START_EXPAND 1 7292 #define DONE_EXPAND 2 7293 7294 static int expanding; 7295 7296 int 7297 igetc(void) 7298 { 7299 int c; 7300 while (1) { 7301 if (file->ungetpos > 0) 7302 c = file->ungetbuf[--file->ungetpos]; 7303 else 7304 c = getc(file->stream); 7305 if (c == START_EXPAND) 7306 expanding = 1; 7307 else if (c == DONE_EXPAND) 7308 expanding = 0; 7309 else 7310 break; 7311 } 7312 return (c); 7313 } 7314 7315 int 7316 lgetc(int quotec) 7317 { 7318 int c, next; 7319 7320 if (quotec) { 7321 if ((c = igetc()) == EOF) { 7322 yyerror("reached end of file while parsing quoted string"); 7323 if (file == topfile || popfile() == EOF) 7324 return (EOF); 7325 return (quotec); 7326 } 7327 return (c); 7328 } 7329 7330 while ((c = igetc()) == '\\') { 7331 next = igetc(); 7332 if (next != '\n') { 7333 c = next; 7334 break; 7335 } 7336 yylval.lineno = file->lineno; 7337 file->lineno++; 7338 } 7339 7340 if (c == EOF) { 7341 /* 7342 * Fake EOL when hit EOF for the first time. This gets line 7343 * count right if last line in included file is syntactically 7344 * invalid and has no newline. 7345 */ 7346 if (file->eof_reached == 0) { 7347 file->eof_reached = 1; 7348 return ('\n'); 7349 } 7350 while (c == EOF) { 7351 if (file == topfile || popfile() == EOF) 7352 return (EOF); 7353 c = igetc(); 7354 } 7355 } 7356 return (c); 7357 } 7358 7359 void 7360 lungetc(int c) 7361 { 7362 if (c == EOF) 7363 return; 7364 if (file->ungetpos >= file->ungetsize) { 7365 void *p = reallocarray(file->ungetbuf, file->ungetsize, 2); 7366 if (p == NULL) 7367 err(1, "%s", __func__); 7368 file->ungetbuf = p; 7369 file->ungetsize *= 2; 7370 } 7371 file->ungetbuf[file->ungetpos++] = c; 7372 } 7373 7374 int 7375 findeol(void) 7376 { 7377 int c; 7378 7379 /* skip to either EOF or the first real EOL */ 7380 while (1) { 7381 c = lgetc(0); 7382 if (c == '\n') { 7383 file->lineno++; 7384 break; 7385 } 7386 if (c == EOF) 7387 break; 7388 } 7389 return (ERROR); 7390 } 7391 7392 int 7393 yylex(void) 7394 { 7395 char buf[8096]; 7396 char *p, *val; 7397 int quotec, next, c; 7398 int token; 7399 7400 top: 7401 p = buf; 7402 while ((c = lgetc(0)) == ' ' || c == '\t' || c == '\014') 7403 ; /* nothing */ 7404 7405 yylval.lineno = file->lineno; 7406 if (c == '#') 7407 while ((c = lgetc(0)) != '\n' && c != EOF) 7408 ; /* nothing */ 7409 if (c == '$' && !expanding) { 7410 while (1) { 7411 if ((c = lgetc(0)) == EOF) 7412 return (0); 7413 7414 if (p + 1 >= buf + sizeof(buf) - 1) { 7415 yyerror("string too long"); 7416 return (findeol()); 7417 } 7418 if (isalnum(c) || c == '_') { 7419 *p++ = (char)c; 7420 continue; 7421 } 7422 *p = '\0'; 7423 lungetc(c); 7424 break; 7425 } 7426 val = symget(buf); 7427 if (val == NULL) { 7428 yyerror("macro '%s' not defined", buf); 7429 return (findeol()); 7430 } 7431 p = val + strlen(val) - 1; 7432 lungetc(DONE_EXPAND); 7433 while (p >= val) { 7434 lungetc(*p); 7435 p--; 7436 } 7437 lungetc(START_EXPAND); 7438 goto top; 7439 } 7440 7441 switch (c) { 7442 case '\'': 7443 case '"': 7444 quotec = c; 7445 while (1) { 7446 if ((c = lgetc(quotec)) == EOF) 7447 return (0); 7448 if (c == '\n') { 7449 file->lineno++; 7450 continue; 7451 } else if (c == '\\') { 7452 if ((next = lgetc(quotec)) == EOF) 7453 return (0); 7454 if (next == quotec || next == ' ' || 7455 next == '\t') 7456 c = next; 7457 else if (next == '\n') { 7458 file->lineno++; 7459 continue; 7460 } 7461 else 7462 lungetc(next); 7463 } else if (c == quotec) { 7464 *p = '\0'; 7465 break; 7466 } else if (c == '\0') { 7467 yyerror("syntax error"); 7468 return (findeol()); 7469 } 7470 if (p + 1 >= buf + sizeof(buf) - 1) { 7471 yyerror("string too long"); 7472 return (findeol()); 7473 } 7474 *p++ = (char)c; 7475 } 7476 yylval.v.string = strdup(buf); 7477 if (yylval.v.string == NULL) 7478 err(1, "%s: strdup", __func__); 7479 return (STRING); 7480 case '!': 7481 next = lgetc(0); 7482 if (next == '=') 7483 return (NE); 7484 lungetc(next); 7485 break; 7486 case '<': 7487 next = lgetc(0); 7488 if (next == '>') { 7489 yylval.v.i = PF_OP_XRG; 7490 return (PORTBINARY); 7491 } else if (next == '=') 7492 return (LE); 7493 lungetc(next); 7494 break; 7495 case '>': 7496 next = lgetc(0); 7497 if (next == '<') { 7498 yylval.v.i = PF_OP_IRG; 7499 return (PORTBINARY); 7500 } else if (next == '=') 7501 return (GE); 7502 lungetc(next); 7503 break; 7504 case '-': 7505 next = lgetc(0); 7506 if (next == '>') 7507 return (ARROW); 7508 lungetc(next); 7509 break; 7510 } 7511 7512 #define allowed_to_end_number(x) \ 7513 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') 7514 7515 if (c == '-' || isdigit(c)) { 7516 do { 7517 *p++ = c; 7518 if ((size_t)(p-buf) >= sizeof(buf)) { 7519 yyerror("string too long"); 7520 return (findeol()); 7521 } 7522 } while ((c = lgetc(0)) != EOF && isdigit(c)); 7523 lungetc(c); 7524 if (p == buf + 1 && buf[0] == '-') 7525 goto nodigits; 7526 if (c == EOF || allowed_to_end_number(c)) { 7527 const char *errstr = NULL; 7528 7529 *p = '\0'; 7530 yylval.v.number = strtonum(buf, LLONG_MIN, 7531 LLONG_MAX, &errstr); 7532 if (errstr) { 7533 yyerror("\"%s\" invalid number: %s", 7534 buf, errstr); 7535 return (findeol()); 7536 } 7537 return (NUMBER); 7538 } else { 7539 nodigits: 7540 while (p > buf + 1) 7541 lungetc(*--p); 7542 c = *--p; 7543 if (c == '-') 7544 return (c); 7545 } 7546 } 7547 7548 #define allowed_in_string(x) \ 7549 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 7550 x != '{' && x != '}' && x != '<' && x != '>' && \ 7551 x != '!' && x != '=' && x != '/' && x != '#' && \ 7552 x != ',')) 7553 7554 if (isalnum(c) || c == ':' || c == '_') { 7555 do { 7556 *p++ = c; 7557 if ((size_t)(p-buf) >= sizeof(buf)) { 7558 yyerror("string too long"); 7559 return (findeol()); 7560 } 7561 } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); 7562 lungetc(c); 7563 *p = '\0'; 7564 if ((token = lookup(buf)) == STRING) 7565 if ((yylval.v.string = strdup(buf)) == NULL) 7566 err(1, "%s: strdup", __func__); 7567 return (token); 7568 } 7569 if (c == '\n') { 7570 yylval.lineno = file->lineno; 7571 file->lineno++; 7572 } 7573 if (c == EOF) 7574 return (0); 7575 return (c); 7576 } 7577 7578 int 7579 check_file_secrecy(int fd, const char *fname) 7580 { 7581 struct stat st; 7582 7583 if (fstat(fd, &st)) { 7584 warn("cannot stat %s", fname); 7585 return (-1); 7586 } 7587 if (st.st_uid != 0 && st.st_uid != getuid()) { 7588 warnx("%s: owner not root or current user", fname); 7589 return (-1); 7590 } 7591 if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) { 7592 warnx("%s: group writable or world read/writable", fname); 7593 return (-1); 7594 } 7595 return (0); 7596 } 7597 7598 struct file * 7599 pushfile(const char *name, int secret) 7600 { 7601 struct file *nfile; 7602 7603 if ((nfile = calloc(1, sizeof(struct file))) == NULL || 7604 (nfile->name = strdup(name)) == NULL) { 7605 warn("%s", __func__); 7606 if (nfile) 7607 free(nfile); 7608 return (NULL); 7609 } 7610 if (TAILQ_FIRST(&files) == NULL && strcmp(nfile->name, "-") == 0) { 7611 nfile->stream = stdin; 7612 free(nfile->name); 7613 if ((nfile->name = strdup("stdin")) == NULL) { 7614 warn("%s", __func__); 7615 free(nfile); 7616 return (NULL); 7617 } 7618 } else if ((nfile->stream = pfctl_fopen(nfile->name, "r")) == NULL) { 7619 warn("%s: %s", __func__, nfile->name); 7620 free(nfile->name); 7621 free(nfile); 7622 return (NULL); 7623 } else if (secret && 7624 check_file_secrecy(fileno(nfile->stream), nfile->name)) { 7625 fclose(nfile->stream); 7626 free(nfile->name); 7627 free(nfile); 7628 return (NULL); 7629 } 7630 nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0; 7631 nfile->ungetsize = 16; 7632 nfile->ungetbuf = malloc(nfile->ungetsize); 7633 if (nfile->ungetbuf == NULL) { 7634 warn("%s", __func__); 7635 fclose(nfile->stream); 7636 free(nfile->name); 7637 free(nfile); 7638 return (NULL); 7639 } 7640 TAILQ_INSERT_TAIL(&files, nfile, entry); 7641 return (nfile); 7642 } 7643 7644 int 7645 popfile(void) 7646 { 7647 struct file *prev; 7648 7649 if ((prev = TAILQ_PREV(file, files, entry)) != NULL) 7650 prev->errors += file->errors; 7651 7652 TAILQ_REMOVE(&files, file, entry); 7653 fclose(file->stream); 7654 free(file->name); 7655 free(file->ungetbuf); 7656 free(file); 7657 file = prev; 7658 7659 return (file ? 0 : EOF); 7660 } 7661 7662 int 7663 parse_config(char *filename, struct pfctl *xpf) 7664 { 7665 int errors = 0; 7666 struct sym *sym; 7667 7668 pf = xpf; 7669 errors = 0; 7670 rulestate = PFCTL_STATE_NONE; 7671 returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 7672 returnicmp6default = 7673 (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT; 7674 blockpolicy = PFRULE_DROP; 7675 failpolicy = PFRULE_DROP; 7676 require_order = 1; 7677 7678 if ((file = pushfile(filename, 0)) == NULL) { 7679 warn("cannot open the main config file!"); 7680 return (-1); 7681 } 7682 topfile = file; 7683 7684 yyparse(); 7685 errors = file->errors; 7686 popfile(); 7687 7688 /* Free macros and check which have not been used. */ 7689 while ((sym = TAILQ_FIRST(&symhead))) { 7690 if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used) 7691 fprintf(stderr, "warning: macro '%s' not " 7692 "used\n", sym->nam); 7693 free(sym->nam); 7694 free(sym->val); 7695 TAILQ_REMOVE(&symhead, sym, entry); 7696 free(sym); 7697 } 7698 7699 return (errors ? -1 : 0); 7700 } 7701 7702 int 7703 symset(const char *nam, const char *val, int persist) 7704 { 7705 struct sym *sym; 7706 7707 TAILQ_FOREACH(sym, &symhead, entry) { 7708 if (strcmp(nam, sym->nam) == 0) 7709 break; 7710 } 7711 7712 if (sym != NULL) { 7713 if (sym->persist == 1) 7714 return (0); 7715 else { 7716 free(sym->nam); 7717 free(sym->val); 7718 TAILQ_REMOVE(&symhead, sym, entry); 7719 free(sym); 7720 } 7721 } 7722 if ((sym = calloc(1, sizeof(*sym))) == NULL) 7723 return (-1); 7724 7725 sym->nam = strdup(nam); 7726 if (sym->nam == NULL) { 7727 free(sym); 7728 return (-1); 7729 } 7730 sym->val = strdup(val); 7731 if (sym->val == NULL) { 7732 free(sym->nam); 7733 free(sym); 7734 return (-1); 7735 } 7736 sym->used = 0; 7737 sym->persist = persist; 7738 TAILQ_INSERT_TAIL(&symhead, sym, entry); 7739 return (0); 7740 } 7741 7742 int 7743 pfctl_cmdline_symset(char *s) 7744 { 7745 char *sym, *val; 7746 int ret; 7747 7748 if ((val = strrchr(s, '=')) == NULL) 7749 return (-1); 7750 7751 sym = strndup(s, val - s); 7752 if (sym == NULL) 7753 err(1, "%s: malloc", __func__); 7754 7755 ret = symset(sym, val + 1, 1); 7756 free(sym); 7757 7758 return (ret); 7759 } 7760 7761 char * 7762 symget(const char *nam) 7763 { 7764 struct sym *sym; 7765 7766 TAILQ_FOREACH(sym, &symhead, entry) { 7767 if (strcmp(nam, sym->nam) == 0) { 7768 sym->used = 1; 7769 return (sym->val); 7770 } 7771 } 7772 return (NULL); 7773 } 7774 7775 void 7776 mv_rules(struct pfctl_ruleset *src, struct pfctl_ruleset *dst) 7777 { 7778 int i; 7779 struct pfctl_rule *r; 7780 7781 for (i = 0; i < PF_RULESET_MAX; ++i) { 7782 TAILQ_FOREACH(r, src->rules[i].active.ptr, entries) 7783 dst->anchor->match++; 7784 TAILQ_CONCAT(dst->rules[i].active.ptr, src->rules[i].active.ptr, entries); 7785 src->anchor->match = 0; 7786 TAILQ_CONCAT(dst->rules[i].inactive.ptr, src->rules[i].inactive.ptr, entries); 7787 } 7788 } 7789 7790 void 7791 mv_eth_rules(struct pfctl_eth_ruleset *src, struct pfctl_eth_ruleset *dst) 7792 { 7793 struct pfctl_eth_rule *r; 7794 7795 while ((r = TAILQ_FIRST(&src->rules)) != NULL) { 7796 TAILQ_REMOVE(&src->rules, r, entries); 7797 TAILQ_INSERT_TAIL(&dst->rules, r, entries); 7798 dst->anchor->match++; 7799 } 7800 src->anchor->match = 0; 7801 } 7802 7803 void 7804 mv_tables(struct pfctl *pf, struct pfr_ktablehead *ktables, 7805 struct pfctl_anchor *a, struct pfctl_anchor *alast) 7806 { 7807 struct pfr_ktable *kt, *kt_safe; 7808 char new_path[PF_ANCHOR_MAXPATH]; 7809 char *path_cut; 7810 int sz; 7811 struct pfr_uktable *ukt; 7812 SLIST_HEAD(, pfr_uktable) ukt_list; 7813 7814 /* 7815 * Here we need to rename anchor path from temporal names such as 7816 * _1/_2/foo to _1/bar/foo etc. 7817 * 7818 * This also means we need to remove and insert table to ktables 7819 * tree as anchor path is being updated. 7820 */ 7821 SLIST_INIT(&ukt_list); 7822 DBGPRINT("%s [ %s ] (%s)\n", __func__, a->path, alast->path); 7823 RB_FOREACH_SAFE(kt, pfr_ktablehead, ktables, kt_safe) { 7824 path_cut = strstr(kt->pfrkt_anchor, alast->path); 7825 if (path_cut != NULL) { 7826 path_cut += strlen(alast->path); 7827 if (*path_cut) 7828 sz = snprintf(new_path, sizeof (new_path), 7829 "%s%s", a->path, path_cut); 7830 else 7831 sz = snprintf(new_path, sizeof (new_path), 7832 "%s", a->path); 7833 if (sz >= sizeof (new_path)) 7834 errx(1, "new path is too long for %s@%s\n", 7835 kt->pfrkt_name, kt->pfrkt_anchor); 7836 7837 DBGPRINT("%s %s@%s -> %s@%s\n", __func__, 7838 kt->pfrkt_name, kt->pfrkt_anchor, 7839 kt->pfrkt_name, new_path); 7840 RB_REMOVE(pfr_ktablehead, ktables, kt); 7841 strlcpy(kt->pfrkt_anchor, new_path, 7842 sizeof(kt->pfrkt_anchor)); 7843 SLIST_INSERT_HEAD(&ukt_list, (struct pfr_uktable *)kt, 7844 pfrukt_entry); 7845 } 7846 } 7847 7848 while ((ukt = SLIST_FIRST(&ukt_list)) != NULL) { 7849 SLIST_REMOVE_HEAD(&ukt_list, pfrukt_entry); 7850 if (RB_INSERT(pfr_ktablehead, ktables, 7851 (struct pfr_ktable *)ukt) != NULL) 7852 errx(1, "%s@%s exists already\n", 7853 ukt->pfrukt_name, 7854 ukt->pfrukt_anchor); 7855 } 7856 } 7857 7858 void 7859 decide_address_family(struct node_host *n, sa_family_t *af) 7860 { 7861 if (*af != 0 || n == NULL) 7862 return; 7863 *af = n->af; 7864 while ((n = n->next) != NULL) { 7865 if (n->af != *af) { 7866 *af = 0; 7867 return; 7868 } 7869 } 7870 } 7871 7872 void 7873 remove_invalid_hosts(struct node_host **nh, sa_family_t *af) 7874 { 7875 struct node_host *n = *nh, *prev = NULL; 7876 7877 while (n != NULL) { 7878 if (*af && n->af && n->af != *af) { 7879 /* unlink and free n */ 7880 struct node_host *next = n->next; 7881 7882 /* adjust tail pointer */ 7883 if (n == (*nh)->tail) 7884 (*nh)->tail = prev; 7885 /* adjust previous node's next pointer */ 7886 if (prev == NULL) 7887 *nh = next; 7888 else 7889 prev->next = next; 7890 /* free node */ 7891 if (n->ifname != NULL) 7892 free(n->ifname); 7893 free(n); 7894 n = next; 7895 } else { 7896 if (n->af && !*af) 7897 *af = n->af; 7898 prev = n; 7899 n = n->next; 7900 } 7901 } 7902 } 7903 7904 int 7905 invalid_redirect(struct node_host *nh, sa_family_t af) 7906 { 7907 if (!af) { 7908 struct node_host *n; 7909 7910 /* tables and dyniftl are ok without an address family */ 7911 for (n = nh; n != NULL; n = n->next) { 7912 if (n->addr.type != PF_ADDR_TABLE && 7913 n->addr.type != PF_ADDR_DYNIFTL) { 7914 yyerror("address family not given and " 7915 "translation address expands to multiple " 7916 "address families"); 7917 return (1); 7918 } 7919 } 7920 } 7921 if (nh == NULL) { 7922 yyerror("no translation address with matching address family " 7923 "found."); 7924 return (1); 7925 } 7926 return (0); 7927 } 7928 7929 int 7930 atoul(char *s, u_long *ulvalp) 7931 { 7932 u_long ulval; 7933 char *ep; 7934 7935 errno = 0; 7936 ulval = strtoul(s, &ep, 0); 7937 if (s[0] == '\0' || *ep != '\0') 7938 return (-1); 7939 if (errno == ERANGE && ulval == ULONG_MAX) 7940 return (-1); 7941 *ulvalp = ulval; 7942 return (0); 7943 } 7944 7945 int 7946 getservice(char *n) 7947 { 7948 struct servent *s; 7949 u_long ulval; 7950 7951 if (atoul(n, &ulval) == 0) { 7952 if (ulval > 65535) { 7953 yyerror("illegal port value %lu", ulval); 7954 return (-1); 7955 } 7956 return (htons(ulval)); 7957 } else { 7958 s = getservbyname(n, "tcp"); 7959 if (s == NULL) 7960 s = getservbyname(n, "udp"); 7961 if (s == NULL) 7962 s = getservbyname(n, "sctp"); 7963 if (s == NULL) { 7964 yyerror("unknown port %s", n); 7965 return (-1); 7966 } 7967 return (s->s_port); 7968 } 7969 } 7970 7971 int 7972 rule_label(struct pfctl_rule *r, char *s[PF_RULE_MAX_LABEL_COUNT]) 7973 { 7974 for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) { 7975 if (s[i] == NULL) 7976 return (0); 7977 7978 if (strlcpy(r->label[i], s[i], sizeof(r->label[0])) >= 7979 sizeof(r->label[0])) { 7980 yyerror("rule label too long (max %d chars)", 7981 sizeof(r->label[0])-1); 7982 return (-1); 7983 } 7984 } 7985 return (0); 7986 } 7987 7988 int 7989 eth_rule_label(struct pfctl_eth_rule *r, char *s[PF_RULE_MAX_LABEL_COUNT]) 7990 { 7991 for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) { 7992 if (s[i] == NULL) 7993 return (0); 7994 7995 if (strlcpy(r->label[i], s[i], sizeof(r->label[0])) >= 7996 sizeof(r->label[0])) { 7997 yyerror("rule label too long (max %d chars)", 7998 sizeof(r->label[0])-1); 7999 return (-1); 8000 } 8001 } 8002 return (0); 8003 } 8004 8005 u_int16_t 8006 parseicmpspec(char *w, sa_family_t af) 8007 { 8008 const struct icmpcodeent *p; 8009 u_long ulval; 8010 u_int8_t icmptype; 8011 8012 if (af == AF_INET) 8013 icmptype = returnicmpdefault >> 8; 8014 else 8015 icmptype = returnicmp6default >> 8; 8016 8017 if (atoul(w, &ulval) == -1) { 8018 if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) { 8019 yyerror("unknown icmp code %s", w); 8020 return (0); 8021 } 8022 ulval = p->code; 8023 } 8024 if (ulval > 255) { 8025 yyerror("invalid icmp code %lu", ulval); 8026 return (0); 8027 } 8028 return (icmptype << 8 | ulval); 8029 } 8030 8031 int 8032 parseport(char *port, struct range *r, int extensions) 8033 { 8034 char *p = strchr(port, ':'); 8035 8036 if (p == NULL) { 8037 if ((r->a = getservice(port)) == -1) 8038 return (-1); 8039 r->b = 0; 8040 r->t = PF_OP_NONE; 8041 return (0); 8042 } 8043 if ((extensions & PPORT_STAR) && !strcmp(p+1, "*")) { 8044 *p = 0; 8045 if ((r->a = getservice(port)) == -1) 8046 return (-1); 8047 r->b = 0; 8048 r->t = PF_OP_IRG; 8049 return (0); 8050 } 8051 if ((extensions & PPORT_RANGE)) { 8052 *p++ = 0; 8053 if ((r->a = getservice(port)) == -1 || 8054 (r->b = getservice(p)) == -1) 8055 return (-1); 8056 if (r->a == r->b) { 8057 r->b = 0; 8058 r->t = PF_OP_NONE; 8059 } else 8060 r->t = PF_OP_RRG; 8061 return (0); 8062 } 8063 return (-1); 8064 } 8065 8066 int 8067 pfctl_load_anchors(int dev, struct pfctl *pf) 8068 { 8069 struct loadanchors *la; 8070 8071 TAILQ_FOREACH(la, &loadanchorshead, entries) { 8072 if (pf->opts & PF_OPT_VERBOSE) 8073 fprintf(stderr, "\nLoading anchor %s from %s\n", 8074 la->anchorname, la->filename); 8075 if (pfctl_rules(dev, la->filename, pf->opts, pf->optimize, 8076 la->anchorname, pf->trans) == -1) 8077 return (-1); 8078 } 8079 8080 return (0); 8081 } 8082 8083 int 8084 kw_casecmp(const void *k, const void *e) 8085 { 8086 return (strcasecmp(k, ((const struct keywords *)e)->k_name)); 8087 } 8088 8089 int 8090 map_tos(char *s, int *val) 8091 { 8092 /* DiffServ Codepoints and other TOS mappings */ 8093 const struct keywords toswords[] = { 8094 { "af11", IPTOS_DSCP_AF11 }, 8095 { "af12", IPTOS_DSCP_AF12 }, 8096 { "af13", IPTOS_DSCP_AF13 }, 8097 { "af21", IPTOS_DSCP_AF21 }, 8098 { "af22", IPTOS_DSCP_AF22 }, 8099 { "af23", IPTOS_DSCP_AF23 }, 8100 { "af31", IPTOS_DSCP_AF31 }, 8101 { "af32", IPTOS_DSCP_AF32 }, 8102 { "af33", IPTOS_DSCP_AF33 }, 8103 { "af41", IPTOS_DSCP_AF41 }, 8104 { "af42", IPTOS_DSCP_AF42 }, 8105 { "af43", IPTOS_DSCP_AF43 }, 8106 { "critical", IPTOS_PREC_CRITIC_ECP }, 8107 { "cs0", IPTOS_DSCP_CS0 }, 8108 { "cs1", IPTOS_DSCP_CS1 }, 8109 { "cs2", IPTOS_DSCP_CS2 }, 8110 { "cs3", IPTOS_DSCP_CS3 }, 8111 { "cs4", IPTOS_DSCP_CS4 }, 8112 { "cs5", IPTOS_DSCP_CS5 }, 8113 { "cs6", IPTOS_DSCP_CS6 }, 8114 { "cs7", IPTOS_DSCP_CS7 }, 8115 { "ef", IPTOS_DSCP_EF }, 8116 { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, 8117 { "lowdelay", IPTOS_LOWDELAY }, 8118 { "netcontrol", IPTOS_PREC_NETCONTROL }, 8119 { "reliability", IPTOS_RELIABILITY }, 8120 { "throughput", IPTOS_THROUGHPUT }, 8121 { "va", IPTOS_DSCP_VA } 8122 }; 8123 const struct keywords *p; 8124 8125 p = bsearch(s, toswords, sizeof(toswords)/sizeof(toswords[0]), 8126 sizeof(toswords[0]), kw_casecmp); 8127 8128 if (p) { 8129 *val = p->k_val; 8130 return (1); 8131 } 8132 return (0); 8133 } 8134 8135 int 8136 rt_tableid_max(void) 8137 { 8138 #ifdef __FreeBSD__ 8139 int fibs; 8140 size_t l = sizeof(fibs); 8141 8142 if (sysctlbyname("net.fibs", &fibs, &l, NULL, 0) == -1) 8143 fibs = 16; /* XXX RT_MAXFIBS, at least limit it some. */ 8144 /* 8145 * As the OpenBSD code only compares > and not >= we need to adjust 8146 * here given we only accept values of 0..n and want to avoid #ifdefs 8147 * in the grammar. 8148 */ 8149 return (fibs - 1); 8150 #else 8151 return (RT_TABLEID_MAX); 8152 #endif 8153 } 8154 8155 struct node_mac* 8156 node_mac_from_string(const char *str) 8157 { 8158 struct node_mac *m; 8159 8160 m = calloc(1, sizeof(struct node_mac)); 8161 if (m == NULL) 8162 err(1, "%s: calloc", __func__); 8163 8164 if (sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", 8165 &m->mac[0], &m->mac[1], &m->mac[2], &m->mac[3], &m->mac[4], 8166 &m->mac[5]) != 6) { 8167 free(m); 8168 yyerror("invalid MAC address"); 8169 return (NULL); 8170 } 8171 8172 memset(m->mask, 0xff, ETHER_ADDR_LEN); 8173 m->isset = true; 8174 m->next = NULL; 8175 m->tail = m; 8176 8177 return (m); 8178 } 8179 8180 struct node_mac* 8181 node_mac_from_string_masklen(const char *str, int masklen) 8182 { 8183 struct node_mac *m; 8184 8185 if (masklen < 0 || masklen > (ETHER_ADDR_LEN * 8)) { 8186 yyerror("invalid MAC mask length"); 8187 return (NULL); 8188 } 8189 8190 m = node_mac_from_string(str); 8191 if (m == NULL) 8192 return (NULL); 8193 8194 memset(m->mask, 0, ETHER_ADDR_LEN); 8195 for (int i = 0; i < masklen; i++) 8196 m->mask[i / 8] |= 1 << (i % 8); 8197 8198 return (m); 8199 } 8200 8201 struct node_mac* 8202 node_mac_from_string_mask(const char *str, const char *mask) 8203 { 8204 struct node_mac *m; 8205 8206 m = node_mac_from_string(str); 8207 if (m == NULL) 8208 return (NULL); 8209 8210 if (sscanf(mask, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", 8211 &m->mask[0], &m->mask[1], &m->mask[2], &m->mask[3], &m->mask[4], 8212 &m->mask[5]) != 6) { 8213 free(m); 8214 yyerror("invalid MAC mask"); 8215 return (NULL); 8216 } 8217 8218 return (m); 8219 } 8220 8221 int 8222 filteropts_to_rule(struct pfctl_rule *r, struct filter_opts *opts) 8223 { 8224 if (opts->marker & FOM_ONCE) { 8225 if ((r->action != PF_PASS && r->action != PF_DROP) || r->anchor) { 8226 yyerror("'once' only applies to pass/block rules"); 8227 return (1); 8228 } 8229 r->rule_flag |= PFRULE_ONCE; 8230 } 8231 8232 if (opts->statelim.id != PF_STATELIM_ID_NONE && r->action != PF_PASS) { 8233 yyerror("state limiter only applies to pass rules"); 8234 return (1); 8235 } 8236 if (opts->sourcelim.id != PF_SOURCELIM_ID_NONE && r->action != PF_PASS) { 8237 yyerror("source limiter only applies to pass rules"); 8238 return (1); 8239 } 8240 8241 r->keep_state = opts->keep.action; 8242 r->pktrate.limit = opts->pktrate.limit; 8243 r->pktrate.seconds = opts->pktrate.seconds; 8244 r->prob = opts->prob; 8245 r->statelim.id = opts->statelim.id; 8246 r->statelim.limiter_action = opts->statelim.limiter_action; 8247 r->sourcelim.id = opts->sourcelim.id; 8248 r->sourcelim.limiter_action = opts->sourcelim.limiter_action; 8249 r->rtableid = opts->rtableid; 8250 r->ridentifier = opts->ridentifier; 8251 r->max_pkt_size = opts->max_pkt_size; 8252 r->tos = opts->tos; 8253 8254 if (opts->nodf) 8255 r->scrub_flags |= PFSTATE_NODF; 8256 if (opts->randomid) 8257 r->scrub_flags |= PFSTATE_RANDOMID; 8258 if (opts->minttl) 8259 r->min_ttl = opts->minttl; 8260 if (opts->max_mss) 8261 r->max_mss = opts->max_mss; 8262 8263 if (opts->tag) 8264 if (strlcpy(r->tagname, opts->tag, 8265 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 8266 yyerror("tag too long, max %u chars", 8267 PF_TAG_NAME_SIZE - 1); 8268 return (1); 8269 } 8270 if (opts->match_tag) 8271 if (strlcpy(r->match_tagname, opts->match_tag, 8272 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 8273 yyerror("tag too long, max %u chars", 8274 PF_TAG_NAME_SIZE - 1); 8275 return (1); 8276 } 8277 r->match_tag_not = opts->match_tag_not; 8278 8279 if (rule_label(r, opts->label)) 8280 return (1); 8281 for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) 8282 free(opts->label[i]); 8283 8284 if (opts->marker & FOM_AFTO) 8285 r->rule_flag |= PFRULE_AFTO; 8286 if (opts->marker & FOM_SCRUB_TCP) 8287 r->scrub_flags |= PFSTATE_SCRUB_TCP; 8288 if (opts->marker & FOM_PRIO) 8289 r->prio = opts->prio ? opts->prio : PF_PRIO_ZERO; 8290 if (opts->marker & FOM_SETPRIO) { 8291 r->set_prio[0] = opts->set_prio[0]; 8292 r->set_prio[1] = opts->set_prio[1]; 8293 r->scrub_flags |= PFSTATE_SETPRIO; 8294 } 8295 if (opts->marker & FOM_SETTOS) { 8296 r->scrub_flags |= PFSTATE_SETTOS; 8297 r->set_tos = opts->settos; 8298 } 8299 8300 r->flags = opts->flags.b1; 8301 r->flagset = opts->flags.b2; 8302 if ((opts->flags.b1 & opts->flags.b2) != opts->flags.b1) { 8303 yyerror("flags always false"); 8304 return (1); 8305 } 8306 8307 if (opts->queues.qname != NULL) { 8308 if (strlcpy(r->qname, opts->queues.qname, 8309 sizeof(r->qname)) >= sizeof(r->qname)) { 8310 yyerror("rule qname too long (max " 8311 "%d chars)", sizeof(r->qname)-1); 8312 return (1); 8313 } 8314 free(opts->queues.qname); 8315 } 8316 if (opts->queues.pqname != NULL) { 8317 if (strlcpy(r->pqname, opts->queues.pqname, 8318 sizeof(r->pqname)) >= sizeof(r->pqname)) { 8319 yyerror("rule pqname too long (max " 8320 "%d chars)", sizeof(r->pqname)-1); 8321 return (1); 8322 } 8323 free(opts->queues.pqname); 8324 } 8325 8326 if (opts->fragment) 8327 r->rule_flag |= PFRULE_FRAGMENT; 8328 r->allow_opts = opts->allowopts; 8329 8330 return (0); 8331 } 8332 8333 static bool 8334 pfctl_setup_anchor(struct pfctl_rule *r, struct pfctl *pf, char *anchorname) 8335 { 8336 char *p; 8337 8338 if (pf->astack[pf->asd + 1]) { 8339 if (anchorname && strchr(anchorname, '/') != NULL) { 8340 free(anchorname); 8341 yyerror("anchor paths containing '/' " 8342 "cannot be used for inline anchors."); 8343 return (false); 8344 } 8345 8346 /* Move inline rules into relative location. */ 8347 pfctl_anchor_setup(r, 8348 &pf->astack[pf->asd]->ruleset, 8349 anchorname ? anchorname : pf->alast->name); 8350 8351 if (r->anchor == NULL) 8352 err(1, "anchorrule: unable to " 8353 "create ruleset"); 8354 8355 if (pf->alast != r->anchor) { 8356 if (r->anchor->match) { 8357 yyerror("inline anchor '%s' " 8358 "already exists", 8359 r->anchor->name); 8360 return (false); 8361 } 8362 mv_rules(&pf->alast->ruleset, 8363 &r->anchor->ruleset); 8364 mv_tables(pf, &pfr_ktables, r->anchor, pf->alast); 8365 } 8366 pf_remove_if_empty_ruleset(&pf->alast->ruleset); 8367 pf->alast = r->anchor; 8368 } else { 8369 if (! anchorname) { 8370 yyerror("anchors without explicit " 8371 "rules must specify a name"); 8372 return (false); 8373 } 8374 /* 8375 * Don't make non-brace anchors part of the main anchor pool. 8376 */ 8377 if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) { 8378 err(1, "anchorrule: calloc"); 8379 } 8380 pf_init_ruleset(&r->anchor->ruleset); 8381 r->anchor->ruleset.anchor = r->anchor; 8382 if (strlcpy(r->anchor->path, anchorname, 8383 sizeof(r->anchor->path)) >= sizeof(r->anchor->path)) { 8384 errx(1, "anchorrule: strlcpy"); 8385 } 8386 if ((p = strrchr(anchorname, '/')) != NULL) { 8387 if (strlen(p) == 1) { 8388 yyerror("anchorrule: bad anchor name %s", 8389 anchorname); 8390 return (false); 8391 } 8392 } else 8393 p = anchorname; 8394 if (strlcpy(r->anchor->name, p, 8395 sizeof(r->anchor->name)) >= sizeof(r->anchor->name)) { 8396 errx(1, "anchorrule: strlcpy"); 8397 } 8398 } 8399 8400 return (true); 8401 } 8402