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