svn commit: r203605 - in stable/8/sys: net netgraph netinet netinet/ipfw netinet6

Julian Elischer julian at FreeBSD.org
Sun Feb 7 09:00:22 UTC 2010


Author: julian
Date: Sun Feb  7 09:00:22 2010
New Revision: 203605
URL: http://svn.freebsd.org/changeset/base/203605

Log:
  MFC of 197952 and 198075
  
      Virtualize the pfil hooks so that different jails may chose different
      packet filters. ALso allows ipfw to be enabled on on ejail and disabled
      on another. In 8.0 it's a global setting.
  and
      Unbreak the VIMAGE build with IPSEC, broken with r197952 by
      virtualizing the pfil hooks.
      For consistency add the V_ to virtualize the pfil hooks in here as well.

Modified:
  stable/8/sys/net/if_bridge.c
  stable/8/sys/net/if_enc.c
  stable/8/sys/net/if_ethersubr.c
  stable/8/sys/net/pfil.c
  stable/8/sys/netgraph/ng_bridge.c
  stable/8/sys/netinet/ip_fastfwd.c
  stable/8/sys/netinet/ip_input.c
  stable/8/sys/netinet/ip_output.c
  stable/8/sys/netinet/ip_var.h
  stable/8/sys/netinet/ipfw/ip_fw2.c
  stable/8/sys/netinet/ipfw/ip_fw_pfil.c
  stable/8/sys/netinet/raw_ip.c
  stable/8/sys/netinet6/ip6_forward.c
  stable/8/sys/netinet6/ip6_input.c
  stable/8/sys/netinet6/ip6_output.c
  stable/8/sys/netinet6/ip6_var.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/net/if_bridge.c
==============================================================================
--- stable/8/sys/net/if_bridge.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/net/if_bridge.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -109,6 +109,7 @@ __FBSDID("$FreeBSD$");
 #include <net/if_types.h>
 #include <net/if_var.h>
 #include <net/pfil.h>
+#include <net/vnet.h>
 
 #include <netinet/in.h> /* for struct arpcom */
 #include <netinet/in_systm.h>
@@ -1800,9 +1801,9 @@ bridge_dummynet(struct mbuf *m, struct i
 		return;
 	}
 
