svn commit: r201527 - in head/sys: net netgraph netinet netinet/ipfw

Luigi Rizzo luigi at FreeBSD.org
Mon Jan 4 19:01:22 UTC 2010


Author: luigi
Date: Mon Jan  4 19:01:22 2010
New Revision: 201527
URL: http://svn.freebsd.org/changeset/base/201527

Log:
  Various cleanup done in ipfw3-head branch including:
  - use a uniform mtag format for all packets that exit and re-enter
    the firewall in the middle of a rulechain. On reentry, all tags
    containing reinject info are renamed to MTAG_IPFW_RULE so the
    processing is simpler.
  
  - make ipfw and dummynet use ip_len and ip_off in network format
    everywhere. Conversion is done only once instead of tracking
    the format in every place.
  
  - use a macro FREE_PKT to dispose of mbufs. This eases portability.
  
  On passing i also removed a few typos, staticise or localise variables,
  remove useless declarations and other minor things.
  
  Overall the code shrinks a bit and is hopefully more readable.
  
  I have tested functionality for all but ng_ipfw and if_bridge/if_ethersubr.
  For ng_ipfw i am actually waiting for feedback from glebius@ because
  we might have some small changes to make.
  For if_bridge and if_ethersubr feedback would be welcome
  (there are still some redundant parts in these two modules that
  I would like to remove, but first i need to check functionality).

Modified:
  head/sys/net/if_bridge.c
  head/sys/net/if_ethersubr.c
  head/sys/netgraph/ng_ipfw.c
  head/sys/netinet/ip_divert.c
  head/sys/netinet/ip_divert.h
  head/sys/netinet/ip_dummynet.h
  head/sys/netinet/ipfw/ip_dummynet.c
  head/sys/netinet/ipfw/ip_fw2.c
  head/sys/netinet/ipfw/ip_fw_dynamic.c
  head/sys/netinet/ipfw/ip_fw_log.c
  head/sys/netinet/ipfw/ip_fw_nat.c
  head/sys/netinet/ipfw/ip_fw_pfil.c
  head/sys/netinet/ipfw/ip_fw_private.h
  head/sys/netinet/ipfw/ip_fw_sockopt.c

Modified: head/sys/net/if_bridge.c
==============================================================================
--- head/sys/net/if_bridge.c	Mon Jan  4 18:57:22 2010	(r201526)
+++ head/sys/net/if_bridge.c	Mon Jan  4 19:01:22 2010	(r201527)
@@ -3040,25 +3040,26 @@ bridge_pfil(struct mbuf **mp, struct ifn
 	}
 
 	/* XXX this section is also in if_ethersubr.c */
