vimage patches and example run.

Norikatsu Shigemura nork at ninth-nine.com
Sat May 17 02:44:03 UTC 2008


On Sat, 17 May 2008 11:32:01 +0900
Norikatsu Shigemura <nork at freebsd.org> wrote:
> 	Please replace my attached patches for your vimage.diff.

	Sorry. I forgot to attach patches.
-------------- next part --------------
--- sys/netinet/ip_fw.h.orig	2008-05-10 16:10:53.000000000 +0900
+++ sys/netinet/ip_fw.h	2008-05-17 10:49:58.974783431 +0900
@@ -28,6 +28,9 @@
 #ifndef _IPFW2_H
 #define _IPFW2_H
 
+#include <sys/rwlock.h>
+#include <net/radix.h>
+
 /*
  * The kernel representation of ipfw rules is made of a list of
  * 'instructions' (for all practical purposes equivalent to BPF
@@ -550,6 +553,34 @@
  */
 #ifdef _KERNEL
 
+/*
+ * Data structure to cache our ucred related
+ * information. This structure only gets used if
+ * the user specified UID/GID based constraints in
+ * a firewall rule.
+ */
+struct ip_fw_ugid {
+	gid_t		fw_groups[NGROUPS];
+	int		fw_ngroups;
+	uid_t		fw_uid;
+	int		fw_prid;
+};
+
+#define	IPFW_TABLES_MAX		128
+struct ip_fw_chain {
+	struct ip_fw	*rules;		/* list of rules */
+	struct ip_fw	*reap;		/* list of rules to reap */
+	LIST_HEAD(, cfg_nat) nat;       /* list of nat entries */
+	struct radix_node_head *tables[IPFW_TABLES_MAX];
+	struct rwlock	rwmtx;
+};
+
+struct table_entry {
+	struct radix_node	rn[2];
+	struct sockaddr_in	addr, mask;
+	u_int32_t		value;
+};
+
 /* Return values from ipfw_chk() */
 enum {
 	IP_FW_PASS = 0,
@@ -619,11 +650,14 @@
 
 typedef int ip_fw_ctl_t(struct sockopt *);
 extern ip_fw_ctl_t *ip_fw_ctl_ptr;
+
+#ifndef VIMAGE
 extern int fw_one_pass;
 extern int fw_enable;
 #ifdef INET6
 extern int fw6_enable;
 #endif
+#endif
 
 /* For kernel ipfw_ether and ipfw_bridge. */
 typedef	int ip_fw_chk_t(struct ip_fw_args *args);
@@ -632,14 +666,6 @@
 
 #ifdef IPFW_INTERNAL
 
-#define	IPFW_TABLES_MAX		128
-struct ip_fw_chain {
-	struct ip_fw	*rules;		/* list of rules */
-	struct ip_fw	*reap;		/* list of rules to reap */
-	LIST_HEAD(, cfg_nat) nat;       /* list of nat entries */
-	struct radix_node_head *tables[IPFW_TABLES_MAX];
-	struct rwlock	rwmtx;
-};
 #define	IPFW_LOCK_INIT(_chain) \
 	rw_init(&(_chain)->rwmtx, "IPFW static rules")
 #define	IPFW_LOCK_DESTROY(_chain)	rw_destroy(&(_chain)->rwmtx)
@@ -662,5 +688,89 @@
 typedef int ipfw_nat_cfg_t(struct sockopt *);
 #endif
 
+/*
+ * Stack virtualization support.
+ */
+#ifdef VIMAGE
+struct vnet_ipfw {
+	int	_fw_one_pass;
+	int	_fw_enable;
+	int	_fw6_enable;
+
+	u_int32_t _set_disable;
+	int	_fw_deny_unknown_exthdrs;
+	int	_fw_verbose;
+	int	_verbose_limit;
+	int	_fw_debug;
+	int	_autoinc_step;
+
+	ipfw_dyn_rule **_ipfw_dyn_v;
+	struct ip_fw_chain _layer3_chain;
+	u_int32_t _dyn_buckets;
+	u_int32_t _curr_dyn_buckets;
+
+	u_int32_t _dyn_ack_lifetime;
+	u_int32_t _dyn_syn_lifetime;
+	u_int32_t _dyn_fin_lifetime;
+	u_int32_t _dyn_rst_lifetime;
+	u_int32_t _dyn_udp_lifetime;
+	u_int32_t _dyn_short_lifetime;
+	u_int32_t _dyn_keepalive_interval;
+	u_int32_t _dyn_keepalive_period;
+	u_int32_t _dyn_keepalive;
+	u_int32_t _static_count;
+	u_int32_t _static_len;
+	u_int32_t _dyn_count;
+	u_int32_t _dyn_max;
+
+	u_int64_t _norule_counter;
+
+	struct callout _ipfw_timeout;
+};
+#endif
+
+/*
+ * Symbol translation macros
+ */
+
+#define INIT_VNET_IPFW(vnet) \
+	INIT_FROM_VNET(vnet, VNET_MOD_IPFW, struct vnet_ipfw, vnet_ipfw)
+ 
+#define VNET_IPFW(sym)		VSYM(vnet_ipfw, sym)
+ 
+#define V_fw_one_pass		VNET_IPFW(fw_one_pass)
+#define V_fw_enable		VNET_IPFW(fw_enable)
+#define V_fw6_enable		VNET_IPFW(fw6_enable)
+
+#define V_set_disable		VNET_IPFW(set_disable)
+#define V_fw_deny_unknown_exthdrs VNET_IPFW(fw_deny_unknown_exthdrs)
+#define V_fw_verbose		VNET_IPFW(fw_verbose)
+#define V_verbose_limit		VNET_IPFW(verbose_limit)
+
+#define V_fw_debug		VNET_IPFW(fw_debug)
+#define V_autoinc_step		VNET_IPFW(autoinc_step)
+
+#define V_ipfw_dyn_v		VNET_IPFW(ipfw_dyn_v)
+#define V_layer3_chain		VNET_IPFW(layer3_chain)
+#define V_dyn_buckets		VNET_IPFW(dyn_buckets)
+#define V_curr_dyn_buckets	VNET_IPFW(curr_dyn_buckets)
+
+#define V_dyn_ack_lifetime	VNET_IPFW(dyn_ack_lifetime)
+#define V_dyn_syn_lifetime	VNET_IPFW(dyn_syn_lifetime)
+#define V_dyn_fin_lifetime	VNET_IPFW(dyn_fin_lifetime)
+#define V_dyn_rst_lifetime	VNET_IPFW(dyn_rst_lifetime)
+#define V_dyn_udp_lifetime	VNET_IPFW(dyn_udp_lifetime)
+#define V_dyn_short_lifetime	VNET_IPFW(dyn_short_lifetime)
+#define V_dyn_keepalive_interval VNET_IPFW(dyn_keepalive_interval)
+#define V_dyn_keepalive_period	VNET_IPFW(dyn_keepalive_period)
+#define V_dyn_keepalive		VNET_IPFW(dyn_keepalive)
+#define V_static_count		VNET_IPFW(static_count)
+#define V_static_len		VNET_IPFW(static_len)
+#define V_dyn_count		VNET_IPFW(dyn_count)
+#define V_dyn_max		VNET_IPFW(dyn_max)
+
+#define V_norule_counter	VNET_IPFW(norule_counter)
+#define V_ipfw_timeout		VNET_IPFW(ipfw_timeout)
+
 #endif /* _KERNEL */
 #endif /* _IPFW2_H */
-------------- next part --------------
--- sys/netinet/ip_fw2.c.orig	2008-05-10 16:10:53.000000000 +0900
+++ sys/netinet/ip_fw2.c	2008-05-17 11:13:34.347364537 +0900
@@ -45,6 +45,7 @@
 #include "opt_inet6.h"
 #include "opt_ipsec.h"
 #include "opt_mac.h"
+#include "opt_vimage.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -64,6 +65,9 @@
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
 #include <sys/ucred.h>
+#include <sys/vimage.h>
+
+#include <net/vnet.h>
 #include <net/if.h>
 #include <net/radix.h>
 #include <net/route.h>
@@ -71,6 +75,7 @@
 
 #define	IPFW_INTERNAL	/* Access to protected data structures in ip_fw.h. */
 
+#include <netinet/vinet.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/in_var.h>
@@ -106,6 +111,11 @@
 
 #include <security/mac/mac_framework.h>
 
+static int	vnet_ipfw_iattach(const void *);
+static int	vnet_ipfw_idetach(const void *);
+
+VNET_MOD_DECLARE(IPFW, ipfw, vnet_ipfw_iattach, vnet_ipfw_idetach, INET, NULL)
+
 /*
  * set_disable contains one bit per set value (0..31).
  * If the bit is set, all rules with the corresponding set
@@ -114,32 +124,24 @@
  * and CANNOT be disabled.
  * Rules in set RESVD_SET can only be deleted explicitly.
  */
+#ifndef VIMAGE
 static u_int32_t set_disable;
 
 static int fw_verbose;
 static int verbose_limit;
 
 static struct callout ipfw_timeout;
+#endif
+
 static uma_zone_t ipfw_dyn_rule_zone;
 #define	IPFW_DEFAULT_RULE	65535
 
 /*
- * Data structure to cache our ucred related
- * information. This structure only gets used if
- * the user specified UID/GID based constraints in
- * a firewall rule.
- */
-struct ip_fw_ugid {
-	gid_t		fw_groups[NGROUPS];
-	int		fw_ngroups;
-	uid_t		fw_uid;
-	int		fw_prid;
-};
-
-/*
  * list of rules for layer 3
  */
+#ifndef VIMAGE
 struct ip_fw_chain layer3_chain;
+#endif
 
 MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's");
 MALLOC_DEFINE(M_IPFW_TBL, "ipfw_tbl", "IpFw tables");
@@ -150,35 +152,35 @@
 ipfw_nat_cfg_t *ipfw_nat_get_cfg_ptr;
 ipfw_nat_cfg_t *ipfw_nat_get_log_ptr;
 
-struct table_entry {
-	struct radix_node	rn[2];
-	struct sockaddr_in	addr, mask;
-	u_int32_t		value;
-};
-
-static int fw_debug = 1;
-static int autoinc_step = 100; /* bounded to 1..1000 in add_rule() */
+#ifndef VIMAGE
+static int fw_debug;
+static int autoinc_step;
+#endif
 
+#ifdef VIMAGE
+extern int ipfw_chg_hook(SYSCTL_HANDLER_V_ARGS);
+#else
 extern int ipfw_chg_hook(SYSCTL_HANDLER_ARGS);
+#endif
 
 #ifdef SYSCTL_NODE
 SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
-SYSCTL_PROC(_net_inet_ip_fw, OID_AUTO, enable,
-    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, &fw_enable, 0,
+SYSCTL_V_PROC(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, enable,
+    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, fw_enable, 0,
     ipfw_chg_hook, "I", "Enable ipfw");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, autoinc_step, CTLFLAG_RW,
-    &autoinc_step, 0, "Rule number autincrement step");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, one_pass,
-    CTLFLAG_RW | CTLFLAG_SECURE3,
-    &fw_one_pass, 0,
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, autoinc_step,
+    CTLFLAG_RW, autoinc_step, 0, "Rule number autincrement step");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, one_pass,
+    CTLFLAG_RW | CTLFLAG_SECURE3, fw_one_pass, 0,
     "Only do a single pass through ipfw when using dummynet(4)");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW,
