parse.y revision 127082
152845Sphk/* $OpenBSD: parse.y,v 1.415 2003/09/01 15:07:40 henning Exp $ */ 252845Sphk 352845Sphk/* 452845Sphk * Copyright (c) 2001 Markus Friedl. All rights reserved. 552845Sphk * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. 652845Sphk * 752845Sphk * Redistribution and use in source and binary forms, with or without 852845Sphk * modification, are permitted provided that the following conditions 952845Sphk * are met: 1052845Sphk * 1. Redistributions of source code must retain the above copyright 1152845Sphk * notice, this list of conditions and the following disclaimer. 1252845Sphk * 2. Redistributions in binary form must reproduce the above copyright 1352845Sphk * notice, this list of conditions and the following disclaimer in the 1452845Sphk * documentation and/or other materials provided with the distribution. 1552845Sphk * 1652845Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1752845Sphk * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1852845Sphk * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1952845Sphk * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2052845Sphk * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2152845Sphk * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2252845Sphk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2352845Sphk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2452845Sphk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2552845Sphk * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2652845Sphk */ 2752845Sphk%{ 2852845Sphk#include <sys/cdefs.h> 2952845Sphk__FBSDID("$FreeBSD: head/contrib/pf/pfctl/parse.y 127082 2004-03-16 17:24:06Z obrien $"); 3052845Sphk 3152845Sphk#include <sys/types.h> 3252845Sphk#include <sys/socket.h> 3352845Sphk#include <net/if.h> 3452845Sphk#include <netinet/in.h> 3552845Sphk#include <netinet/in_systm.h> 3652845Sphk#include <netinet/ip.h> 3752845Sphk#include <netinet/ip_icmp.h> 3852845Sphk#include <netinet/icmp6.h> 3952845Sphk#include <net/pfvar.h> 4052845Sphk#include <arpa/inet.h> 4152845Sphk#include <altq/altq.h> 4252845Sphk#include <altq/altq_cbq.h> 4352845Sphk#include <altq/altq_priq.h> 4452845Sphk#include <altq/altq_hfsc.h> 4552845Sphk 4652845Sphk#include <stdio.h> 4752845Sphk#include <stdlib.h> 4852845Sphk#include <netdb.h> 4952845Sphk#include <stdarg.h> 5052845Sphk#include <errno.h> 5153648Sarchie#include <string.h> 5252845Sphk#include <ctype.h> 5352845Sphk#include <err.h> 5452845Sphk#include <limits.h> 5552845Sphk#include <pwd.h> 5652845Sphk#include <grp.h> 5752845Sphk#include <md5.h> 5852845Sphk 5952845Sphk#include "pfctl_parser.h" 6052845Sphk#include "pfctl.h" 6152845Sphk 6252845Sphk#ifdef __FreeBSD__ 6352845Sphk#define HTONL(x) (x) = htonl((__uint32_t)(x)) 6452845Sphk#endif 6552845Sphk 6652845Sphkstatic struct pfctl *pf = NULL; 6752845Sphkstatic FILE *fin = NULL; 6852845Sphkstatic int debug = 0; 6952845Sphkstatic int lineno = 1; 7052845Sphkstatic int errors = 0; 7152845Sphkstatic int rulestate = 0; 7252845Sphkstatic u_int16_t returnicmpdefault = 7352845Sphk (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 7452845Sphkstatic u_int16_t returnicmp6default = 7552845Sphk (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT; 7652845Sphkstatic int blockpolicy = PFRULE_DROP; 7752845Sphkstatic int require_order = 1; 7852845Sphk 7952845Sphkenum { 8052845Sphk PFCTL_STATE_NONE, 8152845Sphk PFCTL_STATE_OPTION, 8252845Sphk PFCTL_STATE_SCRUB, 8352845Sphk PFCTL_STATE_QUEUE, 8452845Sphk PFCTL_STATE_NAT, 8552845Sphk PFCTL_STATE_FILTER 8652845Sphk}; 8752845Sphk 8852845Sphkstruct node_proto { 8952845Sphk u_int8_t proto; 9052845Sphk struct node_proto *next; 9152845Sphk struct node_proto *tail; 9252845Sphk}; 9352845Sphk 9452845Sphkstruct node_port { 9552845Sphk u_int16_t port[2]; 9652845Sphk u_int8_t op; 9752845Sphk struct node_port *next; 9852845Sphk struct node_port *tail; 9952845Sphk}; 10052845Sphk 10152845Sphkstruct node_uid { 10252845Sphk uid_t uid[2]; 10352845Sphk u_int8_t op; 10452845Sphk struct node_uid *next; 10552845Sphk struct node_uid *tail; 10652845Sphk}; 10752845Sphk 10852845Sphkstruct node_gid { 10952845Sphk gid_t gid[2]; 11052845Sphk u_int8_t op; 11152845Sphk struct node_gid *next; 11252845Sphk struct node_gid *tail; 11352845Sphk}; 11452845Sphk 11552845Sphkstruct node_icmp { 11652845Sphk u_int8_t code; 11752845Sphk u_int8_t type; 11852845Sphk u_int8_t proto; 11952845Sphk struct node_icmp *next; 12052845Sphk struct node_icmp *tail; 12152845Sphk}; 12252845Sphk 12352845Sphkenum { PF_STATE_OPT_MAX=0, PF_STATE_OPT_TIMEOUT=1 }; 12452845Sphkstruct node_state_opt { 12552845Sphk int type; 12652845Sphk union { 12752845Sphk u_int32_t max_states; 12852845Sphk struct { 12952845Sphk int number; 13052845Sphk u_int32_t seconds; 13153648Sarchie } timeout; 13252845Sphk } data; 13352845Sphk struct node_state_opt *next; 134 struct node_state_opt *tail; 135}; 136 137struct peer { 138 struct node_host *host; 139 struct node_port *port; 140}; 141 142struct node_queue { 143 char queue[PF_QNAME_SIZE]; 144 char parent[PF_QNAME_SIZE]; 145 char ifname[IFNAMSIZ]; 146 int scheduler; 147 struct node_queue *next; 148 struct node_queue *tail; 149} *queues = NULL; 150 151struct node_qassign { 152 char *qname; 153 char *pqname; 154}; 155 156struct filter_opts { 157 int marker; 158#define FOM_FLAGS 0x01 159#define FOM_ICMP 0x02 160#define FOM_TOS 0x04 161#define FOM_KEEP 0x08 162 struct node_uid *uid; 163 struct node_gid *gid; 164 struct { 165 u_int8_t b1; 166 u_int8_t b2; 167 u_int16_t w; 168 u_int16_t w2; 169 } flags; 170 struct node_icmp *icmpspec; 171 u_int32_t tos; 172 struct { 173 int action; 174 struct node_state_opt *options; 175 } keep; 176 int fragment; 177 int allowopts; 178 char *label; 179 struct node_qassign queues; 180 char *tag; 181 char *match_tag; 182 u_int8_t match_tag_not; 183} filter_opts; 184 185struct antispoof_opts { 186 char *label; 187} antispoof_opts; 188 189struct scrub_opts { 190 int marker; 191#define SOM_MINTTL 0x01 192#define SOM_MAXMSS 0x02 193#define SOM_FRAGCACHE 0x04 194 int nodf; 195 int minttl; 196 int maxmss; 197 int fragcache; 198 int randomid; 199 int reassemble_tcp; 200} scrub_opts; 201 202struct queue_opts { 203 int marker; 204#define QOM_BWSPEC 0x01 205#define QOM_SCHEDULER 0x02 206#define QOM_PRIORITY 0x04 207#define QOM_TBRSIZE 0x08 208#define QOM_QLIMIT 0x10 209 struct node_queue_bw queue_bwspec; 210 struct node_queue_opt scheduler; 211 int priority; 212 int tbrsize; 213 int qlimit; 214} queue_opts; 215 216struct table_opts { 217 int flags; 218 int init_addr; 219 struct node_tinithead init_nodes; 220} table_opts; 221 222struct node_hfsc_opts hfsc_opts; 223 224int yyerror(const char *, ...); 225int disallow_table(struct node_host *, const char *); 226int rule_consistent(struct pf_rule *); 227int filter_consistent(struct pf_rule *); 228int nat_consistent(struct pf_rule *); 229int rdr_consistent(struct pf_rule *); 230int process_tabledef(char *, struct table_opts *); 231int yyparse(void); 232void expand_label_str(char *, const char *, const char *); 233void expand_label_if(const char *, char *, const char *); 234void expand_label_addr(const char *, char *, u_int8_t, struct node_host *); 235void expand_label_port(const char *, char *, struct node_port *); 236void expand_label_proto(const char *, char *, u_int8_t); 237void expand_label_nr(const char *, char *); 238void expand_label(char *, const char *, u_int8_t, struct node_host *, 239 struct node_port *, struct node_host *, struct node_port *, 240 u_int8_t); 241void expand_rule(struct pf_rule *, struct node_if *, struct node_host *, 242 struct node_proto *, struct node_os*, struct node_host *, 243 struct node_port *, struct node_host *, struct node_port *, 244 struct node_uid *, struct node_gid *, struct node_icmp *); 245int expand_altq(struct pf_altq *, struct node_if *, struct node_queue *, 246 struct node_queue_bw bwspec, struct node_queue_opt *); 247int expand_queue(struct pf_altq *, struct node_if *, struct node_queue *, 248 struct node_queue_bw, struct node_queue_opt *); 249 250int check_rulestate(int); 251int kw_cmp(const void *, const void *); 252int lookup(char *); 253int lgetc(FILE *); 254int lungetc(int); 255int findeol(void); 256int yylex(void); 257int atoul(char *, u_long *); 258int getservice(char *); 259int rule_label(struct pf_rule *, char *); 260 261TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 262struct sym { 263 TAILQ_ENTRY(sym) entries; 264 int used; 265 int persist; 266 char *nam; 267 char *val; 268}; 269 270 271int symset(const char *, const char *, int); 272char *symget(const char *); 273 274void decide_address_family(struct node_host *, sa_family_t *); 275void remove_invalid_hosts(struct node_host **, sa_family_t *); 276int invalid_redirect(struct node_host *, sa_family_t); 277u_int16_t parseicmpspec(char *, sa_family_t); 278 279TAILQ_HEAD(loadanchorshead, loadanchors) loadanchorshead = 280 TAILQ_HEAD_INITIALIZER(loadanchorshead); 281struct loadanchors { 282 TAILQ_ENTRY(loadanchors) entries; 283 char *anchorname; 284 char *rulesetname; 285 char *filename; 286}; 287 288typedef struct { 289 union { 290 u_int32_t number; 291 int i; 292 char *string; 293 struct { 294 u_int8_t b1; 295 u_int8_t b2; 296 u_int16_t w; 297 u_int16_t w2; 298 } b; 299 struct range { 300 int a; 301 int b; 302 int t; 303 } range; 304 struct node_if *interface; 305 struct node_proto *proto; 306 struct node_icmp *icmp; 307 struct node_host *host; 308 struct node_os *os; 309 struct node_port *port; 310 struct node_uid *uid; 311 struct node_gid *gid; 312 struct node_state_opt *state_opt; 313 struct peer peer; 314 struct { 315 struct peer src, dst; 316 struct node_os *src_os; 317 } fromto; 318 struct pf_poolhashkey *hashkey; 319 struct { 320 struct node_host *host; 321 u_int8_t rt; 322 u_int8_t pool_opts; 323 sa_family_t af; 324 struct pf_poolhashkey *key; 325 } route; 326 struct redirection { 327 struct node_host *host; 328 struct range rport; 329 } *redirection; 330 struct { 331 int type; 332 struct pf_poolhashkey *key; 333 } pooltype; 334 struct { 335 int action; 336 struct node_state_opt *options; 337 } keep_state; 338 struct { 339 u_int8_t log; 340 u_int8_t quick; 341 } logquick; 342 struct node_queue *queue; 343 struct node_queue_opt queue_options; 344 struct node_queue_bw queue_bwspec; 345 struct node_qassign qassign; 346 struct filter_opts filter_opts; 347 struct antispoof_opts antispoof_opts; 348 struct queue_opts queue_opts; 349 struct scrub_opts scrub_opts; 350 struct table_opts table_opts; 351 struct node_hfsc_opts hfsc_opts; 352 } v; 353 int lineno; 354} YYSTYPE; 355 356#define PREPARE_ANCHOR_RULE(r, a) \ 357 do { \ 358 memset(&(r), 0, sizeof(r)); \ 359 if (strlcpy(r.anchorname, (a), \ 360 sizeof(r.anchorname)) >= \ 361 sizeof(r.anchorname)) { \ 362 yyerror("anchor name '%s' too long", \ 363 (a)); \ 364 YYERROR; \ 365 } \ 366 } while (0) 367 368%} 369 370%token PASS BLOCK SCRUB RETURN IN OS OUT LOG LOGALL QUICK ON FROM TO FLAGS 371%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE 372%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF 373%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL 374%token NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE 375%token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR 376%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID 377%token REQUIREORDER SYNPROXY FINGERPRINTS 378%token ANTISPOOF FOR 379%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT 380%token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT 381%token QUEUE PRIORITY QLIMIT 382%token LOAD 383%token TAGGED TAG 384%token <v.string> STRING 385%token <v.i> PORTBINARY 386%type <v.interface> interface if_list if_item_not if_item 387%type <v.number> number icmptype icmp6type uid gid 388%type <v.number> tos not yesno natpass 389%type <v.i> no dir log af fragcache 390%type <v.i> staticport unaryop 391%type <v.b> action nataction flags flag blockspec 392%type <v.range> port rport 393%type <v.hashkey> hashkey 394%type <v.pooltype> pooltype 395%type <v.proto> proto proto_list proto_item 396%type <v.icmp> icmpspec 397%type <v.icmp> icmp_list icmp_item 398%type <v.icmp> icmp6_list icmp6_item 399%type <v.fromto> fromto 400%type <v.peer> ipportspec from to 401%type <v.host> ipspec xhost host dynaddr host_list 402%type <v.host> redir_host_list redirspec 403%type <v.host> route_host route_host_list routespec 404%type <v.os> os xos os_list 405%type <v.port> portspec port_list port_item 406%type <v.uid> uids uid_list uid_item 407%type <v.gid> gids gid_list gid_item 408%type <v.route> route 409%type <v.redirection> redirection redirpool 410%type <v.string> label string tag 411%type <v.keep_state> keep 412%type <v.state_opt> state_opt_spec state_opt_list state_opt_item 413%type <v.logquick> logquick 414%type <v.interface> antispoof_ifspc antispoof_iflst 415%type <v.qassign> qname 416%type <v.queue> qassign qassign_list qassign_item 417%type <v.queue_options> scheduler 418%type <v.number> cbqflags_list cbqflags_item 419%type <v.number> priqflags_list priqflags_item 420%type <v.hfsc_opts> hfscopts_list hfscopts_item hfsc_opts 421%type <v.queue_bwspec> bandwidth 422%type <v.filter_opts> filter_opts filter_opt filter_opts_l 423%type <v.antispoof_opts> antispoof_opts antispoof_opt antispoof_opts_l 424%type <v.queue_opts> queue_opts queue_opt queue_opts_l 425%type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l 426%type <v.table_opts> table_opts table_opt table_opts_l 427%% 428 429ruleset : /* empty */ 430 | ruleset '\n' 431 | ruleset option '\n' 432 | ruleset scrubrule '\n' 433 | ruleset natrule '\n' 434 | ruleset binatrule '\n' 435 | ruleset pfrule '\n' 436 | ruleset anchorrule '\n' 437 | ruleset loadrule '\n' 438 | ruleset altqif '\n' 439 | ruleset queuespec '\n' 440 | ruleset varset '\n' 441 | ruleset antispoof '\n' 442 | ruleset tabledef '\n' 443 | ruleset error '\n' { errors++; } 444 ; 445 446option : SET OPTIMIZATION STRING { 447 if (check_rulestate(PFCTL_STATE_OPTION)) 448 YYERROR; 449 if (pfctl_set_optimization(pf, $3) != 0) { 450 yyerror("unknown optimization %s", $3); 451 YYERROR; 452 } 453 } 454 | SET TIMEOUT timeout_spec 455 | SET TIMEOUT '{' timeout_list '}' 456 | SET LIMIT limit_spec 457 | SET LIMIT '{' limit_list '}' 458 | SET LOGINTERFACE STRING { 459 if (check_rulestate(PFCTL_STATE_OPTION)) 460 YYERROR; 461 if ((ifa_exists($3) == NULL) && strcmp($3, "none")) { 462 yyerror("interface %s doesn't exist", $3); 463 YYERROR; 464 } 465 if (pfctl_set_logif(pf, $3) != 0) { 466 yyerror("error setting loginterface %s", $3); 467 YYERROR; 468 } 469 } 470 | SET BLOCKPOLICY DROP { 471 if (pf->opts & PF_OPT_VERBOSE) 472 printf("set block-policy drop\n"); 473 if (check_rulestate(PFCTL_STATE_OPTION)) 474 YYERROR; 475 blockpolicy = PFRULE_DROP; 476 } 477 | SET BLOCKPOLICY RETURN { 478 if (pf->opts & PF_OPT_VERBOSE) 479 printf("set block-policy return\n"); 480 if (check_rulestate(PFCTL_STATE_OPTION)) 481 YYERROR; 482 blockpolicy = PFRULE_RETURN; 483 } 484 | SET REQUIREORDER yesno { 485 if (pf->opts & PF_OPT_VERBOSE) 486 printf("set require-order %s\n", 487 $3 == 1 ? "yes" : "no"); 488 require_order = $3; 489 } 490 | SET FINGERPRINTS STRING { 491 if (pf->opts & PF_OPT_VERBOSE) 492 printf("fingerprints %s\n", $3); 493 if (check_rulestate(PFCTL_STATE_OPTION)) 494 YYERROR; 495 if (pfctl_file_fingerprints(pf->dev, pf->opts, $3)) { 496 yyerror("error loading fingerprints %s", $3); 497 YYERROR; 498 } 499 } 500 ; 501 502string : string STRING { 503 if (asprintf(&$$, "%s %s", $1, $2) == -1) 504 err(1, "string: asprintf"); 505 free($1); 506 free($2); 507 } 508 | STRING 509 ; 510 511varset : STRING '=' string { 512 if (pf->opts & PF_OPT_VERBOSE) 513 printf("%s = \"%s\"\n", $1, $3); 514 if (symset($1, $3, 0) == -1) 515 err(1, "cannot store variable %s", $1); 516 } 517 ; 518 519anchorrule : ANCHOR string dir interface af proto fromto { 520 struct pf_rule r; 521 522 if (check_rulestate(PFCTL_STATE_FILTER)) 523 YYERROR; 524 525 PREPARE_ANCHOR_RULE(r, $2); 526 r.direction = $3; 527 r.af = $5; 528 529 decide_address_family($7.src.host, &r.af); 530 decide_address_family($7.dst.host, &r.af); 531 532 expand_rule(&r, $4, NULL, $6, $7.src_os, 533 $7.src.host, $7.src.port, $7.dst.host, $7.dst.port, 534 0, 0, 0); 535 } 536 | NATANCHOR string interface af proto fromto { 537 struct pf_rule r; 538 539 if (check_rulestate(PFCTL_STATE_NAT)) 540 YYERROR; 541 542 PREPARE_ANCHOR_RULE(r, $2); 543 r.action = PF_NAT; 544 r.af = $4; 545 546 decide_address_family($6.src.host, &r.af); 547 decide_address_family($6.dst.host, &r.af); 548 549 expand_rule(&r, $3, NULL, $5, $6.src_os, 550 $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, 551 0, 0, 0); 552 } 553 | RDRANCHOR string interface af proto fromto { 554 struct pf_rule r; 555 556 if (check_rulestate(PFCTL_STATE_NAT)) 557 YYERROR; 558 559 PREPARE_ANCHOR_RULE(r, $2); 560 r.action = PF_RDR; 561 r.af = $4; 562 563 decide_address_family($6.src.host, &r.af); 564 decide_address_family($6.dst.host, &r.af); 565 566 if ($6.src.port != NULL) { 567 yyerror("source port parameter not supported" 568 " in rdr-anchor"); 569 YYERROR; 570 } 571 if ($6.dst.port != NULL) { 572 if ($6.dst.port->next != NULL) { 573 yyerror("destination port list " 574 "expansion not supported in " 575 "rdr-anchor"); 576 YYERROR; 577 } else if ($6.dst.port->op != PF_OP_EQ) { 578 yyerror("destination port operators" 579 " not supported in rdr-anchor"); 580 YYERROR; 581 } 582 r.dst.port[0] = $6.dst.port->port[0]; 583 r.dst.port[1] = $6.dst.port->port[1]; 584 r.dst.port_op = $6.dst.port->op; 585 } 586 587 expand_rule(&r, $3, NULL, $5, $6.src_os, 588 $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, 589 0, 0, 0); 590 } 591 | BINATANCHOR string interface af proto fromto { 592 struct pf_rule r; 593 594 if (check_rulestate(PFCTL_STATE_NAT)) 595 YYERROR; 596 597 PREPARE_ANCHOR_RULE(r, $2); 598 r.action = PF_BINAT; 599 r.af = $4; 600 if ($5 != NULL) { 601 if ($5->next != NULL) { 602 yyerror("proto list expansion" 603 " not supported in binat-anchor"); 604 YYERROR; 605 } 606 r.proto = $5->proto; 607 free($5); 608 } 609 610 if ($6.src.host != NULL || $6.src.port != NULL || 611 $6.dst.host != NULL || $6.dst.port != NULL) { 612 yyerror("fromto parameter not supported" 613 " in binat-anchor"); 614 YYERROR; 615 } 616 617 decide_address_family($6.src.host, &r.af); 618 decide_address_family($6.dst.host, &r.af); 619 620 pfctl_add_rule(pf, &r); 621 } 622 ; 623 624loadrule : LOAD ANCHOR string FROM string { 625 char *t; 626 struct loadanchors *loadanchor; 627 628 t = strsep(&$3, ":"); 629 if (*t == '\0' || *$3 == '\0') { 630 yyerror("anchor '%s' invalid\n", $3); 631 YYERROR; 632 } 633 if (strlen(t) >= PF_ANCHOR_NAME_SIZE) { 634 yyerror("anchorname %s too long, max %u\n", 635 t, PF_ANCHOR_NAME_SIZE - 1); 636 YYERROR; 637 } 638 if (strlen($3) >= PF_RULESET_NAME_SIZE) { 639 yyerror("rulesetname %s too long, max %u\n", 640 $3, PF_RULESET_NAME_SIZE - 1); 641 YYERROR; 642 } 643 644 loadanchor = calloc(1, sizeof(struct loadanchors)); 645 if (loadanchor == NULL) 646 err(1, "loadrule: calloc"); 647 if ((loadanchor->anchorname = strdup(t)) == NULL) 648 err(1, "loadrule: strdup"); 649 if ((loadanchor->rulesetname = strdup($3)) == NULL) 650 err(1, "loadrule: strdup"); 651 if ((loadanchor->filename = strdup($5)) == NULL) 652 err(1, "loadrule: strdup"); 653 654 TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor, 655 entries); 656 657 free(t); /* not $3 */ 658 free($5); 659 }; 660 661scrubrule : SCRUB dir logquick interface af proto fromto scrub_opts 662 { 663 struct pf_rule r; 664 665 if (check_rulestate(PFCTL_STATE_SCRUB)) 666 YYERROR; 667 668 memset(&r, 0, sizeof(r)); 669 670 r.action = PF_SCRUB; 671 r.direction = $2; 672 673 r.log = $3.log; 674 if ($3.quick) { 675 yyerror("scrub rules do not support 'quick'"); 676 YYERROR; 677 } 678 679 if ($4) { 680 if ($4->not) { 681 yyerror("scrub rules do not support " 682 "'! <if>'"); 683 YYERROR; 684 } 685 } 686 r.af = $5; 687 if ($8.nodf) 688 r.rule_flag |= PFRULE_NODF; 689 if ($8.randomid) 690 r.rule_flag |= PFRULE_RANDOMID; 691 if ($8.reassemble_tcp) { 692 if (r.direction != PF_INOUT) { 693 yyerror("reassemble tcp rules can not " 694 "specify direction"); 695 YYERROR; 696 } 697 r.rule_flag |= PFRULE_REASSEMBLE_TCP; 698 } 699 if ($8.minttl) 700 r.min_ttl = $8.minttl; 701 if ($8.maxmss) 702 r.max_mss = $8.maxmss; 703 if ($8.fragcache) 704 r.rule_flag |= $8.fragcache; 705 706 expand_rule(&r, $4, NULL, $6, $7.src_os, 707 $7.src.host, $7.src.port, $7.dst.host, $7.dst.port, 708 NULL, NULL, NULL); 709 } 710 ; 711 712scrub_opts : { 713 bzero(&scrub_opts, sizeof scrub_opts); 714 } 715 scrub_opts_l 716 { $$ = scrub_opts; } 717 | /* empty */ { 718 bzero(&scrub_opts, sizeof scrub_opts); 719 $$ = scrub_opts; 720 } 721 ; 722 723scrub_opts_l : scrub_opts_l scrub_opt 724 | scrub_opt 725 ; 726 727scrub_opt : NODF { 728 if (scrub_opts.nodf) { 729 yyerror("no-df cannot be respecified"); 730 YYERROR; 731 } 732 scrub_opts.nodf = 1; 733 } 734 | MINTTL number { 735 if (scrub_opts.marker & SOM_MINTTL) { 736 yyerror("min-ttl cannot be respecified"); 737 YYERROR; 738 } 739 if ($2 > 255) { 740 yyerror("illegal min-ttl value %d", $2); 741 YYERROR; 742 } 743 scrub_opts.marker |= SOM_MINTTL; 744 scrub_opts.minttl = $2; 745 } 746 | MAXMSS number { 747 if (scrub_opts.marker & SOM_MAXMSS) { 748 yyerror("max-mss cannot be respecified"); 749 YYERROR; 750 } 751 if ($2 > 65535) { 752 yyerror("illegal max-mss value %d", $2); 753 YYERROR; 754 } 755 scrub_opts.marker |= SOM_MAXMSS; 756 scrub_opts.maxmss = $2; 757 } 758 | fragcache { 759 if (scrub_opts.marker & SOM_FRAGCACHE) { 760 yyerror("fragcache cannot be respecified"); 761 YYERROR; 762 } 763 scrub_opts.marker |= SOM_FRAGCACHE; 764 scrub_opts.fragcache = $1; 765 } 766 | REASSEMBLE STRING { 767 if (strcasecmp($2, "tcp") != 0) 768 YYERROR; 769 if (scrub_opts.reassemble_tcp) { 770 yyerror("reassemble tcp cannot be respecified"); 771 YYERROR; 772 } 773 scrub_opts.reassemble_tcp = 1; 774 } 775 | RANDOMID { 776 if (scrub_opts.randomid) { 777 yyerror("random-id cannot be respecified"); 778 YYERROR; 779 } 780 scrub_opts.randomid = 1; 781 } 782 ; 783 784fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ } 785 | FRAGMENT FRAGCROP { $$ = PFRULE_FRAGCROP; } 786 | FRAGMENT FRAGDROP { $$ = PFRULE_FRAGDROP; } 787 ; 788 789antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { 790 struct pf_rule r; 791 struct node_host *h = NULL; 792 struct node_if *i, *j; 793 794 if (check_rulestate(PFCTL_STATE_FILTER)) 795 YYERROR; 796 797 for (i = $3; i; i = i->next) { 798 bzero(&r, sizeof(r)); 799 800 r.action = PF_DROP; 801 r.direction = PF_IN; 802 r.log = $2.log; 803 r.quick = $2.quick; 804 r.af = $4; 805 if (rule_label(&r, $5.label)) 806 YYERROR; 807 j = calloc(1, sizeof(struct node_if)); 808 if (j == NULL) 809 err(1, "antispoof: calloc"); 810 if (strlcpy(j->ifname, i->ifname, 811 sizeof(j->ifname)) >= sizeof(j->ifname)) { 812 free(j); 813 yyerror("interface name too long"); 814 YYERROR; 815 } 816 j->not = 1; 817 h = ifa_lookup(j->ifname, PFCTL_IFLOOKUP_NET); 818 819 expand_rule(&r, j, NULL, NULL, NULL, h, NULL, 820 NULL, NULL, NULL, NULL, NULL); 821 822 if ((i->ifa_flags & IFF_LOOPBACK) == 0) { 823 bzero(&r, sizeof(r)); 824 825 r.action = PF_DROP; 826 r.direction = PF_IN; 827 r.log = $2.log; 828 r.quick = $2.quick; 829 r.af = $4; 830 if (rule_label(&r, $5.label)) 831 YYERROR; 832 h = ifa_lookup(i->ifname, 833 PFCTL_IFLOOKUP_HOST); 834 expand_rule(&r, NULL, NULL, NULL, NULL, 835 h, NULL, NULL, NULL, NULL, NULL, 836 NULL); 837 } 838 } 839 free($5.label); 840 } 841 ; 842 843antispoof_ifspc : FOR if_item { $$ = $2; } 844 | FOR '{' antispoof_iflst '}' { $$ = $3; } 845 ; 846 847antispoof_iflst : if_item { $$ = $1; } 848 | antispoof_iflst comma if_item { 849 $1->tail->next = $3; 850 $1->tail = $3; 851 $$ = $1; 852 } 853 ; 854 855antispoof_opts : { bzero(&antispoof_opts, sizeof antispoof_opts); } 856 antispoof_opts_l 857 { $$ = antispoof_opts; } 858 | /* empty */ { 859 bzero(&antispoof_opts, sizeof antispoof_opts); 860 $$ = antispoof_opts; 861 } 862 ; 863 864antispoof_opts_l : antispoof_opts_l antispoof_opt 865 | antispoof_opt 866 ; 867 868antispoof_opt : label { 869 if (antispoof_opts.label) { 870 yyerror("label cannot be redefined"); 871 YYERROR; 872 } 873 antispoof_opts.label = $1; 874 } 875 ; 876 877not : '!' { $$ = 1; } 878 | /* empty */ { $$ = 0; } 879 880tabledef : TABLE '<' STRING '>' table_opts { 881 struct node_host *h, *nh; 882 struct node_tinit *ti, *nti; 883 884 if (strlen($3) >= PF_TABLE_NAME_SIZE) { 885 yyerror("table name too long, max %d chars", 886 PF_TABLE_NAME_SIZE - 1); 887 YYERROR; 888 } 889 if (pf->loadopt & PFCTL_FLAG_TABLE) 890 if (process_tabledef($3, &$5)) 891 YYERROR; 892 for (ti = SIMPLEQ_FIRST(&$5.init_nodes); 893 ti != SIMPLEQ_END(&$5.init_nodes); ti = nti) { 894 if (ti->file) 895 free(ti->file); 896 for (h = ti->host; h != NULL; h = nh) { 897 nh = h->next; 898 free(h); 899 } 900 nti = SIMPLEQ_NEXT(ti, entries); 901 free (ti); 902 } 903 } 904 ; 905 906table_opts : { 907 bzero(&table_opts, sizeof table_opts); 908 SIMPLEQ_INIT(&table_opts.init_nodes); 909 } 910 table_opts_l 911 { $$ = table_opts; } 912 | /* empty */ 913 { 914 bzero(&table_opts, sizeof table_opts); 915 SIMPLEQ_INIT(&table_opts.init_nodes); 916 $$ = table_opts; 917 } 918 ; 919 920table_opts_l : table_opts_l table_opt 921 | table_opt 922 ; 923 924table_opt : STRING { 925 if (!strcmp($1, "const")) 926 table_opts.flags |= PFR_TFLAG_CONST; 927 else if (!strcmp($1, "persist")) 928 table_opts.flags |= PFR_TFLAG_PERSIST; 929 else 930 YYERROR; 931 } 932 | '{' '}' { table_opts.init_addr = 1; } 933 | '{' host_list '}' { 934 struct node_host *n; 935 struct node_tinit *ti; 936 937 for (n = $2; n != NULL; n = n->next) { 938 switch(n->addr.type) { 939 case PF_ADDR_ADDRMASK: 940 continue; /* ok */ 941 case PF_ADDR_DYNIFTL: 942 yyerror("dynamic addresses are not " 943 "permitted inside tables"); 944 break; 945 case PF_ADDR_TABLE: 946 yyerror("tables cannot contain tables"); 947 break; 948 case PF_ADDR_NOROUTE: 949 yyerror("\"no-route\" is not permitted " 950 "inside tables"); 951 break; 952 default: 953 yyerror("unknown address type %d", 954 n->addr.type); 955 } 956 YYERROR; 957 } 958 if (!(ti = calloc(1, sizeof(*ti)))) 959 err(1, "table_opt: calloc"); 960 ti->host = $2; 961 SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti, 962 entries); 963 table_opts.init_addr = 1; 964 } 965 | FILENAME STRING { 966 struct node_tinit *ti; 967 968 if (!(ti = calloc(1, sizeof(*ti)))) 969 err(1, "table_opt: calloc"); 970 ti->file = $2; 971 SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti, 972 entries); 973 table_opts.init_addr = 1; 974 } 975 ; 976 977altqif : ALTQ interface queue_opts QUEUE qassign { 978 struct pf_altq a; 979 980 if (check_rulestate(PFCTL_STATE_QUEUE)) 981 YYERROR; 982 983 memset(&a, 0, sizeof(a)); 984 if ($3.scheduler.qtype == ALTQT_NONE) { 985 yyerror("no scheduler specified!"); 986 YYERROR; 987 } 988 a.scheduler = $3.scheduler.qtype; 989 a.qlimit = $3.qlimit; 990 a.tbrsize = $3.tbrsize; 991 if ($5 == NULL) { 992 yyerror("no child queues specified"); 993 YYERROR; 994 } 995 if (expand_altq(&a, $2, $5, $3.queue_bwspec, 996 &$3.scheduler)) 997 YYERROR; 998 } 999 ; 1000 1001queuespec : QUEUE STRING interface queue_opts qassign { 1002 struct pf_altq a; 1003 1004 if (check_rulestate(PFCTL_STATE_QUEUE)) 1005 YYERROR; 1006 1007 memset(&a, 0, sizeof(a)); 1008 1009 if (strlcpy(a.qname, $2, sizeof(a.qname)) >= 1010 sizeof(a.qname)) { 1011 yyerror("queue name too long (max " 1012 "%d chars)", PF_QNAME_SIZE-1); 1013 YYERROR; 1014 } 1015 if ($4.tbrsize) { 1016 yyerror("cannot specify tbrsize for queue"); 1017 YYERROR; 1018 } 1019 if ($4.priority > 255) { 1020 yyerror("priority out of range: max 255"); 1021 YYERROR; 1022 } 1023 a.priority = $4.priority; 1024 a.qlimit = $4.qlimit; 1025 a.scheduler = $4.scheduler.qtype; 1026 if (expand_queue(&a, $3, $5, $4.queue_bwspec, 1027 &$4.scheduler)) { 1028 yyerror("errors in queue definition"); 1029 YYERROR; 1030 } 1031 } 1032 ; 1033 1034queue_opts : { 1035 bzero(&queue_opts, sizeof queue_opts); 1036 queue_opts.priority = DEFAULT_PRIORITY; 1037 queue_opts.qlimit = DEFAULT_QLIMIT; 1038 queue_opts.scheduler.qtype = ALTQT_NONE; 1039 queue_opts.queue_bwspec.bw_percent = 100; 1040 } 1041 queue_opts_l 1042 { $$ = queue_opts; } 1043 | /* empty */ { 1044 bzero(&queue_opts, sizeof queue_opts); 1045 queue_opts.priority = DEFAULT_PRIORITY; 1046 queue_opts.qlimit = DEFAULT_QLIMIT; 1047 queue_opts.scheduler.qtype = ALTQT_NONE; 1048 queue_opts.queue_bwspec.bw_percent = 100; 1049 $$ = queue_opts; 1050 } 1051 ; 1052 1053queue_opts_l : queue_opts_l queue_opt 1054 | queue_opt 1055 ; 1056 1057queue_opt : BANDWIDTH bandwidth { 1058 if (queue_opts.marker & QOM_BWSPEC) { 1059 yyerror("bandwidth cannot be respecified"); 1060 YYERROR; 1061 } 1062 queue_opts.marker |= QOM_BWSPEC; 1063 queue_opts.queue_bwspec = $2; 1064 } 1065 | PRIORITY number { 1066 if (queue_opts.marker & QOM_PRIORITY) { 1067 yyerror("priority cannot be respecified"); 1068 YYERROR; 1069 } 1070 if ($2 > 255) { 1071 yyerror("priority out of range: max 255"); 1072 YYERROR; 1073 } 1074 queue_opts.marker |= QOM_PRIORITY; 1075 queue_opts.priority = $2; 1076 } 1077 | QLIMIT number { 1078 if (queue_opts.marker & QOM_QLIMIT) { 1079 yyerror("qlimit cannot be respecified"); 1080 YYERROR; 1081 } 1082 if ($2 > 65535) { 1083 yyerror("qlimit out of range: max 65535"); 1084 YYERROR; 1085 } 1086 queue_opts.marker |= QOM_QLIMIT; 1087 queue_opts.qlimit = $2; 1088 } 1089 | scheduler { 1090 if (queue_opts.marker & QOM_SCHEDULER) { 1091 yyerror("scheduler cannot be respecified"); 1092 YYERROR; 1093 } 1094 queue_opts.marker |= QOM_SCHEDULER; 1095 queue_opts.scheduler = $1; 1096 } 1097 | TBRSIZE number { 1098 if (queue_opts.marker & QOM_TBRSIZE) { 1099 yyerror("tbrsize cannot be respecified"); 1100 YYERROR; 1101 } 1102 if ($2 > 65535) { 1103 yyerror("tbrsize too big: max 65535"); 1104 YYERROR; 1105 } 1106 queue_opts.marker |= QOM_TBRSIZE; 1107 queue_opts.tbrsize = $2; 1108 } 1109 ; 1110 1111bandwidth : STRING { 1112 double bps; 1113 char *cp; 1114 1115 $$.bw_percent = 0; 1116 1117 bps = strtod($1, &cp); 1118 if (cp != NULL) { 1119 if (!strcmp(cp, "b")) 1120 ; /* nothing */ 1121 else if (!strcmp(cp, "Kb")) 1122 bps *= 1000; 1123 else if (!strcmp(cp, "Mb")) 1124 bps *= 1000 * 1000; 1125 else if (!strcmp(cp, "Gb")) 1126 bps *= 1000 * 1000 * 1000; 1127 else if (!strcmp(cp, "%")) { 1128 if (bps < 0 || bps > 100) { 1129 yyerror("bandwidth spec " 1130 "out of range"); 1131 YYERROR; 1132 } 1133 $$.bw_percent = bps; 1134 bps = 0; 1135 } else { 1136 yyerror("unknown unit %s", cp); 1137 YYERROR; 1138 } 1139 } 1140 $$.bw_absolute = (u_int32_t)bps; 1141 } 1142 1143scheduler : CBQ { 1144 $$.qtype = ALTQT_CBQ; 1145 $$.data.cbq_opts.flags = 0; 1146 } 1147 | CBQ '(' cbqflags_list ')' { 1148 $$.qtype = ALTQT_CBQ; 1149 $$.data.cbq_opts.flags = $3; 1150 } 1151 | PRIQ { 1152 $$.qtype = ALTQT_PRIQ; 1153 $$.data.priq_opts.flags = 0; 1154 } 1155 | PRIQ '(' priqflags_list ')' { 1156 $$.qtype = ALTQT_PRIQ; 1157 $$.data.priq_opts.flags = $3; 1158 } 1159 | HFSC { 1160 $$.qtype = ALTQT_HFSC; 1161 bzero(&$$.data.hfsc_opts, 1162 sizeof(struct node_hfsc_opts)); 1163 } 1164 | HFSC '(' hfsc_opts ')' { 1165 $$.qtype = ALTQT_HFSC; 1166 $$.data.hfsc_opts = $3; 1167 } 1168 ; 1169 1170cbqflags_list : cbqflags_item { $$ |= $1; } 1171 | cbqflags_list comma cbqflags_item { $$ |= $3; } 1172 ; 1173 1174cbqflags_item : STRING { 1175 if (!strcmp($1, "default")) 1176 $$ = CBQCLF_DEFCLASS; 1177 else if (!strcmp($1, "borrow")) 1178 $$ = CBQCLF_BORROW; 1179 else if (!strcmp($1, "red")) 1180 $$ = CBQCLF_RED; 1181 else if (!strcmp($1, "ecn")) 1182 $$ = CBQCLF_RED|CBQCLF_ECN; 1183 else if (!strcmp($1, "rio")) 1184 $$ = CBQCLF_RIO; 1185 else { 1186 yyerror("unknown cbq flag \"%s\"", $1); 1187 YYERROR; 1188 } 1189 } 1190 ; 1191 1192priqflags_list : priqflags_item { $$ |= $1; } 1193 | priqflags_list comma priqflags_item { $$ |= $3; } 1194 ; 1195 1196priqflags_item : STRING { 1197 if (!strcmp($1, "default")) 1198 $$ = PRCF_DEFAULTCLASS; 1199 else if (!strcmp($1, "red")) 1200 $$ = PRCF_RED; 1201 else if (!strcmp($1, "ecn")) 1202 $$ = PRCF_RED|PRCF_ECN; 1203 else if (!strcmp($1, "rio")) 1204 $$ = PRCF_RIO; 1205 else { 1206 yyerror("unknown priq flag \"%s\"", $1); 1207 YYERROR; 1208 } 1209 } 1210 ; 1211 1212hfsc_opts : { 1213 bzero(&hfsc_opts, 1214 sizeof(struct node_hfsc_opts)); 1215 } 1216 hfscopts_list { 1217 $$ = hfsc_opts; 1218 } 1219 ; 1220 1221hfscopts_list : hfscopts_item 1222 | hfscopts_list comma hfscopts_item 1223 ; 1224 1225hfscopts_item : LINKSHARE bandwidth { 1226 if (hfsc_opts.linkshare.used) { 1227 yyerror("linkshare already specified"); 1228 YYERROR; 1229 } 1230 hfsc_opts.linkshare.m2 = $2; 1231 hfsc_opts.linkshare.used = 1; 1232 } 1233 | LINKSHARE '(' bandwidth number bandwidth ')' { 1234 if (hfsc_opts.linkshare.used) { 1235 yyerror("linkshare already specified"); 1236 YYERROR; 1237 } 1238 hfsc_opts.linkshare.m1 = $3; 1239 hfsc_opts.linkshare.d = $4; 1240 hfsc_opts.linkshare.m2 = $5; 1241 hfsc_opts.linkshare.used = 1; 1242 } 1243 | REALTIME bandwidth { 1244 if (hfsc_opts.realtime.used) { 1245 yyerror("realtime already specified"); 1246 YYERROR; 1247 } 1248 hfsc_opts.realtime.m2 = $2; 1249 hfsc_opts.realtime.used = 1; 1250 } 1251 | REALTIME '(' bandwidth number bandwidth ')' { 1252 if (hfsc_opts.realtime.used) { 1253 yyerror("realtime already specified"); 1254 YYERROR; 1255 } 1256 hfsc_opts.realtime.m1 = $3; 1257 hfsc_opts.realtime.d = $4; 1258 hfsc_opts.realtime.m2 = $5; 1259 hfsc_opts.realtime.used = 1; 1260 } 1261 | UPPERLIMIT bandwidth { 1262 if (hfsc_opts.upperlimit.used) { 1263 yyerror("upperlimit already specified"); 1264 YYERROR; 1265 } 1266 hfsc_opts.upperlimit.m2 = $2; 1267 hfsc_opts.upperlimit.used = 1; 1268 } 1269 | UPPERLIMIT '(' bandwidth number bandwidth ')' { 1270 if (hfsc_opts.upperlimit.used) { 1271 yyerror("upperlimit already specified"); 1272 YYERROR; 1273 } 1274 hfsc_opts.upperlimit.m1 = $3; 1275 hfsc_opts.upperlimit.d = $4; 1276 hfsc_opts.upperlimit.m2 = $5; 1277 hfsc_opts.upperlimit.used = 1; 1278 } 1279 | STRING { 1280 if (!strcmp($1, "default")) 1281 hfsc_opts.flags |= HFCF_DEFAULTCLASS; 1282 else if (!strcmp($1, "red")) 1283 hfsc_opts.flags |= HFCF_RED; 1284 else if (!strcmp($1, "ecn")) 1285 hfsc_opts.flags |= HFCF_RED|HFCF_ECN; 1286 else if (!strcmp($1, "rio")) 1287 hfsc_opts.flags |= HFCF_RIO; 1288 else { 1289 yyerror("unknown hfsc flag \"%s\"", $1); 1290 YYERROR; 1291 } 1292 } 1293 ; 1294 1295qassign : /* empty */ { $$ = NULL; } 1296 | qassign_item { $$ = $1; } 1297 | '{' qassign_list '}' { $$ = $2; } 1298 ; 1299 1300qassign_list : qassign_item { $$ = $1; } 1301 | qassign_list comma qassign_item { 1302 $1->tail->next = $3; 1303 $1->tail = $3; 1304 $$ = $1; 1305 } 1306 ; 1307 1308qassign_item : STRING { 1309 $$ = calloc(1, sizeof(struct node_queue)); 1310 if ($$ == NULL) 1311 err(1, "qassign_item: calloc"); 1312 if (strlcpy($$->queue, $1, sizeof($$->queue)) >= 1313 sizeof($$->queue)) { 1314 free($$); 1315 yyerror("queue name '%s' too long (max " 1316 "%d chars)", $1, sizeof($$->queue)-1); 1317 YYERROR; 1318 } 1319 $$->next = NULL; 1320 $$->tail = $$; 1321 } 1322 ; 1323 1324pfrule : action dir logquick interface route af proto fromto 1325 filter_opts 1326 { 1327 struct pf_rule r; 1328 struct node_state_opt *o; 1329 struct node_proto *proto; 1330 1331 if (check_rulestate(PFCTL_STATE_FILTER)) 1332 YYERROR; 1333 1334 memset(&r, 0, sizeof(r)); 1335 1336 r.action = $1.b1; 1337 switch ($1.b2) { 1338 case PFRULE_RETURNRST: 1339 r.rule_flag |= PFRULE_RETURNRST; 1340 r.return_ttl = $1.w; 1341 break; 1342 case PFRULE_RETURNICMP: 1343 r.rule_flag |= PFRULE_RETURNICMP; 1344 r.return_icmp = $1.w; 1345 r.return_icmp6 = $1.w2; 1346 break; 1347 case PFRULE_RETURN: 1348 r.rule_flag |= PFRULE_RETURN; 1349 r.return_icmp = $1.w; 1350 r.return_icmp6 = $1.w2; 1351 break; 1352 } 1353 r.direction = $2; 1354 r.log = $3.log; 1355 r.quick = $3.quick; 1356 1357 r.af = $6; 1358 if ($9.tag) 1359 if (strlcpy(r.tagname, $9.tag, 1360 PF_TAG_NAME_SIZE) > PF_TAG_NAME_SIZE) { 1361 yyerror("tag too long, max %u chars", 1362 PF_TAG_NAME_SIZE - 1); 1363 YYERROR; 1364 } 1365 if ($9.match_tag) 1366 if (strlcpy(r.match_tagname, $9.match_tag, 1367 PF_TAG_NAME_SIZE) > PF_TAG_NAME_SIZE) { 1368 yyerror("tag too long, max %u chars", 1369 PF_TAG_NAME_SIZE - 1); 1370 YYERROR; 1371 } 1372 r.match_tag_not = $9.match_tag_not; 1373 r.flags = $9.flags.b1; 1374 r.flagset = $9.flags.b2; 1375 if (rule_label(&r, $9.label)) 1376 YYERROR; 1377 free($9.label); 1378 if ($9.flags.b1 || $9.flags.b2 || $8.src_os) { 1379 for (proto = $7; proto != NULL && 1380 proto->proto != IPPROTO_TCP; 1381 proto = proto->next) 1382 ; /* nothing */ 1383 if (proto == NULL && $7 != NULL) { 1384 if ($9.flags.b1 || $9.flags.b2) 1385 yyerror( 1386 "flags only apply to tcp"); 1387 if ($8.src_os) 1388 yyerror( 1389 "OS fingerprinting only " 1390 "apply to tcp"); 1391 YYERROR; 1392 } 1393#if 0 1394 if (($9.flags.b1 & parse_flags("S")) == 0 && 1395 $8.src_os) { 1396 yyerror("OS fingerprinting requires " 1397 "the SYN TCP flag (flags S/SA)"); 1398 YYERROR; 1399 } 1400#endif 1401 } 1402 1403 r.tos = $9.tos; 1404 r.keep_state = $9.keep.action; 1405 o = $9.keep.options; 1406 while (o) { 1407 struct node_state_opt *p = o; 1408 1409 switch (o->type) { 1410 case PF_STATE_OPT_MAX: 1411 if (r.max_states) { 1412 yyerror("state option 'max' " 1413 "multiple definitions"); 1414 YYERROR; 1415 } 1416 r.max_states = o->data.max_states; 1417 break; 1418 case PF_STATE_OPT_TIMEOUT: 1419 if (r.timeout[o->data.timeout.number]) { 1420 yyerror("state timeout %s " 1421 "multiple definitions", 1422 pf_timeouts[o->data. 1423 timeout.number].name); 1424 YYERROR; 1425 } 1426 r.timeout[o->data.timeout.number] = 1427 o->data.timeout.seconds; 1428 } 1429 o = o->next; 1430 free(p); 1431 } 1432 1433 if ($9.fragment) 1434 r.rule_flag |= PFRULE_FRAGMENT; 1435 r.allow_opts = $9.allowopts; 1436 1437 decide_address_family($8.src.host, &r.af); 1438 decide_address_family($8.dst.host, &r.af); 1439 1440 if ($5.rt) { 1441 if (!r.direction) { 1442 yyerror("direction must be explicit " 1443 "with rules that specify routing"); 1444 YYERROR; 1445 } 1446 r.rt = $5.rt; 1447 r.rpool.opts = $5.pool_opts; 1448 if ($5.key != NULL) 1449 memcpy(&r.rpool.key, $5.key, 1450 sizeof(struct pf_poolhashkey)); 1451 } 1452 if (r.rt && r.rt != PF_FASTROUTE) { 1453 decide_address_family($5.host, &r.af); 1454 remove_invalid_hosts(&$5.host, &r.af); 1455 if ($5.host == NULL) { 1456 yyerror("no routing address with " 1457 "matching address family found."); 1458 YYERROR; 1459 } 1460 if (r.rpool.opts == PF_POOL_NONE && ( 1461 $5.host->next != NULL || 1462 $5.host->addr.type == PF_ADDR_TABLE)) 1463 r.rpool.opts = PF_POOL_ROUNDROBIN; 1464 if (r.rpool.opts != PF_POOL_ROUNDROBIN) 1465 if (disallow_table($5.host, "tables " 1466 "are only supported in round-robin " 1467 "routing pools")) 1468 YYERROR; 1469 if ($5.host->next != NULL) { 1470 if (r.rpool.opts != 1471 PF_POOL_ROUNDROBIN) { 1472 yyerror("r.rpool.opts must " 1473 "be PF_POOL_ROUNDROBIN"); 1474 YYERROR; 1475 } 1476 } 1477 } 1478 if ($9.queues.qname != NULL) { 1479 if (strlcpy(r.qname, $9.queues.qname, 1480 sizeof(r.qname)) >= sizeof(r.qname)) { 1481 yyerror("rule qname too long (max " 1482 "%d chars)", sizeof(r.qname)-1); 1483 YYERROR; 1484 } 1485 free($9.queues.qname); 1486 } 1487 if ($9.queues.pqname != NULL) { 1488 if (strlcpy(r.pqname, $9.queues.pqname, 1489 sizeof(r.pqname)) >= sizeof(r.pqname)) { 1490 yyerror("rule pqname too long (max " 1491 "%d chars)", sizeof(r.pqname)-1); 1492 YYERROR; 1493 } 1494 free($9.queues.pqname); 1495 } 1496 1497 expand_rule(&r, $4, $5.host, $7, $8.src_os, 1498 $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, 1499 $9.uid, $9.gid, $9.icmpspec); 1500 } 1501 ; 1502 1503filter_opts : { bzero(&filter_opts, sizeof filter_opts); } 1504 filter_opts_l 1505 { $$ = filter_opts; } 1506 | /* empty */ { 1507 bzero(&filter_opts, sizeof filter_opts); 1508 $$ = filter_opts; 1509 } 1510 ; 1511 1512filter_opts_l : filter_opts_l filter_opt 1513 | filter_opt 1514 ; 1515 1516filter_opt : USER uids { 1517 if (filter_opts.uid) 1518 $2->tail->next = filter_opts.uid; 1519 filter_opts.uid = $2; 1520 } 1521 | GROUP gids { 1522 if (filter_opts.gid) 1523 $2->tail->next = filter_opts.gid; 1524 filter_opts.gid = $2; 1525 } 1526 | flags { 1527 if (filter_opts.marker & FOM_FLAGS) { 1528 yyerror("flags cannot be redefined"); 1529 YYERROR; 1530 } 1531 filter_opts.marker |= FOM_FLAGS; 1532 filter_opts.flags.b1 |= $1.b1; 1533 filter_opts.flags.b2 |= $1.b2; 1534 filter_opts.flags.w |= $1.w; 1535 filter_opts.flags.w2 |= $1.w2; 1536 } 1537 | icmpspec { 1538 if (filter_opts.marker & FOM_ICMP) { 1539 yyerror("icmp-type cannot be redefined"); 1540 YYERROR; 1541 } 1542 filter_opts.marker |= FOM_ICMP; 1543 filter_opts.icmpspec = $1; 1544 } 1545 | tos { 1546 if (filter_opts.marker & FOM_TOS) { 1547 yyerror("tos cannot be redefined"); 1548 YYERROR; 1549 } 1550 filter_opts.marker |= FOM_TOS; 1551 filter_opts.tos = $1; 1552 } 1553 | keep { 1554 if (filter_opts.marker & FOM_KEEP) { 1555 yyerror("modulate or keep cannot be redefined"); 1556 YYERROR; 1557 } 1558 filter_opts.marker |= FOM_KEEP; 1559 filter_opts.keep.action = $1.action; 1560 filter_opts.keep.options = $1.options; 1561 } 1562 | FRAGMENT { 1563 filter_opts.fragment = 1; 1564 } 1565 | ALLOWOPTS { 1566 filter_opts.allowopts = 1; 1567 } 1568 | label { 1569 if (filter_opts.label) { 1570 yyerror("label cannot be redefined"); 1571 YYERROR; 1572 } 1573 filter_opts.label = $1; 1574 } 1575 | qname { 1576 if (filter_opts.queues.qname) { 1577 yyerror("queue cannot be redefined"); 1578 YYERROR; 1579 } 1580 filter_opts.queues = $1; 1581 } 1582 | TAG string { 1583 filter_opts.tag = $2; 1584 } 1585 | not TAGGED string { 1586 filter_opts.match_tag = $3; 1587 filter_opts.match_tag_not = $1; 1588 } 1589 ; 1590 1591action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; } 1592 | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } 1593 ; 1594 1595blockspec : /* empty */ { 1596 $$.b2 = blockpolicy; 1597 $$.w = returnicmpdefault; 1598 $$.w2 = returnicmp6default; 1599 } 1600 | DROP { 1601 $$.b2 = PFRULE_DROP; 1602 $$.w = 0; 1603 $$.w2 = 0; 1604 } 1605 | RETURNRST { 1606 $$.b2 = PFRULE_RETURNRST; 1607 $$.w = 0; 1608 $$.w2 = 0; 1609 } 1610 | RETURNRST '(' TTL number ')' { 1611 if ($4 > 255) { 1612 yyerror("illegal ttl value %d", $4); 1613 YYERROR; 1614 } 1615 $$.b2 = PFRULE_RETURNRST; 1616 $$.w = $4; 1617 $$.w2 = 0; 1618 } 1619 | RETURNICMP { 1620 $$.b2 = PFRULE_RETURNICMP; 1621 $$.w = returnicmpdefault; 1622 $$.w2 = returnicmp6default; 1623 } 1624 | RETURNICMP6 { 1625 $$.b2 = PFRULE_RETURNICMP; 1626 $$.w = returnicmpdefault; 1627 $$.w2 = returnicmp6default; 1628 } 1629 | RETURNICMP '(' STRING ')' { 1630 $$.b2 = PFRULE_RETURNICMP; 1631 if (!($$.w = parseicmpspec($3, AF_INET))) 1632 YYERROR; 1633 $$.w2 = returnicmp6default; 1634 } 1635 | RETURNICMP6 '(' STRING ')' { 1636 $$.b2 = PFRULE_RETURNICMP; 1637 $$.w = returnicmpdefault; 1638 if (!($$.w2 = parseicmpspec($3, AF_INET6))) 1639 YYERROR; 1640 } 1641 | RETURNICMP '(' STRING comma STRING ')' { 1642 $$.b2 = PFRULE_RETURNICMP; 1643 if (!($$.w = parseicmpspec($3, AF_INET))) 1644 YYERROR; 1645 if (!($$.w2 = parseicmpspec($5, AF_INET6))) 1646 YYERROR; 1647 } 1648 | RETURN { 1649 $$.b2 = PFRULE_RETURN; 1650 $$.w = returnicmpdefault; 1651 $$.w2 = returnicmp6default; 1652 } 1653 ; 1654 1655dir : /* empty */ { $$ = 0; } 1656 | IN { $$ = PF_IN; } 1657 | OUT { $$ = PF_OUT; } 1658 ; 1659 1660logquick : /* empty */ { $$.log = 0; $$.quick = 0; } 1661 | log { $$.log = $1; $$.quick = 0; } 1662 | QUICK { $$.log = 0; $$.quick = 1; } 1663 | log QUICK { $$.log = $1; $$.quick = 1; } 1664 | QUICK log { $$.log = $2; $$.quick = 1; } 1665 ; 1666 1667log : LOG { $$ = 1; } 1668 | LOGALL { $$ = 2; } 1669 ; 1670 1671interface : /* empty */ { $$ = NULL; } 1672 | ON if_item_not { $$ = $2; } 1673 | ON '{' if_list '}' { $$ = $3; } 1674 ; 1675 1676if_list : if_item_not { $$ = $1; } 1677 | if_list comma if_item_not { 1678 $1->tail->next = $3; 1679 $1->tail = $3; 1680 $$ = $1; 1681 } 1682 ; 1683 1684if_item_not : not if_item { $$ = $2; $$->not = $1; } 1685 ; 1686 1687if_item : STRING { 1688 struct node_host *n; 1689 1690 if ((n = ifa_exists($1)) == NULL) { 1691 yyerror("unknown interface %s", $1); 1692 YYERROR; 1693 } 1694 $$ = calloc(1, sizeof(struct node_if)); 1695 if ($$ == NULL) 1696 err(1, "if_item: calloc"); 1697 if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >= 1698 sizeof($$->ifname)) { 1699 free($$); 1700 yyerror("interface name too long"); 1701 YYERROR; 1702 } 1703 $$->ifa_flags = n->ifa_flags; 1704 $$->not = 0; 1705 $$->next = NULL; 1706 $$->tail = $$; 1707 } 1708 ; 1709 1710af : /* empty */ { $$ = 0; } 1711 | INET { $$ = AF_INET; } 1712 | INET6 { $$ = AF_INET6; } 1713 1714proto : /* empty */ { $$ = NULL; } 1715 | PROTO proto_item { $$ = $2; } 1716 | PROTO '{' proto_list '}' { $$ = $3; } 1717 ; 1718 1719proto_list : proto_item { $$ = $1; } 1720 | proto_list comma proto_item { 1721 $1->tail->next = $3; 1722 $1->tail = $3; 1723 $$ = $1; 1724 } 1725 ; 1726 1727proto_item : STRING { 1728 u_int8_t pr; 1729 u_long ulval; 1730 1731 if (atoul($1, &ulval) == 0) { 1732 if (ulval > 255) { 1733 yyerror("protocol outside range"); 1734 YYERROR; 1735 } 1736 pr = (u_int8_t)ulval; 1737 } else { 1738 struct protoent *p; 1739 1740 p = getprotobyname($1); 1741 if (p == NULL) { 1742 yyerror("unknown protocol %s", $1); 1743 YYERROR; 1744 } 1745 pr = p->p_proto; 1746 } 1747 if (pr == 0) { 1748 yyerror("proto 0 cannot be used"); 1749 YYERROR; 1750 } 1751 $$ = calloc(1, sizeof(struct node_proto)); 1752 if ($$ == NULL) 1753 err(1, "proto_item: calloc"); 1754 $$->proto = pr; 1755 $$->next = NULL; 1756 $$->tail = $$; 1757 } 1758 ; 1759 1760fromto : ALL { 1761 $$.src.host = NULL; 1762 $$.src.port = NULL; 1763 $$.dst.host = NULL; 1764 $$.dst.port = NULL; 1765 $$.src_os = NULL; 1766 } 1767 | from os to { 1768 $$.src = $1; 1769 $$.src_os = $2; 1770 $$.dst = $3; 1771 } 1772 ; 1773 1774os : /* empty */ { $$ = NULL; } 1775 | OS xos { $$ = $2; } 1776 | OS '{' os_list '}' { $$ = $3; } 1777 ; 1778 1779xos : STRING { 1780 $$ = calloc(1, sizeof(struct node_os)); 1781 if ($$ == NULL) 1782 err(1, "os: calloc"); 1783 $$->os = $1; 1784 $$->tail = $$; 1785 } 1786 ; 1787 1788os_list : xos { $$ = $1; } 1789 | os_list comma xos { 1790 $1->tail->next = $3; 1791 $1->tail = $3; 1792 $$ = $1; 1793 } 1794 ; 1795 1796from : /* empty */ { 1797 $$.host = NULL; 1798 $$.port = NULL; 1799 } 1800 | FROM ipportspec { 1801 $$ = $2; 1802 } 1803 ; 1804 1805to : /* empty */ { 1806 $$.host = NULL; 1807 $$.port = NULL; 1808 } 1809 | TO ipportspec { 1810 $$ = $2; 1811 } 1812 ; 1813 1814ipportspec : ipspec { 1815 $$.host = $1; 1816 $$.port = NULL; 1817 } 1818 | ipspec PORT portspec { 1819 $$.host = $1; 1820 $$.port = $3; 1821 } 1822 | PORT portspec { 1823 $$.host = NULL; 1824 $$.port = $2; 1825 } 1826 ; 1827 1828ipspec : ANY { $$ = NULL; } 1829 | xhost { $$ = $1; } 1830 | '{' host_list '}' { $$ = $2; } 1831 ; 1832 1833host_list : xhost { $$ = $1; } 1834 | host_list comma xhost { 1835 if ($3 == NULL) 1836 $$ = $1; 1837 else if ($1 == NULL) 1838 $$ = $3; 1839 else { 1840 $1->tail->next = $3; 1841 $1->tail = $3->tail; 1842 $$ = $1; 1843 } 1844 } 1845 ; 1846 1847xhost : not host { 1848 struct node_host *n; 1849 1850 for (n = $2; n != NULL; n = n->next) 1851 n->not = $1; 1852 $$ = $2; 1853 } 1854 | NOROUTE { 1855 $$ = calloc(1, sizeof(struct node_host)); 1856 if ($$ == NULL) 1857 err(1, "xhost: calloc"); 1858 $$->addr.type = PF_ADDR_NOROUTE; 1859 $$->next = NULL; 1860 $$->tail = $$; 1861 } 1862 ; 1863 1864host : STRING { 1865 if (($$ = host($1)) == NULL) { 1866 /* error. "any" is handled elsewhere */ 1867 yyerror("could not parse host specification"); 1868 YYERROR; 1869 } 1870 1871 } 1872 | STRING '/' number { 1873 char *buf; 1874 1875 if (asprintf(&buf, "%s/%u", $1, $3) == -1) 1876 err(1, "host: asprintf"); 1877 if (($$ = host(buf)) == NULL) { 1878 /* error. "any" is handled elsewhere */ 1879 free(buf); 1880 yyerror("could not parse host specification"); 1881 YYERROR; 1882 } 1883 free(buf); 1884 } 1885 | dynaddr 1886 | dynaddr '/' number { 1887 struct node_host *n; 1888 1889 $$ = $1; 1890 for (n = $1; n != NULL; n = n->next) 1891 set_ipmask(n, $3); 1892 } 1893 | '<' STRING '>' { 1894 if (strlen($2) >= PF_TABLE_NAME_SIZE) { 1895 yyerror("table name '%s' too long"); 1896 YYERROR; 1897 } 1898 $$ = calloc(1, sizeof(struct node_host)); 1899 if ($$ == NULL) 1900 err(1, "host: calloc"); 1901 $$->addr.type = PF_ADDR_TABLE; 1902 if (strlcpy($$->addr.v.tblname, $2, 1903 sizeof($$->addr.v.tblname)) >= 1904 sizeof($$->addr.v.tblname)) 1905 errx(1, "host: strlcpy"); 1906 $$->next = NULL; 1907 $$->tail = $$; 1908 } 1909 ; 1910 1911number : STRING { 1912 u_long ulval; 1913 1914 if (atoul($1, &ulval) == -1) { 1915 yyerror("%s is not a number", $1); 1916 YYERROR; 1917 } else 1918 $$ = ulval; 1919 } 1920 ; 1921 1922dynaddr : '(' STRING ')' { 1923 if (ifa_exists($2) == NULL) { 1924 yyerror("interface %s does not exist", $2); 1925 YYERROR; 1926 } 1927 $$ = calloc(1, sizeof(struct node_host)); 1928 if ($$ == NULL) 1929 err(1, "address: calloc"); 1930 $$->af = 0; 1931 set_ipmask($$, 128); 1932 $$->addr.type = PF_ADDR_DYNIFTL; 1933 if (strlcpy($$->addr.v.ifname, $2, 1934 sizeof($$->addr.v.ifname)) >= 1935 sizeof($$->addr.v.ifname)) { 1936 free($$); 1937 yyerror("interface name too long"); 1938 YYERROR; 1939 } 1940 $$->next = NULL; 1941 $$->tail = $$; 1942 } 1943 ; 1944 1945portspec : port_item { $$ = $1; } 1946 | '{' port_list '}' { $$ = $2; } 1947 ; 1948 1949port_list : port_item { $$ = $1; } 1950 | port_list comma port_item { 1951 $1->tail->next = $3; 1952 $1->tail = $3; 1953 $$ = $1; 1954 } 1955 ; 1956 1957port_item : port { 1958 $$ = calloc(1, sizeof(struct node_port)); 1959 if ($$ == NULL) 1960 err(1, "port_item: calloc"); 1961 $$->port[0] = $1.a; 1962 $$->port[1] = $1.b; 1963 if ($1.t) 1964 $$->op = PF_OP_RRG; 1965 else 1966 $$->op = PF_OP_EQ; 1967 $$->next = NULL; 1968 $$->tail = $$; 1969 } 1970 | unaryop port { 1971 if ($2.t) { 1972 yyerror("':' cannot be used with an other " 1973 "port operator"); 1974 YYERROR; 1975 } 1976 $$ = calloc(1, sizeof(struct node_port)); 1977 if ($$ == NULL) 1978 err(1, "port_item: calloc"); 1979 $$->port[0] = $2.a; 1980 $$->port[1] = $2.b; 1981 $$->op = $1; 1982 $$->next = NULL; 1983 $$->tail = $$; 1984 } 1985 | port PORTBINARY port { 1986 if ($1.t || $3.t) { 1987 yyerror("':' cannot be used with an other " 1988 "port operator"); 1989 YYERROR; 1990 } 1991 $$ = calloc(1, sizeof(struct node_port)); 1992 if ($$ == NULL) 1993 err(1, "port_item: calloc"); 1994 $$->port[0] = $1.a; 1995 $$->port[1] = $3.a; 1996 $$->op = $2; 1997 $$->next = NULL; 1998 $$->tail = $$; 1999 } 2000 ; 2001 2002port : STRING { 2003 char *p = strchr($1, ':'); 2004 struct servent *s = NULL; 2005 u_long ulval; 2006 2007 if (p == NULL) { 2008 if (atoul($1, &ulval) == 0) { 2009 if (ulval > 65535) { 2010 yyerror("illegal port value %d", 2011 ulval); 2012 YYERROR; 2013 } 2014 $$.a = htons(ulval); 2015 } else { 2016 s = getservbyname($1, "tcp"); 2017 if (s == NULL) 2018 s = getservbyname($1, "udp"); 2019 if (s == NULL) { 2020 yyerror("unknown port %s", $1); 2021 YYERROR; 2022 } 2023 $$.a = s->s_port; 2024 } 2025 $$.b = 0; 2026 $$.t = 0; 2027 } else { 2028 int port[2]; 2029 2030 *p++ = 0; 2031 if ((port[0] = getservice($1)) == -1 || 2032 (port[1] = getservice(p)) == -1) 2033 YYERROR; 2034 $$.a = port[0]; 2035 $$.b = port[1]; 2036 $$.t = PF_OP_RRG; 2037 } 2038 } 2039 ; 2040 2041uids : uid_item { $$ = $1; } 2042 | '{' uid_list '}' { $$ = $2; } 2043 ; 2044 2045uid_list : uid_item { $$ = $1; } 2046 | uid_list comma uid_item { 2047 $1->tail->next = $3; 2048 $1->tail = $3; 2049 $$ = $1; 2050 } 2051 ; 2052 2053uid_item : uid { 2054 $$ = calloc(1, sizeof(struct node_uid)); 2055 if ($$ == NULL) 2056 err(1, "uid_item: calloc"); 2057 $$->uid[0] = $1; 2058 $$->uid[1] = $1; 2059 $$->op = PF_OP_EQ; 2060 $$->next = NULL; 2061 $$->tail = $$; 2062 } 2063 | unaryop uid { 2064 if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 2065 yyerror("user unknown requires operator = or " 2066 "!="); 2067 YYERROR; 2068 } 2069 $$ = calloc(1, sizeof(struct node_uid)); 2070 if ($$ == NULL) 2071 err(1, "uid_item: calloc"); 2072 $$->uid[0] = $2; 2073 $$->uid[1] = $2; 2074 $$->op = $1; 2075 $$->next = NULL; 2076 $$->tail = $$; 2077 } 2078 | uid PORTBINARY uid { 2079 if ($1 == UID_MAX || $3 == UID_MAX) { 2080 yyerror("user unknown requires operator = or " 2081 "!="); 2082 YYERROR; 2083 } 2084 $$ = calloc(1, sizeof(struct node_uid)); 2085 if ($$ == NULL) 2086 err(1, "uid_item: calloc"); 2087 $$->uid[0] = $1; 2088 $$->uid[1] = $3; 2089 $$->op = $2; 2090 $$->next = NULL; 2091 $$->tail = $$; 2092 } 2093 ; 2094 2095uid : STRING { 2096 u_long ulval; 2097 2098 if (atoul($1, &ulval) == -1) { 2099 if (!strcmp($1, "unknown")) 2100 $$ = UID_MAX; 2101 else { 2102 struct passwd *pw; 2103 2104 if ((pw = getpwnam($1)) == NULL) { 2105 yyerror("unknown user %s", $1); 2106 YYERROR; 2107 } 2108 $$ = pw->pw_uid; 2109 } 2110 } else { 2111 if (ulval >= UID_MAX) { 2112 yyerror("illegal uid value %lu", ulval); 2113 YYERROR; 2114 } 2115 $$ = ulval; 2116 } 2117 } 2118 ; 2119 2120gids : gid_item { $$ = $1; } 2121 | '{' gid_list '}' { $$ = $2; } 2122 ; 2123 2124gid_list : gid_item { $$ = $1; } 2125 | gid_list comma gid_item { 2126 $1->tail->next = $3; 2127 $1->tail = $3; 2128 $$ = $1; 2129 } 2130 ; 2131 2132gid_item : gid { 2133 $$ = calloc(1, sizeof(struct node_gid)); 2134 if ($$ == NULL) 2135 err(1, "gid_item: calloc"); 2136 $$->gid[0] = $1; 2137 $$->gid[1] = $1; 2138 $$->op = PF_OP_EQ; 2139 $$->next = NULL; 2140 $$->tail = $$; 2141 } 2142 | unaryop gid { 2143 if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 2144 yyerror("group unknown requires operator = or " 2145 "!="); 2146 YYERROR; 2147 } 2148 $$ = calloc(1, sizeof(struct node_gid)); 2149 if ($$ == NULL) 2150 err(1, "gid_item: calloc"); 2151 $$->gid[0] = $2; 2152 $$->gid[1] = $2; 2153 $$->op = $1; 2154 $$->next = NULL; 2155 $$->tail = $$; 2156 } 2157 | gid PORTBINARY gid { 2158 if ($1 == GID_MAX || $3 == GID_MAX) { 2159 yyerror("group unknown requires operator = or " 2160 "!="); 2161 YYERROR; 2162 } 2163 $$ = calloc(1, sizeof(struct node_gid)); 2164 if ($$ == NULL) 2165 err(1, "gid_item: calloc"); 2166 $$->gid[0] = $1; 2167 $$->gid[1] = $3; 2168 $$->op = $2; 2169 $$->next = NULL; 2170 $$->tail = $$; 2171 } 2172 ; 2173 2174gid : STRING { 2175 u_long ulval; 2176 2177 if (atoul($1, &ulval) == -1) { 2178 if (!strcmp($1, "unknown")) 2179 $$ = GID_MAX; 2180 else { 2181 struct group *grp; 2182 2183 if ((grp = getgrnam($1)) == NULL) { 2184 yyerror("unknown group %s", $1); 2185 YYERROR; 2186 } 2187 $$ = grp->gr_gid; 2188 } 2189 } else { 2190 if (ulval >= GID_MAX) { 2191 yyerror("illegal gid value %lu", ulval); 2192 YYERROR; 2193 } 2194 $$ = ulval; 2195 } 2196 } 2197 ; 2198 2199flag : STRING { 2200 int f; 2201 2202 if ((f = parse_flags($1)) < 0) { 2203 yyerror("bad flags %s", $1); 2204 YYERROR; 2205 } 2206 $$.b1 = f; 2207 } 2208 ; 2209 2210flags : FLAGS flag '/' flag { $$.b1 = $2.b1; $$.b2 = $4.b1; } 2211 | FLAGS '/' flag { $$.b1 = 0; $$.b2 = $3.b1; } 2212 ; 2213 2214icmpspec : ICMPTYPE icmp_item { $$ = $2; } 2215 | ICMPTYPE '{' icmp_list '}' { $$ = $3; } 2216 | ICMP6TYPE icmp6_item { $$ = $2; } 2217 | ICMP6TYPE '{' icmp6_list '}' { $$ = $3; } 2218 ; 2219 2220icmp_list : icmp_item { $$ = $1; } 2221 | icmp_list comma icmp_item { 2222 $1->tail->next = $3; 2223 $1->tail = $3; 2224 $$ = $1; 2225 } 2226 ; 2227 2228icmp6_list : icmp6_item { $$ = $1; } 2229 | icmp6_list comma icmp6_item { 2230 $1->tail->next = $3; 2231 $1->tail = $3; 2232 $$ = $1; 2233 } 2234 ; 2235 2236icmp_item : icmptype { 2237 $$ = calloc(1, sizeof(struct node_icmp)); 2238 if ($$ == NULL) 2239 err(1, "icmp_item: calloc"); 2240 $$->type = $1; 2241 $$->code = 0; 2242 $$->proto = IPPROTO_ICMP; 2243 $$->next = NULL; 2244 $$->tail = $$; 2245 } 2246 | icmptype CODE STRING { 2247 const struct icmpcodeent *p; 2248 u_long ulval; 2249 2250 if (atoul($3, &ulval) == 0) { 2251 if (ulval > 255) { 2252 yyerror("illegal icmp-code %d", ulval); 2253 YYERROR; 2254 } 2255 } else { 2256 if ((p = geticmpcodebyname($1-1, $3, 2257 AF_INET)) == NULL) { 2258 yyerror("unknown icmp-code %s", $3); 2259 YYERROR; 2260 } 2261 ulval = p->code; 2262 } 2263 $$ = calloc(1, sizeof(struct node_icmp)); 2264 if ($$ == NULL) 2265 err(1, "icmp_item: calloc"); 2266 $$->type = $1; 2267 $$->code = ulval + 1; 2268 $$->proto = IPPROTO_ICMP; 2269 $$->next = NULL; 2270 $$->tail = $$; 2271 } 2272 ; 2273 2274icmp6_item : icmp6type { 2275 $$ = calloc(1, sizeof(struct node_icmp)); 2276 if ($$ == NULL) 2277 err(1, "icmp_item: calloc"); 2278 $$->type = $1; 2279 $$->code = 0; 2280 $$->proto = IPPROTO_ICMPV6; 2281 $$->next = NULL; 2282 $$->tail = $$; 2283 } 2284 | icmp6type CODE STRING { 2285 const struct icmpcodeent *p; 2286 u_long ulval; 2287 2288 if (atoul($3, &ulval) == 0) { 2289 if (ulval > 255) { 2290 yyerror("illegal icmp6-code %ld", 2291 ulval); 2292 YYERROR; 2293 } 2294 } else { 2295 if ((p = geticmpcodebyname($1-1, $3, 2296 AF_INET6)) == NULL) { 2297 yyerror("unknown icmp6-code %s", $3); 2298 YYERROR; 2299 } 2300 ulval = p->code; 2301 } 2302 $$ = calloc(1, sizeof(struct node_icmp)); 2303 if ($$ == NULL) 2304 err(1, "icmp_item: calloc"); 2305 $$->type = $1; 2306 $$->code = ulval + 1; 2307 $$->proto = IPPROTO_ICMPV6; 2308 $$->next = NULL; 2309 $$->tail = $$; 2310 } 2311 ; 2312 2313icmptype : STRING { 2314 const struct icmptypeent *p; 2315 u_long ulval; 2316 2317 if (atoul($1, &ulval) == 0) { 2318 if (ulval > 255) { 2319 yyerror("illegal icmp-type %d", ulval); 2320 YYERROR; 2321 } 2322 $$ = ulval + 1; 2323 } else { 2324 if ((p = geticmptypebyname($1, AF_INET)) == 2325 NULL) { 2326 yyerror("unknown icmp-type %s", $1); 2327 YYERROR; 2328 } 2329 $$ = p->type + 1; 2330 } 2331 } 2332 ; 2333 2334icmp6type : STRING { 2335 const struct icmptypeent *p; 2336 u_long ulval; 2337 2338 if (atoul($1, &ulval) == 0) { 2339 if (ulval > 255) { 2340 yyerror("illegal icmp6-type %d", ulval); 2341 YYERROR; 2342 } 2343 $$ = ulval + 1; 2344 } else { 2345 if ((p = geticmptypebyname($1, AF_INET6)) == 2346 NULL) { 2347 yyerror("unknown icmp6-type %s", $1); 2348 YYERROR; 2349 } 2350 $$ = p->type + 1; 2351 } 2352 } 2353 ; 2354 2355tos : TOS STRING { 2356 if (!strcmp($2, "lowdelay")) 2357 $$ = IPTOS_LOWDELAY; 2358 else if (!strcmp($2, "throughput")) 2359 $$ = IPTOS_THROUGHPUT; 2360 else if (!strcmp($2, "reliability")) 2361 $$ = IPTOS_RELIABILITY; 2362 else if ($2[0] == '0' && $2[1] == 'x') 2363 $$ = strtoul($2, NULL, 16); 2364 else 2365 $$ = strtoul($2, NULL, 10); 2366 if (!$$ || $$ > 255) { 2367 yyerror("illegal tos value %s", $2); 2368 YYERROR; 2369 } 2370 } 2371 ; 2372 2373keep : KEEP STATE state_opt_spec { 2374 $$.action = PF_STATE_NORMAL; 2375 $$.options = $3; 2376 } 2377 | MODULATE STATE state_opt_spec { 2378 $$.action = PF_STATE_MODULATE; 2379 $$.options = $3; 2380 } 2381 | SYNPROXY STATE state_opt_spec { 2382 $$.action = PF_STATE_SYNPROXY; 2383 $$.options = $3; 2384 } 2385 ; 2386 2387state_opt_spec : '(' state_opt_list ')' { $$ = $2; } 2388 | /* empty */ { $$ = NULL; } 2389 ; 2390 2391state_opt_list : state_opt_item { $$ = $1; } 2392 | state_opt_list comma state_opt_item { 2393 $1->tail->next = $3; 2394 $1->tail = $3; 2395 $$ = $1; 2396 } 2397 ; 2398 2399state_opt_item : MAXIMUM number { 2400 $$ = calloc(1, sizeof(struct node_state_opt)); 2401 if ($$ == NULL) 2402 err(1, "state_opt_item: calloc"); 2403 $$->type = PF_STATE_OPT_MAX; 2404 $$->data.max_states = $2; 2405 $$->next = NULL; 2406 $$->tail = $$; 2407 } 2408 | STRING number { 2409 int i; 2410 2411 for (i = 0; pf_timeouts[i].name && 2412 strcmp(pf_timeouts[i].name, $1); ++i) 2413 ; /* nothing */ 2414 if (!pf_timeouts[i].name) { 2415 yyerror("illegal timeout name %s", $1); 2416 YYERROR; 2417 } 2418 if (strchr(pf_timeouts[i].name, '.') == NULL) { 2419 yyerror("illegal state timeout %s", $1); 2420 YYERROR; 2421 } 2422 $$ = calloc(1, sizeof(struct node_state_opt)); 2423 if ($$ == NULL) 2424 err(1, "state_opt_item: calloc"); 2425 $$->type = PF_STATE_OPT_TIMEOUT; 2426 $$->data.timeout.number = pf_timeouts[i].timeout; 2427 $$->data.timeout.seconds = $2; 2428 $$->next = NULL; 2429 $$->tail = $$; 2430 } 2431 ; 2432 2433label : LABEL STRING { 2434 if (($$ = strdup($2)) == NULL) 2435 err(1, "rule label strdup() failed"); 2436 } 2437 ; 2438 2439qname : QUEUE STRING { 2440 if (($$.qname = strdup($2)) == NULL) 2441 err(1, "qname strdup() failed"); 2442 } 2443 | QUEUE '(' STRING ')' { 2444 if (($$.qname = strdup($3)) == NULL) 2445 err(1, "qname strdup() failed"); 2446 } 2447 | QUEUE '(' STRING comma STRING ')' { 2448 if (($$.qname = strdup($3)) == NULL || 2449 ($$.pqname = strdup($5)) == NULL) 2450 err(1, "qname strdup() failed"); 2451 } 2452 ; 2453 2454no : /* empty */ { $$ = 0; } 2455 | NO { $$ = 1; } 2456 ; 2457 2458rport : STRING { 2459 char *p = strchr($1, ':'); 2460 2461 if (p == NULL) { 2462 if (($$.a = getservice($1)) == -1) 2463 YYERROR; 2464 $$.b = $$.t = 0; 2465 } else if (!strcmp(p+1, "*")) { 2466 *p = 0; 2467 if (($$.a = getservice($1)) == -1) 2468 YYERROR; 2469 $$.b = 0; 2470 $$.t = 1; 2471 } else { 2472 *p++ = 0; 2473 if (($$.a = getservice($1)) == -1 || 2474 ($$.b = getservice(p)) == -1) 2475 YYERROR; 2476 if ($$.a == $$.b) 2477 $$.b = 0; 2478 $$.t = 0; 2479 } 2480 } 2481 ; 2482 2483redirspec : host { $$ = $1; } 2484 | '{' redir_host_list '}' { $$ = $2; } 2485 ; 2486 2487redir_host_list : host { $$ = $1; } 2488 | redir_host_list comma host { 2489 $1->tail->next = $3; 2490 $1->tail = $3->tail; 2491 $$ = $1; 2492 } 2493 ; 2494 2495redirpool : /* empty */ { $$ = NULL; } 2496 | ARROW redirspec { 2497 $$ = calloc(1, sizeof(struct redirection)); 2498 if ($$ == NULL) 2499 err(1, "redirection: calloc"); 2500 $$->host = $2; 2501 $$->rport.a = $$->rport.b = $$->rport.t = 0; 2502 } 2503 | ARROW redirspec PORT rport { 2504 $$ = calloc(1, sizeof(struct redirection)); 2505 if ($$ == NULL) 2506 err(1, "redirection: calloc"); 2507 $$->host = $2; 2508 $$->rport = $4; 2509 } 2510 ; 2511 2512hashkey : /* empty */ 2513 { 2514 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 2515 if ($$ == NULL) 2516 err(1, "hashkey: calloc"); 2517 $$->key32[0] = arc4random(); 2518 $$->key32[1] = arc4random(); 2519 $$->key32[2] = arc4random(); 2520 $$->key32[3] = arc4random(); 2521 } 2522 | string 2523 { 2524 if (!strncmp($1, "0x", 2)) { 2525 if (strlen($1) != 34) { 2526 yyerror("hex key must be 128 bits " 2527 "(32 hex digits) long"); 2528 YYERROR; 2529 } 2530 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 2531 if ($$ == NULL) 2532 err(1, "hashkey: calloc"); 2533 2534 if (sscanf($1, "0x%8x%8x%8x%8x", 2535 &$$->key32[0], &$$->key32[1], 2536 &$$->key32[2], &$$->key32[3]) != 4) { 2537 free($$); 2538 yyerror("invalid hex key"); 2539 YYERROR; 2540 } 2541 } else { 2542 MD5_CTX context; 2543 2544 $$ = calloc(1, sizeof(struct pf_poolhashkey)); 2545 if ($$ == NULL) 2546 err(1, "hashkey: calloc"); 2547 MD5Init(&context); 2548 MD5Update(&context, (unsigned char *)$1, 2549 strlen($1)); 2550 MD5Final((unsigned char *)$$, &context); 2551 HTONL($$->key32[0]); 2552 HTONL($$->key32[1]); 2553 HTONL($$->key32[2]); 2554 HTONL($$->key32[3]); 2555 } 2556 } 2557 ; 2558 2559pooltype : /* empty */ 2560 { 2561 $$.type = PF_POOL_NONE; 2562 $$.key = NULL; 2563 } 2564 | BITMASK 2565 { 2566 $$.type = PF_POOL_BITMASK; 2567 $$.key = NULL; 2568 } 2569 | RANDOM 2570 { 2571 $$.type = PF_POOL_RANDOM; 2572 $$.key = NULL; 2573 } 2574 | SOURCEHASH hashkey 2575 { 2576 $$.type = PF_POOL_SRCHASH; 2577 $$.key = $2; 2578 } 2579 | ROUNDROBIN 2580 { 2581 $$.type = PF_POOL_ROUNDROBIN; 2582 $$.key = NULL; 2583 } 2584 ; 2585 2586staticport : /* empty */ { $$ = 0; } 2587 | STATICPORT { $$ = 1; } 2588 ; 2589 2590redirection : /* empty */ { $$ = NULL; } 2591 | ARROW host { 2592 $$ = calloc(1, sizeof(struct redirection)); 2593 if ($$ == NULL) 2594 err(1, "redirection: calloc"); 2595 $$->host = $2; 2596 $$->rport.a = $$->rport.b = $$->rport.t = 0; 2597 } 2598 | ARROW host PORT rport { 2599 $$ = calloc(1, sizeof(struct redirection)); 2600 if ($$ == NULL) 2601 err(1, "redirection: calloc"); 2602 $$->host = $2; 2603 $$->rport = $4; 2604 } 2605 ; 2606 2607natpass : /* empty */ { $$ = 0; } 2608 | PASS { $$ = 1; } 2609 ; 2610 2611nataction : no NAT natpass { 2612 $$.b2 = $$.w = 0; 2613 if ($1) 2614 $$.b1 = PF_NONAT; 2615 else 2616 $$.b1 = PF_NAT; 2617 $$.b2 = $3; 2618 } 2619 | no RDR natpass { 2620 $$.b2 = $$.w = 0; 2621 if ($1) 2622 $$.b1 = PF_NORDR; 2623 else 2624 $$.b1 = PF_RDR; 2625 $$.b2 = $3; 2626 } 2627 ; 2628 2629natrule : nataction interface af proto fromto tag redirpool pooltype 2630 staticport 2631 { 2632 struct pf_rule r; 2633 2634 if (check_rulestate(PFCTL_STATE_NAT)) 2635 YYERROR; 2636 2637 memset(&r, 0, sizeof(r)); 2638 2639 r.action = $1.b1; 2640 r.natpass = $1.b2; 2641 r.af = $3; 2642 2643 if (!r.af) { 2644 if ($5.src.host && $5.src.host->af && 2645 !$5.src.host->ifindex) 2646 r.af = $5.src.host->af; 2647 else if ($5.dst.host && $5.dst.host->af && 2648 !$5.dst.host->ifindex) 2649 r.af = $5.dst.host->af; 2650 } 2651 2652 if ($6 != NULL) 2653 if (strlcpy(r.tagname, $6, PF_TAG_NAME_SIZE) > 2654 PF_TAG_NAME_SIZE) { 2655 yyerror("tag too long, max %u chars", 2656 PF_TAG_NAME_SIZE - 1); 2657 YYERROR; 2658 } 2659 2660 if (r.action == PF_NONAT || r.action == PF_NORDR) { 2661 if ($7 != NULL) { 2662 yyerror("translation rule with 'no' " 2663 "does not need '->'"); 2664 YYERROR; 2665 } 2666 } else { 2667 if ($7 == NULL || $7->host == NULL) { 2668 yyerror("translation rule requires '-> " 2669 "address'"); 2670 YYERROR; 2671 } 2672 if (!r.af && ! $7->host->ifindex) 2673 r.af = $7->host->af; 2674 2675 remove_invalid_hosts(&$7->host, &r.af); 2676 if (invalid_redirect($7->host, r.af)) 2677 YYERROR; 2678 if (check_netmask($7->host, r.af)) 2679 YYERROR; 2680 2681 r.rpool.proxy_port[0] = ntohs($7->rport.a); 2682 2683 switch (r.action) { 2684 case PF_RDR: 2685 if (!$7->rport.b && $7->rport.t && 2686 $5.dst.port != NULL) { 2687 r.rpool.proxy_port[1] = 2688 ntohs($7->rport.a) + 2689 (ntohs($5.dst.port->port[1]) - 2690 ntohs($5.dst.port->port[0])); 2691 } else 2692 r.rpool.proxy_port[1] = 2693 ntohs($7->rport.b); 2694 break; 2695 case PF_NAT: 2696 r.rpool.proxy_port[1] = ntohs($7->rport.b); 2697 if (!r.rpool.proxy_port[0] && 2698 !r.rpool.proxy_port[1]) { 2699 r.rpool.proxy_port[0] = 2700 PF_NAT_PROXY_PORT_LOW; 2701 r.rpool.proxy_port[1] = 2702 PF_NAT_PROXY_PORT_HIGH; 2703 } else if (!r.rpool.proxy_port[1]) 2704 r.rpool.proxy_port[1] = 2705 r.rpool.proxy_port[0]; 2706 break; 2707 default: 2708 break; 2709 } 2710 2711 r.rpool.opts = $8.type; 2712 if (r.rpool.opts == PF_POOL_NONE) 2713 r.rpool.opts = PF_POOL_ROUNDROBIN; 2714 if (r.rpool.opts != PF_POOL_ROUNDROBIN) 2715 if (disallow_table($7->host, "tables " 2716 "are only supported in round-robin " 2717 "redirection pools")) 2718 YYERROR; 2719 if ($7->host->next) { 2720 if (r.rpool.opts != 2721 PF_POOL_ROUNDROBIN) { 2722 yyerror("only round-robin " 2723 "valid for multiple " 2724 "redirection addresses"); 2725 YYERROR; 2726 } 2727 } else { 2728 if ((r.af == AF_INET && 2729 unmask(&$7->host->addr.v.a.mask, 2730 r.af) == 32) || 2731 (r.af == AF_INET6 && 2732 unmask(&$7->host->addr.v.a.mask, 2733 r.af) == 128)) { 2734 r.rpool.opts = PF_POOL_NONE; 2735 } 2736 } 2737 } 2738 2739 if ($8.key != NULL) 2740 memcpy(&r.rpool.key, $8.key, 2741 sizeof(struct pf_poolhashkey)); 2742 2743 if ($9 != 0) { 2744 if (r.action != PF_NAT) { 2745 yyerror("the 'static-port' option is " 2746 "only valid with nat rules"); 2747 YYERROR; 2748 } 2749 if (r.rpool.proxy_port[0] != 2750 PF_NAT_PROXY_PORT_LOW && 2751 r.rpool.proxy_port[1] != 2752 PF_NAT_PROXY_PORT_HIGH) { 2753 yyerror("the 'static-port' option can't" 2754 " be used when specifying a port" 2755 " range"); 2756 YYERROR; 2757 } 2758 r.rpool.proxy_port[0] = 0; 2759 r.rpool.proxy_port[1] = 0; 2760 } 2761 2762 expand_rule(&r, $2, $7 == NULL ? NULL : $7->host, $4, 2763 $5.src_os, $5.src.host, $5.src.port, $5.dst.host, 2764 $5.dst.port, 0, 0, 0); 2765 free($7); 2766 } 2767 ; 2768 2769binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag 2770 redirection 2771 { 2772 struct pf_rule binat; 2773 struct pf_pooladdr *pa; 2774 2775 if (check_rulestate(PFCTL_STATE_NAT)) 2776 YYERROR; 2777 2778 memset(&binat, 0, sizeof(binat)); 2779 2780 if ($1) 2781 binat.action = PF_NOBINAT; 2782 else 2783 binat.action = PF_BINAT; 2784 binat.natpass = $3; 2785 binat.af = $5; 2786 if (!binat.af && $8 != NULL && $8->af) 2787 binat.af = $8->af; 2788 if (!binat.af && $10 != NULL && $10->af) 2789 binat.af = $10->af; 2790 if (!binat.af && $12 != NULL && $12->host) 2791 binat.af = $12->host->af; 2792 if (!binat.af) { 2793 yyerror("address family (inet/inet6) " 2794 "undefined"); 2795 YYERROR; 2796 } 2797 2798 if ($4 != NULL) { 2799 memcpy(binat.ifname, $4->ifname, 2800 sizeof(binat.ifname)); 2801 free($4); 2802 } 2803 if ($11 != NULL) 2804 if (strlcpy(binat.tagname, $11, 2805 PF_TAG_NAME_SIZE) > PF_TAG_NAME_SIZE) { 2806 yyerror("tag too long, max %u chars", 2807 PF_TAG_NAME_SIZE - 1); 2808 YYERROR; 2809 } 2810 2811 if ($6 != NULL) { 2812 binat.proto = $6->proto; 2813 free($6); 2814 } 2815 2816 if ($8 != NULL && disallow_table($8, "invalid use of " 2817 "table <%s> as the source address of a binat rule")) 2818 YYERROR; 2819 if ($12 != NULL && $12->host != NULL && disallow_table( 2820 $12->host, "invalid use of table <%s> as the " 2821 "redirect address of a binat rule")) 2822 YYERROR; 2823 2824 if ($8 != NULL) { 2825 if ($8->next) { 2826 yyerror("multiple binat ip addresses"); 2827 YYERROR; 2828 } 2829 if ($8->addr.type == PF_ADDR_DYNIFTL) 2830 $8->af = binat.af; 2831 if ($8->af != binat.af) { 2832 yyerror("binat ip versions must match"); 2833 YYERROR; 2834 } 2835 if (check_netmask($8, binat.af)) 2836 YYERROR; 2837 memcpy(&binat.src.addr, &$8->addr, 2838 sizeof(binat.src.addr)); 2839 free($8); 2840 } 2841 if ($10 != NULL) { 2842 if ($10->next) { 2843 yyerror("multiple binat ip addresses"); 2844 YYERROR; 2845 } 2846 if ($10->af != binat.af && $10->af) { 2847 yyerror("binat ip versions must match"); 2848 YYERROR; 2849 } 2850 if (check_netmask($10, binat.af)) 2851 YYERROR; 2852 memcpy(&binat.dst.addr, &$10->addr, 2853 sizeof(binat.dst.addr)); 2854 binat.dst.not = $10->not; 2855 free($10); 2856 } 2857 2858 if (binat.action == PF_NOBINAT) { 2859 if ($12 != NULL) { 2860 yyerror("'no binat' rule does not need" 2861 " '->'"); 2862 YYERROR; 2863 } 2864 } else { 2865 if ($12 == NULL || $12->host == NULL) { 2866 yyerror("'binat' rule requires" 2867 " '-> address'"); 2868 YYERROR; 2869 } 2870 2871 remove_invalid_hosts(&$12->host, &binat.af); 2872 if (invalid_redirect($12->host, binat.af)) 2873 YYERROR; 2874 if ($12->host->next != NULL) { 2875 yyerror("binat rule must redirect to " 2876 "a single address"); 2877 YYERROR; 2878 } 2879 if (check_netmask($12->host, binat.af)) 2880 YYERROR; 2881 2882 if (!PF_AZERO(&binat.src.addr.v.a.mask, 2883 binat.af) && 2884 !PF_AEQ(&binat.src.addr.v.a.mask, 2885 &$12->host->addr.v.a.mask, binat.af)) { 2886 yyerror("'binat' source mask and " 2887 "redirect mask must be the same"); 2888 YYERROR; 2889 } 2890 2891 TAILQ_INIT(&binat.rpool.list); 2892 pa = calloc(1, sizeof(struct pf_pooladdr)); 2893 if (pa == NULL) 2894 err(1, "binat: calloc"); 2895 pa->addr = $12->host->addr; 2896 pa->ifname[0] = 0; 2897 TAILQ_INSERT_TAIL(&binat.rpool.list, 2898 pa, entries); 2899 2900 free($12); 2901 } 2902 2903 pfctl_add_rule(pf, &binat); 2904 } 2905 ; 2906 2907tag : /* empty */ { $$ = NULL; } 2908 | TAG STRING { $$ = $2; } 2909 2910route_host : STRING { 2911 struct node_host *n; 2912 2913 $$ = calloc(1, sizeof(struct node_host)); 2914 if ($$ == NULL) 2915 err(1, "route_host: calloc"); 2916 if (($$->ifname = strdup($1)) == NULL) 2917 err(1, "routeto: strdup"); 2918 if ((n = ifa_exists($$->ifname)) == NULL) { 2919 yyerror("routeto: unknown interface %s", 2920 $$->ifname); 2921 YYERROR; 2922 } 2923 set_ipmask($$, 128); 2924 $$->next = NULL; 2925 $$->tail = $$; 2926 } 2927 | '(' STRING host ')' { 2928 struct node_host *n; 2929 2930 $$ = $3; 2931 if (($$->ifname = strdup($2)) == NULL) 2932 err(1, "routeto: strdup"); 2933 if ((n = ifa_exists($$->ifname)) == NULL) { 2934 yyerror("routeto: unknown interface %s", 2935 $$->ifname); 2936 YYERROR; 2937 } 2938 } 2939 ; 2940 2941route_host_list : route_host { $$ = $1; } 2942 | route_host_list comma route_host { 2943 if ($1->af == 0) 2944 $1->af = $3->af; 2945 if ($1->af != $3->af) { 2946 yyerror("all pool addresses must be in the " 2947 "same address family"); 2948 YYERROR; 2949 } 2950 $1->tail->next = $3; 2951 $1->tail = $3->tail; 2952 $$ = $1; 2953 } 2954 ; 2955 2956routespec : route_host { $$ = $1; } 2957 | '{' route_host_list '}' { $$ = $2; } 2958 ; 2959 2960route : /* empty */ { 2961 $$.host = NULL; 2962 $$.rt = 0; 2963 $$.pool_opts = 0; 2964 } 2965 | FASTROUTE { 2966 $$.host = NULL; 2967 $$.rt = PF_FASTROUTE; 2968 $$.pool_opts = 0; 2969 } 2970 | ROUTETO routespec pooltype { 2971 $$.host = $2; 2972 $$.rt = PF_ROUTETO; 2973 $$.pool_opts = $3.type; 2974 if ($3.key != NULL) 2975 $$.key = $3.key; 2976 } 2977 | REPLYTO routespec pooltype { 2978 $$.host = $2; 2979 $$.rt = PF_REPLYTO; 2980 $$.pool_opts = $3.type; 2981 if ($3.key != NULL) 2982 $$.key = $3.key; 2983 } 2984 | DUPTO routespec pooltype { 2985 $$.host = $2; 2986 $$.rt = PF_DUPTO; 2987 $$.pool_opts = $3.type; 2988 if ($3.key != NULL) 2989 $$.key = $3.key; 2990 } 2991 ; 2992 2993timeout_spec : STRING number 2994 { 2995 if (check_rulestate(PFCTL_STATE_OPTION)) 2996 YYERROR; 2997 if (pfctl_set_timeout(pf, $1, $2, 0) != 0) { 2998 yyerror("unknown timeout %s", $1); 2999 YYERROR; 3000 } 3001 } 3002 ; 3003 3004timeout_list : timeout_list comma timeout_spec 3005 | timeout_spec 3006 ; 3007 3008limit_spec : STRING number 3009 { 3010 if (check_rulestate(PFCTL_STATE_OPTION)) 3011 YYERROR; 3012 if (pfctl_set_limit(pf, $1, $2) != 0) { 3013 yyerror("unable to set limit %s %u", $1, $2); 3014 YYERROR; 3015 } 3016 } 3017 3018limit_list : limit_list comma limit_spec 3019 | limit_spec 3020 ; 3021 3022comma : ',' 3023 | /* empty */ 3024 ; 3025 3026yesno : NO { $$ = 0; } 3027 | STRING { 3028 if (!strcmp($1, "yes")) 3029 $$ = 1; 3030 else 3031 YYERROR; 3032 } 3033 3034unaryop : '=' { $$ = PF_OP_EQ; } 3035 | '!' '=' { $$ = PF_OP_NE; } 3036 | '<' '=' { $$ = PF_OP_LE; } 3037 | '<' { $$ = PF_OP_LT; } 3038 | '>' '=' { $$ = PF_OP_GE; } 3039 | '>' { $$ = PF_OP_GT; } 3040 ; 3041 3042%% 3043 3044int 3045yyerror(const char *fmt, ...) 3046{ 3047 va_list ap; 3048 extern char *infile; 3049 3050 errors = 1; 3051 va_start(ap, fmt); 3052 fprintf(stderr, "%s:%d: ", infile, yylval.lineno); 3053 vfprintf(stderr, fmt, ap); 3054 fprintf(stderr, "\n"); 3055 va_end(ap); 3056 return (0); 3057} 3058 3059int 3060disallow_table(struct node_host *h, const char *fmt) 3061{ 3062 for (; h != NULL; h = h->next) 3063 if (h->addr.type == PF_ADDR_TABLE) { 3064 yyerror(fmt, h->addr.v.tblname); 3065 return (1); 3066 } 3067 return (0); 3068} 3069 3070int 3071rule_consistent(struct pf_rule *r) 3072{ 3073 int problems = 0; 3074 3075 switch (r->action) { 3076 case PF_PASS: 3077 case PF_DROP: 3078 case PF_SCRUB: 3079 problems = filter_consistent(r); 3080 break; 3081 case PF_NAT: 3082 case PF_NONAT: 3083 problems = nat_consistent(r); 3084 break; 3085 case PF_RDR: 3086 case PF_NORDR: 3087 problems = rdr_consistent(r); 3088 break; 3089 case PF_BINAT: 3090 case PF_NOBINAT: 3091 default: 3092 break; 3093 } 3094 return (problems); 3095} 3096 3097int 3098filter_consistent(struct pf_rule *r) 3099{ 3100 int problems = 0; 3101 3102 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 3103 (r->src.port_op || r->dst.port_op)) { 3104 yyerror("port only applies to tcp/udp"); 3105 problems++; 3106 } 3107 if (r->src.port_op == PF_OP_RRG || r->dst.port_op == PF_OP_RRG) { 3108 yyerror("the ':' port operator only applies to rdr"); 3109 problems++; 3110 } 3111 if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 && 3112 (r->type || r->code)) { 3113 yyerror("icmp-type/code only applies to icmp"); 3114 problems++; 3115 } 3116 if (!r->af && (r->type || r->code)) { 3117 yyerror("must indicate address family with icmp-type/code"); 3118 problems++; 3119 } 3120 if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) || 3121 (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) { 3122 yyerror("proto %s doesn't match address family %s", 3123 r->proto == IPPROTO_ICMP ? "icmp" : "icmp6", 3124 r->af == AF_INET ? "inet" : "inet6"); 3125 problems++; 3126 } 3127 if ((r->keep_state == PF_STATE_MODULATE || r->keep_state == 3128 PF_STATE_SYNPROXY) && r->proto && r->proto != IPPROTO_TCP) { 3129 yyerror("modulate/synproxy state can only be applied to " 3130 "TCP rules"); 3131 problems++; 3132 } 3133 if (r->allow_opts && r->action != PF_PASS) { 3134 yyerror("allow-opts can only be specified for pass rules"); 3135 problems++; 3136 } 3137 if (!r->af && (r->src.addr.type == PF_ADDR_DYNIFTL || 3138 r->dst.addr.type == PF_ADDR_DYNIFTL)) { 3139 yyerror("dynamic addresses require address family " 3140 "(inet/inet6)"); 3141 problems++; 3142 } 3143 if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op || 3144 r->dst.port_op || r->flagset || r->type || r->code)) { 3145 yyerror("fragments can be filtered only on IP header fields"); 3146 problems++; 3147 } 3148 if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) { 3149 yyerror("return-rst can only be applied to TCP rules"); 3150 problems++; 3151 } 3152 if (r->action == PF_DROP && r->keep_state) { 3153 yyerror("keep state on block rules doesn't make sense"); 3154 problems++; 3155 } 3156 if ((r->tagname[0] || r->match_tagname[0]) && !r->keep_state && 3157 r->action == PF_PASS) { 3158 yyerror("tags cannot be used without keep state"); 3159 problems++; 3160 } 3161 return (-problems); 3162} 3163 3164int 3165nat_consistent(struct pf_rule *r) 3166{ 3167 int problems = 0; 3168 struct pf_pooladdr *pa; 3169 3170 if (r->src.port_op == PF_OP_RRG || r->dst.port_op == PF_OP_RRG) { 3171 yyerror("the ':' port operator only applies to rdr"); 3172 problems++; 3173 } 3174 if (!r->af) { 3175 TAILQ_FOREACH(pa, &r->rpool.list, entries) { 3176 if (pa->addr.type == PF_ADDR_DYNIFTL) { 3177 yyerror("dynamic addresses require " 3178 "address family (inet/inet6)"); 3179 problems++; 3180 break; 3181 } 3182 } 3183 } 3184 return (-problems); 3185} 3186 3187int 3188rdr_consistent(struct pf_rule *r) 3189{ 3190 int problems = 0; 3191 struct pf_pooladdr *pa; 3192 3193 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP) { 3194 if (r->src.port_op) { 3195 yyerror("src port only applies to tcp/udp"); 3196 problems++; 3197 } 3198 if (r->dst.port_op) { 3199 yyerror("dst port only applies to tcp/udp"); 3200 problems++; 3201 } 3202 if (r->rpool.proxy_port[0]) { 3203 yyerror("rpool port only applies to tcp/udp"); 3204 problems++; 3205 } 3206 } 3207 if (r->dst.port_op && 3208 r->dst.port_op != PF_OP_EQ && r->dst.port_op != PF_OP_RRG) { 3209 yyerror("invalid port operator for rdr destination port"); 3210 problems++; 3211 } 3212 if (r->src.port_op == PF_OP_RRG) { 3213 yyerror("the ':' port operator only applies to rdr " 3214 "destination port"); 3215 problems++; 3216 } 3217 if (!r->af) { 3218 if (r->src.addr.type == PF_ADDR_DYNIFTL || 3219 r->dst.addr.type == PF_ADDR_DYNIFTL) { 3220 yyerror("dynamic addresses require address family " 3221 "(inet/inet6)"); 3222 problems++; 3223 } else { 3224 TAILQ_FOREACH(pa, &r->rpool.list, entries) { 3225 if (pa->addr.type == PF_ADDR_DYNIFTL) { 3226 yyerror("dynamic addresses require " 3227 "address family (inet/inet6)"); 3228 problems++; 3229 break; 3230 } 3231 } 3232 } 3233 } 3234 return (-problems); 3235} 3236 3237int 3238process_tabledef(char *name, struct table_opts *opts) 3239{ 3240 struct pfr_buffer ab; 3241 struct node_tinit *ti; 3242 3243 bzero(&ab, sizeof(ab)); 3244 ab.pfrb_type = PFRB_ADDRS; 3245 SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) { 3246 if (ti->file) 3247 if (pfr_buf_load(&ab, ti->file, 0, append_addr)) { 3248 if (errno) 3249 yyerror("cannot load \"%s\": %s", 3250 ti->file, strerror(errno)); 3251 else 3252 yyerror("file \"%s\" contains bad data", 3253 ti->file); 3254 goto _error; 3255 } 3256 if (ti->host) 3257 if (append_addr_host(&ab, ti->host, 0, 0)) { 3258 yyerror("cannot create address buffer: %s", 3259 strerror(errno)); 3260 goto _error; 3261 } 3262 } 3263 if (pf->opts & PF_OPT_VERBOSE) 3264 print_tabledef(name, opts->flags, opts->init_addr, 3265 &opts->init_nodes); 3266 if (!(pf->opts & PF_OPT_NOACTION) && 3267 pfctl_define_table(name, opts->flags, opts->init_addr, 3268 pf->anchor, pf->ruleset, &ab, pf->tticket)) { 3269 yyerror("cannot define table %s: %s", name, 3270 pfr_strerror(errno)); 3271 goto _error; 3272 } 3273 pf->tdirty = 1; 3274 pfr_buf_clear(&ab); 3275 return (0); 3276_error: 3277 pfr_buf_clear(&ab); 3278 return (-1); 3279} 3280 3281struct keywords { 3282 const char *k_name; 3283 int k_val; 3284}; 3285 3286/* macro gore, but you should've seen the prior indentation nightmare... */ 3287 3288#define FREE_LIST(T,r) \ 3289 do { \ 3290 T *p, *node = r; \ 3291 while (node != NULL) { \ 3292 p = node; \ 3293 node = node->next; \ 3294 free(p); \ 3295 } \ 3296 } while (0) 3297 3298#define LOOP_THROUGH(T,n,r,C) \ 3299 do { \ 3300 T *n; \ 3301 if (r == NULL) { \ 3302 r = calloc(1, sizeof(T)); \ 3303 if (r == NULL) \ 3304 err(1, "LOOP: calloc"); \ 3305 r->next = NULL; \ 3306 } \ 3307 n = r; \ 3308 while (n != NULL) { \ 3309 do { \ 3310 C; \ 3311 } while (0); \ 3312 n = n->next; \ 3313 } \ 3314 } while (0) 3315 3316void 3317expand_label_str(char *label, const char *srch, const char *repl) 3318{ 3319 char tmp[PF_RULE_LABEL_SIZE] = ""; 3320 char *p, *q; 3321 3322 p = q = label; 3323 while ((q = strstr(p, srch)) != NULL) { 3324 *q = '\0'; 3325 if ((strlcat(tmp, p, sizeof(tmp)) >= sizeof(tmp)) || 3326 (strlcat(tmp, repl, sizeof(tmp)) >= sizeof(tmp))) 3327 err(1, "expand_label: label too long"); 3328 q += strlen(srch); 3329 p = q; 3330 } 3331 if (strlcat(tmp, p, sizeof(tmp)) >= sizeof(tmp)) 3332 err(1, "expand_label: label too long"); 3333 strlcpy(label, tmp, PF_RULE_LABEL_SIZE); /* always fits */ 3334} 3335 3336void 3337expand_label_if(const char *name, char *label, const char *ifname) 3338{ 3339 if (strstr(label, name) != NULL) { 3340 if (!*ifname) 3341 expand_label_str(label, name, "any"); 3342 else 3343 expand_label_str(label, name, ifname); 3344 } 3345} 3346 3347void 3348expand_label_addr(const char *name, char *label, sa_family_t af, 3349 struct node_host *h) 3350{ 3351 char tmp[64], tmp_not[66]; 3352 3353 if (strstr(label, name) != NULL) { 3354 switch (h->addr.type) { 3355 case PF_ADDR_DYNIFTL: 3356 snprintf(tmp, sizeof(tmp), "(%s)", h->addr.v.ifname); 3357 break; 3358 case PF_ADDR_TABLE: 3359 snprintf(tmp, sizeof(tmp), "<%s>", h->addr.v.tblname); 3360 break; 3361 case PF_ADDR_NOROUTE: 3362 snprintf(tmp, sizeof(tmp), "no-route"); 3363 break; 3364 case PF_ADDR_ADDRMASK: 3365 if (!af || (PF_AZERO(&h->addr.v.a.addr, af) && 3366 PF_AZERO(&h->addr.v.a.mask, af))) 3367 snprintf(tmp, sizeof(tmp), "any"); 3368 else { 3369 char a[48]; 3370 int bits; 3371 3372 if (inet_ntop(af, &h->addr.v.a.addr, a, 3373 sizeof(a)) == NULL) 3374 snprintf(tmp, sizeof(tmp), "?"); 3375 else { 3376 bits = unmask(&h->addr.v.a.mask, af); 3377 if ((af == AF_INET && bits < 32) || 3378 (af == AF_INET6 && bits < 128)) 3379 snprintf(tmp, sizeof(tmp), 3380 "%s/%d", a, bits); 3381 else 3382 snprintf(tmp, sizeof(tmp), 3383 "%s", a); 3384 } 3385 } 3386 break; 3387 default: 3388 snprintf(tmp, sizeof(tmp), "?"); 3389 break; 3390 } 3391 3392 if (h->not) { 3393 snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp); 3394 expand_label_str(label, name, tmp_not); 3395 } else 3396 expand_label_str(label, name, tmp); 3397 } 3398} 3399 3400void 3401expand_label_port(const char *name, char *label, struct node_port *port) 3402{ 3403 char a1[6], a2[6], op[13] = ""; 3404 3405 if (strstr(label, name) != NULL) { 3406 snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0])); 3407 snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1])); 3408 if (!port->op) 3409 ; 3410 else if (port->op == PF_OP_IRG) 3411 snprintf(op, sizeof(op), "%s><%s", a1, a2); 3412 else if (port->op == PF_OP_XRG) 3413 snprintf(op, sizeof(op), "%s<>%s", a1, a2); 3414 else if (port->op == PF_OP_EQ) 3415 snprintf(op, sizeof(op), "%s", a1); 3416 else if (port->op == PF_OP_NE) 3417 snprintf(op, sizeof(op), "!=%s", a1); 3418 else if (port->op == PF_OP_LT) 3419 snprintf(op, sizeof(op), "<%s", a1); 3420 else if (port->op == PF_OP_LE) 3421 snprintf(op, sizeof(op), "<=%s", a1); 3422 else if (port->op == PF_OP_GT) 3423 snprintf(op, sizeof(op), ">%s", a1); 3424 else if (port->op == PF_OP_GE) 3425 snprintf(op, sizeof(op), ">=%s", a1); 3426 expand_label_str(label, name, op); 3427 } 3428} 3429 3430void 3431expand_label_proto(const char *name, char *label, u_int8_t proto) 3432{ 3433 struct protoent *pe; 3434 char n[4]; 3435 3436 if (strstr(label, name) != NULL) { 3437 pe = getprotobynumber(proto); 3438 if (pe != NULL) 3439 expand_label_str(label, name, pe->p_name); 3440 else { 3441 snprintf(n, sizeof(n), "%u", proto); 3442 expand_label_str(label, name, n); 3443 } 3444 } 3445} 3446 3447void 3448expand_label_nr(const char *name, char *label) 3449{ 3450 char n[11]; 3451 3452 if (strstr(label, name) != NULL) { 3453 snprintf(n, sizeof(n), "%u", pf->rule_nr); 3454 expand_label_str(label, name, n); 3455 } 3456} 3457 3458void 3459expand_label(char *label, const char *ifname, sa_family_t af, 3460 struct node_host *src_host, struct node_port *src_port, 3461 struct node_host *dst_host, struct node_port *dst_port, 3462 u_int8_t proto) 3463{ 3464 expand_label_if("$if", label, ifname); 3465 expand_label_addr("$srcaddr", label, af, src_host); 3466 expand_label_addr("$dstaddr", label, af, dst_host); 3467 expand_label_port("$srcport", label, src_port); 3468 expand_label_port("$dstport", label, dst_port); 3469 expand_label_proto("$proto", label, proto); 3470 expand_label_nr("$nr", label); 3471} 3472 3473int 3474expand_altq(struct pf_altq *a, struct node_if *interfaces, 3475 struct node_queue *nqueues, struct node_queue_bw bwspec, 3476 struct node_queue_opt *opts) 3477{ 3478 struct pf_altq pa, pb; 3479 char qname[PF_QNAME_SIZE]; 3480 struct node_queue *n; 3481 struct node_queue_bw bw; 3482 int errs = 0; 3483 3484 if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) { 3485 FREE_LIST(struct node_if, interfaces); 3486 FREE_LIST(struct node_queue, nqueues); 3487 return (0); 3488 } 3489 3490 LOOP_THROUGH(struct node_if, interface, interfaces, 3491 memcpy(&pa, a, sizeof(struct pf_altq)); 3492 if (strlcpy(pa.ifname, interface->ifname, 3493 sizeof(pa.ifname)) >= sizeof(pa.ifname)) 3494 errx(1, "expand_altq: strlcpy"); 3495 3496 if (interface->not) { 3497 yyerror("altq on ! <interface> is not supported"); 3498 errs++; 3499 } else { 3500 if (eval_pfaltq(pf, &pa, &bwspec, opts)) 3501 errs++; 3502 else 3503 if (pfctl_add_altq(pf, &pa)) 3504 errs++; 3505 3506 if (pf->opts & PF_OPT_VERBOSE) { 3507 print_altq(&pf->paltq->altq, 0, 3508 &bwspec, opts); 3509 if (nqueues && nqueues->tail) { 3510 printf("queue { "); 3511 LOOP_THROUGH(struct node_queue, queue, 3512 nqueues, 3513 printf("%s ", 3514 queue->queue); 3515 ); 3516 printf("}"); 3517 } 3518 printf("\n"); 3519 } 3520 3521 if (pa.scheduler == ALTQT_CBQ || 3522 pa.scheduler == ALTQT_HFSC) { 3523 /* now create a root queue */ 3524 memset(&pb, 0, sizeof(struct pf_altq)); 3525 if (strlcpy(qname, "root_", sizeof(qname)) >= 3526 sizeof(qname)) 3527 errx(1, "expand_altq: strlcpy"); 3528 if (strlcat(qname, interface->ifname, 3529 sizeof(qname)) >= sizeof(qname)) 3530 errx(1, "expand_altq: strlcat"); 3531 if (strlcpy(pb.qname, qname, 3532 sizeof(pb.qname)) >= sizeof(pb.qname)) 3533 errx(1, "expand_altq: strlcpy"); 3534 if (strlcpy(pb.ifname, interface->ifname, 3535 sizeof(pb.ifname)) >= sizeof(pb.ifname)) 3536 errx(1, "expand_altq: strlcpy"); 3537 pb.qlimit = pa.qlimit; 3538 pb.scheduler = pa.scheduler; 3539 bw.bw_absolute = pa.ifbandwidth; 3540 bw.bw_percent = 0; 3541 if (eval_pfqueue(pf, &pb, &bw, opts)) 3542 errs++; 3543 else 3544 if (pfctl_add_altq(pf, &pb)) 3545 errs++; 3546 } 3547 3548 LOOP_THROUGH(struct node_queue, queue, nqueues, 3549 n = calloc(1, sizeof(struct node_queue)); 3550 if (n == NULL) 3551 err(1, "expand_altq: calloc"); 3552 if (pa.scheduler == ALTQT_CBQ || 3553 pa.scheduler == ALTQT_HFSC) 3554 if (strlcpy(n->parent, qname, 3555 sizeof(n->parent)) >= 3556 sizeof(n->parent)) 3557 errx(1, "expand_altq: strlcpy"); 3558 if (strlcpy(n->queue, queue->queue, 3559 sizeof(n->queue)) >= sizeof(n->queue)) 3560 errx(1, "expand_altq: strlcpy"); 3561 if (strlcpy(n->ifname, interface->ifname, 3562 sizeof(n->ifname)) >= sizeof(n->ifname)) 3563 errx(1, "expand_altq: strlcpy"); 3564 n->scheduler = pa.scheduler; 3565 n->next = NULL; 3566 n->tail = n; 3567 if (queues == NULL) 3568 queues = n; 3569 else { 3570 queues->tail->next = n; 3571 queues->tail = n; 3572 } 3573 ); 3574 } 3575 ); 3576 FREE_LIST(struct node_if, interfaces); 3577 FREE_LIST(struct node_queue, nqueues); 3578 3579 return (errs); 3580} 3581 3582int 3583expand_queue(struct pf_altq *a, struct node_if *interfaces, 3584 struct node_queue *nqueues, struct node_queue_bw bwspec, 3585 struct node_queue_opt *opts) 3586{ 3587 struct node_queue *n, *nq; 3588 struct pf_altq pa; 3589 u_int8_t found = 0; 3590 u_int8_t errs = 0; 3591 3592 if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) { 3593 FREE_LIST(struct node_queue, nqueues); 3594 return (0); 3595 } 3596 3597 if (queues == NULL) { 3598 yyerror("queue %s has no parent", a->qname); 3599 FREE_LIST(struct node_queue, nqueues); 3600 return (1); 3601 } 3602 3603 LOOP_THROUGH(struct node_if, interface, interfaces, 3604 LOOP_THROUGH(struct node_queue, tqueue, queues, 3605 if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE) && 3606 (interface->ifname[0] == 0 || 3607 (!interface->not && !strncmp(interface->ifname, 3608 tqueue->ifname, IFNAMSIZ)) || 3609 (interface->not && strncmp(interface->ifname, 3610 tqueue->ifname, IFNAMSIZ)))) { 3611 /* found ourself in queues */ 3612 found++; 3613 3614 memcpy(&pa, a, sizeof(struct pf_altq)); 3615 3616 if (pa.scheduler != ALTQT_NONE && 3617 pa.scheduler != tqueue->scheduler) { 3618 yyerror("exactly one scheduler type " 3619 "per interface allowed"); 3620 return (1); 3621 } 3622 pa.scheduler = tqueue->scheduler; 3623 3624 /* scheduler dependent error checking */ 3625 switch (pa.scheduler) { 3626 case ALTQT_PRIQ: 3627 if (nqueues != NULL) { 3628 yyerror("priq queues cannot " 3629 "have child queues"); 3630 return (1); 3631 } 3632 if (bwspec.bw_absolute > 0 || 3633 bwspec.bw_percent < 100) { 3634 yyerror("priq doesn't take " 3635 "bandwidth"); 3636 return (1); 3637 } 3638 break; 3639 default: 3640 break; 3641 } 3642 3643 if (strlcpy(pa.ifname, tqueue->ifname, 3644 sizeof(pa.ifname)) >= sizeof(pa.ifname)) 3645 errx(1, "expand_queue: strlcpy"); 3646 if (strlcpy(pa.parent, tqueue->parent, 3647 sizeof(pa.parent)) >= sizeof(pa.parent)) 3648 errx(1, "expand_queue: strlcpy"); 3649 3650 if (eval_pfqueue(pf, &pa, &bwspec, opts)) 3651 errs++; 3652 else 3653 if (pfctl_add_altq(pf, &pa)) 3654 errs++; 3655 3656 for (nq = nqueues; nq != NULL; nq = nq->next) { 3657 if (!strcmp(a->qname, nq->queue)) { 3658 yyerror("queue cannot have " 3659 "itself as child"); 3660 errs++; 3661 continue; 3662 } 3663 n = calloc(1, 3664 sizeof(struct node_queue)); 3665 if (n == NULL) 3666 err(1, "expand_queue: calloc"); 3667 if (strlcpy(n->parent, a->qname, 3668 sizeof(n->parent)) >= 3669 sizeof(n->parent)) 3670 errx(1, "expand_queue strlcpy"); 3671 if (strlcpy(n->queue, nq->queue, 3672 sizeof(n->queue)) >= 3673 sizeof(n->queue)) 3674 errx(1, "expand_queue strlcpy"); 3675 if (strlcpy(n->ifname, tqueue->ifname, 3676 sizeof(n->ifname)) >= 3677 sizeof(n->ifname)) 3678 errx(1, "expand_queue strlcpy"); 3679 n->scheduler = tqueue->scheduler; 3680 n->next = NULL; 3681 n->tail = n; 3682 if (queues == NULL) 3683 queues = n; 3684 else { 3685 queues->tail->next = n; 3686 queues->tail = n; 3687 } 3688 } 3689 if ((pf->opts & PF_OPT_VERBOSE) && ( 3690 (found == 1 && interface->ifname[0] == 0) || 3691 (found > 0 && interface->ifname[0] != 0))) { 3692 print_queue(&pf->paltq->altq, 0, 3693 &bwspec, interface->ifname[0] != 0, 3694 opts); 3695 if (nqueues && nqueues->tail) { 3696 printf("{ "); 3697 LOOP_THROUGH(struct node_queue, 3698 queue, nqueues, 3699 printf("%s ", 3700 queue->queue); 3701 ); 3702 printf("}"); 3703 } 3704 printf("\n"); 3705 } 3706 } 3707 ); 3708 ); 3709 3710 FREE_LIST(struct node_queue, nqueues); 3711 FREE_LIST(struct node_if, interfaces); 3712 3713 if (!found) { 3714 yyerror("queue %s has no parent", a->qname); 3715 errs++; 3716 } 3717 3718 if (errs) 3719 return (1); 3720 else 3721 return (0); 3722} 3723 3724void 3725expand_rule(struct pf_rule *r, 3726 struct node_if *interfaces, struct node_host *rpool_hosts, 3727 struct node_proto *protos, struct node_os *src_oses, 3728 struct node_host *src_hosts, struct node_port *src_ports, 3729 struct node_host *dst_hosts, struct node_port *dst_ports, 3730 struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types) 3731{ 3732 sa_family_t af = r->af; 3733 int added = 0, error = 0; 3734 char ifname[IF_NAMESIZE]; 3735 char label[PF_RULE_LABEL_SIZE]; 3736 struct pf_pooladdr *pa; 3737 struct node_host *h; 3738 u_int8_t flags, flagset; 3739 3740 if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label)) 3741 errx(1, "expand_rule: strlcpy"); 3742 flags = r->flags; 3743 flagset = r->flagset; 3744 3745 LOOP_THROUGH(struct node_if, interface, interfaces, 3746 LOOP_THROUGH(struct node_proto, proto, protos, 3747 LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types, 3748 LOOP_THROUGH(struct node_host, src_host, src_hosts, 3749 LOOP_THROUGH(struct node_port, src_port, src_ports, 3750 LOOP_THROUGH(struct node_os, src_os, src_oses, 3751 LOOP_THROUGH(struct node_host, dst_host, dst_hosts, 3752 LOOP_THROUGH(struct node_port, dst_port, dst_ports, 3753 LOOP_THROUGH(struct node_uid, uid, uids, 3754 LOOP_THROUGH(struct node_gid, gid, gids, 3755 3756 r->af = af; 3757 /* for link-local IPv6 address, interface must match up */ 3758 if ((r->af && src_host->af && r->af != src_host->af) || 3759 (r->af && dst_host->af && r->af != dst_host->af) || 3760 (src_host->af && dst_host->af && 3761 src_host->af != dst_host->af) || 3762 (src_host->ifindex && dst_host->ifindex && 3763 src_host->ifindex != dst_host->ifindex) || 3764 (src_host->ifindex && if_nametoindex(interface->ifname) && 3765 src_host->ifindex != if_nametoindex(interface->ifname)) || 3766 (dst_host->ifindex && if_nametoindex(interface->ifname) && 3767 dst_host->ifindex != if_nametoindex(interface->ifname))) 3768 continue; 3769 if (!r->af && src_host->af) 3770 r->af = src_host->af; 3771 else if (!r->af && dst_host->af) 3772 r->af = dst_host->af; 3773 3774 if (if_indextoname(src_host->ifindex, ifname)) 3775 memcpy(r->ifname, ifname, sizeof(r->ifname)); 3776 else if (if_indextoname(dst_host->ifindex, ifname)) 3777 memcpy(r->ifname, ifname, sizeof(r->ifname)); 3778 else 3779 memcpy(r->ifname, interface->ifname, sizeof(r->ifname)); 3780 3781 if (strlcpy(r->label, label, sizeof(r->label)) >= 3782 sizeof(r->label)) 3783 errx(1, "expand_rule: strlcpy"); 3784 expand_label(r->label, r->ifname, r->af, src_host, src_port, 3785 dst_host, dst_port, proto->proto); 3786 3787 error += check_netmask(src_host, r->af); 3788 error += check_netmask(dst_host, r->af); 3789 3790 r->ifnot = interface->not; 3791 r->proto = proto->proto; 3792 r->src.addr = src_host->addr; 3793 r->src.not = src_host->not; 3794 r->src.port[0] = src_port->port[0]; 3795 r->src.port[1] = src_port->port[1]; 3796 r->src.port_op = src_port->op; 3797 r->dst.addr = dst_host->addr; 3798 r->dst.not = dst_host->not; 3799 r->dst.port[0] = dst_port->port[0]; 3800 r->dst.port[1] = dst_port->port[1]; 3801 r->dst.port_op = dst_port->op; 3802 r->uid.op = uid->op; 3803 r->uid.uid[0] = uid->uid[0]; 3804 r->uid.uid[1] = uid->uid[1]; 3805 r->gid.op = gid->op; 3806 r->gid.gid[0] = gid->gid[0]; 3807 r->gid.gid[1] = gid->gid[1]; 3808 r->type = icmp_type->type; 3809 r->code = icmp_type->code; 3810 3811 if (r->proto && r->proto != IPPROTO_TCP) { 3812 r->flags = 0; 3813 r->flagset = 0; 3814 } else { 3815 r->flags = flags; 3816 r->flagset = flagset; 3817 } 3818 if (icmp_type->proto && r->proto != icmp_type->proto) { 3819 yyerror("icmp-type mismatch"); 3820 error++; 3821 } 3822 3823 if (src_os && src_os->os) { 3824 r->os_fingerprint = pfctl_get_fingerprint(src_os->os); 3825 if ((pf->opts & PF_OPT_VERBOSE2) && 3826 r->os_fingerprint == PF_OSFP_NOMATCH) 3827 fprintf(stderr, 3828 "warning: unknown '%s' OS fingerprint\n", 3829 src_os->os); 3830 } else { 3831 r->os_fingerprint = PF_OSFP_ANY; 3832 } 3833 3834 TAILQ_INIT(&r->rpool.list); 3835 for (h = rpool_hosts; h != NULL; h = h->next) { 3836 pa = calloc(1, sizeof(struct pf_pooladdr)); 3837 if (pa == NULL) 3838 err(1, "expand_rule: calloc"); 3839 pa->addr = h->addr; 3840 if (h->ifname != NULL) { 3841 if (strlcpy(pa->ifname, h->ifname, 3842 sizeof(pa->ifname)) >= 3843 sizeof(pa->ifname)) 3844 errx(1, "expand_rule: strlcpy"); 3845 } else 3846 pa->ifname[0] = 0; 3847 TAILQ_INSERT_TAIL(&r->rpool.list, pa, entries); 3848 } 3849 3850 if (rule_consistent(r) < 0 || error) 3851 yyerror("skipping rule due to errors"); 3852 else { 3853 r->nr = pf->rule_nr++; 3854 pfctl_add_rule(pf, r); 3855 added++; 3856 } 3857 3858 )))))))))); 3859 3860 FREE_LIST(struct node_if, interfaces); 3861 FREE_LIST(struct node_proto, protos); 3862 FREE_LIST(struct node_host, src_hosts); 3863 FREE_LIST(struct node_port, src_ports); 3864 FREE_LIST(struct node_os, src_oses); 3865 FREE_LIST(struct node_host, dst_hosts); 3866 FREE_LIST(struct node_port, dst_ports); 3867 FREE_LIST(struct node_uid, uids); 3868 FREE_LIST(struct node_gid, gids); 3869 FREE_LIST(struct node_icmp, icmp_types); 3870 FREE_LIST(struct node_host, rpool_hosts); 3871 3872 if (!added) 3873 yyerror("rule expands to no valid combination"); 3874} 3875 3876#undef FREE_LIST 3877#undef LOOP_THROUGH 3878 3879int 3880check_rulestate(int desired_state) 3881{ 3882 if (require_order && (rulestate > desired_state)) { 3883 yyerror("Rules must be in order: options, normalization, " 3884 "queueing, translation, filtering"); 3885 return (1); 3886 } 3887 rulestate = desired_state; 3888 return (0); 3889} 3890 3891int 3892kw_cmp(const void *k, const void *e) 3893{ 3894 return (strcmp(k, ((const struct keywords *)e)->k_name)); 3895} 3896 3897int 3898lookup(char *s) 3899{ 3900 /* this has to be sorted always */ 3901 static const struct keywords keywords[] = { 3902 { "all", ALL}, 3903 { "allow-opts", ALLOWOPTS}, 3904 { "altq", ALTQ}, 3905 { "anchor", ANCHOR}, 3906 { "antispoof", ANTISPOOF}, 3907 { "any", ANY}, 3908 { "bandwidth", BANDWIDTH}, 3909 { "binat", BINAT}, 3910 { "binat-anchor", BINATANCHOR}, 3911 { "bitmask", BITMASK}, 3912 { "block", BLOCK}, 3913 { "block-policy", BLOCKPOLICY}, 3914 { "cbq", CBQ}, 3915 { "code", CODE}, 3916 { "crop", FRAGCROP}, 3917 { "drop", DROP}, 3918 { "drop-ovl", FRAGDROP}, 3919 { "dup-to", DUPTO}, 3920 { "fastroute", FASTROUTE}, 3921 { "file", FILENAME}, 3922 { "fingerprints", FINGERPRINTS}, 3923 { "flags", FLAGS}, 3924 { "for", FOR}, 3925 { "fragment", FRAGMENT}, 3926 { "from", FROM}, 3927 { "group", GROUP}, 3928 { "hfsc", HFSC}, 3929 { "icmp-type", ICMPTYPE}, 3930 { "icmp6-type", ICMP6TYPE}, 3931 { "in", IN}, 3932 { "inet", INET}, 3933 { "inet6", INET6}, 3934 { "keep", KEEP}, 3935 { "label", LABEL}, 3936 { "limit", LIMIT}, 3937 { "linkshare", LINKSHARE}, 3938 { "load", LOAD}, 3939 { "log", LOG}, 3940 { "log-all", LOGALL}, 3941 { "loginterface", LOGINTERFACE}, 3942 { "max", MAXIMUM}, 3943 { "max-mss", MAXMSS}, 3944 { "min-ttl", MINTTL}, 3945 { "modulate", MODULATE}, 3946 { "nat", NAT}, 3947 { "nat-anchor", NATANCHOR}, 3948 { "no", NO}, 3949 { "no-df", NODF}, 3950 { "no-route", NOROUTE}, 3951 { "on", ON}, 3952 { "optimization", OPTIMIZATION}, 3953 { "os", OS}, 3954 { "out", OUT}, 3955 { "pass", PASS}, 3956 { "port", PORT}, 3957 { "priority", PRIORITY}, 3958 { "priq", PRIQ}, 3959 { "proto", PROTO}, 3960 { "qlimit", QLIMIT}, 3961 { "queue", QUEUE}, 3962 { "quick", QUICK}, 3963 { "random", RANDOM}, 3964 { "random-id", RANDOMID}, 3965 { "rdr", RDR}, 3966 { "rdr-anchor", RDRANCHOR}, 3967 { "realtime", REALTIME}, 3968 { "reassemble", REASSEMBLE}, 3969 { "reply-to", REPLYTO}, 3970 { "require-order", REQUIREORDER}, 3971 { "return", RETURN}, 3972 { "return-icmp", RETURNICMP}, 3973 { "return-icmp6", RETURNICMP6}, 3974 { "return-rst", RETURNRST}, 3975 { "round-robin", ROUNDROBIN}, 3976 { "route-to", ROUTETO}, 3977 { "scrub", SCRUB}, 3978 { "set", SET}, 3979 { "source-hash", SOURCEHASH}, 3980 { "state", STATE}, 3981 { "static-port", STATICPORT}, 3982 { "synproxy", SYNPROXY}, 3983 { "table", TABLE}, 3984 { "tag", TAG}, 3985 { "tagged", TAGGED}, 3986 { "tbrsize", TBRSIZE}, 3987 { "timeout", TIMEOUT}, 3988 { "to", TO}, 3989 { "tos", TOS}, 3990 { "ttl", TTL}, 3991 { "upperlimit", UPPERLIMIT}, 3992 { "user", USER}, 3993 }; 3994 const struct keywords *p; 3995 3996 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 3997 sizeof(keywords[0]), kw_cmp); 3998 3999 if (p) { 4000 if (debug > 1) 4001 fprintf(stderr, "%s: %d\n", s, p->k_val); 4002 return (p->k_val); 4003 } else { 4004 if (debug > 1) 4005 fprintf(stderr, "string: %s\n", s); 4006 return (STRING); 4007 } 4008} 4009 4010#define MAXPUSHBACK 128 4011 4012char *parsebuf; 4013int parseindex; 4014char pushback_buffer[MAXPUSHBACK]; 4015int pushback_index = 0; 4016 4017int 4018lgetc(FILE *f) 4019{ 4020 int c, next; 4021 4022 if (parsebuf) { 4023 /* Read character from the parsebuffer instead of input. */ 4024 if (parseindex >= 0) { 4025 c = parsebuf[parseindex++]; 4026 if (c != '\0') 4027 return (c); 4028 parsebuf = NULL; 4029 } else 4030 parseindex++; 4031 } 4032 4033 if (pushback_index) 4034 return (pushback_buffer[--pushback_index]); 4035 4036 while ((c = getc(f)) == '\\') { 4037 next = getc(f); 4038 if (next != '\n') { 4039 if (isspace(next)) 4040 yyerror("whitespace after \\"); 4041 ungetc(next, f); 4042 break; 4043 } 4044 yylval.lineno = lineno; 4045 lineno++; 4046 } 4047 if (c == '\t' || c == ' ') { 4048 /* Compress blanks to a single space. */ 4049 do { 4050 c = getc(f); 4051 } while (c == '\t' || c == ' '); 4052 ungetc(c, f); 4053 c = ' '; 4054 } 4055 4056 return (c); 4057} 4058 4059int 4060lungetc(int c) 4061{ 4062 if (c == EOF) 4063 return (EOF); 4064 if (parsebuf) { 4065 parseindex--; 4066 if (parseindex >= 0) 4067 return (c); 4068 } 4069 if (pushback_index < MAXPUSHBACK-1) 4070 return (pushback_buffer[pushback_index++] = c); 4071 else 4072 return (EOF); 4073} 4074 4075int 4076findeol(void) 4077{ 4078 int c; 4079 4080 parsebuf = NULL; 4081 pushback_index = 0; 4082 4083 /* skip to either EOF or the first real EOL */ 4084 while (1) { 4085 c = lgetc(fin); 4086 if (c == '\n') { 4087 lineno++; 4088 break; 4089 } 4090 if (c == EOF) 4091 break; 4092 } 4093 return (ERROR); 4094} 4095 4096int 4097yylex(void) 4098{ 4099 char buf[8096]; 4100 char *p, *val; 4101 int endc, c, next; 4102 int token; 4103 4104top: 4105 p = buf; 4106 while ((c = lgetc(fin)) == ' ') 4107 ; /* nothing */ 4108 4109 yylval.lineno = lineno; 4110 if (c == '#') 4111 while ((c = lgetc(fin)) != '\n' && c != EOF) 4112 ; /* nothing */ 4113 if (c == '$' && parsebuf == NULL) { 4114 while (1) { 4115 if ((c = lgetc(fin)) == EOF) 4116 return (0); 4117 4118 if (p + 1 >= buf + sizeof(buf) - 1) { 4119 yyerror("string too long"); 4120 return (findeol()); 4121 } 4122 if (isalnum(c) || c == '_') { 4123 *p++ = (char)c; 4124 continue; 4125 } 4126 *p = '\0'; 4127 lungetc(c); 4128 break; 4129 } 4130 val = symget(buf); 4131 if (val == NULL) { 4132 yyerror("macro '%s' not defined", buf); 4133 return (findeol()); 4134 } 4135 parsebuf = val; 4136 parseindex = 0; 4137 goto top; 4138 } 4139 4140 switch (c) { 4141 case '\'': 4142 case '"': 4143 endc = c; 4144 while (1) { 4145 if ((c = lgetc(fin)) == EOF) 4146 return (0); 4147 if (c == endc) { 4148 *p = '\0'; 4149 break; 4150 } 4151 if (c == '\n') { 4152 lineno++; 4153 continue; 4154 } 4155 if (p + 1 >= buf + sizeof(buf) - 1) { 4156 yyerror("string too long"); 4157 return (findeol()); 4158 } 4159 *p++ = (char)c; 4160 } 4161 yylval.v.string = strdup(buf); 4162 if (yylval.v.string == NULL) 4163 err(1, "yylex: strdup"); 4164 return (STRING); 4165 case '<': 4166 next = lgetc(fin); 4167 if (next == '>') { 4168 yylval.v.i = PF_OP_XRG; 4169 return (PORTBINARY); 4170 } 4171 lungetc(next); 4172 break; 4173 case '>': 4174 next = lgetc(fin); 4175 if (next == '<') { 4176 yylval.v.i = PF_OP_IRG; 4177 return (PORTBINARY); 4178 } 4179 lungetc(next); 4180 break; 4181 case '-': 4182 next = lgetc(fin); 4183 if (next == '>') 4184 return (ARROW); 4185 lungetc(next); 4186 break; 4187 } 4188 4189#define allowed_in_string(x) \ 4190 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 4191 x != '{' && x != '}' && x != '<' && x != '>' && \ 4192 x != '!' && x != '=' && x != '/' && x != '#' && \ 4193 x != ',')) 4194 4195 if (isalnum(c) || c == ':' || c == '_') { 4196 do { 4197 *p++ = c; 4198 if ((unsigned)(p-buf) >= sizeof(buf)) { 4199 yyerror("string too long"); 4200 return (findeol()); 4201 } 4202 } while ((c = lgetc(fin)) != EOF && (allowed_in_string(c))); 4203 lungetc(c); 4204 *p = '\0'; 4205 token = lookup(buf); 4206 yylval.v.string = strdup(buf); 4207 if (yylval.v.string == NULL) 4208 err(1, "yylex: strdup"); 4209 return (token); 4210 } 4211 if (c == '\n') { 4212 yylval.lineno = lineno; 4213 lineno++; 4214 } 4215 if (c == EOF) 4216 return (0); 4217 return (c); 4218} 4219 4220int 4221parse_rules(FILE *input, struct pfctl *xpf) 4222{ 4223 struct sym *sym; 4224 4225 fin = input; 4226 pf = xpf; 4227 lineno = 1; 4228 errors = 0; 4229 rulestate = PFCTL_STATE_NONE; 4230 returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 4231 returnicmp6default = 4232 (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT; 4233 blockpolicy = PFRULE_DROP; 4234 require_order = 1; 4235 4236 yyparse(); 4237 4238 /* Free macros and check which have not been used. */ 4239 TAILQ_FOREACH(sym, &symhead, entries) { 4240 if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used) 4241 fprintf(stderr, "warning: macro '%s' not " 4242 "used\n", sym->nam); 4243 free(sym->nam); 4244 free(sym->val); 4245 TAILQ_REMOVE(&symhead, sym, entries); 4246 } 4247 4248 return (errors ? -1 : 0); 4249} 4250 4251/* 4252 * Over-designed efficiency is a French and German concept, so how about 4253 * we wait until they discover this ugliness and make it all fancy. 4254 */ 4255int 4256symset(const char *nam, const char *val, int persist) 4257{ 4258 struct sym *sym; 4259 4260 for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam); 4261 sym = TAILQ_NEXT(sym, entries)) 4262 ; /* nothing */ 4263 4264 if (sym != NULL) { 4265 if (sym->persist == 1) 4266 return (0); 4267 else { 4268 free(sym->nam); 4269 free(sym->val); 4270 TAILQ_REMOVE(&symhead, sym, entries); 4271 free(sym); 4272 } 4273 } 4274 if ((sym = calloc(1, sizeof(*sym))) == NULL) 4275 return (-1); 4276 4277 sym->nam = strdup(nam); 4278 if (sym->nam == NULL) { 4279 free(sym); 4280 return (-1); 4281 } 4282 sym->val = strdup(val); 4283 if (sym->val == NULL) { 4284 free(sym->nam); 4285 free(sym); 4286 return (-1); 4287 } 4288 sym->used = 0; 4289 sym->persist = persist; 4290 TAILQ_INSERT_TAIL(&symhead, sym, entries); 4291 return (0); 4292} 4293 4294int 4295pfctl_cmdline_symset(char *s) 4296{ 4297 char *sym, *val; 4298 int ret; 4299 4300 if ((val = strrchr(s, '=')) == NULL) 4301 return (-1); 4302 4303 if ((sym = malloc(strlen(s) - strlen(val) + 1)) == NULL) 4304 err(1, "pfctl_cmdline_symset: malloc"); 4305 4306 strlcpy(sym, s, strlen(s) - strlen(val) + 1); 4307 4308 ret = symset(sym, val + 1, 1); 4309 free(sym); 4310 4311 return (ret); 4312} 4313 4314char * 4315symget(const char *nam) 4316{ 4317 struct sym *sym; 4318 4319 TAILQ_FOREACH(sym, &symhead, entries) 4320 if (strcmp(nam, sym->nam) == 0) { 4321 sym->used = 1; 4322 return (sym->val); 4323 } 4324 return (NULL); 4325} 4326 4327void 4328decide_address_family(struct node_host *n, sa_family_t *af) 4329{ 4330 sa_family_t target_af = 0; 4331 4332 while (!*af && n != NULL) { 4333 if (n->af) { 4334 if (target_af == 0) 4335 target_af = n->af; 4336 if (target_af != n->af) 4337 return; 4338 } 4339 n = n->next; 4340 } 4341 if (!*af && target_af) 4342 *af = target_af; 4343} 4344 4345void 4346remove_invalid_hosts(struct node_host **nh, sa_family_t *af) 4347{ 4348 struct node_host *n = *nh, *prev = NULL; 4349 4350 while (n != NULL) { 4351 if (*af && n->af && n->af != *af) { 4352 /* unlink and free n */ 4353 struct node_host *next = n->next; 4354 4355 /* adjust tail pointer */ 4356 if (n == (*nh)->tail) 4357 (*nh)->tail = prev; 4358 /* adjust previous node's next pointer */ 4359 if (prev == NULL) 4360 *nh = next; 4361 else 4362 prev->next = next; 4363 /* free node */ 4364 if (n->ifname != NULL) 4365 free(n->ifname); 4366 free(n); 4367 n = next; 4368 } else { 4369 if (n->af && !*af) 4370 *af = n->af; 4371 prev = n; 4372 n = n->next; 4373 } 4374 } 4375} 4376 4377int 4378invalid_redirect(struct node_host *nh, sa_family_t af) 4379{ 4380 if (!af) { 4381 struct node_host *n; 4382 4383 /* only tables are ok without an address family */ 4384 for (n = nh; n != NULL; n = n->next) { 4385 if (n->addr.type != PF_ADDR_TABLE) { 4386 yyerror("address family not given and " 4387 "translation address expands to multiple " 4388 "address families"); 4389 return (1); 4390 } 4391 } 4392 } 4393 if (nh == NULL) { 4394 yyerror("no translation address with matching address family " 4395 "found."); 4396 return (1); 4397 } 4398 return (0); 4399} 4400 4401int 4402atoul(char *s, u_long *ulvalp) 4403{ 4404 u_long ulval; 4405 char *ep; 4406 4407 errno = 0; 4408 ulval = strtoul(s, &ep, 0); 4409 if (s[0] == '\0' || *ep != '\0') 4410 return (-1); 4411 if (errno == ERANGE && ulval == ULONG_MAX) 4412 return (-1); 4413 *ulvalp = ulval; 4414 return (0); 4415} 4416 4417int 4418getservice(char *n) 4419{ 4420 struct servent *s; 4421 u_long ulval; 4422 4423 if (atoul(n, &ulval) == 0) { 4424 if (ulval > 65535) { 4425 yyerror("illegal port value %d", ulval); 4426 return (-1); 4427 } 4428 return (htons(ulval)); 4429 } else { 4430 s = getservbyname(n, "tcp"); 4431 if (s == NULL) 4432 s = getservbyname(n, "udp"); 4433 if (s == NULL) { 4434 yyerror("unknown port %s", n); 4435 return (-1); 4436 } 4437 return (s->s_port); 4438 } 4439} 4440 4441int 4442rule_label(struct pf_rule *r, char *s) 4443{ 4444 if (s) { 4445 if (strlcpy(r->label, s, sizeof(r->label)) >= 4446 sizeof(r->label)) { 4447 yyerror("rule label too long (max %d chars)", 4448 sizeof(r->label)-1); 4449 return (-1); 4450 } 4451 } 4452 return (0); 4453} 4454 4455u_int16_t 4456parseicmpspec(char *w, sa_family_t af) 4457{ 4458 const struct icmpcodeent *p; 4459 u_long ulval; 4460 u_int8_t icmptype; 4461 4462 if (af == AF_INET) 4463 icmptype = returnicmpdefault >> 8; 4464 else 4465 icmptype = returnicmp6default >> 8; 4466 4467 if (atoul(w, &ulval) == -1) { 4468 if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) { 4469 yyerror("unknown icmp code %s", w); 4470 return (0); 4471 } 4472 ulval = p->code; 4473 } 4474 if (ulval > 255) { 4475 yyerror("invalid icmp code %ld", ulval); 4476 return (0); 4477 } 4478 return (icmptype << 8 | ulval); 4479} 4480 4481int 4482pfctl_load_anchors(int dev, int opts) 4483{ 4484 struct loadanchors *la; 4485 4486 TAILQ_FOREACH(la, &loadanchorshead, entries) { 4487 if (opts & PF_OPT_VERBOSE) 4488 fprintf(stderr, "\nLoading anchor %s:%s from %s\n", 4489 la->anchorname, la->rulesetname, la->filename); 4490 if (pfctl_rules(dev, la->filename, opts, la->anchorname, 4491 la->rulesetname) == -1) 4492 return (-1); 4493 } 4494 4495 return (0); 4496} 4497 4498