pfctl: extend pf.conf(5) syntax. Let the operator supply an optional

"state lock" flag (if-bound, gr-bound, floating) at the end of a
NAT rule.  The new syntax is backwards-compatbile with the old
syntax.

PF (kernel): change the macro BOUND_IFACE() to the inline function
bound_iface(), and add a new argument, the applicable NAT rule.
Use both the flags on the applicable filter rule and on the applicable
NAT rule to decide whether or not to bind a state to the interface
or the group where it is created.
This commit is contained in:
dyoung 2007-05-10 22:30:54 +00:00
parent d4be10ac51
commit f7748bc6aa
2 changed files with 49 additions and 11 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: parse.y,v 1.7 2006/09/27 15:35:12 christos Exp $ */
/* $NetBSD: parse.y,v 1.8 2007/05/10 22:30:54 dyoung Exp $ */
/* $OpenBSD: parse.y,v 1.482 2005/03/07 13:20:03 henning Exp $ */
/*
@ -441,6 +441,7 @@ typedef struct {
%type <v.string> label string tag
%type <v.keep_state> keep
%type <v.state_opt> state_opt_spec state_opt_list state_opt_item
%type <v.state_opt> opt_statelock
%type <v.logquick> logquick
%type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if
%type <v.qassign> qname
@ -1835,6 +1836,22 @@ pfrule : action dir logquick interface route af proto fromto
}
;
opt_statelock : statelock
{
$$ = calloc(1, sizeof(struct node_state_opt));
if ($$ == NULL)
err(EXIT_FAILURE, "opt_statelock: calloc");
$$->type = PF_STATE_OPT_STATELOCK;
$$->data.statelock = $1;
$$->next = NULL;
$$->tail = $$;
}
| /* empty */ {
$$ = NULL;
}
;
filter_opts : { bzero(&filter_opts, sizeof filter_opts); }
filter_opts_l
{ $$ = filter_opts; }
@ -3224,7 +3241,7 @@ nataction : no NAT natpass {
}
;
natrule : nataction interface af proto fromto tag tagged redirpool pool_opts
natrule : nataction interface af proto fromto tag tagged redirpool pool_opts opt_statelock
{
struct pf_rule r;
@ -3372,6 +3389,13 @@ natrule : nataction interface af proto fromto tag tagged redirpool pool_opts
r.rpool.proxy_port[1] = 0;
}
if ($10 == NULL)
r.rule_flag |= default_statelock;
else {
r.rule_flag |= $10->data.statelock;
free($10);
}
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, "");

32
sys/dist/pf/net/pf.c vendored
View File

@ -1,4 +1,4 @@
/* $NetBSD: pf.c,v 1.37 2007/05/02 20:40:22 dyoung Exp $ */
/* $NetBSD: pf.c,v 1.38 2007/05/10 22:30:55 dyoung Exp $ */
/* $OpenBSD: pf.c,v 1.487 2005/04/22 09:53:18 dhartmei Exp $ */
/*
@ -274,10 +274,6 @@ struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
(s)->lan.addr.addr32[3] != (s)->gwy.addr.addr32[3])) || \
(s)->lan.port != (s)->gwy.port
#define BOUND_IFACE(r, k) (((r)->rule_flag & PFRULE_IFBOUND) ? (k) : \
((r)->rule_flag & PFRULE_GRBOUND) ? (k)->pfik_parent : \
(k)->pfik_parent->pfik_parent)
#define STATE_INC_COUNTERS(s) \
do { \
s->rule.ptr->states++; \
@ -320,6 +316,24 @@ RB_GENERATE(pf_state_tree_id, pf_state,
RB_GENERATE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare);
RB_GENERATE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare);
static inline struct pfi_kif *
bound_iface(const struct pf_rule *r, const struct pf_rule *nr,
struct pfi_kif *k)
{
uint32_t rule_flag;
rule_flag = r->rule_flag;
if (nr != NULL)
rule_flag |= nr->rule_flag;
if ((rule_flag & PFRULE_IFBOUND) != 0)
return k;
else if ((rule_flag & PFRULE_GRBOUND) != 0)
return k->pfik_parent;
else
return k->pfik_parent->pfik_parent;
}
static __inline int
pf_src_compare(struct pf_src_node *a, struct pf_src_node *b)
{
@ -3091,7 +3105,7 @@ cleanup:
pool_put(&pf_state_pl, s);
return (PF_DROP);
}
if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
if (pf_insert_state(bound_iface(r, nr, kif), s)) {
pf_normalize_tcp_cleanup(s);
REASON_SET(&reason, PFRES_STATEINS);
pf_src_tree_remove_state(s);
@ -3396,7 +3410,7 @@ cleanup:
s->nat_src_node = nsn;
s->nat_src_node->states++;
}
if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
if (pf_insert_state(bound_iface(r, nr, kif), s)) {
REASON_SET(&reason, PFRES_STATEINS);
pf_src_tree_remove_state(s);
STATE_DEC_COUNTERS(s);
@ -3686,7 +3700,7 @@ cleanup:
s->nat_src_node = nsn;
s->nat_src_node->states++;
}
if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
if (pf_insert_state(bound_iface(r, nr, kif), s)) {
REASON_SET(&reason, PFRES_STATEINS);
pf_src_tree_remove_state(s);
STATE_DEC_COUNTERS(s);
@ -3959,7 +3973,7 @@ cleanup:
s->nat_src_node = nsn;
s->nat_src_node->states++;
}
if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
if (pf_insert_state(bound_iface(r, nr, kif), s)) {
REASON_SET(&reason, PFRES_STATEINS);
pf_src_tree_remove_state(s);
STATE_DEC_COUNTERS(s);