-	if (V_ip_fw_chk_ptr && pfil_ipfw != 0 && dir == PFIL_OUT && ifp != NULL) {
+	// XXX PFIL_OUT or DIR_OUT ?
+	if (V_ip_fw_chk_ptr && pfil_ipfw != 0 &&
+			dir == PFIL_OUT && ifp != NULL) {
 		struct m_tag *mtag;
 
 		error = -1;
-		mtag = m_tag_find(*mp, PACKET_TAG_DUMMYNET, NULL);
+		/* fetch the start point from existing tags, if any */
+		mtag = m_tag_locate(*mp, MTAG_IPFW_RULE, 0, NULL);
 		if (mtag == NULL) {
-			args.slot = 0;
+			args.rule.slot = 0;
 		} else {
 			struct dn_pkt_tag *dn_tag;
 
+			/* XXX can we free the tag after use ? */
 			mtag->m_tag_id = PACKET_TAG_NONE;
 			dn_tag = (struct dn_pkt_tag *)(mtag + 1);
-			if (dn_tag->slot != 0 && V_fw_one_pass)
-				/* packet already partially processed */
+			/* packet already partially processed ? */
+			if (dn_tag->rule.slot != 0 && V_fw_one_pass)
 				goto ipfwpass;
-			args.slot = dn_tag->slot; /* next rule to use */
-			args.chain_id = dn_tag->chain_id;
-			args.rulenum = dn_tag->rulenum;
-			args.rule_id = dn_tag->rule_id;
+			args.rule = dn_tag->rule;
 		}
 
 		args.m = *mp;

Modified: head/sys/net/if_ethersubr.c
==============================================================================
--- head/sys/net/if_ethersubr.c	Mon Jan  4 18:57:22 2010	(r201526)
+++ head/sys/net/if_ethersubr.c	Mon Jan  4 19:01:22 2010	(r201527)
@@ -469,21 +469,20 @@ ether_ipfw_chk(struct mbuf **m0, struct 
 	struct ip_fw_args args;
 	struct m_tag *mtag;
 
-	mtag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL);
+	/* fetch start point from rule, if any */
+	mtag = m_tag_locate(*m0, MTAG_IPFW_RULE, 0, NULL);
 	if (mtag == NULL) {
-		args.slot = 0;
+		args.rule.slot = 0;
 	} else {
 		struct dn_pkt_tag *dn_tag;
 
+		/* XXX can we free it after use ? */
 		mtag->m_tag_id = PACKET_TAG_NONE;
 		dn_tag = (struct dn_pkt_tag *)(mtag + 1);
-		if (dn_tag->slot != 0 && V_fw_one_pass)
+		if (dn_tag->rule.slot != 0 && V_fw_one_pass)
 			/* dummynet packet, already partially processed */
 			return (1);
-		args.slot = dn_tag->slot;	/* matching rule to restart */
-		args.rulenum = dn_tag->rulenum;
-		args.rule_id = dn_tag->rule_id;
-		args.chain_id = dn_tag->chain_id;
+		args.rule = dn_tag->rule;
 	}
 
 	/*

Modified: head/sys/netgraph/ng_ipfw.c
==============================================================================
--- head/sys/netgraph/ng_ipfw.c	Mon Jan  4 18:57:22 2010	(r201526)
+++ head/sys/netgraph/ng_ipfw.c	Mon Jan  4 19:01:22 2010	(r201527)
@@ -221,21 +221,23 @@ ng_ipfw_findhook1(node_p node, u_int16_t
 static int
 ng_ipfw_rcvdata(hook_p hook, item_p item)
 {
-	struct ng_ipfw_tag	*ngit;
+	struct ipfw_rule_ref	*tag;
 	struct mbuf *m;
 
 	NGI_GET_M(item, m);
 	NG_FREE_ITEM(item);
 
-	if ((ngit = (struct ng_ipfw_tag *)m_tag_locate(m, NGM_IPFW_COOKIE, 0,
-	    NULL)) == NULL) {
+	tag = (struct ipfw_rule_ref *)
+		m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL);
+	if (tag == NULL) {
 		NG_FREE_M(m);
 		return (EINVAL);	/* XXX: find smth better */
 	};
 
-	switch (ngit->dir) {
-	case DIR_OUT:
-	    {
+	if (tag->info & IPFW_INFO_IN) {
+		ip_input(m);
+		return (0);
+	} else {
 		struct ip *ip;
 
 		if (m->m_len < sizeof(struct ip) &&
@@ -244,27 +246,16 @@ ng_ipfw_rcvdata(hook_p hook, item_p item
 
 		ip = mtod(m, struct ip *);
 
-		ip->ip_len = ntohs(ip->ip_len);
-		ip->ip_off = ntohs(ip->ip_off);
+		SET_HOST_IPLEN(ip);
 
 		return ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
-	    }
-	case DIR_IN:
-		ip_input(m);
-		return (0);
-	default:
-		panic("ng_ipfw_rcvdata: bad dir %u", ngit->dir);
 	}	
-
-	/* not reached */
-	return (0);
 }
 
 static int
 ng_ipfw_input(struct mbuf **m0, int dir, struct ip_fw_args *fwa, int tee)
 {
 	struct mbuf *m;
-	struct ng_ipfw_tag *ngit;
 	struct ip *ip;
 	hook_p	hook;
 	int error = 0;
@@ -273,7 +264,7 @@ ng_ipfw_input(struct mbuf **m0, int dir,
 	 * Node must be loaded and corresponding hook must be present.
 	 */
 	if (fw_node == NULL || 
-	   (hook = ng_ipfw_findhook1(fw_node, fwa->cookie)) == NULL) {
+	   (hook = ng_ipfw_findhook1(fw_node, fwa->rule.info)) == NULL) {
 		if (tee == 0)
 			m_freem(*m0);
 		return (ESRCH);		/* no hook associated with this rule */
@@ -285,21 +276,21 @@ ng_ipfw_input(struct mbuf **m0, int dir,
 	 * a copy of a packet and forward it into netgraph without a tag.
 	 */
 	if (tee == 0) {
+		struct m_tag *tag;
+		struct ipfw_rule_ref *r;
 		m = *m0;
 		*m0 = NULL;	/* it belongs now to netgraph */
 
-		if ((ngit = (struct ng_ipfw_tag *)m_tag_alloc(NGM_IPFW_COOKIE,
-		    0, TAGSIZ, M_NOWAIT|M_ZERO)) == NULL) {
+		tag = m_tag_alloc(MTAG_IPFW_RULE, 0, sizeof(*r),
+			M_NOWAIT|M_ZERO);
+		if (tag == NULL) {
 			m_freem(m);
 			return (ENOMEM);
 		}
-		ngit->slot = fwa->slot;
-		ngit->rulenum = fwa->rulenum;
-		ngit->rule_id = fwa->rule_id;
-		ngit->chain_id = fwa->chain_id;
-		ngit->dir = dir;
-//		ngit->ifp = fwa->oif; /* XXX do we use it ? */
-		m_tag_prepend(m, &ngit->mt);
+		r = (struct ipfw_rule_ref *)(tag + 1);
+		*r = fwa->rule;
+		r->info = dir ? IPFW_INFO_IN : IPFW_INFO_OUT;
+		m_tag_prepend(m, tag);
 
 	} else
 		if ((m = m_dup(*m0, M_DONTWAIT)) == NULL)
@@ -310,8 +301,6 @@ ng_ipfw_input(struct mbuf **m0, int dir,
 		return (EINVAL);
 
 	ip = mtod(m, struct ip *);
-	ip->ip_len = htons(ip->ip_len);
-	ip->ip_off = htons(ip->ip_off);
 
 	NG_SEND_DATA_ONLY(error, hook, m);
 

Modified: head/sys/netinet/ip_divert.c
==============================================================================
--- head/sys/netinet/ip_divert.c	Mon Jan  4 18:57:22 2010	(r201526)
+++ head/sys/netinet/ip_divert.c	Mon Jan  4 19:01:22 2010	(r201527)
@@ -52,19 +52,12 @@ __FBSDID("$FreeBSD$");
 #include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/protosw.h>
-#include <sys/rwlock.h>
-#include <sys/signalvar.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
-#include <sys/sx.h>
 #include <sys/sysctl.h>
-#include <sys/systm.h>
-
-#include <vm/uma.h>
 
 #include <net/if.h>
 #include <net/netisr.h> 
-#include <net/route.h>
 #include <net/vnet.h>
 
 #include <netinet/in.h>
@@ -72,7 +65,6 @@ __FBSDID("$FreeBSD$");
 #include <netinet/in_systm.h>
 #include <netinet/in_var.h>
 #include <netinet/ip.h>
-#include <netinet/ip_divert.h>
 #include <netinet/ip_var.h>
 #include <netinet/ip_fw.h>
 #include <netinet/ipfw/ip_fw_private.h>
@@ -194,7 +186,7 @@ div_destroy(void)
  * IPPROTO_DIVERT is not in the real IP protocol number space; this
  * function should never be called.  Just in case, drop any packets.
  */
-void
+static void
 div_input(struct mbuf *m, int off)
 {
 
@@ -218,9 +210,8 @@ divert_packet(struct mbuf *m, int incomi
 	struct sockaddr_in divsrc;
 	struct m_tag *mtag;
 
-	mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
+	mtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL);
 	if (mtag == NULL) {
-		printf("%s: no divert tag\n", __func__);
 		m_freem(m);
 		return;
 	}
@@ -245,14 +236,15 @@ divert_packet(struct mbuf *m, int incomi
 		ip->ip_len = htons(ip->ip_len);
 	}
 #endif
+	bzero(&divsrc, sizeof(divsrc));
+	divsrc.sin_len = sizeof(divsrc);
+	divsrc.sin_family = AF_INET;
+	/* record matching rule, in host format */
+	divsrc.sin_port = ((struct ipfw_rule_ref *)(mtag+1))->rulenum;
 	/*
 	 * Record receive interface address, if any.
 	 * But only for incoming packets.
 	 */
-	bzero(&divsrc, sizeof(divsrc));
-	divsrc.sin_len = sizeof(divsrc);
-	divsrc.sin_family = AF_INET;
-	divsrc.sin_port = divert_cookie(mtag);	/* record matching rule */
 	if (incoming) {
 		struct ifaddr *ifa;
 		struct ifnet *ifp;
@@ -300,7 +292,7 @@ divert_packet(struct mbuf *m, int incomi
 
 	/* Put packet on socket queue, if any */
 	sa = NULL;
-	nport = htons((u_int16_t)divert_info(mtag));
+	nport = htons((u_int16_t)(((struct ipfw_rule_ref *)(mtag+1))->info));
 	INP_INFO_RLOCK(&V_divcbinfo);
 	LIST_FOREACH(inp, &V_divcb, inp_list) {
 		/* XXX why does only one socket match? */
@@ -339,7 +331,7 @@ div_output(struct socket *so, struct mbu
     struct mbuf *control)
 {
 	struct m_tag *mtag;
-	struct divert_tag *dt;
+	struct ipfw_rule_ref *dt;
 	int error = 0;
 	struct mbuf *options;
 
@@ -354,23 +346,31 @@ div_output(struct socket *so, struct mbu
 	if (control)
 		m_freem(control);		/* XXX */
 
-	if ((mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL)) == NULL) {
-		mtag = m_tag_get(PACKET_TAG_DIVERT, sizeof(struct divert_tag),
-		    M_NOWAIT | M_ZERO);
+	mtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL);
+	if (mtag == NULL) {
+		/* this should be normal */
+		mtag = m_tag_alloc(MTAG_IPFW_RULE, 0,
+		    sizeof(struct ipfw_rule_ref), M_NOWAIT | M_ZERO);
 		if (mtag == NULL) {
 			error = ENOBUFS;
 			goto cantsend;
 		}
-		dt = (struct divert_tag *)(mtag+1);
 		m_tag_prepend(m, mtag);
-	} else
-		dt = (struct divert_tag *)(mtag+1);
+	}
+	dt = (struct ipfw_rule_ref *)(mtag+1);
 
 	/* Loopback avoidance and state recovery */
 	if (sin) {
 		int i;
 
-		dt->cookie = sin->sin_port;
+		/* set the starting point. We provide a non-zero slot,
+		 * but a non_matching chain_id to skip that info and use
+		 * the rulenum/rule_id.
+		 */
+		dt->slot = 1; /* dummy, chain_id is invalid */
+		dt->chain_id = 0;
+		dt->rulenum = sin->sin_port+1; /* host format ? */
+		dt->rule_id = 0;
 		/*
 		 * Find receive interface with the given name, stuffed
 		 * (if it exists) in the sin_zero[] field.
@@ -388,7 +388,7 @@ div_output(struct socket *so, struct mbu
 		struct ip *const ip = mtod(m, struct ip *);
 		struct inpcb *inp;
 
-		dt->info |= IP_FW_DIVERT_OUTPUT_FLAG;
+		dt->info |= IPFW_IS_DIVERT | IPFW_INFO_OUT;
 		INP_INFO_WLOCK(&V_divcbinfo);
 		inp = sotoinpcb(so);
 		INP_RLOCK(inp);
@@ -454,7 +454,7 @@ div_output(struct socket *so, struct mbu
 				m_freem(options);
 		}
 	} else {
-		dt->info |= IP_FW_DIVERT_LOOPBACK_FLAG;
+		dt->info |= IPFW_IS_DIVERT | IPFW_INFO_IN;
 		if (m->m_pkthdr.rcvif == NULL) {
 			/*
 			 * No luck with the name, check by IP address.
@@ -588,7 +588,7 @@ div_send(struct socket *so, int flags, s
 	return div_output(so, m, (struct sockaddr_in *)nam, control);
 }
 
-void
+static void
 div_ctlinput(int cmd, struct sockaddr *sa, void *vip)
 {
         struct in_addr faddr;
@@ -801,5 +801,5 @@ static moduledata_t ipdivertmod = {
 };
 
 DECLARE_MODULE(ipdivert, ipdivertmod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
-MODULE_DEPEND(dummynet, ipfw, 2, 2, 2);
+MODULE_DEPEND(ipdivert, ipfw, 2, 2, 2);
 MODULE_VERSION(ipdivert, 1);

Modified: head/sys/netinet/ip_divert.h
==============================================================================
--- head/sys/netinet/ip_divert.h	Mon Jan  4 18:57:22 2010	(r201526)
+++ head/sys/netinet/ip_divert.h	Mon Jan  4 19:01:22 2010	(r201527)
@@ -36,53 +36,20 @@
 #define	_NETINET_IP_DIVERT_H_
 
 /*
- * Sysctl declaration.
+ * divert has no custom kernel-userland API.
+ *
+ * All communication occurs through a sockaddr_in socket where
+ *
+ * kernel-->userland
+ *	sin_port = matching rule, host format;
+ * 	sin_addr = IN: first address of the incoming interface;
+ *		   OUT: INADDR_ANY
+ *	sin_zero = if fits, the interface name (max 7 bytes + NUL)
+ *
+ * userland->kernel
+ *	sin_port = restart-rule - 1, host order
+ *		(we restart at sin_port + 1)
+ *	sin_addr = IN: address of the incoming interface;
+ *		   OUT: INADDR_ANY
  */
-#ifdef SYSCTL_DECL
-SYSCTL_DECL(_net_inet_divert);
-#endif
-
-/*
- * Divert socket definitions.
- */
-struct divert_tag {
-	u_int32_t	info;		/* port & flags */
-	u_int16_t	cookie;		/* ipfw rule number */
-};
-
-/*
- * Return the divert cookie associated with the mbuf; if any.
- */
-static __inline u_int16_t
-divert_cookie(struct m_tag *mtag)
-{
-	return ((struct divert_tag *)(mtag+1))->cookie;
-}
-static __inline u_int16_t
-divert_find_cookie(struct mbuf *m)
-{
-	struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
-	return mtag ? divert_cookie(mtag) : 0;
-}
-
-/*
- * Return the divert info associated with the mbuf; if any.
- */
-static __inline u_int32_t
-divert_info(struct m_tag *mtag)
-{
-	return ((struct divert_tag *)(mtag+1))->info;
-}
-static __inline u_int32_t
-divert_find_info(struct mbuf *m)
-{
-	struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
-	return mtag ? divert_info(mtag) : 0;
-}
-
-typedef	void ip_divert_packet_t(struct mbuf *m, int incoming);
-extern	ip_divert_packet_t *ip_divert_ptr;
-
-extern	void div_input(struct mbuf *, int);
-extern	void div_ctlinput(int, struct sockaddr *, void *);
 #endif /* _NETINET_IP_DIVERT_H_ */

Modified: head/sys/netinet/ip_dummynet.h
==============================================================================
--- head/sys/netinet/ip_dummynet.h	Mon Jan  4 18:57:22 2010	(r201526)
+++ head/sys/netinet/ip_dummynet.h	Mon Jan  4 19:01:22 2010	(r201527)
@@ -114,11 +114,7 @@ struct dn_heap {
  * other forms of packet reinjection.
  */
 struct dn_pkt_tag {
-    /* first part, reinject info */
-    uint32_t slot;		/* slot of next rule to use */
-    uint32_t rulenum;		/* matching rule number */
-    uint32_t rule_id;		/* matching rule id */
-    uint32_t chain_id;		/* ruleset id */
+	struct ipfw_rule_ref rule;	/* matching rule */
 
     /* second part, dummynet specific */
     int dn_dir;			/* action when packet comes out. */

Modified: head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- head/sys/netinet/ipfw/ip_dummynet.c	Mon Jan  4 18:57:22 2010	(r201526)
+++ head/sys/netinet/ipfw/ip_dummynet.c	Mon Jan  4 19:01:22 2010	(r201527)
@@ -462,15 +462,10 @@ heap_free(struct dn_heap *h)
  */
 
 /*
- * Dispose a packet in dummynet. Use an inline functions so if we
+ * Dispose a list of packet. Use an inline functions so if we
  * need to free extra state associated to a packet, this is a
  * central point to do it.
  */
-static __inline void *dn_free_pkt(struct mbuf *m)
-{
-	m_freem(m);
-	return NULL;
-}
 
 static __inline void dn_free_pkts(struct mbuf *mnext)
 {
@@ -478,7 +473,7 @@ static __inline void dn_free_pkts(struct
 
 	while ((m = mnext) != NULL) {
 		mnext = m->m_nextpkt;
-		dn_free_pkt(m);
+		FREE_PKT(m);
 	}
 }
 
@@ -968,24 +963,31 @@ dummynet_send(struct mbuf *m)
 	for (; m != NULL; m = n) {
 		struct ifnet *ifp;
 		int dst;
+        	struct m_tag *tag;
 
 		n = m->m_nextpkt;
 		m->m_nextpkt = NULL;
-		if (m_tag_first(m) == NULL) {
+		tag = m_tag_first(m);
+		if (tag == NULL) {
 			dst = DIR_DROP;
 		} else {
 			struct dn_pkt_tag *pkt = dn_tag_get(m);
+			/* extract the dummynet info, rename the tag */
 			dst = pkt->dn_dir;
 			ifp = pkt->ifp;
+			/* rename the tag so it carries reinject info */
+			tag->m_tag_cookie = MTAG_IPFW_RULE;
+			tag->m_tag_id = 0;
 		}
 
 		switch (dst) {
 		case DIR_OUT:
+			SET_HOST_IPLEN(mtod(m, struct ip *));
 			ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
 			break ;
 		case DIR_IN :
 			/* put header in network format for ip_input() */
-			SET_NET_IPLEN(mtod(m, struct ip *));
+			//SET_NET_IPLEN(mtod(m, struct ip *));
 			netisr_dispatch(NETISR_IP, m);
 			break;
 #ifdef INET6
@@ -994,6 +996,7 @@ dummynet_send(struct mbuf *m)
 			break;
 
 		case DIR_OUT | PROTO_IPV6:
+			SET_HOST_IPLEN(mtod(m, struct ip *));
 			ip6_output(m, NULL, NULL, IPV6_FORWARDING, NULL, NULL, NULL);
 			break;
 #endif
@@ -1024,12 +1027,12 @@ dummynet_send(struct mbuf *m)
 
 		case DIR_DROP:
 			/* drop the packet after some time */
-			dn_free_pkt(m);
+			FREE_PKT(m);
 			break;
 
 		default:
 			printf("dummynet: bad switch %d!\n", dst);
-			dn_free_pkt(m);
+			FREE_PKT(m);
 			break;
 		}
 	}
@@ -1362,7 +1365,7 @@ dummynet_io(struct mbuf **m0, int dir, s
 	struct dn_pipe *pipe;
 	uint64_t len = m->m_pkthdr.len;
 	struct dn_flow_queue *q = NULL;
-	int is_pipe = fwa->cookie & 0x8000000 ? 0 : 1;
+	int is_pipe = fwa->rule.info & IPFW_IS_PIPE;
 
 	KASSERT(m->m_nextpkt == NULL,
 	    ("dummynet_io: mbuf queue passed to dummynet"));
@@ -1371,16 +1374,13 @@ dummynet_io(struct mbuf **m0, int dir, s
 	io_pkt++;
 	/*
 	 * This is a dummynet rule, so we expect an O_PIPE or O_QUEUE rule.
-	 *
-	 * XXXGL: probably the pipe->fs and fs->pipe logic here
-	 * below can be simplified.
 	 */
 	if (is_pipe) {
-		pipe = locate_pipe(fwa->cookie & 0xffff);
+		pipe = locate_pipe(fwa->rule.info & IPFW_INFO_MASK);
 		if (pipe != NULL)
 			fs = &(pipe->fs);
 	} else
-		fs = locate_flowset(fwa->cookie & 0xffff);
+		fs = locate_flowset(fwa->rule.info & IPFW_INFO_MASK);
 
 	if (fs == NULL)
 		goto dropit;	/* This queue/pipe does not exist! */
@@ -1426,12 +1426,9 @@ dummynet_io(struct mbuf **m0, int dir, s
 	 * Ok, i can handle the pkt now...
 	 * Build and enqueue packet + parameters.
 	 */
-	pkt->slot = fwa->slot;
-	pkt->rulenum = fwa->rulenum;
-	pkt->rule_id = fwa->rule_id;
-	pkt->chain_id = fwa->chain_id;
+	pkt->rule = fwa->rule;
+	pkt->rule.info &= IPFW_ONEPASS;	/* only keep this info */
 	pkt->dn_dir = dir;
-
 	pkt->ifp = fwa->oif;
 
 	if (q->head == NULL)
@@ -1562,7 +1559,8 @@ dropit:
 	if (q)
 		q->drops++;
 	DUMMYNET_UNLOCK();
-	*m0 = dn_free_pkt(m);
+	FREE_PKT(m);
+	*m0 = NULL;
 	return ((fs && (fs->flags_fs & DN_NOERROR)) ? 0 : ENOBUFS);
 }
 

Modified: head/sys/netinet/ipfw/ip_fw2.c
==============================================================================
--- head/sys/netinet/ipfw/ip_fw2.c	Mon Jan  4 18:57:22 2010	(r201526)
+++ head/sys/netinet/ipfw/ip_fw2.c	Mon Jan  4 19:01:22 2010	(r201527)
@@ -74,7 +74,6 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ip_icmp.h>
 #include <netinet/ip_fw.h>
 #include <netinet/ipfw/ip_fw_private.h>
-#include <netinet/ip_divert.h>
 #include <netinet/ip_carp.h>
 #include <netinet/pim.h>
 #include <netinet/tcp_var.h>
@@ -560,7 +559,7 @@ send_reject6(struct ip_fw_args *args, in
 				ip6_output(m0, NULL, NULL, 0, NULL, NULL,
 				    NULL);
 		}
-		m_freem(m);
+		FREE_PKT(m);
 	} else if (code != ICMP6_UNREACH_RST) { /* Send an ICMPv6 unreach. */
 #if 0
 		/*
@@ -576,7 +575,7 @@ send_reject6(struct ip_fw_args *args, in
 #endif
 		icmp6_error(m, ICMP6_DST_UNREACH, code, 0);
 	} else
-		m_freem(m);
+		FREE_PKT(m);
 
 	args->m = NULL;
 }
@@ -603,9 +602,7 @@ send_reject(struct ip_fw_args *args, int
 #endif
 	if (code != ICMP_REJECT_RST) { /* Send an ICMP unreach */
 		/* We need the IP header in host order for icmp_error(). */
-		if (args->eh != NULL) {
-			SET_HOST_IPLEN(ip);
-		}
+		SET_HOST_IPLEN(ip);
 		icmp_error(args->m, ICMP_UNREACH, code, 0L, 0);
 	} else if (args->f_id.proto == IPPROTO_TCP) {
 		struct tcphdr *const tcp =
@@ -618,9 +615,9 @@ send_reject(struct ip_fw_args *args, int
 			if (m != NULL)
 				ip_output(m, NULL, NULL, 0, NULL, NULL);
 		}
-		m_freem(args->m);
+		FREE_PKT(args->m);
 	} else
-		m_freem(args->m);
+		FREE_PKT(args->m);
 	args->m = NULL;
 }
 
@@ -709,16 +706,18 @@ check_uidgid(ipfw_insn_u32 *insn, int pr
 }
 
 /*
- * Helper function to write the matching rule into args
+ * Helper function to set args with info on the rule after the matching
+ * one. slot is precise, whereas we guess rule_id as they are
+ * assigned sequentially.
  */
 static inline void
 set_match(struct ip_fw_args *args, int slot,
 	struct ip_fw_chain *chain)
 {
-	args->chain_id = chain->id;
-	args->slot = slot + 1; /* we use 0 as a marker */
-	args->rule_id = chain->map[slot]->id;
-	args->rulenum = chain->map[slot]->rulenum;
+	args->rule.chain_id = chain->id;
+	args->rule.slot = slot + 1; /* we use 0 as a marker */
+	args->rule.rule_id = 1 + chain->map[slot]->id;
+	args->rule.rulenum = chain->map[slot]->rulenum;
 }
 
 /*
@@ -743,7 +742,7 @@ set_match(struct ip_fw_args *args, int s
  *	args->rule	Pointer to the last matching rule (in/out)
  *	args->next_hop	Socket we are forwarding to (out).
  *	args->f_id	Addresses grabbed from the packet (out)
- * 	args->cookie	a cookie depending on rule action
+ * 	args->rule.info	a cookie depending on rule action
  *
  * Return value:
  *
@@ -753,6 +752,8 @@ set_match(struct ip_fw_args *args, int s
  *	IP_FW_TEE	tee packet, port in m_tag
  *	IP_FW_DUMMYNET	to dummynet, pipe in args->cookie
  *	IP_FW_NETGRAPH	into netgraph, cookie args->cookie
+ *		args->rule contains the matching rule,
+ *		args->rule.info has additional information.
  *
  */
 int
@@ -797,14 +798,6 @@ ipfw_chk(struct ip_fw_args *args)
 	int ucred_lookup = 0;
 
 	/*
-	 * divinput_flags	If non-zero, set to the IP_FW_DIVERT_*_FLAG
-	 *	associated with a packet input on a divert socket.  This
-	 *	will allow to distinguish traffic and its direction when
-	 *	it originates from a divert socket.
-	 */
-	u_int divinput_flags = 0;
-
-	/*
 	 * oif | args->oif	If NULL, ipfw_chk has been called on the
 	 *	inbound path (ether_input, ip_input).
 	 *	If non-NULL, ipfw_chk has been called on the outbound path
@@ -862,7 +855,6 @@ ipfw_chk(struct ip_fw_args *args)
 	int dyn_dir = MATCH_UNKNOWN;
 	ipfw_dyn_rule *q = NULL;
 	struct ip_fw_chain *chain = &V_layer3_chain;
-	struct m_tag *mtag;
 
 	/*
 	 * We store in ulp a pointer to the upper layer protocol header.
@@ -1090,16 +1082,8 @@ do {								\
 		proto = ip->ip_p;
 		src_ip = ip->ip_src;
 		dst_ip = ip->ip_dst;
-#ifndef HAVE_NET_IPLEN
-		if (args->eh == NULL) { /* on l3 these are in host format */
-			offset = ip->ip_off & IP_OFFMASK;
-			iplen = ip->ip_len;
-		} else
-#endif /* !HAVE_NET_IPLEN */
-		{	/* otherwise they are in net format */
-			offset = ntohs(ip->ip_off) & IP_OFFMASK;
-			iplen = ntohs(ip->ip_len);
-		}
+		offset = ntohs(ip->ip_off) & IP_OFFMASK;
+		iplen = ntohs(ip->ip_len);
 		pktlen = iplen < pktlen ? iplen : pktlen;
 
 		if (offset == 0) {
@@ -1143,44 +1127,20 @@ do {								\
 		IPFW_RUNLOCK(chain);
 		return (IP_FW_PASS);	/* accept */
 	}
-	/* XXX divert should be handled same as other tags */
-	mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
-	if (args->slot) {
+	if (args->rule.slot) {
 		/*
 		 * Packet has already been tagged as a result of a previous
 		 * match on rule args->rule aka args->rule_id (PIPE, QUEUE,
-		 * REASS, NETGRAPH and similar, never a skipto).
+		 * REASS, NETGRAPH, DIVERT/TEE...)
 		 * Validate the slot and continue from the next one
 		 * if still present, otherwise do a lookup.
 		 */
-		if (V_fw_one_pass) {
-			IPFW_RUNLOCK(chain);
-			return (IP_FW_PASS);
-		}
-		f_pos = (args->chain_id == chain->id) ?
-		    args->slot /* already incremented */ :
-		    ipfw_find_rule(chain, args->rulenum, args->rule_id+1);
+		f_pos = (args->rule.chain_id == chain->id) ?
+		    args->rule.slot :
+		    ipfw_find_rule(chain, args->rule.rulenum,
+			args->rule.rule_id);
 	} else {
-		/*
-		 * Find the starting rule. It can be either the first
-		 * one, or the one after divert_rule if asked so.
-		 */
-		int skipto = mtag ? divert_cookie(mtag) : 0;
-
 		f_pos = 0;
-		if (args->eh == NULL && skipto != 0) {
-			if (skipto >= IPFW_DEFAULT_RULE) {
-				IPFW_RUNLOCK(chain);
-				return (IP_FW_DENY); /* invalid */
-			}
-			f_pos = ipfw_find_rule(chain, skipto+1, 0);
-		}
-	}
-	/* reset divert rule to avoid confusion later */
-	if (mtag) {
-		divinput_flags = divert_info(mtag) &
-		    (IP_FW_DIVERT_OUTPUT_FLAG | IP_FW_DIVERT_LOOPBACK_FLAG);
-		m_tag_delete(m, mtag);
 	}
 
 	/*
@@ -1332,10 +1292,15 @@ do {								\
 				break;
 
 			case O_DIVERTED:
-				match = (cmd->arg1 & 1 && divinput_flags &
-				    IP_FW_DIVERT_LOOPBACK_FLAG) ||
-					(cmd->arg1 & 2 && divinput_flags &
-				    IP_FW_DIVERT_OUTPUT_FLAG);
+			    {
+				/* For diverted packets, args->rule.info
+				 * contains the divert port (in host format)
+				 * reason and direction.
+	 			 */
+				uint32_t i = args->rule.info;
+				match = (i&IPFW_IS_MASK) == IPFW_IS_DIVERT &&
+				    cmd->arg1 & ((i & IPFW_INFO_IN) ? 1 : 2);
+			    }
 				break;
 
 			case O_PROTO:
@@ -1755,6 +1720,7 @@ do {								\
 				break;
 
 			case O_TAG: {
+				struct m_tag *mtag;
 				uint32_t tag = (cmd->arg1 == IP_FW_TABLEARG) ?
 				    tablearg : cmd->arg1;
 
@@ -1771,12 +1737,13 @@ do {								\
 				if (cmd->len & F_NOT) { /* `untag' action */
 					if (mtag != NULL)
 						m_tag_delete(m, mtag);
+					match = 0;
 				} else if (mtag == NULL) {
 					if ((mtag = m_tag_alloc(MTAG_IPFW,
 					    tag, 0, M_NOWAIT)) != NULL)
 						m_tag_prepend(m, mtag);
+					match = 1;
 				}
-				match = (cmd->len & F_NOT) ? 0: 1;
 				break;
 			}
 
@@ -1786,6 +1753,7 @@ do {								\
 				break;
 
 			case O_TAGGED: {
+				struct m_tag *mtag;
 				uint32_t tag = (cmd->arg1 == IP_FW_TABLEARG) ?
 				    tablearg : cmd->arg1;
 
@@ -1926,10 +1894,12 @@ do {								\
 			case O_PIPE:
 			case O_QUEUE:
 				set_match(args, f_pos, chain);
-				args->cookie = (cmd->arg1 == IP_FW_TABLEARG) ?
+				args->rule.info = (cmd->arg1 == IP_FW_TABLEARG) ?
 					tablearg : cmd->arg1;
-				if (cmd->opcode == O_QUEUE)
-					args->cookie |= 0x80000000;
+				if (cmd->opcode == O_PIPE)
+					args->rule.info |= IPFW_IS_PIPE;
+				if (V_fw_one_pass)
+					args->rule.info |= IPFW_ONEPASS;
 				retval = IP_FW_DUMMYNET;
 				l = 0;          /* exit inner loop */
 				done = 1;       /* exit outer loop */
@@ -1942,23 +1912,11 @@ do {								\
 				/* otherwise this is terminal */
 				l = 0;		/* exit inner loop */
 				done = 1;	/* exit outer loop */
-				mtag = m_tag_get(PACKET_TAG_DIVERT,
-					sizeof(struct divert_tag),
-					M_NOWAIT);
-				if (mtag == NULL) {
-				    retval = IP_FW_DENY;
-				} else {
-				    struct divert_tag *dt;
-				    dt = (struct divert_tag *)(mtag+1);
-				    dt->cookie = f->rulenum;
-				    if (cmd->arg1 == IP_FW_TABLEARG)
-					dt->info = tablearg;
-				    else
-					dt->info = cmd->arg1;
-				    m_tag_prepend(m, mtag);
-				    retval = (cmd->opcode == O_DIVERT) ?
+				retval = (cmd->opcode == O_DIVERT) ?
 					IP_FW_DIVERT : IP_FW_TEE;
-				}
+				set_match(args, f_pos, chain);
+				args->rule.info = (cmd->arg1 == IP_FW_TABLEARG) ?
+				    tablearg : cmd->arg1;
 				break;
 
 			case O_COUNT:
@@ -2074,7 +2032,7 @@ do {								\
 			case O_NETGRAPH:
 			case O_NGTEE:
 				set_match(args, f_pos, chain);
-				args->cookie = (cmd->arg1 == IP_FW_TABLEARG) ?
+				args->rule.info = (cmd->arg1 == IP_FW_TABLEARG) ?
 					tablearg : cmd->arg1;
 				retval = (cmd->opcode == O_NETGRAPH) ?
 				    IP_FW_NETGRAPH : IP_FW_NGTEE;
@@ -2126,12 +2084,6 @@ do {								\
 				f->pcnt++;
 				f->bcnt += pktlen;
 				l = 0;	/* in any case exit inner loop */
-
-#ifndef HAVE_NET_IPLEN
-				if (args->eh == NULL)
-					ip_off = ip->ip_off;
-				else
-#endif /* !HAVE_NET_IPLEN */
 				ip_off = ntohs(ip->ip_off);
 
 				/* if not fragmented, go to next rule */
@@ -2139,19 +2091,14 @@ do {								\
 				    break;
 				/* 
 				 * ip_reass() expects len & off in host
-				 * byte order: fix them in case we come
-				 * from layer2.
+				 * byte order.
 				 */
-				if (args->eh != NULL) {
-					SET_HOST_IPLEN(ip);
-				}
+				SET_HOST_IPLEN(ip);
 
 				args->m = m = ip_reass(m);
 
 				/*
-				 * IP header checksum fixup after 
-				 * reassembly and leave header
-				 * in network byte order.
+				 * do IP header checksum fixup.
 				 */
 				if (m == NULL) { /* fragment got swallowed */
 				    retval = IP_FW_DENY;
@@ -2160,10 +2107,7 @@ do {								\
 
 				    ip = mtod(m, struct ip *);
 				    hlen = ip->ip_hl << 2;
-				    /* revert len. & off to net format if needed */
-				    if (args->eh != NULL) {
-					SET_NET_IPLEN(ip);
-				    }
+				    SET_NET_IPLEN(ip);
 				    ip->ip_sum = 0;
 				    if (hlen == sizeof(struct ip))
 					ip->ip_sum = in_cksum_hdr(ip);

Modified: head/sys/netinet/ipfw/ip_fw_dynamic.c
==============================================================================
--- head/sys/netinet/ipfw/ip_fw_dynamic.c	Mon Jan  4 18:57:22 2010	(r201526)
+++ head/sys/netinet/ipfw/ip_fw_dynamic.c	Mon Jan  4 19:01:22 2010	(r201527)
@@ -917,7 +917,7 @@ ipfw_send_pkt(struct mbuf *replyto, stru
 #endif
 	default:
 		/* XXX: log me?!? */
-		m_freem(m);
+		FREE_PKT(m);
 		return (NULL);
 	}
 	dir = ((flags & (TH_SYN | TH_RST)) == TH_SYN);
@@ -1002,11 +1002,7 @@ ipfw_send_pkt(struct mbuf *replyto, stru
 		h->ip_hl = sizeof(*h) >> 2;
 		h->ip_tos = IPTOS_LOWDELAY;
 		h->ip_off = 0;
-#ifdef HAVE_NET_IPLEN /* XXX do we handle layer2 ? */
 		h->ip_len = htons(len);
-#else
-		h->ip_len = len;
-#endif
 		h->ip_ttl = V_ip_defttl;
 		h->ip_sum = 0;
 		break;

Modified: head/sys/netinet/ipfw/ip_fw_log.c
==============================================================================
--- head/sys/netinet/ipfw/ip_fw_log.c	Mon Jan  4 18:57:22 2010	(r201526)
+++ head/sys/netinet/ipfw/ip_fw_log.c	Mon Jan  4 19:01:22 2010	(r201527)
@@ -165,16 +165,8 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
 			 * more info in the header
 			 */
 			mh.mh_data = "DDDDDDSSSSSS\x08\x00";
-			if (args->f_id.addr_type == 4) {
-				/* restore wire format */
-				SET_NET_IPLEN(ip);
-			}
 		}
 		BPF_MTAP(log_if, (struct mbuf *)&mh);
-		if (args->eh == NULL && args->f_id.addr_type == 4) {
-			/* restore host format */
-			SET_HOST_IPLEN(ip);
-		}
 #endif /* !WITHOUT_BPF */
 		return;
 	}
@@ -409,23 +401,15 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
 		} else
 #endif
 		{
-			int ip_off, ip_len;
-#ifndef HAVE_NET_IPLEN
-			if (args->eh == NULL) {
-				ip_off = ip->ip_off;
-				ip_len = ip->ip_len;
-			} else
-#endif /* !HAVE_NET_IPLEN */
-			{
-				ip_off = ntohs(ip->ip_off);
-				ip_len = ntohs(ip->ip_len);
-			}
-			if (ip_off & (IP_MF | IP_OFFMASK))
+			int ipoff, iplen;
+			ipoff = ntohs(ip->ip_off);
+			iplen = ntohs(ip->ip_len);
+			if (ipoff & (IP_MF | IP_OFFMASK))
 				snprintf(SNPARGS(fragment, 0),
 				    " (frag %d:%d@%d%s)",
-				    ntohs(ip->ip_id), ip_len - (ip->ip_hl << 2),
+				    ntohs(ip->ip_id), iplen - (ip->ip_hl << 2),
 				    offset << 3,
-				    (ip_off & IP_MF) ? "+" : "");
+				    (ipoff & IP_MF) ? "+" : "");
 		}
 	}
 	if (oif || m->m_pkthdr.rcvif)

Modified: head/sys/netinet/ipfw/ip_fw_nat.c
==============================================================================
--- head/sys/netinet/ipfw/ip_fw_nat.c	Mon Jan  4 18:57:22 2010	(r201526)
+++ head/sys/netinet/ipfw/ip_fw_nat.c	Mon Jan  4 19:01:22 2010	(r201527)
@@ -219,9 +219,6 @@ ipfw_nat(struct ip_fw_args *args, struct
 		return (IP_FW_DENY);
 	}
 	ip = mtod(mcl, struct ip *);
-	if (args->eh == NULL) {
-		SET_NET_IPLEN(ip);
-	}
 
 	/*
 	 * XXX - Libalias checksum offload 'duct tape':
@@ -330,9 +327,6 @@ ipfw_nat(struct ip_fw_args *args, struct
 			mcl->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
 		}
 	}
-	if (args->eh == NULL) {
-		SET_HOST_IPLEN(ip);
-	}
 	args->m = mcl;
 	return (IP_FW_NAT);
 }

Modified: head/sys/netinet/ipfw/ip_fw_pfil.c
==============================================================================
--- head/sys/netinet/ipfw/ip_fw_pfil.c	Mon Jan  4 18:57:22 2010	(r201526)
+++ head/sys/netinet/ipfw/ip_fw_pfil.c	Mon Jan  4 19:01:22 2010	(r201527)
@@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ip_var.h>
 #include <netinet/ip_fw.h>

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list