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