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:
parent
d4be10ac51
commit
f7748bc6aa
28
dist/pf/sbin/pfctl/parse.y
vendored
28
dist/pf/sbin/pfctl/parse.y
vendored
@ -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
32
sys/dist/pf/net/pf.c
vendored
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user