-	if (PFIL_HOOKED(&inet_pfil_hook)
+	if (PFIL_HOOKED(&V_inet_pfil_hook)
 #ifdef INET6
-	    || PFIL_HOOKED(&inet6_pfil_hook)
+	    || PFIL_HOOKED(&V_inet6_pfil_hook)
 #endif
 	    ) {
 		if (bridge_pfil(&m, sc->sc_ifp, ifp, PFIL_OUT) != 0)
@@ -2062,9 +2063,9 @@ bridge_forward(struct bridge_softc *sc, 
 		ETHER_BPF_MTAP(ifp, m);
 
 	/* run the packet filter */
-	if (PFIL_HOOKED(&inet_pfil_hook)
+	if (PFIL_HOOKED(&V_inet_pfil_hook)
 #ifdef INET6
-	    || PFIL_HOOKED(&inet6_pfil_hook)
+	    || PFIL_HOOKED(&V_inet6_pfil_hook)
 #endif
 	    ) {
 		BRIDGE_UNLOCK(sc);
@@ -2102,9 +2103,9 @@ bridge_forward(struct bridge_softc *sc, 
 
 	BRIDGE_UNLOCK(sc);
 
-	if (PFIL_HOOKED(&inet_pfil_hook)
+	if (PFIL_HOOKED(&V_inet_pfil_hook)
 #ifdef INET6
-	    || PFIL_HOOKED(&inet6_pfil_hook)
+	    || PFIL_HOOKED(&V_inet6_pfil_hook)
 #endif
 	    ) {
 		if (bridge_pfil(&m, ifp, dst_if, PFIL_OUT) != 0)
@@ -2243,7 +2244,7 @@ bridge_input(struct ifnet *ifp, struct m
 
 #ifdef INET6
 #   define OR_PFIL_HOOKED_INET6 \
-	|| PFIL_HOOKED(&inet6_pfil_hook)
+	|| PFIL_HOOKED(&V_inet6_pfil_hook)
 #else
 #   define OR_PFIL_HOOKED_INET6
 #endif
@@ -2260,7 +2261,7 @@ bridge_input(struct ifnet *ifp, struct m
 			iface->if_ipackets++;				\
 			/* Filter on the physical interface. */		\
 			if (pfil_local_phys &&				\
-			    (PFIL_HOOKED(&inet_pfil_hook)		\
+			    (PFIL_HOOKED(&V_inet_pfil_hook)		\
 			     OR_PFIL_HOOKED_INET6)) {			\
 				if (bridge_pfil(&m, NULL, ifp,		\
 				    PFIL_IN) != 0 || m == NULL) {	\
@@ -2349,9 +2350,9 @@ bridge_broadcast(struct bridge_softc *sc
 	}
 
 	/* Filter on the bridge interface before broadcasting */
-	if (runfilt && (PFIL_HOOKED(&inet_pfil_hook)
+	if (runfilt && (PFIL_HOOKED(&V_inet_pfil_hook)
 #ifdef INET6
-	    || PFIL_HOOKED(&inet6_pfil_hook)
+	    || PFIL_HOOKED(&V_inet6_pfil_hook)
 #endif
 	    )) {
 		if (bridge_pfil(&m, sc->sc_ifp, NULL, PFIL_OUT) != 0)
@@ -2396,9 +2397,9 @@ bridge_broadcast(struct bridge_softc *sc
 		 * pointer so we do not redundantly filter on the bridge for
 		 * each interface we broadcast on.
 		 */
-		if (runfilt && (PFIL_HOOKED(&inet_pfil_hook)
+		if (runfilt && (PFIL_HOOKED(&V_inet_pfil_hook)
 #ifdef INET6
-		    || PFIL_HOOKED(&inet6_pfil_hook)
+		    || PFIL_HOOKED(&V_inet6_pfil_hook)
 #endif
 		    )) {
 			if (used == 0) {
@@ -3037,7 +3038,7 @@ bridge_pfil(struct mbuf **mp, struct ifn
 			goto bad;
 	}
 
-	if (ip_fw_chk_ptr && pfil_ipfw != 0 && dir == PFIL_OUT && ifp != NULL) {
+	if (V_ip_fw_chk_ptr && pfil_ipfw != 0 && dir == PFIL_OUT && ifp != NULL) {
 		struct dn_pkt_tag *dn_tag;
 
 		error = -1;
@@ -3057,7 +3058,7 @@ bridge_pfil(struct mbuf **mp, struct ifn
 		args.next_hop = NULL;
 		args.eh = &eh2;
 		args.inp = NULL;	/* used by ipfw uid/gid/jail rules */
-		i = ip_fw_chk_ptr(&args);
+		i = V_ip_fw_chk_ptr(&args);
 		*mp = args.m;
 
 		if (*mp == NULL)
@@ -3109,21 +3110,21 @@ ipfwpass:
 		 *   in_if -> bridge_if -> out_if
 		 */
 		if (pfil_bridge && dir == PFIL_OUT && bifp != NULL)
-			error = pfil_run_hooks(&inet_pfil_hook, mp, bifp,
+			error = pfil_run_hooks(&V_inet_pfil_hook, mp, bifp,
 					dir, NULL);
 
 		if (*mp == NULL || error != 0) /* filter may consume */
 			break;
 
 		if (pfil_member && ifp != NULL)
-			error = pfil_run_hooks(&inet_pfil_hook, mp, ifp,
+			error = pfil_run_hooks(&V_inet_pfil_hook, mp, ifp,
 					dir, NULL);
 
 		if (*mp == NULL || error != 0) /* filter may consume */
 			break;
 
 		if (pfil_bridge && dir == PFIL_IN && bifp != NULL)
-			error = pfil_run_hooks(&inet_pfil_hook, mp, bifp,
+			error = pfil_run_hooks(&V_inet_pfil_hook, mp, bifp,
 					dir, NULL);
 
 		if (*mp == NULL || error != 0) /* filter may consume */
@@ -3163,21 +3164,21 @@ ipfwpass:
 #ifdef INET6
 	case ETHERTYPE_IPV6:
 		if (pfil_bridge && dir == PFIL_OUT && bifp != NULL)
-			error = pfil_run_hooks(&inet6_pfil_hook, mp, bifp,
+			error = pfil_run_hooks(&V_inet6_pfil_hook, mp, bifp,
 					dir, NULL);
 
 		if (*mp == NULL || error != 0) /* filter may consume */
 			break;
 
 		if (pfil_member && ifp != NULL)
-			error = pfil_run_hooks(&inet6_pfil_hook, mp, ifp,
+			error = pfil_run_hooks(&V_inet6_pfil_hook, mp, ifp,
 					dir, NULL);
 
 		if (*mp == NULL || error != 0) /* filter may consume */
 			break;
 
 		if (pfil_bridge && dir == PFIL_IN && bifp != NULL)
-			error = pfil_run_hooks(&inet6_pfil_hook, mp, bifp,
+			error = pfil_run_hooks(&V_inet6_pfil_hook, mp, bifp,
 					dir, NULL);
 		break;
 #endif

Modified: stable/8/sys/net/if_enc.c
==============================================================================
--- stable/8/sys/net/if_enc.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/net/if_enc.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -243,9 +243,9 @@ ipsec_filter(struct mbuf **mp, int dir, 
 	}
 
 	/* Skip pfil(9) if no filters are loaded */
-	if (!(PFIL_HOOKED(&inet_pfil_hook)
+	if (!(PFIL_HOOKED(&V_inet_pfil_hook)
 #ifdef INET6
-	    || PFIL_HOOKED(&inet6_pfil_hook)
+	    || PFIL_HOOKED(&V_inet6_pfil_hook)
 #endif
 	    )) {
 		return (0);
@@ -271,7 +271,7 @@ ipsec_filter(struct mbuf **mp, int dir, 
 			ip->ip_len = ntohs(ip->ip_len);
 			ip->ip_off = ntohs(ip->ip_off);
 
-			error = pfil_run_hooks(&inet_pfil_hook, mp,
+			error = pfil_run_hooks(&V_inet_pfil_hook, mp,
 			    encif, dir, NULL);
 
 			if (*mp == NULL || error != 0)
@@ -285,7 +285,7 @@ ipsec_filter(struct mbuf **mp, int dir, 
 
 #ifdef INET6
 		case 6:
-			error = pfil_run_hooks(&inet6_pfil_hook, mp,
+			error = pfil_run_hooks(&V_inet6_pfil_hook, mp,
 			    encif, dir, NULL);
 			break;
 #endif

Modified: stable/8/sys/net/if_ethersubr.c
==============================================================================
--- stable/8/sys/net/if_ethersubr.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/net/if_ethersubr.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -434,7 +434,7 @@ ether_output_frame(struct ifnet *ifp, st
 {
 #if defined(INET) || defined(INET6)
 
-	if (ip_fw_chk_ptr && V_ether_ipfw != 0) {
+	if (V_ip_fw_chk_ptr && V_ether_ipfw != 0) {
 		if (ether_ipfw_chk(&m, ifp, 0) == 0) {
 			if (m) {
 				m_freem(m);
@@ -502,7 +502,7 @@ ether_ipfw_chk(struct mbuf **m0, struct 
 	args.next_hop = NULL;	/* we do not support forward yet	*/
 	args.eh = &save_eh;	/* MAC header for bridged/MAC packets	*/
 	args.inp = NULL;	/* used by ipfw uid/gid/jail rules	*/
-	i = ip_fw_chk_ptr(&args);
+	i = V_ip_fw_chk_ptr(&args);
 	m = args.m;
 	if (m != NULL) {
 		/*
@@ -775,7 +775,7 @@ ether_demux(struct ifnet *ifp, struct mb
 	 * Allow dummynet and/or ipfw to claim the frame.
 	 * Do not do this for PROMISC frames in case we are re-entered.
 	 */
-	if (ip_fw_chk_ptr && V_ether_ipfw != 0 && !(m->m_flags & M_PROMISC)) {
+	if (V_ip_fw_chk_ptr && V_ether_ipfw != 0 && !(m->m_flags & M_PROMISC)) {
 		if (ether_ipfw_chk(&m, NULL, 0) == 0) {
 			if (m)
 				m_freem(m);	/* dropped; free mbuf chain */

Modified: stable/8/sys/net/pfil.c
==============================================================================
--- stable/8/sys/net/pfil.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/net/pfil.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -58,8 +58,9 @@ static int pfil_list_remove(pfil_list_t 
     int (*)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *),
     void *);
 
-LIST_HEAD(, pfil_head) pfil_head_list =
-    LIST_HEAD_INITIALIZER(&pfil_head_list);
+LIST_HEAD(pfilheadhead, pfil_head);
+VNET_DEFINE(struct pfilheadhead, pfil_head_list);
+#define	V_pfil_head_list	VNET(pfil_head_list)
 
 /*
  * pfil_run_hooks() runs the specified packet filter hooks.
@@ -99,7 +100,7 @@ pfil_head_register(struct pfil_head *ph)
 	struct pfil_head *lph;
 
 	PFIL_LIST_LOCK();
-	LIST_FOREACH(lph, &pfil_head_list, ph_list) {
+	LIST_FOREACH(lph, &V_pfil_head_list, ph_list) {
 		if (ph->ph_type == lph->ph_type &&
 		    ph->ph_un.phu_val == lph->ph_un.phu_val) {
 			PFIL_LIST_UNLOCK();
@@ -110,7 +111,7 @@ pfil_head_register(struct pfil_head *ph)
 	ph->ph_nhooks = 0;
 	TAILQ_INIT(&ph->ph_in);
 	TAILQ_INIT(&ph->ph_out);
-	LIST_INSERT_HEAD(&pfil_head_list, ph, ph_list);
+	LIST_INSERT_HEAD(&V_pfil_head_list, ph, ph_list);
 	PFIL_LIST_UNLOCK();
 	return (0);
 }
@@ -145,7 +146,7 @@ pfil_head_get(int type, u_long val)
 	struct pfil_head *ph;
 
 	PFIL_LIST_LOCK();
-	LIST_FOREACH(ph, &pfil_head_list, ph_list)
+	LIST_FOREACH(ph, &V_pfil_head_list, ph_list)
 		if (ph->ph_type == type && ph->ph_un.phu_val == val)
 			break;
 	PFIL_LIST_UNLOCK();
@@ -284,3 +285,45 @@ pfil_list_remove(pfil_list_t *list,
 		}
 	return (ENOENT);
 }
+
+/****************
+ * Stuff that must be initialized for every instance
+ * (including the first of course).
+ */
+static int
+vnet_pfil_init(const void *unused)
+{
+	LIST_INIT(&V_pfil_head_list);
+	return (0);
+}
+
+/***********************
+ * Called for the removal of each instance.
+ */
+static int
+vnet_pfil_uninit(const void *unused)
+{
+	/*  XXX should panic if list is not empty */
+	return 0;
+}
+
+/* Define startup order. */
+#define	PFIL_SYSINIT_ORDER	SI_SUB_PROTO_BEGIN
+#define	PFIL_MODEVENT_ORDER	(SI_ORDER_FIRST) /* On boot slot in here. */
+#define	PFIL_VNET_ORDER		(PFIL_MODEVENT_ORDER + 2) /* Later still. */
+
+/*
+ * Starting up. 
+ * VNET_SYSINIT is called for each existing vnet and each new vnet.
+ */
+VNET_SYSINIT(vnet_pfil_init, PFIL_SYSINIT_ORDER, PFIL_VNET_ORDER,
+	    vnet_pfil_init, NULL);
+ 
+/*
+ * Closing up shop. These are done in REVERSE ORDER, 
+ * Not called on reboot.
+ * VNET_SYSUNINIT is called for each exiting vnet as it exits.
+ */
+VNET_SYSUNINIT(vnet_pfil_uninit, PFIL_SYSINIT_ORDER, PFIL_VNET_ORDER,
+	    vnet_pfil_uninit, NULL);
+

Modified: stable/8/sys/netgraph/ng_bridge.c
==============================================================================
--- stable/8/sys/netgraph/ng_bridge.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/netgraph/ng_bridge.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -634,7 +634,7 @@ ng_bridge_rcvdata(hook_p hook, item_p it
 
 	/* Run packet through ipfw processing, if enabled */
 #if 0
-	if (priv->conf.ipfw[linkNum] && V_fw_enable && ip_fw_chk_ptr != NULL) {
+	if (priv->conf.ipfw[linkNum] && V_fw_enable && V_ip_fw_chk_ptr != NULL) {
 		/* XXX not implemented yet */
 	}
 #endif

Modified: stable/8/sys/netinet/ip_fastfwd.c
==============================================================================
--- stable/8/sys/netinet/ip_fastfwd.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/netinet/ip_fastfwd.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -351,10 +351,11 @@ ip_fastforward(struct mbuf *m)
 	/*
 	 * Run through list of ipfilter hooks for input packets
 	 */
-	if (!PFIL_HOOKED(&inet_pfil_hook))
+	if (!PFIL_HOOKED(&V_inet_pfil_hook))
 		goto passin;
 
-	if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL) ||
+	if (pfil_run_hooks(
+	    &V_inet_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL) ||
 	    m == NULL)
 		goto drop;
 
@@ -438,10 +439,10 @@ passin:
 	/*
 	 * Run through list of hooks for output packets.
 	 */
-	if (!PFIL_HOOKED(&inet_pfil_hook))
+	if (!PFIL_HOOKED(&V_inet_pfil_hook))
 		goto passout;
 
-	if (pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT, NULL) || m == NULL) {
+	if (pfil_run_hooks(&V_inet_pfil_hook, &m, ifp, PFIL_OUT, NULL) || m == NULL) {
 		goto drop;
 	}
 

Modified: stable/8/sys/netinet/ip_input.c
==============================================================================
--- stable/8/sys/netinet/ip_input.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/netinet/ip_input.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -170,7 +170,7 @@ SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, 
     &VNET_NAME(ip_checkinterface), 0,
     "Verify packet arrives on correct interface");
 
-struct pfil_head inet_pfil_hook;	/* Packet filter hooks */
+VNET_DEFINE(struct pfil_head, inet_pfil_hook);	/* Packet filter hooks */
 
 static struct netisr_handler ip_nh = {
 	.nh_name = "ip",
@@ -318,6 +318,13 @@ ip_init(void)
 	    NULL, UMA_ALIGN_PTR, 0);
 	maxnipq_update();
 
+	/* Initialize packet filter hooks. */
+	V_inet_pfil_hook.ph_type = PFIL_TYPE_AF;
+	V_inet_pfil_hook.ph_af = AF_INET;
+	if ((i = pfil_head_register(&V_inet_pfil_hook)) != 0)
+		printf("%s: WARNING: unable to register pfil hook, "
+			"error %d\n", __func__, i);
+
 #ifdef FLOWTABLE
 	TUNABLE_INT_FETCH("net.inet.ip.output_flowtable_size",
 	    &V_ip_output_flowtable_size);
@@ -348,13 +355,6 @@ ip_init(void)
 				ip_protox[pr->pr_protocol] = pr - inetsw;
 		}
 
-	/* Initialize packet filter hooks. */
-	inet_pfil_hook.ph_type = PFIL_TYPE_AF;
-	inet_pfil_hook.ph_af = AF_INET;
-	if ((i = pfil_head_register(&inet_pfil_hook)) != 0)
-		printf("%s: WARNING: unable to register pfil hook, "
-			"error %d\n", __func__, i);
-
 	/* Start ipport_tick. */
 	callout_init(&ipport_tick_callout, CALLOUT_MPSAFE);
 	callout_reset(&ipport_tick_callout, 1, ipport_tick, NULL);
@@ -510,11 +510,11 @@ tooshort:
 	 */
 
 	/* Jump over all PFIL processing if hooks are not active. */
-	if (!PFIL_HOOKED(&inet_pfil_hook))
+	if (!PFIL_HOOKED(&V_inet_pfil_hook))
 		goto passin;
 
 	odst = ip->ip_dst;
-	if (pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_IN, NULL) != 0)
+	if (pfil_run_hooks(&V_inet_pfil_hook, &m, ifp, PFIL_IN, NULL) != 0)
 		return;
 	if (m == NULL)			/* consumed by filter */
 		return;

Modified: stable/8/sys/netinet/ip_output.c
==============================================================================
--- stable/8/sys/netinet/ip_output.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/netinet/ip_output.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -489,12 +489,12 @@ sendit:
 #endif /* IPSEC */
 
 	/* Jump over all PFIL processing if hooks are not active. */
-	if (!PFIL_HOOKED(&inet_pfil_hook))
+	if (!PFIL_HOOKED(&V_inet_pfil_hook))
 		goto passout;
 
 	/* Run through list of hooks for output packets. */
 	odst.s_addr = ip->ip_dst.s_addr;
-	error = pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT, inp);
+	error = pfil_run_hooks(&V_inet_pfil_hook, &m, ifp, PFIL_OUT, inp);
 	if (error != 0 || m == NULL)
 		goto done;
 

Modified: stable/8/sys/netinet/ip_var.h
==============================================================================
--- stable/8/sys/netinet/ip_var.h	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/netinet/ip_var.h	Sun Feb  7 09:00:22 2010	(r203605)
@@ -244,14 +244,20 @@ extern int	(*ip_rsvp_vif)(struct socket 
 extern void	(*ip_rsvp_force_done)(struct socket *);
 extern void	(*rsvp_input_p)(struct mbuf *m, int off);
 
-extern	struct pfil_head inet_pfil_hook;	/* packet filter hooks */
+VNET_DECLARE(struct pfil_head, inet_pfil_hook);	/* packet filter hooks */
+#define	V_inet_pfil_hook	VNET(inet_pfil_hook)
 
 void	in_delayed_cksum(struct mbuf *m);
 
 /* ipfw and dummynet hooks. Most are declared in raw_ip.c */
 struct ip_fw_args;
-extern int	(*ip_fw_chk_ptr)(struct ip_fw_args *args);
-extern int	(*ip_fw_ctl_ptr)(struct sockopt *);
+typedef int	(*ip_fw_chk_ptr_t)(struct ip_fw_args *args);
+typedef int	(*ip_fw_ctl_ptr_t)(struct sockopt *);
+VNET_DECLARE(ip_fw_chk_ptr_t, ip_fw_chk_ptr);
+VNET_DECLARE(ip_fw_ctl_ptr_t, ip_fw_ctl_ptr);
+#define	V_ip_fw_chk_ptr		VNET(ip_fw_chk_ptr)
+#define	V_ip_fw_ctl_ptr		VNET(ip_fw_ctl_ptr)
+
 extern int	(*ip_dn_ctl_ptr)(struct sockopt *);
 extern int	(*ip_dn_io_ptr)(struct mbuf **m, int dir, struct ip_fw_args *fwa);
 extern void	(*ip_dn_ruledel_ptr)(void *);		/* in ip_fw2.c */

Modified: stable/8/sys/netinet/ipfw/ip_fw2.c
==============================================================================
--- stable/8/sys/netinet/ipfw/ip_fw2.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/netinet/ipfw/ip_fw2.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -2581,6 +2581,10 @@ do {									\
 	}
 
 	IPFW_RLOCK(chain);
+	if (! V_ipfw_vnet_ready) { /* shutting down, leave NOW. */
+		IPFW_RUNLOCK(chain);
+		return (IP_FW_PASS);	/* accept */
+	}
 	mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
 	if (args->rule) {
 		/*
@@ -4760,29 +4764,21 @@ ipfw_init(void)
 		printf("limited to %d packets/entry by default\n",
 		    V_verbose_limit);
 
-	/*
-	 * Hook us up to pfil.
-	 * Eventually pfil will be per vnet.
-	 */
-	if ((error = ipfw_hook()) != 0) {
-		printf("ipfw_hook() error\n");
-		return (error);
-	}
-#ifdef INET6
-	if ((error = ipfw6_hook()) != 0) {
-		printf("ipfw6_hook() error\n");
-		return (error);
-	}
-#endif
-	/*
-	 * 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);
 }
 
+/**********************
+ * Called for the removal of the last instance only on module unload.
+ */
+static void
+ipfw_destroy(void)
+{
+
+	uma_zdestroy(ipfw_dyn_rule_zone);
+	IPFW_DYN_LOCK_DESTROY();
+	printf("IP firewall unloaded\n");
+}
+
 /****************
  * Stuff that must be initialized for every instance
  * (including the first of course).
@@ -4866,19 +4862,30 @@ vnet_ipfw_init(const void *unused)
 
 	/* First set up some values that are compile time options */
 	V_ipfw_vnet_ready = 1;		/* Open for business */
-	return (0);
-}
 
-/**********************
- * Called for the removal of the last instance only on module unload.
- */
-static void
-ipfw_destroy(void)
-{
+	/* Hook up the raw inputs */
+	V_ip_fw_ctl_ptr = ipfw_ctl;
+	V_ip_fw_chk_ptr = ipfw_chk;
 
-	uma_zdestroy(ipfw_dyn_rule_zone);
-	IPFW_DYN_LOCK_DESTROY();
-	printf("IP firewall unloaded\n");
+	/*
+	 * Hook us up to pfil.
+	 */
+	if (V_fw_enable) {
+		if ((error = ipfw_hook()) != 0) {
+			printf("ipfw_hook() error\n");
+			return (error);
+		}
+	}
+#ifdef INET6
+	if (V_fw6_enable) {
+		if ((error = ipfw6_hook()) != 0) {
+			printf("ipfw6_hook() error\n");
+			/* XXX should we unhook everything else? */
+			return (error);
+		}
+	}
+#endif
+	return (0);
 }
 
 /***********************
@@ -4890,9 +4897,18 @@ vnet_ipfw_uninit(const void *unused)
 	struct ip_fw *reap;
 
 	V_ipfw_vnet_ready = 0; /* tell new callers to go away */
-	callout_drain(&V_ipfw_timeout);
+	ipfw_unhook();
+#ifdef INET6
+	ipfw6_unhook();
+#endif
+	/* layer2 and other entrypoints still come in this way. */
+	V_ip_fw_chk_ptr = NULL;
+	V_ip_fw_ctl_ptr = NULL;
+	IPFW_WLOCK(&V_layer3_chain);
 	/* We wait on the wlock here until the last user leaves */
+	IPFW_WUNLOCK(&V_layer3_chain);
 	IPFW_WLOCK(&V_layer3_chain);
+	callout_drain(&V_ipfw_timeout);
 	flush_tables(&V_layer3_chain);
 	V_layer3_chain.reap = NULL;
 	free_chain(&V_layer3_chain, 1 /* kill default rule */);
@@ -4926,21 +4942,10 @@ ipfw_modevent(module_t mod, int type, vo
 		/* Called once at module load or
 	 	 * system boot if compiled in. */
 		break;
-	case MOD_UNLOAD:
-		break;
 	case MOD_QUIESCE:
-		/* Yes, the unhooks can return errors, we can safely ignore
-		 * them. Eventually these will be done per jail as they
-		 * shut down. We will wait on each vnet's l3 lock as existing
-		 * callers go away.
-		 */
-		ipfw_unhook();
-#ifdef INET6
-		ipfw6_unhook();
-#endif
-		/* layer2 and other entrypoints still come in this way. */
-		ip_fw_chk_ptr = NULL;
-		ip_fw_ctl_ptr = NULL;
+		/* Called before unload. May veto unloading. */
+		break;
+	case MOD_UNLOAD:
 		/* Called during unload. */
 		break;
 	case MOD_SHUTDOWN:
@@ -4989,4 +4994,3 @@ SYSUNINIT(ipfw_destroy, IPFW_SI_SUB_FIRE
 VNET_SYSUNINIT(vnet_ipfw_uninit, IPFW_SI_SUB_FIREWALL, IPFW_VNET_ORDER,
 	    vnet_ipfw_uninit, NULL);
 
- 

Modified: stable/8/sys/netinet/ipfw/ip_fw_pfil.c
==============================================================================
--- stable/8/sys/netinet/ipfw/ip_fw_pfil.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/netinet/ipfw/ip_fw_pfil.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -515,42 +515,54 @@ ipfw6_unhook(void)
 int
 ipfw_chg_hook(SYSCTL_HANDLER_ARGS)
 {
-	int enable = *(int *)arg1;
+	int enable;
+	int oldenable;
 	int error;
 
-#ifdef VIMAGE /* Since enabling is global, only let base do it. */
-	if (! IS_DEFAULT_VNET(curvnet))
-		return (EPERM);
+	if (arg1 == &VNET_NAME(fw_enable)) {
+		enable = V_fw_enable;
+	}
+#ifdef INET6
+	else if (arg1 == &VNET_NAME(fw6_enable)) {
+		enable = V_fw6_enable;
+	}
 #endif
+	else 
+		return (EINVAL);
+
+	oldenable = enable;
+
 	error = sysctl_handle_int(oidp, &enable, 0, req);
+
 	if (error)
 		return (error);
 
 	enable = (enable) ? 1 : 0;
 
-	if (enable == *(int *)arg1)
+	if (enable == oldenable)
 		return (0);
 
-	if (arg1 == &V_fw_enable) {
+	if (arg1 == &VNET_NAME(fw_enable)) {
 		if (enable)
 			error = ipfw_hook();
 		else
 			error = ipfw_unhook();
+		if (error)
+			return (error);
+		V_fw_enable = enable;
 	}
 #ifdef INET6
-	if (arg1 == &V_fw6_enable) {
+	else if (arg1 == &VNET_NAME(fw6_enable)) {
 		if (enable)
 			error = ipfw6_hook();
 		else
 			error = ipfw6_unhook();
+		if (error)
+			return (error);
+		V_fw6_enable = enable;
 	}
 #endif
 
-	if (error)
-		return (error);
-
-	*(int *)arg1 = enable;
-
 	return (0);
 }
 

Modified: stable/8/sys/netinet/raw_ip.c
==============================================================================
--- stable/8/sys/netinet/raw_ip.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/netinet/raw_ip.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -84,9 +84,9 @@ VNET_DEFINE(struct inpcbinfo, ripcbinfo)
  * The data hooks are not used here but it is convenient
  * to keep them all in one place.
  */
-int (*ip_fw_ctl_ptr)(struct sockopt *) = NULL;
+VNET_DEFINE(ip_fw_chk_ptr_t, ip_fw_chk_ptr) = NULL;
+VNET_DEFINE(ip_fw_ctl_ptr_t, ip_fw_ctl_ptr) = NULL;
 int (*ip_dn_ctl_ptr)(struct sockopt *) = NULL;
-int (*ip_fw_chk_ptr)(struct ip_fw_args *args) = NULL;
 int (*ip_dn_io_ptr)(struct mbuf **m, int dir, struct ip_fw_args *fwa) = NULL;
 
 /*
@@ -542,8 +542,8 @@ rip_ctloutput(struct socket *so, struct 
 		case IP_FW_TABLE_LIST:
 		case IP_FW_NAT_GET_CONFIG:
 		case IP_FW_NAT_GET_LOG:
-			if (ip_fw_ctl_ptr != NULL)
-				error = ip_fw_ctl_ptr(sopt);
+			if (V_ip_fw_ctl_ptr != NULL)
+				error = V_ip_fw_ctl_ptr(sopt);
 			else
 				error = ENOPROTOOPT;
 			break;
@@ -605,8 +605,8 @@ rip_ctloutput(struct socket *so, struct 
 		case IP_FW_TABLE_FLUSH:
 		case IP_FW_NAT_CFG:
 		case IP_FW_NAT_DEL:
-			if (ip_fw_ctl_ptr != NULL)
-				error = ip_fw_ctl_ptr(sopt);
+			if (V_ip_fw_ctl_ptr != NULL)
+				error = V_ip_fw_ctl_ptr(sopt);
 			else
 				error = ENOPROTOOPT;
 			break;

Modified: stable/8/sys/netinet6/ip6_forward.c
==============================================================================
--- stable/8/sys/netinet6/ip6_forward.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/netinet6/ip6_forward.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -551,11 +551,11 @@ skip_routing:
 	in6_clearscope(&ip6->ip6_dst);
 
 	/* Jump over all PFIL processing if hooks are not active. */
-	if (!PFIL_HOOKED(&inet6_pfil_hook))
+	if (!PFIL_HOOKED(&V_inet6_pfil_hook))
 		goto pass;
 
 	/* Run through list of hooks for output packets. */
-	error = pfil_run_hooks(&inet6_pfil_hook, &m, rt->rt_ifp, PFIL_OUT, NULL);
+	error = pfil_run_hooks(&V_inet6_pfil_hook, &m, rt->rt_ifp, PFIL_OUT, NULL);
 	if (error != 0)
 		goto senderr;
 	if (m == NULL)

Modified: stable/8/sys/netinet6/ip6_input.c
==============================================================================
--- stable/8/sys/netinet6/ip6_input.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/netinet6/ip6_input.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -152,7 +152,7 @@ VNET_DECLARE(int, udp6_recvspace);
 struct rwlock in6_ifaddr_lock;
 RW_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock");
 
-struct pfil_head inet6_pfil_hook;
+VNET_DEFINE (struct pfil_head, inet6_pfil_hook);
 
 static void ip6_init2(void *);
 static struct ip6aux *ip6_setdstifaddr(struct mbuf *, struct in6_ifaddr *);
@@ -247,6 +247,13 @@ ip6_init(void)
 
 	V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR;
 
+	/* Initialize packet filter hooks. */
+	V_inet6_pfil_hook.ph_type = PFIL_TYPE_AF;
+	V_inet6_pfil_hook.ph_af = AF_INET6;
+	if ((i = pfil_head_register(&V_inet6_pfil_hook)) != 0)
+		printf("%s: WARNING: unable to register pfil hook, "
+			"error %d\n", __func__, i);
+
 	/* Skip global initialization stuff for non-default instances. */
 	if (!IS_DEFAULT_VNET(curvnet))
 		return;
@@ -275,13 +282,6 @@ ip6_init(void)
 				ip6_protox[pr->pr_protocol] = pr - inet6sw;
 		}
 
-	/* Initialize packet filter hooks. */
-	inet6_pfil_hook.ph_type = PFIL_TYPE_AF;
-	inet6_pfil_hook.ph_af = AF_INET6;
-	if ((i = pfil_head_register(&inet6_pfil_hook)) != 0)
-		printf("%s: WARNING: unable to register pfil hook, "
-			"error %d\n", __func__, i);
-
 	netisr_register(&ip6_nh);
 }
 
@@ -515,10 +515,11 @@ ip6_input(struct mbuf *m)
 	odst = ip6->ip6_dst;
 
 	/* Jump over all PFIL processing if hooks are not active. */
-	if (!PFIL_HOOKED(&inet6_pfil_hook))
+	if (!PFIL_HOOKED(&V_inet6_pfil_hook))
 		goto passin;
 
-	if (pfil_run_hooks(&inet6_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL))
+	if (pfil_run_hooks(&V_inet6_pfil_hook, &m,
+	    m->m_pkthdr.rcvif, PFIL_IN, NULL))
 		return;
 	if (m == NULL)			/* consumed by filter */
 		return;

Modified: stable/8/sys/netinet6/ip6_output.c
==============================================================================
--- stable/8/sys/netinet6/ip6_output.c	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/netinet6/ip6_output.c	Sun Feb  7 09:00:22 2010	(r203605)
@@ -805,12 +805,12 @@ again:
 	}
 
 	/* Jump over all PFIL processing if hooks are not active. */
-	if (!PFIL_HOOKED(&inet6_pfil_hook))
+	if (!PFIL_HOOKED(&V_inet6_pfil_hook))
 		goto passout;
 
 	odst = ip6->ip6_dst;
 	/* Run through list of hooks for output packets. */
-	error = pfil_run_hooks(&inet6_pfil_hook, &m, ifp, PFIL_OUT, inp);
+	error = pfil_run_hooks(&V_inet6_pfil_hook, &m, ifp, PFIL_OUT, inp);
 	if (error != 0 || m == NULL)
 		goto done;
 	ip6 = mtod(m, struct ip6_hdr *);

Modified: stable/8/sys/netinet6/ip6_var.h
==============================================================================
--- stable/8/sys/netinet6/ip6_var.h	Sun Feb  7 07:50:41 2010	(r203604)
+++ stable/8/sys/netinet6/ip6_var.h	Sun Feb  7 09:00:22 2010	(r203605)
@@ -358,7 +358,8 @@ VNET_DECLARE(int, ip6_use_defzone);	/* W
 #endif
 #define	V_ip6_use_defzone		VNET(ip6_use_defzone)
 
-extern	struct pfil_head inet6_pfil_hook;	/* packet filter hooks */
+VNET_DECLARE (struct pfil_head, inet6_pfil_hook);	/* packet filter hooks */
+#define	V_inet6_pfil_hook	VNET(inet6_pfil_hook)
 
 extern struct	pr_usrreqs rip6_usrreqs;
 struct sockopt;


More information about the svn-src-all mailing list