-    &fw_debug, 0, "Enable printing of debug ip_fw statements");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose,
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW,
+    fw_debug, 0, "Enable printing of debug ip_fw statements");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, verbose,
     CTLFLAG_RW | CTLFLAG_SECURE3,
-    &fw_verbose, 0, "Log matches to ipfw rules");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW,
-    &verbose_limit, 0, "Set upper limit of matches of ipfw rules logged");
+    fw_verbose, 0, "Log matches to ipfw rules");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, verbose_limit,
+    CTLFLAG_RW,
+    verbose_limit, 0, "Set upper limit of matches of ipfw rules logged");
 
 /*
  * Description of dynamic rules.
@@ -216,9 +218,11 @@
  * obey the 'randomized match', and we do not do multiple
  * passes through the firewall. XXX check the latter!!!
  */
+#ifndef VIMAGE
 static ipfw_dyn_rule **ipfw_dyn_v = NULL;
-static u_int32_t dyn_buckets = 256; /* must be power of 2 */
-static u_int32_t curr_dyn_buckets = 256; /* must be power of 2 */
+static u_int32_t dyn_buckets;
+static u_int32_t curr_dyn_buckets;
+#endif
 
 static struct mtx ipfw_dyn_mtx;		/* mutex guarding dynamic rules */
 #define	IPFW_DYN_LOCK_INIT() \
@@ -231,12 +235,14 @@
 /*
  * Timeouts for various events in handing dynamic rules.
  */
-static u_int32_t dyn_ack_lifetime = 300;
-static u_int32_t dyn_syn_lifetime = 20;
-static u_int32_t dyn_fin_lifetime = 1;
-static u_int32_t dyn_rst_lifetime = 1;
-static u_int32_t dyn_udp_lifetime = 10;
-static u_int32_t dyn_short_lifetime = 5;
+#ifndef VIMAGE
+static u_int32_t dyn_ack_lifetime;
+static u_int32_t dyn_syn_lifetime;
+static u_int32_t dyn_fin_lifetime;
+static u_int32_t dyn_rst_lifetime;
+static u_int32_t dyn_udp_lifetime;
+static u_int32_t dyn_short_lifetime;
+#endif
 
 /*
  * Keepalives are sent if dyn_keepalive is set. They are sent every
@@ -245,54 +251,65 @@
  * dyn_rst_lifetime and dyn_fin_lifetime should be strictly lower
  * than dyn_keepalive_period.
  */
-
-static u_int32_t dyn_keepalive_interval = 20;
-static u_int32_t dyn_keepalive_period = 5;
-static u_int32_t dyn_keepalive = 1;	/* do send keepalives */
+#ifndef VIMAGE
+static u_int32_t dyn_keepalive_interval;
+static u_int32_t dyn_keepalive_period;
+static u_int32_t dyn_keepalive;
 
 static u_int32_t static_count;	/* # of static rules */
 static u_int32_t static_len;	/* size in bytes of static rules */
