summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>2009-07-25 06:42:42 +0000
committerjulian <julian@FreeBSD.org>2009-07-25 06:42:42 +0000
commit5ae2162b7c0fd69907ef464cd8eb2647ed5f441b (patch)
treec1dff88d0b07dc3515d0fa3713a91d6e5370ef3a
parent7611813d491ae802fa004045339be16cf248330f (diff)
downloadFreeBSD-src-5ae2162b7c0fd69907ef464cd8eb2647ed5f441b.zip
FreeBSD-src-5ae2162b7c0fd69907ef464cd8eb2647ed5f441b.tar.gz
Catch ipfw up to the rest of the vimage code.
It got left behind when it moved to its new location. Approved by: re (kensmith)
-rw-r--r--sys/netinet/ipfw/ip_fw2.c272
1 files changed, 163 insertions, 109 deletions
diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c
index b1e8480..82c5381 100644
--- a/sys/netinet/ipfw/ip_fw2.c
+++ b/sys/netinet/ipfw/ip_fw2.c
@@ -152,6 +152,8 @@ struct table_entry {
static VNET_DEFINE(int, autoinc_step);
#define V_autoinc_step VNET(autoinc_step)
+static VNET_DEFINE(int, fw_deny_unknown_exthdrs);
+#define V_fw_deny_unknown_exthdrs VNET(fw_deny_unknown_exthdrs)
extern int ipfw_chg_hook(SYSCTL_HANDLER_ARGS);
@@ -161,24 +163,38 @@ SYSCTL_VNET_PROC(_net_inet_ip_fw, OID_AUTO, enable,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_enable), 0,
ipfw_chg_hook, "I", "Enable ipfw");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, autoinc_step,
- CTLFLAG_RW, &VNET_NAME(autoinc_step), 0, "Rule number auto-increment step");
+ CTLFLAG_RW, &VNET_NAME(autoinc_step), 0,
+ "Rule number auto-increment step");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, one_pass,
CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_one_pass), 0,
"Only do a single pass through ipfw when using dummynet(4)");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, verbose,
- CTLFLAG_RW | CTLFLAG_SECURE3,
- &VNET_NAME(fw_verbose), 0, "Log matches to ipfw rules");
+ CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_verbose), 0,
+ "Log matches to ipfw rules");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit,
CTLFLAG_RW, &VNET_NAME(verbose_limit), 0,
"Set upper limit of matches of ipfw rules logged");
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
- NULL, IPFW_DEFAULT_RULE, "The default/max possible rule number.");
+ NULL, IPFW_DEFAULT_RULE,
+ "The default/max possible rule number.");
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD,
- NULL, IPFW_TABLES_MAX, "The maximum number of tables.");
+ NULL, IPFW_TABLES_MAX,
+ "The maximum number of tables.");
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN,
- &default_to_accept, 0, "Make the default rule accept all packets.");
+ &default_to_accept, 0,
+ "Make the default rule accept all packets.");
TUNABLE_INT("net.inet.ip.fw.default_to_accept", &default_to_accept);
-#endif /* SYSCTL_NODE */
+#ifdef INET6
+SYSCTL_DECL(_net_inet6_ip6);
+SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
+SYSCTL_VNET_PROC(_net_inet6_ip6_fw, OID_AUTO, enable,
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw6_enable), 0,
+ ipfw_chg_hook, "I", "Enable ipfw+6");
+SYSCTL_VNET_INT(_net_inet6_ip6_fw, OID_AUTO, deny_unknown_exthdrs,
+ CTLFLAG_RW | CTLFLAG_SECURE, &VNET_NAME(fw_deny_unknown_exthdrs), 0,
+ "Deny packets with unknown IPv6 Extension Headers");
+#endif
+#endif
/*
* Description of dynamic rules.
@@ -277,16 +293,20 @@ static VNET_DEFINE(u_int32_t, dyn_max); /* max # of dynamic rules */
#ifdef SYSCTL_NODE
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, dyn_buckets,
- CTLFLAG_RW, &VNET_NAME(dyn_buckets), 0, "Number of dyn. buckets");
+ CTLFLAG_RW, &VNET_NAME(dyn_buckets), 0,
+ "Number of dyn. buckets");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, curr_dyn_buckets,
CTLFLAG_RD, &VNET_NAME(curr_dyn_buckets), 0,
"Current Number of dyn. buckets");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, dyn_count,
- CTLFLAG_RD, &VNET_NAME(dyn_count), 0, "Number of dyn. rules");
+ CTLFLAG_RD, &VNET_NAME(dyn_count), 0,
+ "Number of dyn. rules");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, dyn_max,
- CTLFLAG_RW, &VNET_NAME(dyn_max), 0, "Max number of dyn. rules");
+ CTLFLAG_RW, &VNET_NAME(dyn_max), 0,
+ "Max number of dyn. rules");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, static_count,
- CTLFLAG_RD, &VNET_NAME(static_count), 0, "Number of static rules");
+ CTLFLAG_RD, &VNET_NAME(static_count), 0,
+ "Number of static rules");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, dyn_ack_lifetime,
CTLFLAG_RW, &VNET_NAME(dyn_ack_lifetime), 0,
"Lifetime of dyn. rules for acks");
@@ -310,21 +330,6 @@ SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, dyn_keepalive,
"Enable keepalives for dyn. rules");
#endif /* SYSCTL_NODE */
-#ifdef INET6
-/*
- * IPv6 specific variables
- */
-#ifdef SYSCTL_NODE
-SYSCTL_DECL(_net_inet6_ip6);
-#endif /* SYSCTL_NODE */
-
-static struct sysctl_ctx_list ip6_fw_sysctl_ctx;
-static struct sysctl_oid *ip6_fw_sysctl_tree;
-#endif /* INET6 */
-
-static VNET_DEFINE(int, fw_deny_unknown_exthdrs);
-#define V_fw_deny_unknown_exthdrs VNET(fw_deny_unknown_exthdrs)
-
/*
* L3HDR maps an ipv4 pointer into a layer3 header pointer of type T
* Other macros just cast void * into the appropriate type
@@ -4511,17 +4516,22 @@ ipfw_ctl(struct sockopt *sopt)
#undef RULE_MAXSIZE
}
+
/*
* This procedure is only used to handle keepalives. It is invoked
* every dyn_keepalive_period
*/
static void
-ipfw_tick(void * __unused unused)
+ipfw_tick(void * vnetx)
{
struct mbuf *m0, *m, *mnext, **mtailp;
int i;
ipfw_dyn_rule *q;
+#ifdef VIMAGE
+ struct vnet *vp = vnetx;
+#endif
+ CURVNET_SET(vp);
if (V_dyn_keepalive == 0 || V_ipfw_dyn_v == NULL || V_dyn_count == 0)
goto done;
@@ -4566,14 +4576,100 @@ ipfw_tick(void * __unused unused)
}
done:
callout_reset(&V_ipfw_timeout, V_dyn_keepalive_period * hz,
- ipfw_tick, NULL);
+ ipfw_tick, vnetx);
+ CURVNET_RESTORE();
}
+
+
+/****************
+ * Stuff that must be initialised only on boot or module load
+ */
int
ipfw_init(void)
{
- struct ip_fw default_rule;
+ int error = 0;
+
+ ipfw_dyn_rule_zone = uma_zcreate("IPFW dynamic rule",
+ sizeof(ipfw_dyn_rule), NULL, NULL, NULL, NULL,
+ UMA_ALIGN_PTR, 0);
+
+ IPFW_DYN_LOCK_INIT();
+ /*
+ * Only print out this stuff the first time around,
+ * when called from the sysinit code.
+ */
+ printf("ipfw2 "
+#ifdef INET6
+ "(+ipv6) "
+#endif
+ "initialized, divert %s, nat %s, "
+ "rule-based forwarding "
+#ifdef IPFIREWALL_FORWARD
+ "enabled, "
+#else
+ "disabled, "
+#endif
+ "default to %s, logging ",
+#ifdef IPDIVERT
+ "enabled",
+#else
+ "loadable",
+#endif
+#ifdef IPFIREWALL_NAT
+ "enabled",
+#else
+ "loadable",
+#endif
+ default_to_accept ? "accept" : "deny");
+
+ /*
+ * Note: V_xxx variables can be accessed here but the iattach()
+ * may not have been called yet for the VIMGE case.
+ * Tuneables will have been processed.
+ */
+ if (V_fw_verbose == 0)
+ printf("disabled\n");
+ else if (V_verbose_limit == 0)
+ printf("unlimited\n");
+ else
+ printf("limited to %d packets/entry by default\n",
+ V_verbose_limit);
+
+ /*
+ * Other things that are only done the first time.
+ * (now that we a re cuaranteed of success).
+ */
+ ip_fw_ctl_ptr = ipfw_ctl;
+ ip_fw_chk_ptr = ipfw_chk;
+ return (error);
+}
+
+/****************
+ * Stuff that must be initialised for every instance
+ * (including the forst of course).
+ */
+static int
+vnet_ipfw_init(const void *unused)
+{
int error;
+ struct ip_fw default_rule;
+
+ /* First set up some values that are compile time options */
+#ifdef IPFIREWALL_VERBOSE
+ V_fw_verbose = 1;
+#endif
+#ifdef IPFIREWALL_VERBOSE_LIMIT
+ V_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
+#endif
+
+ error = init_tables(&V_layer3_chain);
+ if (error) {
+ panic("init_tables"); /* XXX Marko fix this ! */
+ }
+#ifdef IPFIREWALL_NAT
+ LIST_INIT(&V_layer3_chain.nat);
+#endif
V_autoinc_step = 100; /* bounded to 1..1000 in add_rule() */
@@ -4596,127 +4692,85 @@ ipfw_init(void)
V_fw_deny_unknown_exthdrs = 1;
-#ifdef INET6
- /* Setup IPv6 fw sysctl tree. */
- sysctl_ctx_init(&ip6_fw_sysctl_ctx);
- ip6_fw_sysctl_tree = SYSCTL_ADD_NODE(&ip6_fw_sysctl_ctx,
- SYSCTL_STATIC_CHILDREN(_net_inet6_ip6), OID_AUTO, "fw",
- CTLFLAG_RW | CTLFLAG_SECURE, 0, "Firewall");
- SYSCTL_ADD_PROC(&ip6_fw_sysctl_ctx, SYSCTL_CHILDREN(ip6_fw_sysctl_tree),
- OID_AUTO, "enable", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3,
- &V_fw6_enable, 0, ipfw_chg_hook, "I", "Enable ipfw+6");
- SYSCTL_ADD_INT(&ip6_fw_sysctl_ctx, SYSCTL_CHILDREN(ip6_fw_sysctl_tree),
- OID_AUTO, "deny_unknown_exthdrs", CTLFLAG_RW | CTLFLAG_SECURE,
- &V_fw_deny_unknown_exthdrs, 0,
- "Deny packets with unknown IPv6 Extension Headers");
-#endif
-
V_layer3_chain.rules = NULL;
IPFW_LOCK_INIT(&V_layer3_chain);
- ipfw_dyn_rule_zone = uma_zcreate("IPFW dynamic rule",
- sizeof(ipfw_dyn_rule), NULL, NULL, NULL, NULL,
- UMA_ALIGN_PTR, 0);
- IPFW_DYN_LOCK_INIT();
callout_init(&V_ipfw_timeout, CALLOUT_MPSAFE);
bzero(&default_rule, sizeof default_rule);
-
default_rule.act_ofs = 0;
default_rule.rulenum = IPFW_DEFAULT_RULE;
default_rule.cmd_len = 1;
default_rule.set = RESVD_SET;
-
default_rule.cmd[0].len = 1;
default_rule.cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
-
error = add_rule(&V_layer3_chain, &default_rule);
+
if (error != 0) {
printf("ipfw2: error %u initializing default rule "
"(support disabled)\n", error);
- IPFW_DYN_LOCK_DESTROY();
IPFW_LOCK_DESTROY(&V_layer3_chain);
- uma_zdestroy(ipfw_dyn_rule_zone);
+ printf("leaving ipfw_iattach (1) with error %d\n", error);
return (error);
}
ip_fw_default_rule = V_layer3_chain.rules;
- printf("ipfw2 "
-#ifdef INET6
- "(+ipv6) "
-#endif
- "initialized, divert %s, nat %s, "
- "rule-based forwarding "
-#ifdef IPFIREWALL_FORWARD
- "enabled, "
-#else
- "disabled, "
-#endif
- "default to %s, logging ",
-#ifdef IPDIVERT
- "enabled",
-#else
- "loadable",
-#endif
-#ifdef IPFIREWALL_NAT
- "enabled",
-#else
- "loadable",
-#endif
-
- default_rule.cmd[0].opcode == O_ACCEPT ? "accept" : "deny");
-#ifdef IPFIREWALL_VERBOSE
- V_fw_verbose = 1;
-#endif
-#ifdef IPFIREWALL_VERBOSE_LIMIT
- V_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
-#endif
- if (V_fw_verbose == 0)
- printf("disabled\n");
- else if (V_verbose_limit == 0)
- printf("unlimited\n");
- else
- printf("limited to %d packets/entry by default\n",
- V_verbose_limit);
-
- error = init_tables(&V_layer3_chain);
if (error) {
- IPFW_DYN_LOCK_DESTROY();
IPFW_LOCK_DESTROY(&V_layer3_chain);
- uma_zdestroy(ipfw_dyn_rule_zone);
+ printf("leaving ipfw_iattach (2) with error %d\n", error);
return (error);
}
- ip_fw_ctl_ptr = ipfw_ctl;
- ip_fw_chk_ptr = ipfw_chk;
+#ifdef VIMAGE /* want a better way to do this */
+ callout_reset(&V_ipfw_timeout, hz, ipfw_tick, curvnet);
+#else
callout_reset(&V_ipfw_timeout, hz, ipfw_tick, NULL);
- LIST_INIT(&V_layer3_chain.nat);
+#endif
+
+ /* First set up some values that are compile time options */
return (0);
}
+/**********************
+ * Called for the removal of the last instance only on module unload.
+ */
void
ipfw_destroy(void)
{
- struct ip_fw *reap;
-
ip_fw_chk_ptr = NULL;
ip_fw_ctl_ptr = NULL;
+ uma_zdestroy(ipfw_dyn_rule_zone);
+ IPFW_DYN_LOCK_DESTROY();
+ printf("IP firewall unloaded\n");
+}
+
+/***********************
+ * Called for the removal of each instance.
+ */
+static int
+vnet_ipfw_uninit(const void *unused)
+{
+ struct ip_fw *reap;
+
callout_drain(&V_ipfw_timeout);
IPFW_WLOCK(&V_layer3_chain);
flush_tables(&V_layer3_chain);
+ V_layer3_chain.reap = NULL;
free_chain(&V_layer3_chain, 1 /* kill default rule */);
reap = V_layer3_chain.reap;
+ V_layer3_chain.reap = NULL;
IPFW_WUNLOCK(&V_layer3_chain);
- reap_rules(reap);
- IPFW_DYN_LOCK_DESTROY();
- uma_zdestroy(ipfw_dyn_rule_zone);
+ if (reap != NULL)
+ reap_rules(reap);
+ IPFW_LOCK_DESTROY(&V_layer3_chain);
if (V_ipfw_dyn_v != NULL)
free(V_ipfw_dyn_v, M_IPFW);
- IPFW_LOCK_DESTROY(&V_layer3_chain);
+ return 0;
+}
-#ifdef INET6
- /* Free IPv6 fw sysctl tree. */
- sysctl_ctx_free(&ip6_fw_sysctl_ctx);
-#endif
+VNET_SYSINIT(vnet_ipfw_init, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY,
+ vnet_ipfw_init, NULL);
- printf("IP firewall unloaded\n");
-}
+VNET_SYSUNINIT(vnet_ipfw_uninit, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY,
+ vnet_ipfw_uninit, NULL);
+
+
OpenPOWER on IntegriCloud