summaryrefslogtreecommitdiffstats
path: root/sys/netpfil
diff options
context:
space:
mode:
authormelifaro <melifaro@FreeBSD.org>2013-12-18 20:17:05 +0000
committermelifaro <melifaro@FreeBSD.org>2013-12-18 20:17:05 +0000
commitce16a97371169a2ff661ae838180ec527f383e52 (patch)
treeff26a5b2fef152bea4afc4464edccc687d0e1919 /sys/netpfil
parent2f0743dad34f9fe5f923cf3f0490c19d31fcb3cf (diff)
downloadFreeBSD-src-ce16a97371169a2ff661ae838180ec527f383e52.zip
FreeBSD-src-ce16a97371169a2ff661ae838180ec527f383e52.tar.gz
Add net.inet.ip.fw.dyn_keep_states sysctl which
re-links dynamic states to default rule instead of flushing on rule deletion. This can be useful while performing ruleset reload (think about `atomic` reload via changing sets). Currently it is turned off by default. MFC after: 2 weeks Sponsored by: Yandex LLC
Diffstat (limited to 'sys/netpfil')
-rw-r--r--sys/netpfil/ipfw/ip_fw_dynamic.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/sys/netpfil/ipfw/ip_fw_dynamic.c b/sys/netpfil/ipfw/ip_fw_dynamic.c
index cf4071e..f28dfcb 100644
--- a/sys/netpfil/ipfw/ip_fw_dynamic.c
+++ b/sys/netpfil/ipfw/ip_fw_dynamic.c
@@ -106,7 +106,8 @@ __FBSDID("$FreeBSD$");
*
* Each dynamic rule holds a pointer to the parent ipfw rule so
* we know what action to perform. Dynamic rules are removed when
- * the parent rule is deleted. XXX we should make them survive.
+ * the parent rule is deleted. This can be changed by dyn_keep_states
+ * sysctl.
*
* There are some limitations with dynamic rules -- we do not
* obey the 'randomized match', and we do not do multiple
@@ -141,6 +142,10 @@ static VNET_DEFINE(uma_zone_t, ipfw_dyn_rule_zone);
#define IPFW_BUCK_UNLOCK(i) mtx_unlock(&V_ipfw_dyn_v[(i)].mtx)
#define IPFW_BUCK_ASSERT(i) mtx_assert(&V_ipfw_dyn_v[(i)].mtx, MA_OWNED)
+
+static VNET_DEFINE(int, dyn_keep_states);
+#define V_dyn_keep_states VNET(dyn_keep_states)
+
/*
* Timeouts for various events in handing dynamic rules.
*/
@@ -234,6 +239,9 @@ SYSCTL_VNET_UINT(_net_inet_ip_fw, OID_AUTO, dyn_short_lifetime,
SYSCTL_VNET_UINT(_net_inet_ip_fw, OID_AUTO, dyn_keepalive,
CTLFLAG_RW, &VNET_NAME(dyn_keepalive), 0,
"Enable keepalives for dyn. rules");
+SYSCTL_VNET_UINT(_net_inet_ip_fw, OID_AUTO, dyn_keep_states,
+ CTLFLAG_RW, &VNET_NAME(dyn_keep_states), 0,
+ "Do not flush dynamic states on rule deletion");
SYSEND
@@ -307,6 +315,7 @@ print_dyn_rule_flags(struct ipfw_flow_id *id, int dyn_type, int log_flags,
print_dyn_rule_flags(id, dtype, LOG_DEBUG, prefix, postfix)
#define TIME_LEQ(a,b) ((int)((a)-(b)) <= 0)
+#define TIME_LE(a,b) ((int)((a)-(b)) < 0)
/*
* Lookup a dynamic rule, locked version.
@@ -1100,6 +1109,20 @@ check_dyn_rules(struct ip_fw_chain *chain, struct ip_fw *rule,
if ((TIME_LEQ(q->expire, time_uptime)) ||
((rule != NULL) && (q->rule == rule)) ||
((set != RESVD_SET) && (q->rule->set == set))) {
+ if (TIME_LE(time_uptime, q->expire) &&
+ q->dyn_type == O_KEEP_STATE &&
+ V_dyn_keep_states != 0) {
+ /*
+ * Do not delete state if
+ * it is not expired and
+ * dyn_keep_states is ON.
+ * However we need to re-link it
+ * to any other stable rule
+ */
+ q->rule = chain->default_rule;
+ NEXT_RULE();
+ }
+
/* Unlink q from current list */
q_next = q->next;
if (q == V_ipfw_dyn_v[i].head)
OpenPOWER on IntegriCloud