-static u_int32_t dyn_count;		/* # of dynamic rules */
-static u_int32_t dyn_max = 4096;	/* max # of dynamic rules */
+static u_int32_t dyn_count;	/* # of dynamic rules */
+static u_int32_t dyn_max;	/* max # of dynamic rules */
+#endif
 
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_buckets, CTLFLAG_RW,
-    &dyn_buckets, 0, "Number of dyn. buckets");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, curr_dyn_buckets, CTLFLAG_RD,
-    &curr_dyn_buckets, 0, "Current Number of dyn. buckets");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_count, CTLFLAG_RD,
-    &dyn_count, 0, "Number of dyn. rules");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_max, CTLFLAG_RW,
-    &dyn_max, 0, "Max number of dyn. rules");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, static_count, CTLFLAG_RD,
-    &static_count, 0, "Number of static rules");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_ack_lifetime, CTLFLAG_RW,
-    &dyn_ack_lifetime, 0, "Lifetime of dyn. rules for acks");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_syn_lifetime, CTLFLAG_RW,
-    &dyn_syn_lifetime, 0, "Lifetime of dyn. rules for syn");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_fin_lifetime, CTLFLAG_RW,
-    &dyn_fin_lifetime, 0, "Lifetime of dyn. rules for fin");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_rst_lifetime, CTLFLAG_RW,
-    &dyn_rst_lifetime, 0, "Lifetime of dyn. rules for rst");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_udp_lifetime, CTLFLAG_RW,
-    &dyn_udp_lifetime, 0, "Lifetime of dyn. rules for UDP");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_short_lifetime, CTLFLAG_RW,
-    &dyn_short_lifetime, 0, "Lifetime of dyn. rules for other situations");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_keepalive, CTLFLAG_RW,
-    &dyn_keepalive, 0, "Enable keepalives for dyn. rules");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_buckets,
+    CTLFLAG_RW, dyn_buckets, 0, "Number of dyn. buckets");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, curr_dyn_buckets,
+    CTLFLAG_RD, curr_dyn_buckets, 0, "Current Number of dyn. buckets");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_count,
+    CTLFLAG_RD, dyn_count, 0, "Number of dyn. rules");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_max,
+    CTLFLAG_RW, dyn_max, 0, "Max number of dyn. rules");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, static_count,
+    CTLFLAG_RD, static_count, 0, "Number of static rules");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_ack_lifetime,
+    CTLFLAG_RW, dyn_ack_lifetime, 0, "Lifetime of dyn. rules for acks");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_syn_lifetime,
+    CTLFLAG_RW, dyn_syn_lifetime, 0, "Lifetime of dyn. rules for syn");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_fin_lifetime,
+    CTLFLAG_RW, dyn_fin_lifetime, 0, "Lifetime of dyn. rules for fin");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_rst_lifetime,
+    CTLFLAG_RW, dyn_rst_lifetime, 0, "Lifetime of dyn. rules for rst");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_udp_lifetime,
+    CTLFLAG_RW, dyn_udp_lifetime, 0, "Lifetime of dyn. rules for UDP");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_short_lifetime,
+    CTLFLAG_RW, dyn_short_lifetime, 0,
+    "Lifetime of dyn. rules for other situations");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_keepalive,
+    CTLFLAG_RW, dyn_keepalive, 0, "Enable keepalives for dyn. rules");
+
+#ifndef VIMAGE
+static int fw_deny_unknown_exthdrs;
+#endif
 
 #ifdef INET6
 /*
  * IPv6 specific variables
  */
-SYSCTL_DECL(_net_inet6_ip6);
 
-static struct sysctl_ctx_list ip6_fw_sysctl_ctx;
-static struct sysctl_oid *ip6_fw_sysctl_tree;
+SYSCTL_DECL(_net_inet6_ip6);
+SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW | CTLFLAG_SECURE,
+	0, "Firewall");
+SYSCTL_V_PROC(V_NET, vnet_ipfw, _net_inet6_ip6_fw, OID_AUTO, enable,
+    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, fw6_enable, 0,
+    ipfw_chg_hook, "I", "Enable ipfw+6");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet6_ip6_fw, OID_AUTO,
+    deny_unknown_exthdrs, CTLFLAG_RW | CTLFLAG_SECURE,
+    fw_deny_unknown_exthdrs, 0,
+    "Deny packets with unknown IPv6 Extension Headers");
 #endif /* INET6 */
 #endif /* SYSCTL_NODE */
 
-static int fw_deny_unknown_exthdrs = 1;
-
 
 /*
  * L3HDR maps an ipv4 pointer into a layer3 header pointer of type T
@@ -562,12 +579,13 @@
 static int
 search_ip6_addr_net (struct in6_addr * ip6_addr)
 {
+	INIT_VNET_NET(curvnet);
 	struct ifnet *mdc;
 	struct ifaddr *mdc2;
 	struct in6_ifaddr *fdm;
 	struct in6_addr copia;
 
-	TAILQ_FOREACH(mdc, &ifnet, if_link)
+	TAILQ_FOREACH(mdc, &V_ifnet, if_link)
 		TAILQ_FOREACH(mdc2, &mdc->if_addrlist, ifa_list) {
 			if (mdc2->ifa_addr->sa_family == AF_INET6) {
 				fdm = (struct in6_ifaddr *)mdc2;
@@ -629,6 +647,7 @@
 	return 1;
 
 }
+
 static __inline int
 hash_packet6(struct ipfw_flow_id *id)
 {
@@ -739,7 +758,9 @@
 
 #endif /* INET6 */
 
+#ifndef VIMAGE
 static u_int64_t norule_counter;	/* counter for ipfw_log(NULL...) */
+#endif
 
 #define SNPARGS(buf, len) buf + len, sizeof(buf) > len ? sizeof(buf) - len : 0
 #define SNP(buf) buf, sizeof(buf)
@@ -753,6 +774,7 @@
     struct mbuf *m, struct ifnet *oif, u_short offset, uint32_t tablearg,
     struct ip *ip)
 {
+	INIT_VNET_IPFW(curvnet);
 	struct ether_header *eh = args->eh;
 	char *action;
 	int limit_reached = 0;
@@ -762,11 +784,11 @@
 	proto[0] = '\0';
 
 	if (f == NULL) {	/* bogus pkt */
-		if (verbose_limit != 0 && norule_counter >= verbose_limit)
+		if (V_verbose_limit != 0 && V_norule_counter >= V_verbose_limit)
 			return;
-		norule_counter++;
-		if (norule_counter == verbose_limit)
-			limit_reached = verbose_limit;
+		V_norule_counter++;
+		if (V_norule_counter == V_verbose_limit)
+			limit_reached = V_verbose_limit;
 		action = "Refuse";
 	} else {	/* O_LOG is the first action, find the real one */
 		ipfw_insn *cmd = ACTION_PTR(f);
@@ -1023,6 +1045,7 @@
 static __inline int
 hash_packet(struct ipfw_flow_id *id)
 {
+	INIT_VNET_IPFW(curvnet);
 	u_int32_t i;
 
 #ifdef INET6
@@ -1031,7 +1054,7 @@
 	else
 #endif /* INET6 */
 	i = (id->dst_ip) ^ (id->src_ip) ^ (id->dst_port) ^ (id->src_port);
-	i &= (curr_dyn_buckets - 1);
+	i &= (V_curr_dyn_buckets - 1);
 	return i;
 }
 
@@ -1049,12 +1072,12 @@
 		q->parent->count--;					\
 	DEB(printf("ipfw: unlink entry 0x%08x %d -> 0x%08x %d, %d left\n",\
 		(q->id.src_ip), (q->id.src_port),			\
-		(q->id.dst_ip), (q->id.dst_port), dyn_count-1 ); )	\
+		(q->id.dst_ip), (q->id.dst_port), V_dyn_count-1 ); )	\
 	if (prev != NULL)						\
 		prev->next = q = q->next;				\
 	else								\
 		head = q = q->next;					\
-	dyn_count--;							\
+	V_dyn_count--;							\
 	uma_zfree(ipfw_dyn_rule_zone, old_q); }
 
 #define TIME_LEQ(a,b)       ((int)((a)-(b)) <= 0)
