summaryrefslogtreecommitdiffstats
path: root/contrib/pf/pfctl/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/pf/pfctl/parse.y')
-rw-r--r--contrib/pf/pfctl/parse.y644
1 files changed, 457 insertions, 187 deletions
diff --git a/contrib/pf/pfctl/parse.y b/contrib/pf/pfctl/parse.y
index 2c82bcd..a06a5de 100644
--- a/contrib/pf/pfctl/parse.y
+++ b/contrib/pf/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.449 2004/03/20 23:20:20 david Exp $ */
+/* $OpenBSD: parse.y,v 1.482 2005/03/07 13:20:03 henning Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <string.h>
#include <ctype.h>
+#include <math.h>
#include <err.h>
#include <limits.h>
#include <pwd.h>
@@ -124,8 +125,10 @@ struct node_icmp {
};
enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK,
- PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_NODES,
- PF_STATE_OPT_STATELOCK, PF_STATE_OPT_TIMEOUT };
+ PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN,
+ PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES,
+ PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK,
+ PF_STATE_OPT_TIMEOUT };
enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE };
@@ -134,6 +137,15 @@ struct node_state_opt {
union {
u_int32_t max_states;
u_int32_t max_src_states;
+ u_int32_t max_src_conn;
+ struct {
+ u_int32_t limit;
+ u_int32_t seconds;
+ } max_src_conn_rate;
+ struct {
+ u_int8_t flush;
+ char tblname[PF_TABLE_NAME_SIZE];
+ } overload;
u_int32_t max_src_nodes;
u_int8_t src_track;
u_int32_t statelock;
@@ -182,6 +194,7 @@ struct filter_opts {
} flags;
struct node_icmp *icmpspec;
u_int32_t tos;
+ u_int32_t prob;
struct {
int action;
struct node_state_opt *options;
@@ -268,11 +281,13 @@ void expand_label(char *, size_t, const char *, u_int8_t, struct node_host *,
void expand_rule(struct pf_rule *, struct node_if *, struct node_host *,
struct node_proto *, struct node_os*, struct node_host *,
struct node_port *, struct node_host *, struct node_port *,
- struct node_uid *, struct node_gid *, struct node_icmp *);
+ struct node_uid *, struct node_gid *, struct node_icmp *,
+ const char *);
int expand_altq(struct pf_altq *, struct node_if *, struct node_queue *,
struct node_queue_bw bwspec, struct node_queue_opt *);
int expand_queue(struct pf_altq *, struct node_if *, struct node_queue *,
struct node_queue_bw, struct node_queue_opt *);
+int expand_skip_interface(struct node_if *);
int check_rulestate(int);
int kw_cmp(const void *, const void *);
@@ -309,7 +324,6 @@ TAILQ_HEAD(loadanchorshead, loadanchors)
struct loadanchors {
TAILQ_ENTRY(loadanchors) entries;
char *anchorname;
- char *rulesetname;
char *filename;
};
@@ -362,6 +376,10 @@ typedef struct {
u_int8_t log;
u_int8_t quick;
} logquick;
+ struct {
+ int neg;
+ char *name;
+ } tagged;
struct pf_poolhashkey *hashkey;
struct node_queue *queue;
struct node_queue_opt queue_options;
@@ -378,18 +396,6 @@ typedef struct {
int lineno;
} YYSTYPE;
-#define PREPARE_ANCHOR_RULE(r, a) \
- do { \
- memset(&(r), 0, sizeof(r)); \
- if (strlcpy(r.anchorname, (a), \
- sizeof(r.anchorname)) >= \
- sizeof(r.anchorname)) { \
- yyerror("anchor name '%s' too long", \
- (a)); \
- YYERROR; \
- } \
- } while (0)
-
#define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \
(!((addr).iflags & PFI_AFLAG_NOALIAS) || \
!isdigit((addr).v.ifname[strlen((addr).v.ifname)-1])))
@@ -403,22 +409,24 @@ typedef struct {
%token NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
%token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
-%token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG HOSTID
+%token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
%token ANTISPOOF FOR
-%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT
+%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
%token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
%token QUEUE PRIORITY QLIMIT
%token LOAD
%token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
-%token TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY
+%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH
+%token TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY ROUTE
%token <v.string> STRING
%token <v.i> PORTBINARY
%type <v.interface> interface if_list if_item_not if_item
%type <v.number> number icmptype icmp6type uid gid
%type <v.number> tos not yesno natpass
-%type <v.i> no dir log af fragcache sourcetrack
+%type <v.i> no dir log af fragcache sourcetrack flush
%type <v.i> unaryop statelock
-%type <v.b> action nataction flags flag blockspec
+%type <v.b> action nataction scrubaction
+%type <v.b> flags flag blockspec
%type <v.range> port rport
%type <v.hashkey> hashkey
%type <v.proto> proto proto_list proto_item
@@ -440,7 +448,7 @@ typedef struct {
%type <v.keep_state> keep
%type <v.state_opt> state_opt_spec state_opt_list state_opt_item
%type <v.logquick> logquick
-%type <v.interface> antispoof_ifspc antispoof_iflst
+%type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if
%type <v.qassign> qname
%type <v.queue> qassign qassign_list qassign_item
%type <v.queue_options> scheduler
@@ -454,6 +462,7 @@ typedef struct {
%type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l
%type <v.table_opts> table_opts table_opt table_opts_l
%type <v.pool_opts> pool_opts pool_opt pool_opts_l
+%type <v.tagged> tagged
%%
ruleset : /* empty */
@@ -494,11 +503,6 @@ option : SET OPTIMIZATION STRING {
free($3);
YYERROR;
}
- if ((ifa_exists($3, 0) == NULL) && strcmp($3, "none")) {
- yyerror("interface %s doesn't exist", $3);
- free($3);
- YYERROR;
- }
if (pfctl_set_logif(pf, $3) != 0) {
yyerror("error setting loginterface %s", $3);
free($3);
@@ -512,7 +516,7 @@ option : SET OPTIMIZATION STRING {
YYERROR;
}
if (pfctl_set_hostid(pf, $3) != 0) {
- yyerror("error setting loginterface %08x", $3);
+ yyerror("error setting hostid %08x", $3);
YYERROR;
}
}
@@ -538,15 +542,19 @@ option : SET OPTIMIZATION STRING {
}
| SET FINGERPRINTS STRING {
if (pf->opts & PF_OPT_VERBOSE)
- printf("fingerprints %s\n", $3);
+ printf("set fingerprints %s\n", $3);
if (check_rulestate(PFCTL_STATE_OPTION)) {
free($3);
YYERROR;
}
- if (pfctl_file_fingerprints(pf->dev, pf->opts, $3)) {
- yyerror("error loading fingerprints %s", $3);
- free($3);
- YYERROR;
+ if (!pf->anchor[0]) {
+ if (pfctl_file_fingerprints(pf->dev,
+ pf->opts, $3)) {
+ yyerror("error loading "
+ "fingerprints %s", $3);
+ free($3);
+ YYERROR;
+ }
}
free($3);
}
@@ -578,6 +586,12 @@ option : SET OPTIMIZATION STRING {
}
free($3);
}
+ | SET SKIP interface {
+ if (expand_skip_interface($3) != 0) {
+ yyerror("error setting skip interface(s)");
+ YYERROR;
+ }
+ }
;
string : string STRING {
@@ -607,9 +621,10 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
YYERROR;
}
- PREPARE_ANCHOR_RULE(r, $2);
+ memset(&r, 0, sizeof(r));
r.direction = $3;
r.af = $5;
+ r.prob = $8.prob;
if ($8.match_tag)
if (strlcpy(r.match_tagname, $8.match_tag,
@@ -625,7 +640,8 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
expand_rule(&r, $4, NULL, $6, $7.src_os,
$7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
- 0, 0, 0);
+ 0, 0, 0, $2);
+ free($2);
}
| NATANCHOR string interface af proto fromto {
struct pf_rule r;
@@ -635,8 +651,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
YYERROR;
}
- PREPARE_ANCHOR_RULE(r, $2);
- free($2);
+ memset(&r, 0, sizeof(r));
r.action = PF_NAT;
r.af = $4;
@@ -645,7 +660,8 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
expand_rule(&r, $3, NULL, $5, $6.src_os,
$6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
- 0, 0, 0);
+ 0, 0, 0, $2);
+ free($2);
}
| RDRANCHOR string interface af proto fromto {
struct pf_rule r;
@@ -655,8 +671,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
YYERROR;
}
- PREPARE_ANCHOR_RULE(r, $2);
- free($2);
+ memset(&r, 0, sizeof(r));
r.action = PF_RDR;
r.af = $4;
@@ -686,7 +701,8 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
expand_rule(&r, $3, NULL, $5, $6.src_os,
$6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
- 0, 0, 0);
+ 0, 0, 0, $2);
+ free($2);
}
| BINATANCHOR string interface af proto fromto {
struct pf_rule r;
@@ -696,8 +712,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
YYERROR;
}
- PREPARE_ANCHOR_RULE(r, $2);
- free($2);
+ memset(&r, 0, sizeof(r));
r.action = PF_BINAT;
r.af = $4;
if ($5 != NULL) {
@@ -720,39 +735,24 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
decide_address_family($6.src.host, &r.af);
decide_address_family($6.dst.host, &r.af);
- pfctl_add_rule(pf, &r);
+ pfctl_add_rule(pf, &r, $2);
+ free($2);
}
;
loadrule : LOAD ANCHOR string FROM string {
- char *t;
struct loadanchors *loadanchor;
- t = strsep(&$3, ":");
- if (*t == '\0' || $3 == NULL || *$3 == '\0') {
- yyerror("anchor '%s' invalid\n", $3);
- free(t);
- YYERROR;
- }
- if (strlen(t) >= PF_ANCHOR_NAME_SIZE) {
+ if (strlen($3) >= MAXPATHLEN) {
yyerror("anchorname %s too long, max %u\n",
- t, PF_ANCHOR_NAME_SIZE - 1);
- free(t);
- YYERROR;
- }
- if (strlen($3) >= PF_RULESET_NAME_SIZE) {
- yyerror("rulesetname %s too long, max %u\n",
- $3, PF_RULESET_NAME_SIZE - 1);
- free(t);
+ $3, MAXPATHLEN - 1);
+ free($3);
YYERROR;
}
-
loadanchor = calloc(1, sizeof(struct loadanchors));
if (loadanchor == NULL)
err(1, "loadrule: calloc");
- if ((loadanchor->anchorname = strdup(t)) == NULL)
- err(1, "loadrule: strdup");
- if ((loadanchor->rulesetname = strdup($3)) == NULL)
+ if ((loadanchor->anchorname = strdup($3)) == NULL)
err(1, "loadrule: strdup");
if ((loadanchor->filename = strdup($5)) == NULL)
err(1, "loadrule: strdup");
@@ -760,11 +760,20 @@ loadrule : LOAD ANCHOR string FROM string {
TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor,
entries);
- free(t); /* not $3 */
+ free($3);
free($5);
};
-scrubrule : SCRUB dir logquick interface af proto fromto scrub_opts
+scrubaction : no SCRUB {
+ $$.b2 = $$.w = 0;
+ if ($1)
+ $$.b1 = PF_NOSCRUB;
+ else
+ $$.b1 = PF_SCRUB;
+ }
+ ;
+
+scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts
{
struct pf_rule r;
@@ -773,7 +782,7 @@ scrubrule : SCRUB dir logquick interface af proto fromto scrub_opts
memset(&r, 0, sizeof(r));
- r.action = PF_SCRUB;
+ r.action = $1.b1;
r.direction = $2;
r.log = $3.log;
@@ -804,7 +813,7 @@ scrubrule : SCRUB dir logquick interface af proto fromto scrub_opts
expand_rule(&r, $4, NULL, $6, $7.src_os,
$7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, "");
}
;
@@ -864,6 +873,8 @@ scrub_opt : NODF {
}
| REASSEMBLE STRING {
if (strcasecmp($2, "tcp") != 0) {
+ yyerror("scrub reassemble supports only tcp, "
+ "not '%s'", $2);
free($2);
YYERROR;
}
@@ -890,7 +901,7 @@ fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ }
antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
struct pf_rule r;
- struct node_host *h = NULL;
+ struct node_host *h = NULL, *hh;
struct node_if *i, *j;
if (check_rulestate(PFCTL_STATE_FILTER))
@@ -916,11 +927,35 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
YYERROR;
}
j->not = 1;
- h = ifa_lookup(j->ifname, PFI_AFLAG_NETWORK);
+ if (i->dynamic) {
+ h = calloc(1, sizeof(*h));
+ if (h == NULL)
+ err(1, "address: calloc");
+ h->addr.type = PF_ADDR_DYNIFTL;
+ set_ipmask(h, 128);
+ if (strlcpy(h->addr.v.ifname, i->ifname,
+ sizeof(h->addr.v.ifname)) >=
+ sizeof(h->addr.v.ifname)) {
+ free(h);
+ yyerror(
+ "interface name too long");
+ YYERROR;
+ }
+ hh = malloc(sizeof(*hh));
+ if (hh == NULL)
+ err(1, "address: malloc");
+ bcopy(h, hh, sizeof(*hh));
+ h->addr.iflags = PFI_AFLAG_NETWORK;
+ } else {
+ h = ifa_lookup(j->ifname,
+ PFI_AFLAG_NETWORK);
+ hh = NULL;
+ }
if (h != NULL)
expand_rule(&r, j, NULL, NULL, NULL, h,
- NULL, NULL, NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, "");
if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
bzero(&r, sizeof(r));
@@ -932,29 +967,40 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
r.af = $4;
if (rule_label(&r, $5.label))
YYERROR;
- h = ifa_lookup(i->ifname, 0);
+ if (hh != NULL)
+ h = hh;
+ else
+ h = ifa_lookup(i->ifname, 0);
if (h != NULL)
expand_rule(&r, NULL, NULL,
NULL, NULL, h, NULL, NULL,
- NULL, NULL, NULL, NULL);
- }
+ NULL, NULL, NULL, NULL, "");
+ } else
+ free(hh);
}
free($5.label);
}
;
-antispoof_ifspc : FOR if_item { $$ = $2; }
+antispoof_ifspc : FOR antispoof_if { $$ = $2; }
| FOR '{' antispoof_iflst '}' { $$ = $3; }
;
-antispoof_iflst : if_item { $$ = $1; }
- | antispoof_iflst comma if_item {
+antispoof_iflst : antispoof_if { $$ = $1; }
+ | antispoof_iflst comma antispoof_if {
$1->tail->next = $3;
$1->tail = $3;
$$ = $1;
}
;
+antispoof_if : if_item { $$ = $1; }
+ | '(' if_item ')' {
+ $2->dynamic = 1;
+ $$ = $2;
+ }
+ ;
+
antispoof_opts : { bzero(&antispoof_opts, sizeof antispoof_opts); }
antispoof_opts_l
{ $$ = antispoof_opts; }
@@ -1035,6 +1081,7 @@ table_opt : STRING {
else if (!strcmp($1, "persist"))
table_opts.flags |= PFR_TFLAG_PERSIST;
else {
+ yyerror("invalid table option '%s'", $1);
free($1);
YYERROR;
}
@@ -1353,14 +1400,15 @@ hfscopts_item : LINKSHARE bandwidth {
hfsc_opts.linkshare.m2 = $2;
hfsc_opts.linkshare.used = 1;
}
- | LINKSHARE '(' bandwidth number bandwidth ')' {
+ | LINKSHARE '(' bandwidth comma number comma bandwidth ')'
+ {
if (hfsc_opts.linkshare.used) {
yyerror("linkshare already specified");
YYERROR;
}
hfsc_opts.linkshare.m1 = $3;
- hfsc_opts.linkshare.d = $4;
- hfsc_opts.linkshare.m2 = $5;
+ hfsc_opts.linkshare.d = $5;
+ hfsc_opts.linkshare.m2 = $7;
hfsc_opts.linkshare.used = 1;
}
| REALTIME bandwidth {
@@ -1371,14 +1419,15 @@ hfscopts_item : LINKSHARE bandwidth {
hfsc_opts.realtime.m2 = $2;
hfsc_opts.realtime.used = 1;
}
- | REALTIME '(' bandwidth number bandwidth ')' {
+ | REALTIME '(' bandwidth comma number comma bandwidth ')'
+ {
if (hfsc_opts.realtime.used) {
yyerror("realtime already specified");
YYERROR;
}
hfsc_opts.realtime.m1 = $3;
- hfsc_opts.realtime.d = $4;
- hfsc_opts.realtime.m2 = $5;
+ hfsc_opts.realtime.d = $5;
+ hfsc_opts.realtime.m2 = $7;
hfsc_opts.realtime.used = 1;
}
| UPPERLIMIT bandwidth {
@@ -1389,14 +1438,15 @@ hfscopts_item : LINKSHARE bandwidth {
hfsc_opts.upperlimit.m2 = $2;
hfsc_opts.upperlimit.used = 1;
}
- | UPPERLIMIT '(' bandwidth number bandwidth ')' {
+ | UPPERLIMIT '(' bandwidth comma number comma bandwidth ')'
+ {
if (hfsc_opts.upperlimit.used) {
yyerror("upperlimit already specified");
YYERROR;
}
hfsc_opts.upperlimit.m1 = $3;
- hfsc_opts.upperlimit.d = $4;
- hfsc_opts.upperlimit.m2 = $5;
+ hfsc_opts.upperlimit.d = $5;
+ hfsc_opts.upperlimit.m2 = $7;
hfsc_opts.upperlimit.used = 1;
}
| STRING {
@@ -1482,6 +1532,7 @@ pfrule : action dir logquick interface route af proto fromto
r.direction = $2;
r.log = $3.log;
r.quick = $3.quick;
+ r.prob = $9.prob;
r.af = $6;
if ($9.tag)
@@ -1560,6 +1611,7 @@ pfrule : action dir logquick interface route af proto fromto
YYERROR;
}
srctrack = o->data.src_track;
+ r.rule_flag |= PFRULE_SRCTRACK;
break;
case PF_STATE_OPT_MAX_SRC_STATES:
if (r.max_src_states) {
@@ -1568,7 +1620,7 @@ pfrule : action dir logquick interface route af proto fromto
"multiple definitions");
YYERROR;
}
- if (o->data.max_src_nodes == 0) {
+ if (o->data.max_src_states == 0) {
yyerror("'max-src-states' must "
"be > 0");
YYERROR;
@@ -1577,6 +1629,66 @@ pfrule : action dir logquick interface route af proto fromto
o->data.max_src_states;
r.rule_flag |= PFRULE_SRCTRACK;
break;
+ case PF_STATE_OPT_OVERLOAD:
+ if (r.overload_tblname[0]) {
+ yyerror("multiple 'overload' "
+ "table definitions");
+ YYERROR;
+ }
+ if (strlcpy(r.overload_tblname,
+ o->data.overload.tblname,
+ PF_TABLE_NAME_SIZE) >=
+ PF_TABLE_NAME_SIZE) {
+ yyerror("state option: "
+ "strlcpy");
+ YYERROR;
+ }
+ r.flush = o->data.overload.flush;
+ break;
+ case PF_STATE_OPT_MAX_SRC_CONN:
+ if (r.max_src_conn) {
+ yyerror("state option "
+ "'max-src-conn' "
+ "multiple definitions");
+ YYERROR;
+ }
+ if (o->data.max_src_conn == 0) {
+ yyerror("'max-src-conn' "
+ "must be > 0");
+ YYERROR;
+ }
+ r.max_src_conn =
+ o->data.max_src_conn;
+ r.rule_flag |= PFRULE_SRCTRACK |
+ PFRULE_RULESRCTRACK;
+ break;
+ case PF_STATE_OPT_MAX_SRC_CONN_RATE:
+ if (r.max_src_conn_rate.limit) {
+ yyerror("state option "
+ "'max-src-conn-rate' "
+ "multiple definitions");
+ YYERROR;
+ }
+ if (!o->data.max_src_conn_rate.limit ||
+ !o->data.max_src_conn_rate.seconds) {
+ yyerror("'max-src-conn-rate' "
+ "values must be > 0");
+ YYERROR;
+ }
+ if (o->data.max_src_conn_rate.limit >
+ PF_THRESHOLD_MAX) {
+ yyerror("'max-src-conn-rate' "
+ "maximum rate must be < %u",
+ PF_THRESHOLD_MAX);
+ YYERROR;
+ }
+ r.max_src_conn_rate.limit =
+ o->data.max_src_conn_rate.limit;
+ r.max_src_conn_rate.seconds =
+ o->data.max_src_conn_rate.seconds;
+ r.rule_flag |= PFRULE_SRCTRACK |
+ PFRULE_RULESRCTRACK;
+ break;
case PF_STATE_OPT_MAX_SRC_NODES:
if (r.max_src_nodes) {
yyerror("state option "
@@ -1617,7 +1729,7 @@ pfrule : action dir logquick interface route af proto fromto
o = o->next;
free(p);
}
- if (srctrack) {
+ if (r.rule_flag & PFRULE_SRCTRACK) {
if (srctrack == PF_SRCTRACK_GLOBAL &&
r.max_src_nodes) {
yyerror("'max-src-nodes' is "
@@ -1625,6 +1737,24 @@ pfrule : action dir logquick interface route af proto fromto
"'source-track global'");
YYERROR;
}
+ if (srctrack == PF_SRCTRACK_GLOBAL &&
+ r.max_src_conn) {
+ yyerror("'max-src-conn' is "
+ "incompatible with "
+ "'source-track global'");
+ YYERROR;
+ }
+ if (srctrack == PF_SRCTRACK_GLOBAL &&
+ r.max_src_conn_rate.seconds) {
+ yyerror("'max-src-conn-rate' is "
+ "incompatible with "
+ "'source-track global'");
+ YYERROR;
+ }
+ if (r.timeout[PFTM_SRC_NODE] <
+ r.max_src_conn_rate.seconds)
+ r.timeout[PFTM_SRC_NODE] =
+ r.max_src_conn_rate.seconds;
r.rule_flag |= PFRULE_SRCTRACK;
if (srctrack == PF_SRCTRACK_RULE)
r.rule_flag |= PFRULE_RULESRCTRACK;
@@ -1705,7 +1835,7 @@ pfrule : action dir logquick interface route af proto fromto
expand_rule(&r, $4, $5.host, $7, $8.src_os,
$8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
- $9.uid, $9.gid, $9.icmpspec);
+ $9.uid, $9.gid, $9.icmpspec, "");
}
;
@@ -1795,6 +1925,28 @@ filter_opt : USER uids {
filter_opts.match_tag = $3;
filter_opts.match_tag_not = $1;
}
+ | PROBABILITY STRING {
+ char *e;
+ double p = strtod($2, &e);
+
+ if (*e == '%') {
+ p *= 0.01;
+ e++;
+ }
+ if (*e) {
+ yyerror("invalid probability: %s", $2);
+ free($2);
+ YYERROR;
+ }
+ p = floor(p * (UINT_MAX+1.0) + 0.5);
+ if (p < 1.0 || p >= (UINT_MAX+1.0)) {
+ yyerror("invalid probability: %s", $2);
+ free($2);
+ YYERROR;
+ }
+ filter_opts.prob = (u_int32_t)p;
+ free($2);
+ }
;
action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
@@ -1906,13 +2058,6 @@ if_item_not : not if_item { $$ = $2; $$->not = $1; }
if_item : STRING {
struct node_host *n;
- if ((n = ifa_exists($1, 1)) == NULL) {
-#ifndef __FreeBSD__
- yyerror("unknown interface %s", $1);
- free($1);
- YYERROR;
-#endif
- }
$$ = calloc(1, sizeof(struct node_if));
if ($$ == NULL)
err(1, "if_item: calloc");
@@ -1923,13 +2068,11 @@ if_item : STRING {
yyerror("interface name too long");
YYERROR;
}
+
+ if ((n = ifa_exists($1, 1)) != NULL)
+ $$->ifa_flags = n->ifa_flags;
+
free($1);
-#ifdef __FreeBSD__
- if (n == NULL)
- $$->ifa_flags = PF_IFA_FLAG_DYNAMIC;
- else /* XXX ugly */
-#endif
- $$->ifa_flags = n->ifa_flags;
$$->not = 0;
$$->next = NULL;
$$->tail = $$;
@@ -2144,6 +2287,26 @@ host : STRING {
$$->next = NULL;
$$->tail = $$;
}
+ | ROUTE STRING {
+ $$ = calloc(1, sizeof(struct node_host));
+ if ($$ == NULL) {
+ free($2);
+ err(1, "host: calloc");
+ }
+ $$->addr.type = PF_ADDR_RTLABEL;
+ if (strlcpy($$->addr.v.rtlabelname, $2,
+ sizeof($$->addr.v.rtlabelname)) >=
+ sizeof($$->addr.v.rtlabelname)) {
+ yyerror("route label too long, max %u chars",
+ sizeof($$->addr.v.rtlabelname) - 1);
+ free($2);
+ free($$);
+ YYERROR;
+ }
+ $$->next = NULL;
+ $$->tail = $$;
+ free($2);
+ }
;
number : STRING {
@@ -2164,6 +2327,11 @@ dynaddr : '(' STRING ')' {
char *p, *op;
op = $2;
+ if (!isalpha(op[0])) {
+ yyerror("invalid interface name '%s'", op);
+ free(op);
+ YYERROR;
+ }
while ((p = strrchr($2, ':')) != NULL) {
if (!strcmp(p+1, "network"))
flags |= PFI_AFLAG_NETWORK;
@@ -2187,13 +2355,6 @@ dynaddr : '(' STRING ')' {
"interface modifiers");
YYERROR;
}
- if (ifa_exists($2, 1) == NULL && strcmp($2, "self")) {
-#ifndef __FreeBSD__
- yyerror("interface %s does not exist", $2);
- free(op);
- YYERROR;
-#endif
- }
$$ = calloc(1, sizeof(struct node_host));
if ($$ == NULL)
err(1, "address: calloc");
@@ -2281,7 +2442,7 @@ port : STRING {
if (atoul($1, &ulval) == 0) {
if (ulval > 65535) {
free($1);
- yyerror("illegal port value %d",
+ yyerror("illegal port value %lu",
ulval);
YYERROR;
}
@@ -2536,7 +2697,7 @@ icmp_item : icmptype {
if (atoul($3, &ulval) == 0) {
if (ulval > 255) {
free($3);
- yyerror("illegal icmp-code %d", ulval);
+ yyerror("illegal icmp-code %lu", ulval);
YYERROR;
}
} else {
@@ -2576,7 +2737,7 @@ icmp6_item : icmp6type {
if (atoul($3, &ulval) == 0) {
if (ulval > 255) {
- yyerror("illegal icmp6-code %ld",
+ yyerror("illegal icmp6-code %lu",
ulval);
free($3);
YYERROR;
@@ -2608,7 +2769,7 @@ icmptype : STRING {
if (atoul($1, &ulval) == 0) {
if (ulval > 255) {
- yyerror("illegal icmp-type %d", ulval);
+ yyerror("illegal icmp-type %lu", ulval);
free($1);
YYERROR;
}
@@ -2632,7 +2793,7 @@ icmp6type : STRING {
if (atoul($1, &ulval) == 0) {
if (ulval > 255) {
- yyerror("illegal icmp6-type %d", ulval);
+ yyerror("illegal icmp6-type %lu", ulval);
free($1);
YYERROR;
}
@@ -2700,6 +2861,13 @@ keep : KEEP STATE state_opt_spec {
}
;
+flush : /* empty */ { $$ = 0; }
+ | FLUSH { $$ = PF_FLUSH; }
+ | FLUSH GLOBAL {
+ $$ = PF_FLUSH | PF_FLUSH_GLOBAL;
+ }
+ ;
+
state_opt_spec : '(' state_opt_list ')' { $$ = $2; }
| /* empty */ { $$ = NULL; }
;
@@ -2738,6 +2906,43 @@ state_opt_item : MAXIMUM number {
$$->next = NULL;
$$->tail = $$;
}
+ | MAXSRCCONN number {
+ $$ = calloc(1, sizeof(struct node_state_opt));
+ if ($$ == NULL)
+ err(1, "state_opt_item: calloc");
+ $$->type = PF_STATE_OPT_MAX_SRC_CONN;
+ $$->data.max_src_conn = $2;
+ $$->next = NULL;
+ $$->tail = $$;
+ }
+ | MAXSRCCONNRATE number '/' number {
+ $$ = calloc(1, sizeof(struct node_state_opt));
+ if ($$ == NULL)
+ err(1, "state_opt_item: calloc");
+ $$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE;
+ $$->data.max_src_conn_rate.limit = $2;
+ $$->data.max_src_conn_rate.seconds = $4;
+ $$->next = NULL;
+ $$->tail = $$;
+ }
+ | OVERLOAD '<' STRING '>' flush {
+ if (strlen($3) >= PF_TABLE_NAME_SIZE) {
+ yyerror("table name '%s' too long", $3);
+ free($3);
+ YYERROR;
+ }
+ $$ = calloc(1, sizeof(struct node_state_opt));
+ if ($$ == NULL)
+ err(1, "state_opt_item: calloc");
+ if (strlcpy($$->data.overload.tblname, $3,
+ PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE)
+ errx(1, "state_opt_item: strlcpy");
+ free($3);
+ $$->type = PF_STATE_OPT_OVERLOAD;
+ $$->data.overload.flush = $5;
+ $$->next = NULL;
+ $$->tail = $$;
+ }
| MAXSRCNODES number {
$$ = calloc(1, sizeof(struct node_state_opt));
if ($$ == NULL)
@@ -3023,7 +3228,7 @@ nataction : no NAT natpass {
}
;
-natrule : nataction interface af proto fromto tag redirpool pool_opts
+natrule : nataction interface af proto fromto tag tagged redirpool pool_opts
{
struct pf_rule r;
@@ -3053,46 +3258,55 @@ natrule : nataction interface af proto fromto tag redirpool pool_opts
YYERROR;
}
+ if ($7.name)
+ if (strlcpy(r.match_tagname, $7.name,
+ PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
+ yyerror("tag too long, max %u chars",
+ PF_TAG_NAME_SIZE - 1);
+ YYERROR;
+ }
+ r.match_tag_not = $7.neg;
+
if (r.action == PF_NONAT || r.action == PF_NORDR) {
- if ($7 != NULL) {
+ if ($8 != NULL) {
yyerror("translation rule with 'no' "
"does not need '->'");
YYERROR;
}
} else {
- if ($7 == NULL || $7->host == NULL) {
+ if ($8 == NULL || $8->host == NULL) {
yyerror("translation rule requires '-> "
"address'");
YYERROR;
}
- if (!r.af && ! $7->host->ifindex)
- r.af = $7->host->af;
+ if (!r.af && ! $8->host->ifindex)
+ r.af = $8->host->af;
- remove_invalid_hosts(&$7->host, &r.af);
- if (invalid_redirect($7->host, r.af))
+ remove_invalid_hosts(&$8->host, &r.af);
+ if (invalid_redirect($8->host, r.af))
YYERROR;
- if (check_netmask($7->host, r.af))
+ if (check_netmask($8->host, r.af))
YYERROR;
- r.rpool.proxy_port[0] = ntohs($7->rport.a);
+ r.rpool.proxy_port[0] = ntohs($8->rport.a);
switch (r.action) {
case PF_RDR:
- if (!$7->rport.b && $7->rport.t &&
+ if (!$8->rport.b && $8->rport.t &&
$5.dst.port != NULL) {
r.rpool.proxy_port[1] =
- ntohs($7->rport.a) +
+ ntohs($8->rport.a) +
(ntohs(
$5.dst.port->port[1]) -
ntohs(
$5.dst.port->port[0]));
} else
r.rpool.proxy_port[1] =
- ntohs($7->rport.b);
+ ntohs($8->rport.b);
break;
case PF_NAT:
r.rpool.proxy_port[1] =
- ntohs($7->rport.b);
+ ntohs($8->rport.b);
if (!r.rpool.proxy_port[0] &&
!r.rpool.proxy_port[1]) {
r.rpool.proxy_port[0] =
@@ -3107,25 +3321,25 @@ natrule : nataction interface af proto fromto tag redirpool pool_opts
break;
}
- r.rpool.opts = $8.type;
+ r.rpool.opts = $9.type;
if ((r.rpool.opts & PF_POOL_TYPEMASK) ==
- PF_POOL_NONE && ($7->host->next != NULL ||
- $7->host->addr.type == PF_ADDR_TABLE ||
- DYNIF_MULTIADDR($7->host->addr)))
+ PF_POOL_NONE && ($8->host->next != NULL ||
+ $8->host->addr.type == PF_ADDR_TABLE ||
+ DYNIF_MULTIADDR($8->host->addr)))
r.rpool.opts = PF_POOL_ROUNDROBIN;
if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
PF_POOL_ROUNDROBIN &&
- disallow_table($7->host, "tables are only "
+ disallow_table($8->host, "tables are only "
"supported in round-robin redirection "
"pools"))
YYERROR;
if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
PF_POOL_ROUNDROBIN &&
- disallow_alias($7->host, "interface (%s) "
+ disallow_alias($8->host, "interface (%s) "
"is only supported in round-robin "
"redirection pools"))
YYERROR;
- if ($7->host->next != NULL) {
+ if ($8->host->next != NULL) {
if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
PF_POOL_ROUNDROBIN) {
yyerror("only round-robin "
@@ -3136,14 +3350,14 @@ natrule : nataction interface af proto fromto tag redirpool pool_opts
}
}
- if ($8.key != NULL)
- memcpy(&r.rpool.key, $8.key,
+ if ($9.key != NULL)
+ memcpy(&r.rpool.key, $9.key,
sizeof(struct pf_poolhashkey));
- if ($8.opts)
- r.rpool.opts |= $8.opts;
+ if ($9.opts)
+ r.rpool.opts |= $9.opts;
- if ($8.staticport) {
+ if ($9.staticport) {
if (r.action != PF_NAT) {
yyerror("the 'static-port' option is "
"only valid with nat rules");
@@ -3162,14 +3376,14 @@ natrule : nataction interface af proto fromto tag redirpool pool_opts
r.rpool.proxy_port[1] = 0;
}
- expand_rule(&r, $2, $7 == NULL ? NULL : $7->host, $4,
+ expand_rule(&r, $2, $8 == NULL ? NULL : $8->host, $4,
$5.src_os, $5.src.host, $5.src.port, $5.dst.host,
- $5.dst.port, 0, 0, 0);
- free($7);
+ $5.dst.port, 0, 0, 0, "");
+ free($8);
}
;
-binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
+binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag tagged
redirection
{
struct pf_rule binat;
@@ -3190,8 +3404,9 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
binat.af = $8->af;
if (!binat.af && $10 != NULL && $10->af)
binat.af = $10->af;
- if (!binat.af && $12 != NULL && $12->host)
- binat.af = $12->host->af;
+
+ if (!binat.af && $13 != NULL && $13->host)
+ binat.af = $13->host->af;
if (!binat.af) {
yyerror("address family (inet/inet6) "
"undefined");
@@ -3204,6 +3419,7 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
binat.ifnot = $4->not;
free($4);
}
+
if ($11 != NULL)
if (strlcpy(binat.tagname, $11,
PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
@@ -3211,6 +3427,14 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
PF_TAG_NAME_SIZE - 1);
YYERROR;
}
+ if ($12.name)
+ if (strlcpy(binat.match_tagname, $12.name,
+ PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
+ yyerror("tag too long, max %u chars",
+ PF_TAG_NAME_SIZE - 1);
+ YYERROR;
+ }
+ binat.match_tag_not = $12.neg;
if ($6 != NULL) {
binat.proto = $6->proto;
@@ -3224,12 +3448,12 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
"interface (%s) as the source address of a binat "
"rule"))
YYERROR;
- if ($12 != NULL && $12->host != NULL && disallow_table(
- $12->host, "invalid use of table <%s> as the "
+ if ($13 != NULL && $13->host != NULL && disallow_table(
+ $13->host, "invalid use of table <%s> as the "
"redirect address of a binat rule"))
YYERROR;
- if ($12 != NULL && $12->host != NULL && disallow_alias(
- $12->host, "invalid use of interface (%s) as the "
+ if ($13 != NULL && $13->host != NULL && disallow_alias(
+ $13->host, "invalid use of interface (%s) as the "
"redirect address of a binat rule"))
YYERROR;
@@ -3263,38 +3487,38 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
YYERROR;
memcpy(&binat.dst.addr, &$10->addr,
sizeof(binat.dst.addr));
- binat.dst.not = $10->not;
+ binat.dst.neg = $10->not;
free($10);
}
if (binat.action == PF_NOBINAT) {
- if ($12 != NULL) {
+ if ($13 != NULL) {
yyerror("'no binat' rule does not need"
" '->'");
YYERROR;
}
} else {
- if ($12 == NULL || $12->host == NULL) {
+ if ($13 == NULL || $13->host == NULL) {
yyerror("'binat' rule requires"
" '-> address'");
YYERROR;
}
- remove_invalid_hosts(&$12->host, &binat.af);
- if (invalid_redirect($12->host, binat.af))
+ remove_invalid_hosts(&$13->host, &binat.af);
+ if (invalid_redirect($13->host, binat.af))
YYERROR;
- if ($12->host->next != NULL) {
+ if ($13->host->next != NULL) {
yyerror("binat rule must redirect to "
"a single address");
YYERROR;
}
- if (check_netmask($12->host, binat.af))
+ if (check_netmask($13->host, binat.af))
YYERROR;
if (!PF_AZERO(&binat.src.addr.v.a.mask,
binat.af) &&
!PF_AEQ(&binat.src.addr.v.a.mask,
- &$12->host->addr.v.a.mask, binat.af)) {
+ &$13->host->addr.v.a.mask, binat.af)) {
yyerror("'binat' source mask and "
"redirect mask must be the same");
YYERROR;
@@ -3304,15 +3528,15 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
pa = calloc(1, sizeof(struct pf_pooladdr));
if (pa == NULL)
err(1, "binat: calloc");
- pa->addr = $12->host->addr;
+ pa->addr = $13->host->addr;
pa->ifname[0] = 0;
TAILQ_INSERT_TAIL(&binat.rpool.list,
pa, entries);
- free($12);
+ free($13);
}
- pfctl_add_rule(pf, &binat);
+ pfctl_add_rule(pf, &binat, "");
}
;
@@ -3320,18 +3544,15 @@ tag : /* empty */ { $$ = NULL; }
| TAG STRING { $$ = $2; }
;
+tagged : /* empty */ { $$.neg = 0; $$.name = NULL; }
+ | not TAGGED string { $$.neg = $1; $$.name = $3; }
+ ;
+
route_host : STRING {
$$ = calloc(1, sizeof(struct node_host));
if ($$ == NULL)
err(1, "route_host: calloc");
$$->ifname = $1;
- if (ifa_exists($$->ifname, 0) == NULL) {
- yyerror("routeto: unknown interface %s",
- $$->ifname);
- free($1);
- free($$);
- YYERROR;
- }
set_ipmask($$, 128);
$$->next = NULL;
$$->tail = $$;
@@ -3339,11 +3560,6 @@ route_host : STRING {
| '(' STRING host ')' {
$$ = $3;
$$->ifname = $2;
- if (ifa_exists($$->ifname, 0) == NULL) {
- yyerror("routeto: unknown interface %s",
- $$->ifname);
- YYERROR;
- }
}
;
@@ -3446,6 +3662,8 @@ yesno : NO { $$ = 0; }
if (!strcmp($1, "yes"))
$$ = 1;
else {
+ yyerror("invalid value '%s', expected 'yes' "
+ "or 'no'", $1);
free($1);
YYERROR;
}
@@ -3509,6 +3727,7 @@ rule_consistent(struct pf_rule *r)
case PF_PASS:
case PF_DROP:
case PF_SCRUB:
+ case PF_NOSCRUB:
problems = filter_consistent(r);
break;
case PF_NAT:
@@ -3546,6 +3765,12 @@ filter_consistent(struct pf_rule *r)
yyerror("must indicate address family with icmp-type/code");
problems++;
}
+ if (r->overload_tblname[0] &&
+ r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) {
+ yyerror("'overload' requires 'max-src-conn' "
+ "or 'max-src-conn-rate'");
+ problems++;
+ }
if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
(r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
yyerror("proto %s doesn't match address family %s",
@@ -3575,7 +3800,7 @@ filter_consistent(struct pf_rule *r)
problems++;
}
if ((r->tagname[0] || r->match_tagname[0]) && !r->keep_state &&
- r->action == PF_PASS && !r->anchorname[0]) {
+ r->action == PF_PASS) {
yyerror("tags cannot be used without keep state");
problems++;
}
@@ -3646,7 +3871,7 @@ process_tabledef(char *name, struct table_opts *opts)
&opts->init_nodes);
if (!(pf->opts & PF_OPT_NOACTION) &&
pfctl_define_table(name, opts->flags, opts->init_addr,
- pf->anchor, pf->ruleset, &ab, pf->tticket)) {
+ pf->anchor, &ab, pf->tticket)) {
yyerror("cannot define table %s: %s", name,
pfr_strerror(errno));
goto _error;
@@ -4112,7 +4337,8 @@ expand_rule(struct pf_rule *r,
struct node_proto *protos, struct node_os *src_oses,
struct node_host *src_hosts, struct node_port *src_ports,
struct node_host *dst_hosts, struct node_port *dst_ports,
- struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types)
+ struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types,
+ const char *anchor_call)
{
sa_family_t af = r->af;
int added = 0, error = 0;
@@ -4165,11 +4391,12 @@ expand_rule(struct pf_rule *r,
r->af = dst_host->af;
if (*interface->ifname)
- memcpy(r->ifname, interface->ifname, sizeof(r->ifname));
+ strlcpy(r->ifname, interface->ifname,
+ sizeof(r->ifname));
else if (if_indextoname(src_host->ifindex, ifname))
- memcpy(r->ifname, ifname, sizeof(r->ifname));
+ strlcpy(r->ifname, ifname, sizeof(r->ifname));
else if (if_indextoname(dst_host->ifindex, ifname))
- memcpy(r->ifname, ifname, sizeof(r->ifname));
+ strlcpy(r->ifname, ifname, sizeof(r->ifname));
else
memset(r->ifname, '\0', sizeof(r->ifname));
@@ -4196,12 +4423,12 @@ expand_rule(struct pf_rule *r,
r->ifnot = interface->not;
r->proto = proto->proto;
r->src.addr = src_host->addr;
- r->src.not = src_host->not;
+ r->src.neg = src_host->not;
r->src.port[0] = src_port->port[0];
r->src.port[1] = src_port->port[1];
r->src.port_op = src_port->op;
r->dst.addr = dst_host->addr;
- r->dst.not = dst_host->not;
+ r->dst.neg = dst_host->not;
r->dst.port[0] = dst_port->port[0];
r->dst.port[1] = dst_port->port[1];
r->dst.port_op = dst_port->op;
@@ -4264,7 +4491,7 @@ expand_rule(struct pf_rule *r,
yyerror("skipping rule due to errors");
else {
r->nr = pf->rule_nr++;
- pfctl_add_rule(pf, r);
+ pfctl_add_rule(pf, r, anchor_call);
added++;
}
@@ -4286,6 +4513,42 @@ expand_rule(struct pf_rule *r,
yyerror("rule expands to no valid combination");
}
+int
+expand_skip_interface(struct node_if *interfaces)
+{
+ int errs = 0;
+
+ if (!interfaces || (!interfaces->next && !interfaces->not &&
+ !strcmp(interfaces->ifname, "none"))) {
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf("set skip on none\n");
+ errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0);
+ return (errs);
+ }
+
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf("set skip on {");
+ LOOP_THROUGH(struct node_if, interface, interfaces,
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf(" %s", interface->ifname);
+ if (interface->not) {
+ yyerror("skip on ! <interface> is not supported");
+ errs++;
+ } else
+ errs += pfctl_set_interface_flags(pf,
+ interface->ifname, PFI_IFLAG_SKIP, 1);
+ );
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf(" }\n");
+
+ FREE_LIST(struct node_if, interfaces);
+
+ if (errs)
+ return (1);
+ else
+ return (0);
+}
+
#undef FREE_LIST
#undef LOOP_THROUGH
@@ -4336,6 +4599,7 @@ lookup(char *s)
{ "fingerprints", FINGERPRINTS},
{ "flags", FLAGS},
{ "floating", FLOATING},
+ { "flush", FLUSH},
{ "for", FOR},
{ "fragment", FRAGMENT},
{ "from", FROM},
@@ -4360,6 +4624,8 @@ lookup(char *s)
{ "loginterface", LOGINTERFACE},
{ "max", MAXIMUM},
{ "max-mss", MAXMSS},
+ { "max-src-conn", MAXSRCCONN},
+ { "max-src-conn-rate", MAXSRCCONNRATE},
{ "max-src-nodes", MAXSRCNODES},
{ "max-src-states", MAXSRCSTATES},
{ "min-ttl", MINTTL},
@@ -4374,10 +4640,12 @@ lookup(char *s)
{ "optimization", OPTIMIZATION},
{ "os", OS},
{ "out", OUT},
+ { "overload", OVERLOAD},
{ "pass", PASS},
{ "port", PORT},
{ "priority", PRIORITY},
{ "priq", PRIQ},
+ { "probability", PROBABILITY},
{ "proto", PROTO},
{ "qlimit", QLIMIT},
{ "queue", QUEUE},
@@ -4395,10 +4663,12 @@ lookup(char *s)
{ "return-icmp6", RETURNICMP6},
{ "return-rst", RETURNRST},
{ "round-robin", ROUNDROBIN},
+ { "route", ROUTE},
{ "route-to", ROUTETO},
{ "rule", RULE},
{ "scrub", SCRUB},
{ "set", SET},
+ { "skip", SKIP},
{ "source-hash", SOURCEHASH},
{ "source-track", SOURCETRACK},
{ "state", STATE},
@@ -4850,7 +5120,7 @@ getservice(char *n)
if (atoul(n, &ulval) == 0) {
if (ulval > 65535) {
- yyerror("illegal port value %d", ulval);
+ yyerror("illegal port value %lu", ulval);
return (-1);
}
return (htons(ulval));
@@ -4900,7 +5170,7 @@ parseicmpspec(char *w, sa_family_t af)
ulval = p->code;
}
if (ulval > 255) {
- yyerror("invalid icmp code %ld", ulval);
+ yyerror("invalid icmp code %lu", ulval);
return (0);
}
return (icmptype << 8 | ulval);
@@ -4913,10 +5183,10 @@ pfctl_load_anchors(int dev, int opts, struct pfr_buffer *trans)
TAILQ_FOREACH(la, &loadanchorshead, entries) {
if (opts & PF_OPT_VERBOSE)
- fprintf(stderr, "\nLoading anchor %s:%s from %s\n",
- la->anchorname, la->rulesetname, la->filename);
+ fprintf(stderr, "\nLoading anchor %s from %s\n",
+ la->anchorname, la->filename);
if (pfctl_rules(dev, la->filename, opts, la->anchorname,
- la->rulesetname, trans) == -1)
+ trans) == -1)
return (-1);
}
OpenPOWER on IntegriCloud