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.y642
1 files changed, 474 insertions, 168 deletions
diff --git a/contrib/pf/pfctl/parse.y b/contrib/pf/pfctl/parse.y
index 179898f..ef5d77b 100644
--- a/contrib/pf/pfctl/parse.y
+++ b/contrib/pf/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.482 2005/03/07 13:20:03 henning Exp $ */
+/* $OpenBSD: parse.y,v 1.517 2007/02/03 23:26:40 dhartmei Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -199,10 +199,12 @@ struct filter_opts {
char *tag;
char *match_tag;
u_int8_t match_tag_not;
+ int rtableid;
} filter_opts;
struct antispoof_opts {
char *label;
+ int rtableid;
} antispoof_opts;
struct scrub_opts {
@@ -216,6 +218,7 @@ struct scrub_opts {
int fragcache;
int randomid;
int reassemble_tcp;
+ int rtableid;
} scrub_opts;
struct queue_opts {
@@ -254,9 +257,10 @@ struct node_hfsc_opts hfsc_opts;
int yyerror(const char *, ...);
int disallow_table(struct node_host *, const char *);
+int disallow_urpf_failed(struct node_host *, const char *);
int disallow_alias(struct node_host *, const char *);
-int rule_consistent(struct pf_rule *);
-int filter_consistent(struct pf_rule *);
+int rule_consistent(struct pf_rule *, int);
+int filter_consistent(struct pf_rule *, int);
int nat_consistent(struct pf_rule *);
int rdr_consistent(struct pf_rule *);
int process_tabledef(char *, struct table_opts *);
@@ -306,6 +310,7 @@ struct sym {
int symset(const char *, const char *, int);
char *symget(const char *);
+void mv_rules(struct pf_ruleset *, struct pf_ruleset *);
void decide_address_family(struct node_host *, sa_family_t *);
void remove_invalid_hosts(struct node_host **, sa_family_t *);
int invalid_redirect(struct node_host *, sa_family_t);
@@ -325,6 +330,7 @@ typedef struct {
u_int32_t number;
int i;
char *string;
+ int rtableid;
struct {
u_int8_t b1;
u_int8_t b2;
@@ -367,6 +373,7 @@ typedef struct {
} keep_state;
struct {
u_int8_t log;
+ u_int8_t logif;
u_int8_t quick;
} logquick;
struct {
@@ -395,30 +402,30 @@ typedef struct {
%}
-%token PASS BLOCK SCRUB RETURN IN OS OUT LOG LOGALL QUICK ON FROM TO FLAGS
+%token PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
-%token NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
+%token NOROUTE URPFFAILED 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 SKIP HOSTID
%token ANTISPOOF FOR
%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
%token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
-%token QUEUE PRIORITY QLIMIT
-%token LOAD
+%token QUEUE PRIORITY QLIMIT RTABLE
+%token LOAD RULESET_OPTIMIZATION
%token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH
-%token TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY ROUTE
+%token TAGGED TAG IFBOUND 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 flush
-%type <v.i> unaryop statelock
-%type <v.b> action nataction scrubaction
+%type <v.number> tos not yesno
+%type <v.i> no dir af fragcache optimizer
+%type <v.i> sourcetrack flush unaryop statelock
+%type <v.b> action nataction natpass scrubaction
%type <v.b> flags flag blockspec
%type <v.range> port rport
%type <v.hashkey> hashkey
@@ -437,10 +444,10 @@ typedef struct {
%type <v.gid> gids gid_list gid_item
%type <v.route> route
%type <v.redirection> redirection redirpool
-%type <v.string> label string tag
+%type <v.string> label string tag anchorname
%type <v.keep_state> keep
%type <v.state_opt> state_opt_spec state_opt_list state_opt_item
-%type <v.logquick> logquick
+%type <v.logquick> logquick quick log logopts logopt
%type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if
%type <v.qassign> qname
%type <v.queue> qassign qassign_list qassign_item
@@ -456,6 +463,7 @@ typedef struct {
%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
+%type <v.rtableid> rtable
%%
ruleset : /* empty */
@@ -472,9 +480,36 @@ ruleset : /* empty */
| ruleset varset '\n'
| ruleset antispoof '\n'
| ruleset tabledef '\n'
+ | '{' fakeanchor '}' '\n';
| ruleset error '\n' { errors++; }
;
+/*
+ * apply to previouslys specified rule: must be careful to note
+ * what that is: pf or nat or binat or rdr
+ */
+fakeanchor : fakeanchor '\n'
+ | fakeanchor anchorrule '\n'
+ | fakeanchor binatrule '\n'
+ | fakeanchor natrule '\n'
+ | fakeanchor pfrule '\n'
+ | fakeanchor error '\n'
+ ;
+
+optimizer : string {
+ if (!strcmp($1, "none"))
+ $$ = 0;
+ else if (!strcmp($1, "basic"))
+ $$ = PF_OPTIMIZE_BASIC;
+ else if (!strcmp($1, "profile"))
+ $$ = PF_OPTIMIZE_BASIC | PF_OPTIMIZE_PROFILE;
+ else {
+ yyerror("unknown ruleset-optimization %s", $$);
+ YYERROR;
+ }
+ }
+ ;
+
option : SET OPTIMIZATION STRING {
if (check_rulestate(PFCTL_STATE_OPTION)) {
free($3);
@@ -485,7 +520,13 @@ option : SET OPTIMIZATION STRING {
free($3);
YYERROR;
}
- free ($3);
+ free($3);
+ }
+ | SET RULESET_OPTIMIZATION optimizer {
+ if (!(pf->opts & PF_OPT_OPTIMIZE)) {
+ pf->opts |= PF_OPT_OPTIMIZE;
+ pf->optimize = $3;
+ }
}
| SET TIMEOUT timeout_spec
| SET TIMEOUT '{' timeout_list '}'
@@ -535,12 +576,12 @@ option : SET OPTIMIZATION STRING {
}
| SET FINGERPRINTS STRING {
if (pf->opts & PF_OPT_VERBOSE)
- printf("set fingerprints %s\n", $3);
+ printf("set fingerprints \"%s\"\n", $3);
if (check_rulestate(PFCTL_STATE_OPTION)) {
free($3);
YYERROR;
}
- if (!pf->anchor[0]) {
+ if (!pf->anchor->name[0]) {
if (pfctl_file_fingerprints(pf->dev,
pf->opts, $3)) {
yyerror("error loading "
@@ -560,10 +601,6 @@ option : SET OPTIMIZATION STRING {
case PFRULE_IFBOUND:
printf("set state-policy if-bound\n");
break;
- case PFRULE_GRBOUND:
- printf("set state-policy "
- "group-bound\n");
- break;
}
default_statelock = $3;
}
@@ -606,37 +643,120 @@ varset : STRING '=' string {
}
;
-anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
+anchorname : STRING { $$ = $1; }
+ | /* empty */ { $$ = NULL; }
+ ;
+
+optnl : optnl '\n'
+ |
+ ;
+
+pfa_anchorlist : pfrule optnl
+ | anchorrule optnl
+ | pfa_anchorlist pfrule optnl
+ | pfa_anchorlist anchorrule optnl
+ ;
+
+pfa_anchor : '{'
+ {
+ char ta[PF_ANCHOR_NAME_SIZE];
+ struct pf_ruleset *rs;
+
+ /* steping into a brace anchor */
+ pf->asd++;
+ pf->bn++;
+ pf->brace = 1;
+
+ /* create a holding ruleset in the root */
+ snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn);
+ rs = pf_find_or_create_ruleset(ta);
+ if (rs == NULL)
+ err(1, "pfa_anchor: pf_find_or_create_ruleset");
+ pf->astack[pf->asd] = rs->anchor;
+ pf->anchor = rs->anchor;
+ } '\n' pfa_anchorlist '}'
+ {
+ pf->alast = pf->anchor;
+ pf->asd--;
+ pf->anchor = pf->astack[pf->asd];
+ }
+ | /* empty */
+ ;
+
+anchorrule : ANCHOR anchorname dir quick interface af proto fromto
+ filter_opts pfa_anchor
+ {
struct pf_rule r;
if (check_rulestate(PFCTL_STATE_FILTER)) {
+ if ($2)
+ free($2);
+ YYERROR;
+ }
+
+ if ($2 && ($2[0] == '_' || strstr($2, "/_") != NULL)) {
free($2);
+ yyerror("anchor names beginning with '_' "
+ "are reserved for internal use");
YYERROR;
}
memset(&r, 0, sizeof(r));
+ if (pf->astack[pf->asd + 1]) {
+ /* move inline rules into relative location */
+ pf_anchor_setup(&r,
+ &pf->astack[pf->asd]->ruleset,
+ $2 ? $2 : pf->alast->name);
+
+ if (r.anchor == NULL)
+ err(1, "anchorrule: unable to "
+ "create ruleset");
+
+ if (pf->alast != r.anchor) {
+ if (r.anchor->match) {
+ yyerror("inline anchor '%s' "
+ "already exists",
+ r.anchor->name);
+ YYERROR;
+ }
+ mv_rules(&pf->alast->ruleset,
+ &r.anchor->ruleset);
+ }
+ pf_remove_if_empty_ruleset(&pf->alast->ruleset);
+ pf->alast = r.anchor;
+ } else {
+ if (!$2) {
+ yyerror("anchors without explicit "
+ "rules must specify a name");
+ YYERROR;
+ }
+ }
r.direction = $3;
- r.af = $5;
- r.prob = $8.prob;
+ r.quick = $4.quick;
+ r.af = $6;
+ r.prob = $9.prob;
+ r.rtableid = $9.rtableid;
- if ($8.match_tag)
- if (strlcpy(r.match_tagname, $8.match_tag,
+ if ($9.match_tag)
+ if (strlcpy(r.match_tagname, $9.match_tag,
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 = $8.match_tag_not;
+ r.match_tag_not = $9.match_tag_not;
- decide_address_family($7.src.host, &r.af);
- decide_address_family($7.dst.host, &r.af);
+ decide_address_family($8.src.host, &r.af);
+ decide_address_family($8.dst.host, &r.af);
- expand_rule(&r, $4, NULL, $6, $7.src_os,
- $7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
- 0, 0, 0, $2);
+ expand_rule(&r, $5, NULL, $7, $8.src_os,
+ $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
+ 0, 0, 0, pf->astack[pf->asd + 1] ?
+ pf->alast->name : $2);
free($2);
+ pf->astack[pf->asd + 1] = NULL;
}
- | NATANCHOR string interface af proto fromto {
+ | NATANCHOR string interface af proto fromto rtable {
struct pf_rule r;
if (check_rulestate(PFCTL_STATE_NAT)) {
@@ -647,6 +767,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
memset(&r, 0, sizeof(r));
r.action = PF_NAT;
r.af = $4;
+ r.rtableid = $7;
decide_address_family($6.src.host, &r.af);
decide_address_family($6.dst.host, &r.af);
@@ -656,7 +777,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
0, 0, 0, $2);
free($2);
}
- | RDRANCHOR string interface af proto fromto {
+ | RDRANCHOR string interface af proto fromto rtable {
struct pf_rule r;
if (check_rulestate(PFCTL_STATE_NAT)) {
@@ -667,6 +788,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
memset(&r, 0, sizeof(r));
r.action = PF_RDR;
r.af = $4;
+ r.rtableid = $7;
decide_address_family($6.src.host, &r.af);
decide_address_family($6.dst.host, &r.af);
@@ -697,7 +819,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
0, 0, 0, $2);
free($2);
}
- | BINATANCHOR string interface af proto fromto {
+ | BINATANCHOR string interface af proto fromto rtable {
struct pf_rule r;
if (check_rulestate(PFCTL_STATE_NAT)) {
@@ -708,6 +830,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
memset(&r, 0, sizeof(r));
r.action = PF_BINAT;
r.af = $4;
+ r.rtableid = $7;
if ($5 != NULL) {
if ($5->next != NULL) {
yyerror("proto list expansion"
@@ -736,7 +859,8 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
loadrule : LOAD ANCHOR string FROM string {
struct loadanchors *loadanchor;
- if (strlen($3) >= MAXPATHLEN) {
+ if (strlen(pf->anchor->name) + 1 +
+ strlen($3) >= MAXPATHLEN) {
yyerror("anchorname %s too long, max %u\n",
$3, MAXPATHLEN - 1);
free($3);
@@ -745,8 +869,14 @@ loadrule : LOAD ANCHOR string FROM string {
loadanchor = calloc(1, sizeof(struct loadanchors));
if (loadanchor == NULL)
err(1, "loadrule: calloc");
- if ((loadanchor->anchorname = strdup($3)) == NULL)
- err(1, "loadrule: strdup");
+ if ((loadanchor->anchorname = malloc(MAXPATHLEN)) ==
+ NULL)
+ err(1, "loadrule: malloc");
+ if (pf->anchor->name[0])
+ snprintf(loadanchor->anchorname, MAXPATHLEN,
+ "%s/%s", pf->anchor->name, $3);
+ else
+ strlcpy(loadanchor->anchorname, $3, MAXPATHLEN);
if ((loadanchor->filename = strdup($5)) == NULL)
err(1, "loadrule: strdup");
@@ -779,6 +909,7 @@ scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts
r.direction = $2;
r.log = $3.log;
+ r.logif = $3.logif;
if ($3.quick) {
yyerror("scrub rules do not support 'quick'");
YYERROR;
@@ -803,6 +934,7 @@ scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts
r.max_mss = $8.maxmss;
if ($8.fragcache)
r.rule_flag |= $8.fragcache;
+ r.rtableid = $8.rtableid;
expand_rule(&r, $4, NULL, $6, $7.src_os,
$7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
@@ -811,12 +943,14 @@ scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts
;
scrub_opts : {
- bzero(&scrub_opts, sizeof scrub_opts);
- }
+ bzero(&scrub_opts, sizeof scrub_opts);
+ scrub_opts.rtableid = -1;
+ }
scrub_opts_l
{ $$ = scrub_opts; }
| /* empty */ {
bzero(&scrub_opts, sizeof scrub_opts);
+ scrub_opts.rtableid = -1;
$$ = scrub_opts;
}
;
@@ -885,6 +1019,13 @@ scrub_opt : NODF {
}
scrub_opts.randomid = 1;
}
+ | RTABLE number {
+ if ($2 > RT_TABLEID_MAX || $2 < 0) {
+ yyerror("invalid rtable id");
+ YYERROR;
+ }
+ scrub_opts.rtableid = $2;
+ }
;
fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ }
@@ -906,10 +1047,12 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
r.action = PF_DROP;
r.direction = PF_IN;
r.log = $2.log;
+ r.logif = $2.logif;
r.quick = $2.quick;
r.af = $4;
if (rule_label(&r, $5.label))
YYERROR;
+ r.rtableid = $5.rtableid;
j = calloc(1, sizeof(struct node_if));
if (j == NULL)
err(1, "antispoof: calloc");
@@ -960,6 +1103,7 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
r.af = $4;
if (rule_label(&r, $5.label))
YYERROR;
+ r.rtableid = $5.rtableid;
if (hh != NULL)
h = hh;
else
@@ -994,11 +1138,15 @@ antispoof_if : if_item { $$ = $1; }
}
;
-antispoof_opts : { bzero(&antispoof_opts, sizeof antispoof_opts); }
+antispoof_opts : {
+ bzero(&antispoof_opts, sizeof antispoof_opts);
+ antispoof_opts.rtableid = -1;
+ }
antispoof_opts_l
{ $$ = antispoof_opts; }
| /* empty */ {
bzero(&antispoof_opts, sizeof antispoof_opts);
+ antispoof_opts.rtableid = -1;
$$ = antispoof_opts;
}
;
@@ -1014,6 +1162,13 @@ antispoof_opt : label {
}
antispoof_opts.label = $1;
}
+ | RTABLE number {
+ if ($2 > RT_TABLEID_MAX || $2 < 0) {
+ yyerror("invalid rtable id");
+ YYERROR;
+ }
+ antispoof_opts.rtableid = $2;
+ }
;
not : '!' { $$ = 1; }
@@ -1100,6 +1255,10 @@ table_opt : STRING {
yyerror("\"no-route\" is not permitted "
"inside tables");
break;
+ case PF_ADDR_URPFFAILED:
+ yyerror("\"urpf-failed\" is not "
+ "permitted inside tables");
+ break;
default:
yyerror("unknown address type %d",
n->addr.type);
@@ -1499,6 +1658,7 @@ pfrule : action dir logquick interface route af proto fromto
struct node_proto *proto;
int srctrack = 0;
int statelock = 0;
+ int adaptive = 0;
if (check_rulestate(PFCTL_STATE_FILTER))
YYERROR;
@@ -1524,8 +1684,10 @@ pfrule : action dir logquick interface route af proto fromto
}
r.direction = $2;
r.log = $3.log;
+ r.logif = $3.logif;
r.quick = $3.quick;
r.prob = $9.prob;
+ r.rtableid = $9.rtableid;
r.af = $6;
if ($9.tag)
@@ -1543,11 +1705,15 @@ pfrule : action dir logquick interface route af proto fromto
YYERROR;
}
r.match_tag_not = $9.match_tag_not;
- r.flags = $9.flags.b1;
- r.flagset = $9.flags.b2;
if (rule_label(&r, $9.label))
YYERROR;
free($9.label);
+ r.flags = $9.flags.b1;
+ r.flagset = $9.flags.b2;
+ if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) {
+ yyerror("flags always false");
+ YYERROR;
+ }
if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
for (proto = $7; proto != NULL &&
proto->proto != IPPROTO_TCP;
@@ -1575,6 +1741,12 @@ pfrule : action dir logquick interface route af proto fromto
r.tos = $9.tos;
r.keep_state = $9.keep.action;
+
+ /* 'keep state' by default on pass rules. */
+ if (!r.keep_state && !r.action &&
+ !($9.marker & FOM_KEEP))
+ r.keep_state = PF_STATE_NORMAL;
+
o = $9.keep.options;
while (o) {
struct node_state_opt *p = o;
@@ -1671,8 +1843,8 @@ pfrule : action dir logquick interface route af proto fromto
if (o->data.max_src_conn_rate.limit >
PF_THRESHOLD_MAX) {
yyerror("'max-src-conn-rate' "
- "maximum rate must be < %u",
- PF_THRESHOLD_MAX);
+ "maximum rate must be < %u",
+ PF_THRESHOLD_MAX);
YYERROR;
}
r.max_src_conn_rate.limit =
@@ -1709,6 +1881,11 @@ pfrule : action dir logquick interface route af proto fromto
r.rule_flag |= o->data.statelock;
break;
case PF_STATE_OPT_TIMEOUT:
+ if (o->data.timeout.number ==
+ PFTM_ADAPTIVE_START ||
+ o->data.timeout.number ==
+ PFTM_ADAPTIVE_END)
+ adaptive = 1;
if (r.timeout[o->data.timeout.number]) {
yyerror("state timeout %s "
"multiple definitions",
@@ -1722,6 +1899,20 @@ pfrule : action dir logquick interface route af proto fromto
o = o->next;
free(p);
}
+
+ /* 'flags S/SA' by default on stateful rules */
+ if (!r.action && !r.flags && !r.flagset &&
+ !$9.fragment && !($9.marker & FOM_FLAGS) &&
+ r.keep_state) {
+ r.flags = parse_flags("S");
+ r.flagset = parse_flags("SA");
+ }
+ if (!adaptive && r.max_states) {
+ r.timeout[PFTM_ADAPTIVE_START] =
+ (r.max_states / 10) * 6;
+ r.timeout[PFTM_ADAPTIVE_END] =
+ (r.max_states / 10) * 12;
+ }
if (r.rule_flag & PFRULE_SRCTRACK) {
if (srctrack == PF_SRCTRACK_GLOBAL &&
r.max_src_nodes) {
@@ -1832,11 +2023,15 @@ pfrule : action dir logquick interface route af proto fromto
}
;
-filter_opts : { bzero(&filter_opts, sizeof filter_opts); }
+filter_opts : {
+ bzero(&filter_opts, sizeof filter_opts);
+ filter_opts.rtableid = -1;
+ }
filter_opts_l
{ $$ = filter_opts; }
| /* empty */ {
bzero(&filter_opts, sizeof filter_opts);
+ filter_opts.rtableid = -1;
$$ = filter_opts;
}
;
@@ -1940,6 +2135,13 @@ filter_opt : USER uids {
filter_opts.prob = (u_int32_t)p;
free($2);
}
+ | RTABLE number {
+ if ($2 > RT_TABLEID_MAX || $2 < 0) {
+ yyerror("invalid rtable id");
+ YYERROR;
+ }
+ filter_opts.rtableid = $2;
+ }
;
action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
@@ -2021,15 +2223,55 @@ dir : /* empty */ { $$ = 0; }
| OUT { $$ = PF_OUT; }
;
-logquick : /* empty */ { $$.log = 0; $$.quick = 0; }
- | log { $$.log = $1; $$.quick = 0; }
- | QUICK { $$.log = 0; $$.quick = 1; }
- | log QUICK { $$.log = $1; $$.quick = 1; }
- | QUICK log { $$.log = $2; $$.quick = 1; }
+quick : /* empty */ { $$.quick = 0; }
+ | QUICK { $$.quick = 1; }
+ ;
+
+logquick : /* empty */ { $$.log = 0; $$.quick = 0; $$.logif = 0; }
+ | log { $$ = $1; $$.quick = 0; }
+ | QUICK { $$.quick = 1; $$.log = 0; $$.logif = 0; }
+ | log QUICK { $$ = $1; $$.quick = 1; }
+ | QUICK log { $$ = $2; $$.quick = 1; }
+ ;
+
+log : LOG { $$.log = PF_LOG; $$.logif = 0; }
+ | LOG '(' logopts ')' {
+ $$.log = PF_LOG | $3.log;
+ $$.logif = $3.logif;
+ }
;
-log : LOG { $$ = 1; }
- | LOGALL { $$ = 2; }
+logopts : logopt { $$ = $1; }
+ | logopts comma logopt {
+ $$.log = $1.log | $3.log;
+ $$.logif = $3.logif;
+ if ($$.logif == 0)
+ $$.logif = $1.logif;
+ }
+ ;
+
+logopt : ALL { $$.log = PF_LOG_ALL; $$.logif = 0; }
+ | USER { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
+ | GROUP { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
+ | TO string {
+ const char *errstr;
+ u_int i;
+
+ $$.log = 0;
+ if (strncmp($2, "pflog", 5)) {
+ yyerror("%s: should be a pflog interface", $2);
+ free($2);
+ YYERROR;
+ }
+ i = strtonum($2 + 5, 0, 255, &errstr);
+ if (errstr) {
+ yyerror("%s: %s", $2, errstr);
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ $$.logif = i;
+ }
;
interface : /* empty */ { $$ = NULL; }
@@ -2062,7 +2304,7 @@ if_item : STRING {
YYERROR;
}
- if ((n = ifa_exists($1, 1)) != NULL)
+ if ((n = ifa_exists($1)) != NULL)
$$->ifa_flags = n->ifa_flags;
free($1);
@@ -2176,6 +2418,9 @@ to : /* empty */ {
$$.port = NULL;
}
| TO ipportspec {
+ if (disallow_urpf_failed($2.host, "\"urpf-failed\" is "
+ "not permitted in a destination address"))
+ YYERROR;
$$ = $2;
}
;
@@ -2199,8 +2444,8 @@ ipspec : ANY { $$ = NULL; }
| '{' host_list '}' { $$ = $2; }
;
-host_list : xhost { $$ = $1; }
- | host_list comma xhost {
+host_list : ipspec { $$ = $1; }
+ | host_list comma ipspec {
if ($3 == NULL)
$$ = $1;
else if ($1 == NULL)
@@ -2220,12 +2465,22 @@ xhost : not host {
n->not = $1;
$$ = $2;
}
- | NOROUTE {
+ | not NOROUTE {
$$ = calloc(1, sizeof(struct node_host));
if ($$ == NULL)
err(1, "xhost: calloc");
$$->addr.type = PF_ADDR_NOROUTE;
$$->next = NULL;
+ $$->not = $1;
+ $$->tail = $$;
+ }
+ | not URPFFAILED {
+ $$ = calloc(1, sizeof(struct node_host));
+ if ($$ == NULL)
+ err(1, "xhost: calloc");
+ $$->addr.type = PF_ADDR_URPFFAILED;
+ $$->next = NULL;
+ $$->not = $1;
$$->tail = $$;
}
;
@@ -2428,31 +2683,13 @@ port_item : port {
port : STRING {
char *p = strchr($1, ':');
- struct servent *s = NULL;
- u_long ulval;
if (p == NULL) {
- if (atoul($1, &ulval) == 0) {
- if (ulval > 65535) {
- free($1);
- yyerror("illegal port value %lu",
- ulval);
- YYERROR;
- }
- $$.a = htons(ulval);
- } else {
- s = getservbyname($1, "tcp");
- if (s == NULL)
- s = getservbyname($1, "udp");
- if (s == NULL) {
- yyerror("unknown port %s", $1);
- free($1);
- YYERROR;
- }
- $$.a = s->s_port;
+ if (($$.a = getservice($1)) == -1) {
+ free($1);
+ YYERROR;
}
- $$.b = 0;
- $$.t = 0;
+ $$.b = $$.t = 0;
} else {
int port[2];
@@ -2649,6 +2886,7 @@ flag : STRING {
flags : FLAGS flag '/' flag { $$.b1 = $2.b1; $$.b2 = $4.b1; }
| FLAGS '/' flag { $$.b1 = 0; $$.b2 = $3.b1; }
+ | FLAGS ANY { $$.b1 = 0; $$.b2 = 0; }
;
icmpspec : ICMPTYPE icmp_item { $$ = $2; }
@@ -2786,7 +3024,8 @@ icmp6type : STRING {
if (atoul($1, &ulval) == 0) {
if (ulval > 255) {
- yyerror("illegal icmp6-type %lu", ulval);
+ yyerror("illegal icmp6-type %lu",
+ ulval);
free($1);
YYERROR;
}
@@ -2832,15 +3071,16 @@ sourcetrack : SOURCETRACK { $$ = PF_SRCTRACK; }
statelock : IFBOUND {
$$ = PFRULE_IFBOUND;
}
- | GRBOUND {
- $$ = PFRULE_GRBOUND;
- }
| FLOATING {
$$ = 0;
}
;
-keep : KEEP STATE state_opt_spec {
+keep : NO STATE {
+ $$.action = 0;
+ $$.options = NULL;
+ }
+ | KEEP STATE state_opt_spec {
$$.action = PF_STATE_NORMAL;
$$.options = $3;
}
@@ -3199,29 +3439,41 @@ redirection : /* empty */ { $$ = NULL; }
}
;
-natpass : /* empty */ { $$ = 0; }
- | PASS { $$ = 1; }
+natpass : /* empty */ { $$.b1 = $$.b2 = 0; }
+ | PASS { $$.b1 = 1; $$.b2 = 0; }
+ | PASS log { $$.b1 = 1; $$.b2 = $2.log; $$.w2 = $2.logif; }
;
nataction : no NAT natpass {
- $$.b2 = $$.w = 0;
+ if ($1 && $3.b1) {
+ yyerror("\"pass\" not valid with \"no\"");
+ YYERROR;
+ }
if ($1)
$$.b1 = PF_NONAT;
else
$$.b1 = PF_NAT;
- $$.b2 = $3;
+ $$.b2 = $3.b1;
+ $$.w = $3.b2;
+ $$.w2 = $3.w2;
}
| no RDR natpass {
- $$.b2 = $$.w = 0;
+ if ($1 && $3.b1) {
+ yyerror("\"pass\" not valid with \"no\"");
+ YYERROR;
+ }
if ($1)
$$.b1 = PF_NORDR;
else
$$.b1 = PF_RDR;
- $$.b2 = $3;
+ $$.b2 = $3.b1;
+ $$.w = $3.b2;
+ $$.w2 = $3.w2;
}
;
-natrule : nataction interface af proto fromto tag tagged redirpool pool_opts
+natrule : nataction interface af proto fromto tag tagged rtable
+ redirpool pool_opts
{
struct pf_rule r;
@@ -3232,6 +3484,8 @@ natrule : nataction interface af proto fromto tag tagged redirpool pool_opts
r.action = $1.b1;
r.natpass = $1.b2;
+ r.log = $1.w;
+ r.logif = $1.w2;
r.af = $3;
if (!r.af) {
@@ -3259,47 +3513,48 @@ natrule : nataction interface af proto fromto tag tagged redirpool pool_opts
YYERROR;
}
r.match_tag_not = $7.neg;
+ r.rtableid = $8;
if (r.action == PF_NONAT || r.action == PF_NORDR) {
- if ($8 != NULL) {
+ if ($9 != NULL) {
yyerror("translation rule with 'no' "
"does not need '->'");
YYERROR;
}
} else {
- if ($8 == NULL || $8->host == NULL) {
+ if ($9 == NULL || $9->host == NULL) {
yyerror("translation rule requires '-> "
"address'");
YYERROR;
}
- if (!r.af && ! $8->host->ifindex)
- r.af = $8->host->af;
+ if (!r.af && ! $9->host->ifindex)
+ r.af = $9->host->af;
- remove_invalid_hosts(&$8->host, &r.af);
- if (invalid_redirect($8->host, r.af))
+ remove_invalid_hosts(&$9->host, &r.af);
+ if (invalid_redirect($9->host, r.af))
YYERROR;
- if (check_netmask($8->host, r.af))
+ if (check_netmask($9->host, r.af))
YYERROR;
- r.rpool.proxy_port[0] = ntohs($8->rport.a);
+ r.rpool.proxy_port[0] = ntohs($9->rport.a);
switch (r.action) {
case PF_RDR:
- if (!$8->rport.b && $8->rport.t &&
+ if (!$9->rport.b && $9->rport.t &&
$5.dst.port != NULL) {
r.rpool.proxy_port[1] =
- ntohs($8->rport.a) +
+ ntohs($9->rport.a) +
(ntohs(
$5.dst.port->port[1]) -
ntohs(
$5.dst.port->port[0]));
} else
r.rpool.proxy_port[1] =
- ntohs($8->rport.b);
+ ntohs($9->rport.b);
break;
case PF_NAT:
r.rpool.proxy_port[1] =
- ntohs($8->rport.b);
+ ntohs($9->rport.b);
if (!r.rpool.proxy_port[0] &&
!r.rpool.proxy_port[1]) {
r.rpool.proxy_port[0] =
@@ -3314,25 +3569,25 @@ natrule : nataction interface af proto fromto tag tagged redirpool pool_opts
break;
}
- r.rpool.opts = $9.type;
+ r.rpool.opts = $10.type;
if ((r.rpool.opts & PF_POOL_TYPEMASK) ==
- PF_POOL_NONE && ($8->host->next != NULL ||
- $8->host->addr.type == PF_ADDR_TABLE ||
- DYNIF_MULTIADDR($8->host->addr)))
+ PF_POOL_NONE && ($9->host->next != NULL ||
+ $9->host->addr.type == PF_ADDR_TABLE ||
+ DYNIF_MULTIADDR($9->host->addr)))
r.rpool.opts = PF_POOL_ROUNDROBIN;
if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
PF_POOL_ROUNDROBIN &&
- disallow_table($8->host, "tables are only "
+ disallow_table($9->host, "tables are only "
"supported in round-robin redirection "
"pools"))
YYERROR;
if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
PF_POOL_ROUNDROBIN &&
- disallow_alias($8->host, "interface (%s) "
+ disallow_alias($9->host, "interface (%s) "
"is only supported in round-robin "
"redirection pools"))
YYERROR;
- if ($8->host->next != NULL) {
+ if ($9->host->next != NULL) {
if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
PF_POOL_ROUNDROBIN) {
yyerror("only round-robin "
@@ -3343,14 +3598,14 @@ natrule : nataction interface af proto fromto tag tagged redirpool pool_opts
}
}
- if ($9.key != NULL)
- memcpy(&r.rpool.key, $9.key,
+ if ($10.key != NULL)
+ memcpy(&r.rpool.key, $10.key,
sizeof(struct pf_poolhashkey));
- if ($9.opts)
- r.rpool.opts |= $9.opts;
+ if ($10.opts)
+ r.rpool.opts |= $10.opts;
- if ($9.staticport) {
+ if ($10.staticport) {
if (r.action != PF_NAT) {
yyerror("the 'static-port' option is "
"only valid with nat rules");
@@ -3369,37 +3624,46 @@ natrule : nataction interface af proto fromto tag tagged redirpool pool_opts
r.rpool.proxy_port[1] = 0;
}
- expand_rule(&r, $2, $8 == NULL ? NULL : $8->host, $4,
+ expand_rule(&r, $2, $9 == NULL ? NULL : $9->host, $4,
$5.src_os, $5.src.host, $5.src.port, $5.dst.host,
$5.dst.port, 0, 0, 0, "");
- free($8);
+ free($9);
}
;
-binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag tagged
- redirection
+binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
+ tagged rtable redirection
{
struct pf_rule binat;
struct pf_pooladdr *pa;
if (check_rulestate(PFCTL_STATE_NAT))
YYERROR;
+ if (disallow_urpf_failed($10, "\"urpf-failed\" is not "
+ "permitted as a binat destination"))
+ YYERROR;
memset(&binat, 0, sizeof(binat));
+ if ($1 && $3.b1) {
+ yyerror("\"pass\" not valid with \"no\"");
+ YYERROR;
+ }
if ($1)
binat.action = PF_NOBINAT;
else
binat.action = PF_BINAT;
- binat.natpass = $3;
+ binat.natpass = $3.b1;
+ binat.log = $3.b2;
+ binat.logif = $3.w2;
binat.af = $5;
if (!binat.af && $8 != NULL && $8->af)
binat.af = $8->af;
if (!binat.af && $10 != NULL && $10->af)
binat.af = $10->af;
- if (!binat.af && $13 != NULL && $13->host)
- binat.af = $13->host->af;
+ if (!binat.af && $14 != NULL && $14->host)
+ binat.af = $14->host->af;
if (!binat.af) {
yyerror("address family (inet/inet6) "
"undefined");
@@ -3428,6 +3692,7 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag tagged
YYERROR;
}
binat.match_tag_not = $12.neg;
+ binat.rtableid = $13;
if ($6 != NULL) {
binat.proto = $6->proto;
@@ -3441,12 +3706,12 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag tagged
"interface (%s) as the source address of a binat "
"rule"))
YYERROR;
- if ($13 != NULL && $13->host != NULL && disallow_table(
- $13->host, "invalid use of table <%s> as the "
+ if ($14 != NULL && $14->host != NULL && disallow_table(
+ $14->host, "invalid use of table <%s> as the "
"redirect address of a binat rule"))
YYERROR;
- if ($13 != NULL && $13->host != NULL && disallow_alias(
- $13->host, "invalid use of interface (%s) as the "
+ if ($14 != NULL && $14->host != NULL && disallow_alias(
+ $14->host, "invalid use of interface (%s) as the "
"redirect address of a binat rule"))
YYERROR;
@@ -3485,33 +3750,33 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag tagged
}
if (binat.action == PF_NOBINAT) {
- if ($13 != NULL) {
+ if ($14 != NULL) {
yyerror("'no binat' rule does not need"
" '->'");
YYERROR;
}
} else {
- if ($13 == NULL || $13->host == NULL) {
+ if ($14 == NULL || $14->host == NULL) {
yyerror("'binat' rule requires"
" '-> address'");
YYERROR;
}
- remove_invalid_hosts(&$13->host, &binat.af);
- if (invalid_redirect($13->host, binat.af))
+ remove_invalid_hosts(&$14->host, &binat.af);
+ if (invalid_redirect($14->host, binat.af))
YYERROR;
- if ($13->host->next != NULL) {
+ if ($14->host->next != NULL) {
yyerror("binat rule must redirect to "
"a single address");
YYERROR;
}
- if (check_netmask($13->host, binat.af))
+ if (check_netmask($14->host, binat.af))
YYERROR;
if (!PF_AZERO(&binat.src.addr.v.a.mask,
binat.af) &&
!PF_AEQ(&binat.src.addr.v.a.mask,
- &$13->host->addr.v.a.mask, binat.af)) {
+ &$14->host->addr.v.a.mask, binat.af)) {
yyerror("'binat' source mask and "
"redirect mask must be the same");
YYERROR;
@@ -3521,12 +3786,12 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag tagged
pa = calloc(1, sizeof(struct pf_pooladdr));
if (pa == NULL)
err(1, "binat: calloc");
- pa->addr = $13->host->addr;
+ pa->addr = $14->host->addr;
pa->ifname[0] = 0;
TAILQ_INSERT_TAIL(&binat.rpool.list,
pa, entries);
- free($13);
+ free($14);
}
pfctl_add_rule(pf, &binat, "");
@@ -3541,6 +3806,16 @@ tagged : /* empty */ { $$.neg = 0; $$.name = NULL; }
| not TAGGED string { $$.neg = $1; $$.name = $3; }
;
+rtable : /* empty */ { $$ = -1; }
+ | RTABLE number {
+ if ($2 > RT_TABLEID_MAX || $2 < 0) {
+ yyerror("invalid rtable id");
+ YYERROR;
+ }
+ $$ = $2;
+ }
+ ;
+
route_host : STRING {
$$ = calloc(1, sizeof(struct node_host));
if ($$ == NULL)
@@ -3701,6 +3976,17 @@ disallow_table(struct node_host *h, const char *fmt)
}
int
+disallow_urpf_failed(struct node_host *h, const char *fmt)
+{
+ for (; h != NULL; h = h->next)
+ if (h->addr.type == PF_ADDR_URPFFAILED) {
+ yyerror(fmt);
+ return (1);
+ }
+ return (0);
+}
+
+int
disallow_alias(struct node_host *h, const char *fmt)
{
for (; h != NULL; h = h->next)
@@ -3712,7 +3998,7 @@ disallow_alias(struct node_host *h, const char *fmt)
}
int
-rule_consistent(struct pf_rule *r)
+rule_consistent(struct pf_rule *r, int anchor_call)
{
int problems = 0;
@@ -3721,7 +4007,7 @@ rule_consistent(struct pf_rule *r)
case PF_DROP:
case PF_SCRUB:
case PF_NOSCRUB:
- problems = filter_consistent(r);
+ problems = filter_consistent(r, anchor_call);
break;
case PF_NAT:
case PF_NONAT:
@@ -3740,7 +4026,7 @@ rule_consistent(struct pf_rule *r)
}
int
-filter_consistent(struct pf_rule *r)
+filter_consistent(struct pf_rule *r, int anchor_call)
{
int problems = 0;
@@ -3792,11 +4078,6 @@ filter_consistent(struct pf_rule *r)
yyerror("keep state on block rules doesn't make sense");
problems++;
}
- if ((r->tagname[0] || r->match_tagname[0]) && !r->keep_state &&
- r->action == PF_PASS) {
- yyerror("tags cannot be used without keep state");
- problems++;
- }
return (-problems);
}
@@ -3864,7 +4145,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, &ab, pf->tticket)) {
+ pf->anchor->name, &ab, pf->anchor->ruleset.tticket)) {
yyerror("cannot define table %s: %s", name,
pfr_strerror(errno));
goto _error;
@@ -3963,6 +4244,9 @@ expand_label_addr(const char *name, char *label, size_t len, sa_family_t af,
case PF_ADDR_NOROUTE:
snprintf(tmp, sizeof(tmp), "no-route");
break;
+ case PF_ADDR_URPFFAILED:
+ snprintf(tmp, sizeof(tmp), "urpf-failed");
+ break;
case PF_ADDR_ADDRMASK:
if (!af || (PF_AZERO(&h->addr.v.a.addr, af) &&
PF_AZERO(&h->addr.v.a.mask, af)))
@@ -4053,7 +4337,7 @@ expand_label_nr(const char *name, char *label, size_t len)
char n[11];
if (strstr(label, name) != NULL) {
- snprintf(n, sizeof(n), "%u", pf->rule_nr);
+ snprintf(n, sizeof(n), "%u", pf->anchor->match);
expand_label_str(label, len, name, n);
}
}
@@ -4480,10 +4764,10 @@ expand_rule(struct pf_rule *r,
TAILQ_INSERT_TAIL(&r->rpool.list, pa, entries);
}
- if (rule_consistent(r) < 0 || error)
+ if (rule_consistent(r, anchor_call[0]) < 0 || error)
yyerror("skipping rule due to errors");
else {
- r->nr = pf->rule_nr++;
+ r->nr = pf->astack[pf->asd]->match++;
pfctl_add_rule(pf, r, anchor_call);
added++;
}
@@ -4598,7 +4882,6 @@ lookup(char *s)
{ "from", FROM},
{ "global", GLOBAL},
{ "group", GROUP},
- { "group-bound", GRBOUND},
{ "hfsc", HFSC},
{ "hostid", HOSTID},
{ "icmp-type", ICMPTYPE},
@@ -4613,7 +4896,6 @@ lookup(char *s)
{ "linkshare", LINKSHARE},
{ "load", LOAD},
{ "log", LOG},
- { "log-all", LOGALL},
{ "loginterface", LOGINTERFACE},
{ "max", MAXIMUM},
{ "max-mss", MAXMSS},
@@ -4658,7 +4940,9 @@ lookup(char *s)
{ "round-robin", ROUNDROBIN},
{ "route", ROUTE},
{ "route-to", ROUTETO},
+ { "rtable", RTABLE},
{ "rule", RULE},
+ { "ruleset-optimization", RULESET_OPTIMIZATION},
{ "scrub", SCRUB},
{ "set", SET},
{ "skip", SKIP},
@@ -4678,6 +4962,7 @@ lookup(char *s)
{ "tos", TOS},
{ "ttl", TTL},
{ "upperlimit", UPPERLIMIT},
+ { "urpf-failed", URPFFAILED},
{ "user", USER},
};
const struct keywords *p;
@@ -4725,9 +5010,7 @@ lgetc(FILE *f)
while ((c = getc(f)) == '\\') {
next = getc(f);
if (next != '\n') {
- if (isspace(next))
- yyerror("whitespace after \\");
- ungetc(next, f);
+ c = next;
break;
}
yylval.lineno = lineno;
@@ -5015,21 +5298,40 @@ symget(const char *nam)
}
void
-decide_address_family(struct node_host *n, sa_family_t *af)
+mv_rules(struct pf_ruleset *src, struct pf_ruleset *dst)
{
- sa_family_t target_af = 0;
+ int i;
+ struct pf_rule *r;
+
+ for (i = 0; i < PF_RULESET_MAX; ++i) {
+ while ((r = TAILQ_FIRST(src->rules[i].active.ptr))
+ != NULL) {
+ TAILQ_REMOVE(src->rules[i].active.ptr, r, entries);
+ TAILQ_INSERT_TAIL(dst->rules[i].active.ptr, r, entries);
+ dst->anchor->match++;
+ }
+ src->anchor->match = 0;
+ while ((r = TAILQ_FIRST(src->rules[i].inactive.ptr))
+ != NULL) {
+ TAILQ_REMOVE(src->rules[i].inactive.ptr, r, entries);
+ TAILQ_INSERT_TAIL(dst->rules[i].inactive.ptr,
+ r, entries);
+ }
+ }
+}
- while (!*af && n != NULL) {
- if (n->af) {
- if (target_af == 0)
- target_af = n->af;
- if (target_af != n->af)
- return;
+void
+decide_address_family(struct node_host *n, sa_family_t *af)
+{
+ if (*af != 0 || n == NULL)
+ return;
+ *af = n->af;
+ while ((n = n->next) != NULL) {
+ if (n->af != *af) {
+ *af = 0;
+ return;
}
- n = n->next;
}
- if (!*af && target_af)
- *af = target_af;
}
void
@@ -5170,19 +5472,23 @@ parseicmpspec(char *w, sa_family_t af)
}
int
-pfctl_load_anchors(int dev, int opts, struct pfr_buffer *trans)
+pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans)
{
struct loadanchors *la;
+ FILE *fin;
TAILQ_FOREACH(la, &loadanchorshead, entries) {
- if (opts & PF_OPT_VERBOSE)
+ if (pf->opts & PF_OPT_VERBOSE)
fprintf(stderr, "\nLoading anchor %s from %s\n",
la->anchorname, la->filename);
- if (pfctl_rules(dev, la->filename, opts, la->anchorname,
- trans) == -1)
+ if ((fin = pfctl_fopen(la->filename, "r")) == NULL) {
+ warn("%s", la->filename);
+ continue;
+ }
+ if (pfctl_rules(dev, la->filename, fin, pf->opts, pf->optimize,
+ la->anchorname, trans) == -1)
return (-1);
}
return (0);
}
-
OpenPOWER on IntegriCloud