@@ -1074,6 +1097,7 @@
 static void
 remove_dyn_rule(struct ip_fw *rule, ipfw_dyn_rule *keep_me)
 {
+	INIT_VNET_IPFW(curvnet);
 	static u_int32_t last_remove = 0;
 
 #define FORCE (keep_me == NULL)
@@ -1083,7 +1107,7 @@
 
 	IPFW_DYN_LOCK_ASSERT();
 
-	if (ipfw_dyn_v == NULL || dyn_count == 0)
+	if (V_ipfw_dyn_v == NULL || V_dyn_count == 0)
 		return;
 	/* do not expire more than once per second, it is useless */
 	if (!FORCE && last_remove == time_uptime)
@@ -1096,8 +1120,8 @@
 	 * them in a second pass.
 	 */
 next_pass:
-	for (i = 0 ; i < curr_dyn_buckets ; i++) {
-		for (prev=NULL, q = ipfw_dyn_v[i] ; q ; ) {
+	for (i = 0 ; i < V_curr_dyn_buckets ; i++) {
+		for (prev=NULL, q = V_ipfw_dyn_v[i] ; q ; ) {
 			/*
 			 * Logic can become complex here, so we split tests.
 			 */
@@ -1124,7 +1148,7 @@
 					goto next;
 			}
              if (q->dyn_type != O_LIMIT_PARENT || !q->count) {
-                     UNLINK_DYN_RULE(prev, ipfw_dyn_v[i], q);
+                     UNLINK_DYN_RULE(prev, V_ipfw_dyn_v[i], q);
                      continue;
              }
 next:
@@ -1144,6 +1168,7 @@
 lookup_dyn_rule_locked(struct ipfw_flow_id *pkt, int *match_direction,
     struct tcphdr *tcp)
 {
+	INIT_VNET_IPFW(curvnet);
 	/*
 	 * stateful ipfw extensions.
 	 * Lookup into dynamic session queue
@@ -1157,14 +1182,14 @@
 
 	IPFW_DYN_LOCK_ASSERT();
 
-	if (ipfw_dyn_v == NULL)
+	if (V_ipfw_dyn_v == NULL)
 		goto done;	/* not found */
 	i = hash_packet( pkt );
-	for (prev=NULL, q = ipfw_dyn_v[i] ; q != NULL ; ) {
+	for (prev=NULL, q = V_ipfw_dyn_v[i] ; q != NULL ; ) {
 		if (q->dyn_type == O_LIMIT_PARENT && q->count)
 			goto next;
 		if (TIME_LEQ( q->expire, time_uptime)) { /* expire entry */
-			UNLINK_DYN_RULE(prev, ipfw_dyn_v[i], q);
+			UNLINK_DYN_RULE(prev, V_ipfw_dyn_v[i], q);
 			continue;
 		}
 		if (pkt->proto == q->id.proto &&
@@ -1214,8 +1239,8 @@
 
 	if ( prev != NULL) { /* found and not in front */
 		prev->next = q->next;
-		q->next = ipfw_dyn_v[i];
-		ipfw_dyn_v[i] = q;
+		q->next = V_ipfw_dyn_v[i];
+		V_ipfw_dyn_v[i] = q;
 	}
 	if (pkt->proto == IPPROTO_TCP) { /* update state according to flags */
 		u_char flags = pkt->flags & (TH_FIN|TH_SYN|TH_RST);
@@ -1225,7 +1250,7 @@
 		q->state |= (dir == MATCH_FORWARD ) ? flags : (flags << 8);
 		switch (q->state) {
 		case TH_SYN:				/* opening */
-			q->expire = time_uptime + dyn_syn_lifetime;
+			q->expire = time_uptime + V_dyn_syn_lifetime;
 			break;
 
 		case BOTH_SYN:			/* move to established */
@@ -1248,13 +1273,13 @@
 				}
 			    }
 			}
-			q->expire = time_uptime + dyn_ack_lifetime;
+			q->expire = time_uptime + V_dyn_ack_lifetime;
 			break;
 
 		case BOTH_SYN | BOTH_FIN:	/* both sides closed */
-			if (dyn_fin_lifetime >= dyn_keepalive_period)
-				dyn_fin_lifetime = dyn_keepalive_period - 1;
-			q->expire = time_uptime + dyn_fin_lifetime;
+			if (V_dyn_fin_lifetime >= V_dyn_keepalive_period)
+				V_dyn_fin_lifetime = V_dyn_keepalive_period - 1;
+			q->expire = time_uptime + V_dyn_fin_lifetime;
 			break;
 
 		default:
@@ -1266,16 +1291,16 @@
 			if ( (q->state & ((TH_RST << 8)|TH_RST)) == 0)
 				printf("invalid state: 0x%x\n", q->state);
 #endif
-			if (dyn_rst_lifetime >= dyn_keepalive_period)
-				dyn_rst_lifetime = dyn_keepalive_period - 1;
-			q->expire = time_uptime + dyn_rst_lifetime;
+			if (V_dyn_rst_lifetime >= V_dyn_keepalive_period)
+				V_dyn_rst_lifetime = V_dyn_keepalive_period - 1;
+			q->expire = time_uptime + V_dyn_rst_lifetime;
 			break;
 		}
 	} else if (pkt->proto == IPPROTO_UDP) {
-		q->expire = time_uptime + dyn_udp_lifetime;
+		q->expire = time_uptime + V_dyn_udp_lifetime;
 	} else {
 		/* other protocols */
-		q->expire = time_uptime + dyn_short_lifetime;
+		q->expire = time_uptime + V_dyn_short_lifetime;
 	}
 done:
 	if (match_direction)
@@ -1300,6 +1325,7 @@
 static void
 realloc_dynamic_table(void)
 {
+	INIT_VNET_IPFW(curvnet);
 	IPFW_DYN_LOCK_ASSERT();
 
 	/*
@@ -1308,21 +1334,21 @@
 	 * default to 1024.
 	 */
 
-	if (dyn_buckets > 65536)
-		dyn_buckets = 1024;
-	if ((dyn_buckets & (dyn_buckets-1)) != 0) { /* not a power of 2 */
-		dyn_buckets = curr_dyn_buckets; /* reset */
+	if (V_dyn_buckets > 65536)
+		V_dyn_buckets = 1024;
+	if ((V_dyn_buckets & (V_dyn_buckets-1)) != 0) { /* not a power of 2 */
+		V_dyn_buckets = V_curr_dyn_buckets; /* reset */
 		return;
 	}
-	curr_dyn_buckets = dyn_buckets;
-	if (ipfw_dyn_v != NULL)
-		free(ipfw_dyn_v, M_IPFW);
+	V_curr_dyn_buckets = V_dyn_buckets;
+	if (V_ipfw_dyn_v != NULL)
+		free(V_ipfw_dyn_v, M_IPFW);
 	for (;;) {
-		ipfw_dyn_v = malloc(curr_dyn_buckets * sizeof(ipfw_dyn_rule *),
+		V_ipfw_dyn_v = malloc(V_curr_dyn_buckets * sizeof(ipfw_dyn_rule *),
 		       M_IPFW, M_NOWAIT | M_ZERO);
-		if (ipfw_dyn_v != NULL || curr_dyn_buckets <= 2)
+		if (V_ipfw_dyn_v != NULL || V_curr_dyn_buckets <= 2)
 			break;
-		curr_dyn_buckets /= 2;
+		V_curr_dyn_buckets /= 2;
 	}
 }
 
@@ -1339,15 +1365,16 @@
 static ipfw_dyn_rule *
 add_dyn_rule(struct ipfw_flow_id *id, u_int8_t dyn_type, struct ip_fw *rule)
 {
+	INIT_VNET_IPFW(curvnet);
 	ipfw_dyn_rule *r;
 	int i;
 
 	IPFW_DYN_LOCK_ASSERT();
 
-	if (ipfw_dyn_v == NULL ||
-	    (dyn_count == 0 && dyn_buckets != curr_dyn_buckets)) {
+	if (V_ipfw_dyn_v == NULL ||
+	    (V_dyn_count == 0 && V_dyn_buckets != V_curr_dyn_buckets)) {
 		realloc_dynamic_table();
-		if (ipfw_dyn_v == NULL)
+		if (V_ipfw_dyn_v == NULL)
 			return NULL; /* failed ! */
 	}
 	i = hash_packet(id);
@@ -1369,21 +1396,21 @@
 	}
 
 	r->id = *id;
-	r->expire = time_uptime + dyn_syn_lifetime;
+	r->expire = time_uptime + V_dyn_syn_lifetime;
 	r->rule = rule;
 	r->dyn_type = dyn_type;
 	r->pcnt = r->bcnt = 0;
 	r->count = 0;
 
 	r->bucket = i;
-	r->next = ipfw_dyn_v[i];
-	ipfw_dyn_v[i] = r;
-	dyn_count++;
+	r->next = V_ipfw_dyn_v[i];
+	V_ipfw_dyn_v[i] = r;
+	V_dyn_count++;
 	DEB(printf("ipfw: add dyn entry ty %d 0x%08x %d -> 0x%08x %d, total %d\n",
 	   dyn_type,
 	   (r->id.src_ip), (r->id.src_port),
 	   (r->id.dst_ip), (r->id.dst_port),
-	   dyn_count ); )
+	   V_dyn_count ); )
 	return r;
 }
 
@@ -1394,15 +1421,16 @@
 static ipfw_dyn_rule *
 lookup_dyn_parent(struct ipfw_flow_id *pkt, struct ip_fw *rule)
 {
+	INIT_VNET_IPFW(curvnet);
 	ipfw_dyn_rule *q;
 	int i;
 
 	IPFW_DYN_LOCK_ASSERT();
 
-	if (ipfw_dyn_v) {
+	if (V_ipfw_dyn_v) {
 		int is_v6 = IS_IP6_FLOW_ID(pkt);
 		i = hash_packet( pkt );
-		for (q = ipfw_dyn_v[i] ; q != NULL ; q=q->next)
+		for (q = V_ipfw_dyn_v[i] ; q != NULL ; q=q->next)
 			if (q->dyn_type == O_LIMIT_PARENT &&
 			    rule== q->rule &&
 			    pkt->proto == q->id.proto &&
@@ -1419,7 +1447,7 @@
 				 pkt->dst_ip == q->id.dst_ip)
 			    )
 			) {
-				q->expire = time_uptime + dyn_short_lifetime;
+				q->expire = time_uptime + V_dyn_short_lifetime;
 				DEB(printf("ipfw: lookup_dyn_parent found 0x%p\n",q);)
 				return q;
 			}
@@ -1437,6 +1465,7 @@
 install_state(struct ip_fw *rule, ipfw_insn_limit *cmd,
     struct ip_fw_args *args, uint32_t tablearg)
 {
+	INIT_VNET_IPFW(curvnet);
 	static int last_log;
 	ipfw_dyn_rule *q;
 	struct in_addr da;
@@ -1466,11 +1495,11 @@
 		return (0);
 	}
 
-	if (dyn_count >= dyn_max)
+	if (V_dyn_count >= V_dyn_max)
 		/* Run out of slots, try to remove any expired rule. */
 		remove_dyn_rule(NULL, (ipfw_dyn_rule *)1);
 
-	if (dyn_count >= dyn_max) {
+	if (V_dyn_count >= V_dyn_max) {
 		if (last_log != time_uptime) {
 			last_log = time_uptime;
 			printf("ipfw: %s: Too many dynamic rules\n", __func__);
@@ -1532,7 +1561,7 @@
 			/* See if we can remove some expired rule. */
 			remove_dyn_rule(rule, parent);
 			if (parent->count >= conn_limit) {
-				if (fw_verbose && last_log != time_uptime) {
+				if (V_fw_verbose && last_log != time_uptime) {
 					last_log = time_uptime;
 #ifdef INET6
 					/*
@@ -1598,6 +1627,7 @@
 send_pkt(struct mbuf *replyto, struct ipfw_flow_id *id, u_int32_t seq,
     u_int32_t ack, int flags)
 {
+	INIT_VNET_INET(curvnet);
 	struct mbuf *m;
 	struct ip *ip;
 	struct tcphdr *tcp;
@@ -1675,7 +1705,7 @@
 	/*
 	 * now fill fields left out earlier
 	 */
-	ip->ip_ttl = ip_defttl;
+	ip->ip_ttl = V_ip_defttl;
 	ip->ip_len = m->m_pkthdr.len;
 	m->m_flags |= M_SKIP_FIREWALL;
 	return (m);
@@ -1765,6 +1795,7 @@
 add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
     uint8_t mlen, uint32_t value)
 {
+	INIT_VNET_IPFW(curvnet);
 	struct radix_node_head *rnh;
 	struct table_entry *ent;
 
@@ -1778,14 +1809,14 @@
 	ent->addr.sin_len = ent->mask.sin_len = 8;
 	ent->mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
 	ent->addr.sin_addr.s_addr = addr & ent->mask.sin_addr.s_addr;
-	IPFW_WLOCK(&layer3_chain);
+	IPFW_WLOCK(&V_layer3_chain);
 	if (rnh->rnh_addaddr(&ent->addr, &ent->mask, rnh, (void *)ent) ==
 	    NULL) {
-		IPFW_WUNLOCK(&layer3_chain);
+		IPFW_WUNLOCK(&V_layer3_chain);
 		free(ent, M_IPFW_TBL);
 		return (EEXIST);
 	}
-	IPFW_WUNLOCK(&layer3_chain);
+	IPFW_WUNLOCK(&V_layer3_chain);
 	return (0);
 }
 
@@ -1969,6 +2000,7 @@
     u_int16_t src_port, struct ip_fw_ugid *ugp, int *lookup,
     struct inpcb *inp)
 {
+	INIT_VNET_INET(curvnet);
 	struct inpcbinfo *pi;
 	int wildcard;
 	struct inpcb *pcb;
@@ -1996,10 +2028,10 @@
 		return (0);
 	if (proto == IPPROTO_TCP) {
 		wildcard = 0;
-		pi = &tcbinfo;
+		pi = &V_tcbinfo;
 	} else if (proto == IPPROTO_UDP) {
 		wildcard = INPLOOKUP_WILDCARD;
-		pi = &udbinfo;
+		pi = &V_udbinfo;
 	} else
 		return 0;
 	match = 0;
@@ -2085,6 +2117,9 @@
 int
 ipfw_chk(struct ip_fw_args *args)
 {
+	INIT_VNET_INET(curvnet);
+	INIT_VNET_IPFW(curvnet);
+
 	/*
 	 * Local variables holding state during the processing of a packet:
 	 *
@@ -2187,7 +2222,7 @@
 	 */
 	int dyn_dir = MATCH_UNKNOWN;
 	ipfw_dyn_rule *q = NULL;
-	struct ip_fw_chain *chain = &layer3_chain;
+	struct ip_fw_chain *chain = &V_layer3_chain;
 	struct m_tag *mtag;
 
 	/*
@@ -2291,7 +2326,7 @@
 					printf("IPFW2: IPV6 - Unknown Routing "
 					    "Header type(%d)\n",
 					    ((struct ip6_rthdr *)ulp)->ip6r_type);
-					if (fw_deny_unknown_exthdrs)
+					if (V_fw_deny_unknown_exthdrs)
 					    return (IP_FW_DENY);
 					break;
 				}
@@ -2315,7 +2350,7 @@
 				if (offset == 0) {
 					printf("IPFW2: IPV6 - Invalid Fragment "
 					    "Header\n");
-					if (fw_deny_unknown_exthdrs)
+					if (V_fw_deny_unknown_exthdrs)
 					    return (IP_FW_DENY);
 					break;
 				}
@@ -2387,7 +2422,7 @@
 			default:
 				printf("IPFW2: IPV6 - Unknown Extension "
 				    "Header(%d), ext_hd=%x\n", proto, ext_hd);
-				if (fw_deny_unknown_exthdrs)
+				if (V_fw_deny_unknown_exthdrs)
 				    return (IP_FW_DENY);
 				PULLUP_TO(hlen, ulp, struct ip6_ext);
 				break;
@@ -2468,7 +2503,7 @@
 		 * XXX should not happen here, but optimized out in
 		 * the caller.
 		 */
-		if (fw_one_pass) {
+		if (V_fw_one_pass) {
 			IPFW_RUNLOCK(chain);
 			return (IP_FW_PASS);
 		}
@@ -2513,7 +2548,7 @@
 		int l, cmdlen, skip_or; /* skip rest of OR block */
 
 again:
-		if (set_disable & (1 << f->set) )
+		if (V_set_disable & (1 << f->set) )
 			continue;
 
 		skip_or = 0;
@@ -2899,7 +2934,7 @@
 			}
 
 			case O_LOG:
-				if (fw_verbose)
+				if (V_fw_verbose)
 					ipfw_log(f, hlen, args, m,
 					    oif, offset, tablearg, ip);
 				match = 1;
@@ -3315,7 +3350,7 @@
 					if (t == NULL) {
 						nat_id = (cmd->arg1 == IP_FW_TABLEARG) ?
 						    tablearg : cmd->arg1;
-						LOOKUP_NAT(layer3_chain, nat_id, t);
+						LOOKUP_NAT(V_layer3_chain, nat_id, t);
 						if (t == NULL) {
 							retval = IP_FW_DENY;
 							goto done;
@@ -3362,7 +3397,7 @@
 	return (retval);
 
 pullup_failed:
-	if (fw_verbose)
+	if (V_fw_verbose)
 		printf("ipfw: pullup failed\n");
 	return (IP_FW_DENY);
 }
@@ -3390,6 +3425,7 @@
 static int
 add_rule(struct ip_fw_chain *chain, struct ip_fw *input_rule)
 {
+	INIT_VNET_IPFW(curvnet);
 	struct ip_fw *rule, *f, *prev;
 	int l = RULESIZE(input_rule);
 
@@ -3420,10 +3456,10 @@
 	 * If rulenum is 0, find highest numbered rule before the
 	 * default rule, and add autoinc_step
 	 */
-	if (autoinc_step < 1)
-		autoinc_step = 1;
-	else if (autoinc_step > 1000)
-		autoinc_step = 1000;
+	if (V_autoinc_step < 1)
+		V_autoinc_step = 1;
+	else if (V_autoinc_step > 1000)
+		V_autoinc_step = 1000;
 	if (rule->rulenum == 0) {
 		/*
 		 * locate the highest numbered rule before default
@@ -3433,8 +3469,8 @@
 				break;
 			rule->rulenum = f->rulenum;
 		}
-		if (rule->rulenum < IPFW_DEFAULT_RULE - autoinc_step)
-			rule->rulenum += autoinc_step;
+		if (rule->rulenum < IPFW_DEFAULT_RULE - V_autoinc_step)
+			rule->rulenum += V_autoinc_step;
 		input_rule->rulenum = rule->rulenum;
 	}
 
@@ -3455,11 +3491,11 @@
 	}
 	flush_rule_ptrs(chain);
 done:
-	static_count++;
-	static_len += l;
+	V_static_count++;
+	V_static_len += l;
 	IPFW_WUNLOCK(chain);
 	DEB(printf("ipfw: installed rule %d, static count now %d\n",
-		rule->rulenum, static_count);)
+		rule->rulenum, V_static_count);)
 	return (0);
 }
 
@@ -3475,6 +3511,7 @@
 remove_rule(struct ip_fw_chain *chain, struct ip_fw *rule,
     struct ip_fw *prev)
 {
+	INIT_VNET_IPFW(curvnet);
 	struct ip_fw *n;
 	int l = RULESIZE(rule);
 
@@ -3488,8 +3525,8 @@
 		chain->rules = n;
 	else
 		prev->next = n;
-	static_count--;
-	static_len -= l;
+	V_static_count--;
+	V_static_len -= l;
 
 	rule->next = chain->reap;
 	chain->reap = rule;
@@ -3689,6 +3726,7 @@
 static int
 zero_entry(struct ip_fw_chain *chain, u_int32_t arg, int log_only)
 {
+	INIT_VNET_IPFW(curvnet);
 	struct ip_fw *rule;
 	char *msg;
 
@@ -3703,7 +3741,7 @@
 
 	IPFW_WLOCK(chain);
 	if (rulenum == 0) {
-		norule_counter = 0;
+		V_norule_counter = 0;
 		for (rule = chain->rules; rule; rule = rule->next) {
 			/* Skip rules from another set. */
 			if (cmd == 1 && rule->set != set)
@@ -3737,7 +3775,7 @@
 	}
 	IPFW_WUNLOCK(chain);
 
-	if (fw_verbose)
+	if (V_fw_verbose)
 		log(LOG_SECURITY | LOG_NOTICE, msg, rulenum);
 	return (0);
 }
@@ -4056,6 +4094,7 @@
 static size_t
 ipfw_getrules(struct ip_fw_chain *chain, void *buf, size_t space)
 {
+	INIT_VNET_IPFW(curvnet);
 	char *bp = buf;
 	char *ep = bp + space;
 	struct ip_fw *rule;
@@ -4080,20 +4119,21 @@
 			 * in a wild attempt to keep the ABI the same.
 			 * Why do we do this on EVERY rule?
 			 */
-			bcopy(&set_disable, &(((struct ip_fw *)bp)->next_rule),
-			    sizeof(set_disable));
+			bcopy(&V_set_disable,
+			    &(((struct ip_fw *)bp)->next_rule),
+			    sizeof(V_set_disable));
 			if (((struct ip_fw *)bp)->timestamp)
 				((struct ip_fw *)bp)->timestamp += boot_seconds;
 			bp += i;
 		}
 	}
 	IPFW_RUNLOCK(chain);
-	if (ipfw_dyn_v) {
+	if (V_ipfw_dyn_v) {
 		ipfw_dyn_rule *p, *last = NULL;
 
 		IPFW_DYN_LOCK();
-		for (i = 0 ; i < curr_dyn_buckets; i++)
-			for (p = ipfw_dyn_v[i] ; p != NULL; p = p->next) {
+		for (i = 0 ; i < V_curr_dyn_buckets; i++)
+			for (p = V_ipfw_dyn_v[i] ; p != NULL; p = p->next) {
 				if (bp + sizeof *p <= ep) {
 					ipfw_dyn_rule *dst =
 						(ipfw_dyn_rule *)bp;
@@ -4136,6 +4176,7 @@
 static int
 ipfw_ctl(struct sockopt *sopt)
 {
+	INIT_VNET_IPFW(curvnet);
 #define	RULE_MAXSIZE	(256*sizeof(u_int32_t))
 	int error;
 	size_t size;
@@ -4172,9 +4213,9 @@
 		 * change between calculating the size and returning the
 		 * data in which case we'll just return what fits.
 		 */
-		size = static_len;	/* size of static rules */
-		if (ipfw_dyn_v)		/* add size of dyn.rules */
-			size += (dyn_count * sizeof(ipfw_dyn_rule));
+		size = V_static_len;	/* size of static rules */
+		if (V_ipfw_dyn_v)		/* add size of dyn.rules */
+			size += (V_dyn_count * sizeof(ipfw_dyn_rule));
 
 		/*
 		 * XXX todo: if the user passes a short length just to know
@@ -4183,7 +4224,7 @@
 		 */
 		buf = malloc(size, M_TEMP, M_WAITOK);
 		error = sooptcopyout(sopt, buf,
-				ipfw_getrules(&layer3_chain, buf, size));
+				ipfw_getrules(&V_layer3_chain, buf, size));
 		free(buf, M_TEMP);
 		break;
 
@@ -4201,12 +4242,12 @@
 		 * the old list without the need for a lock.
 		 */
 
-		IPFW_WLOCK(&layer3_chain);
-		layer3_chain.reap = NULL;
-		free_chain(&layer3_chain, 0 /* keep default rule */);
-		rule = layer3_chain.reap;
-		layer3_chain.reap = NULL;
-		IPFW_WUNLOCK(&layer3_chain);
+		IPFW_WLOCK(&V_layer3_chain);
+		V_layer3_chain.reap = NULL;
+		free_chain(&V_layer3_chain, 0 /* keep default rule */);
+		rule = V_layer3_chain.reap;
+		V_layer3_chain.reap = NULL;
+		IPFW_WUNLOCK(&V_layer3_chain);
 		if (rule != NULL)
 			reap_rules(rule);
 		break;
@@ -4218,7 +4259,7 @@
 		if (error == 0)
 			error = check_ipfw_struct(rule, sopt->sopt_valsize);
 		if (error == 0) {
-			error = add_rule(&layer3_chain, rule);
+			error = add_rule(&V_layer3_chain, rule);
 			size = RULESIZE(rule);
 			if (!error && sopt->sopt_dir == SOPT_GET)
 				error = sooptcopyout(sopt, rule, size);
@@ -4245,10 +4286,10 @@
 			break;
 		size = sopt->sopt_valsize;
 		if (size == sizeof(u_int32_t))	/* delete or reassign */
-			error = del_entry(&layer3_chain, rulenum[0]);
+			error = del_entry(&V_layer3_chain, rulenum[0]);
 		else if (size == 2*sizeof(u_int32_t)) /* set enable/disable */
-			set_disable =
-			    (set_disable | rulenum[0]) & ~rulenum[1] &
+			V_set_disable =
+			    (V_set_disable | rulenum[0]) & ~rulenum[1] &
 			    ~(1<<RESVD_SET); /* set RESVD_SET always enabled */
 		else
 			error = EINVAL;
@@ -4263,7 +4304,7 @@
 		    if (error)
 			break;
 		}
-		error = zero_entry(&layer3_chain, rulenum[0],
+		error = zero_entry(&V_layer3_chain, rulenum[0],
 			sopt->sopt_name == IP_FW_RESETLOG);
 		break;
 
@@ -4275,7 +4316,7 @@
 			    sizeof(ent), sizeof(ent));
 			if (error)
 				break;
-			error = add_table_entry(&layer3_chain, ent.tbl,
+			error = add_table_entry(&V_layer3_chain, ent.tbl,
 			    ent.addr, ent.masklen, ent.value);
 		}
 		break;
@@ -4288,7 +4329,7 @@
 			    sizeof(ent), sizeof(ent));
 			if (error)
 				break;
-			error = del_table_entry(&layer3_chain, ent.tbl,
+			error = del_table_entry(&V_layer3_chain, ent.tbl,
 			    ent.addr, ent.masklen);
 		}
 		break;
@@ -4301,9 +4342,9 @@
 			    sizeof(tbl), sizeof(tbl));
 			if (error)
 				break;
-			IPFW_WLOCK(&layer3_chain);
-			error = flush_table(&layer3_chain, tbl);
-			IPFW_WUNLOCK(&layer3_chain);
+			IPFW_WLOCK(&V_layer3_chain);
+			error = flush_table(&V_layer3_chain, tbl);
+			IPFW_WUNLOCK(&V_layer3_chain);
 		}
 		break;
 
@@ -4314,9 +4355,9 @@
 			if ((error = sooptcopyin(sopt, &tbl, sizeof(tbl),
 			    sizeof(tbl))))
 				break;
-			IPFW_RLOCK(&layer3_chain);
-			error = count_table(&layer3_chain, tbl, &cnt);
-			IPFW_RUNLOCK(&layer3_chain);
+			IPFW_RLOCK(&V_layer3_chain);
+			error = count_table(&V_layer3_chain, tbl, &cnt);
+			IPFW_RUNLOCK(&V_layer3_chain);
 			if (error)
 				break;
 			error = sooptcopyout(sopt, &cnt, sizeof(cnt));
@@ -4340,9 +4381,9 @@
 			}
 			tbl->size = (size - sizeof(*tbl)) /
 			    sizeof(ipfw_table_entry);
-			IPFW_RLOCK(&layer3_chain);
-			error = dump_table(&layer3_chain, tbl);
-			IPFW_RUNLOCK(&layer3_chain);
+			IPFW_RLOCK(&V_layer3_chain);
+			error = dump_table(&V_layer3_chain, tbl);
+			IPFW_RUNLOCK(&V_layer3_chain);
 			if (error) {
 				free(tbl, M_TEMP);
 				break;
@@ -4420,13 +4461,16 @@
  * every dyn_keepalive_period
  */
 static void
-ipfw_tick(void * __unused unused)
+ipfw_tick(void *arg)
 {
+#ifdef VIMAGE
+	struct vnet_ipfw *vnet_ipfw = arg;
+#endif
 	struct mbuf *m0, *m, *mnext, **mtailp;
 	int i;
 	ipfw_dyn_rule *q;
 
-	if (dyn_keepalive == 0 || ipfw_dyn_v == NULL || dyn_count == 0)
+	if (V_dyn_keepalive == 0 || V_ipfw_dyn_v == NULL || V_dyn_count == 0)
 		goto done;
 
 	/*
@@ -4438,15 +4482,15 @@
 	m0 = NULL;
 	mtailp = &m0;
 	IPFW_DYN_LOCK();
-	for (i = 0 ; i < curr_dyn_buckets ; i++) {
-		for (q = ipfw_dyn_v[i] ; q ; q = q->next ) {
+	for (i = 0 ; i < V_curr_dyn_buckets ; i++) {
+		for (q = V_ipfw_dyn_v[i] ; q ; q = q->next ) {
 			if (q->dyn_type == O_LIMIT_PARENT)
 				continue;
 			if (q->id.proto != IPPROTO_TCP)
 				continue;
 			if ( (q->state & BOTH_SYN) != BOTH_SYN)
 				continue;
-			if (TIME_LEQ( time_uptime+dyn_keepalive_interval,
+			if (TIME_LEQ( time_uptime + V_dyn_keepalive_interval,
 			    q->expire))
 				continue;	/* too early */
 			if (TIME_LEQ(q->expire, time_uptime))
@@ -4469,37 +4513,40 @@
 		ip_output(m, NULL, NULL, 0, NULL, NULL);
 	}
 done:
-	callout_reset(&ipfw_timeout, dyn_keepalive_period*hz, ipfw_tick, NULL);
+	callout_reset(&V_ipfw_timeout, V_dyn_keepalive_period * hz,
+		      ipfw_tick, arg);
 }
 
-int
-ipfw_init(void)
+static int vnet_ipfw_iattach(const void *unused)
 {
+	INIT_VNET_IPFW(curvnet);
 	struct ip_fw default_rule;
 	int error;
 
-#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,
-	    &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,
-	    &fw_deny_unknown_exthdrs, 0,
-	    "Deny packets with unknown IPv6 Extension Headers");
-#endif
-
-	layer3_chain.rules = NULL;
-	IPFW_LOCK_INIT(&layer3_chain);
+	V_fw_debug = 1;
+	V_autoinc_step = 100; /* bounded to 1..1000 in add_rule() */
+	V_dyn_buckets = 256; /* must be power of 2 */
+	V_curr_dyn_buckets = 256; /* must be power of 2 */
+	V_dyn_ack_lifetime = 300;
+	V_dyn_syn_lifetime = 20;
+	V_dyn_fin_lifetime = 1;
+	V_dyn_rst_lifetime = 1;
+	V_dyn_udp_lifetime = 10;
+	V_dyn_short_lifetime = 5;
+	V_dyn_keepalive_interval = 20;
+	V_dyn_keepalive_period = 5;
+	V_dyn_keepalive = 1;	/* do send keepalives */
+	V_dyn_max = 4096;	/* max # of dynamic rules */
+	V_fw_deny_unknown_exthdrs = 1;
+
+	V_layer3_chain.rules = NULL;
+	IPFW_LOCK_INIT(&V_layer3_chain);
+#if 0 /* XXX Marko fix this! */
 	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(&ipfw_timeout, CALLOUT_MPSAFE);
+#endif
+	callout_init(&V_ipfw_timeout, CALLOUT_MPSAFE);
 
 	bzero(&default_rule, sizeof default_rule);
 
@@ -4515,17 +4562,66 @@
 #endif
 				O_DENY;
 
-	error = add_rule(&layer3_chain, &default_rule);
+	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(&layer3_chain);
+		IPFW_LOCK_DESTROY(&V_layer3_chain);
 		uma_zdestroy(ipfw_dyn_rule_zone);
 		return (error);
 	}
 
-	ip_fw_default_rule = layer3_chain.rules;
+	ip_fw_default_rule = V_layer3_chain.rules;
+
+#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 VIMAGE
+	callout_reset(&V_ipfw_timeout, hz, ipfw_tick, (void *) vnet_ipfw);	
+#else
+	callout_reset(&V_ipfw_timeout, hz, ipfw_tick, NULL);	
+#endif
+
+#ifdef IPFIREWALL_NAT
+	LIST_INIT(&V_layer3_chain.nat);
+#endif
+
+	return 0;
+}
+
+int
+ipfw_init(void)
+{
+	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();
+
+#if 0 /* MARKO XXX */
+	/* error = init_tables(&V_layer3_chain); moved to _iattach() */
+	if (error) {
+		IPFW_DYN_LOCK_DESTROY();
+		IPFW_LOCK_DESTROY(&V_layer3_chain);
+		uma_zdestroy(ipfw_dyn_rule_zone);
+		return (error);
+	}
+#endif
+
+#ifdef VIMAGE
+	vnet_mod_register(&vnet_ipfw_modinfo);
+#else
+	vnet_ipfw_iattach(NULL);
+#endif
+
 	printf("ipfw2 "
 #ifdef INET6
 		"(+ipv6) "
@@ -4543,68 +4639,74 @@
 #else
 		"loadable",
 #endif
+
 #ifdef IPFIREWALL_NAT
 		"enabled",
 #else
-		"loadable",
+		"disabled, ",
 #endif
 
-		default_rule.cmd[0].opcode == O_ACCEPT ? "accept" : "deny");
+#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
+		"accept"
+#else
+		"deny"
+#endif
+		);
 
 #ifdef IPFIREWALL_VERBOSE
-	fw_verbose = 1;
-#endif
-#ifdef IPFIREWALL_VERBOSE_LIMIT
-	verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
-#endif
-	if (fw_verbose == 0)
 		printf("disabled\n");
-	else if (verbose_limit == 0)
+#else
+# ifndef IPFIREWALL_VERBOSE_LIMIT
 		printf("unlimited\n");
-	else
+# else
 		printf("limited to %d packets/entry by default\n",
-		    verbose_limit);
+		    IPFIREWALL_VERBOSE_LIMIT);
+# endif
+#endif
 
-	error = init_tables(&layer3_chain);
-	if (error) {
-		IPFW_DYN_LOCK_DESTROY();
-		IPFW_LOCK_DESTROY(&layer3_chain);
-		uma_zdestroy(ipfw_dyn_rule_zone);
-		return (error);
-	}
 	ip_fw_ctl_ptr = ipfw_ctl;
 	ip_fw_chk_ptr = ipfw_chk;
-	callout_reset(&ipfw_timeout, hz, ipfw_tick, NULL);	
-	LIST_INIT(&layer3_chain.nat);
 	return (0);
 }
 
-void
-ipfw_destroy(void)
+static int vnet_ipfw_idetach(const void *unused)
 {
+	INIT_VNET_IPFW(curvnet);
 	struct ip_fw *reap;
 
-	ip_fw_chk_ptr = NULL;
-	ip_fw_ctl_ptr = NULL;
-	callout_drain(&ipfw_timeout);
-	IPFW_WLOCK(&layer3_chain);
-	flush_tables(&layer3_chain);
-	layer3_chain.reap = NULL;
-	free_chain(&layer3_chain, 1 /* kill default rule */);
-	reap = layer3_chain.reap, layer3_chain.reap = NULL;
-	IPFW_WUNLOCK(&layer3_chain);
+	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);
 	if (reap != NULL)
 		reap_rules(reap);
-	IPFW_DYN_LOCK_DESTROY();
-	uma_zdestroy(ipfw_dyn_rule_zone);
-	if (ipfw_dyn_v != NULL)
-		free(ipfw_dyn_v, M_IPFW);
-	IPFW_LOCK_DESTROY(&layer3_chain);
+	IPFW_LOCK_DESTROY(&V_layer3_chain);
+	if (V_ipfw_dyn_v != NULL)
+		free(V_ipfw_dyn_v, M_IPFW);
 
-#ifdef INET6
-	/* Free IPv6 fw sysctl tree. */
-	sysctl_ctx_free(&ip6_fw_sysctl_ctx);
+	return 0;
+}
+
+void
+ipfw_destroy(void)
+{
+	ip_fw_chk_ptr = NULL;
+	ip_fw_ctl_ptr = NULL;
+
+#ifdef VIMAGE
+	vnet_mod_deregister(&vnet_ipfw_modinfo);
+#else
+	vnet_ipfw_idetach(NULL);
+#endif
+
+#ifdef IPFIREWALL_NAT
+	EVENTHANDLER_DEREGISTER(ifaddr_event, ifaddr_event_tag);
 #endif
+	IPFW_DYN_LOCK_DESTROY();
+	uma_zdestroy(ipfw_dyn_rule_zone);
 
 	printf("IP firewall unloaded\n");
 }


More information about the freebsd-current mailing list