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

Luigi Rizzo luigi at FreeBSD.org
Mon Dec 28 10:47:05 UTC 2009


Author: luigi
Date: Mon Dec 28 10:47:04 2009
New Revision: 201122
URL: http://svn.freebsd.org/changeset/base/201122

Log:
  bring in several cleanups tested in ipfw3-head branch, namely:
  
  r201011
  - move most of ng_ipfw.h into ip_fw_private.h, as this code is
    ipfw-specific. This removes a dependency on ng_ipfw.h from some files.
  
  - move many equivalent definitions of direction (IN, OUT) for
    reinjected packets into ip_fw_private.h
  
  - document the structure of the packet tags used for dummynet
    and netgraph;
  
  r201049
  - merge some common code to attach/detach hooks into
    a single function.
  
  r201055
  - remove some duplicated code in ip_fw_pfil. The input
    and output processing uses almost exactly the same code so
    there is no need to use two separate hooks.
    ip_fw_pfil.o goes from 2096 to 1382 bytes of .text
  
  r201057 (see the svn log for full details)
  - macros to make the conversion of ip_len and ip_off
    between host and network format more explicit
  
  r201113 (the remaining parts)
  - readability fixes -- put braces around some large for() blocks,
    localize variables so the compiler does not think they are uninitialized,
    do not insist on precise allocation size if we have more than we need.
  
  r201119
  - when doing a lookup, keys must be in big endian format because
    this is what the radix code expects (this fixes a bug in the
    recently-introduced 'lookup' option)
  
  No ABI changes in this commit.
  
  MFC after:	1 week

Modified:
  head/sys/net/if_bridge.c
  head/sys/net/if_ethersubr.c
  head/sys/netgraph/ng_ipfw.c
  head/sys/netgraph/ng_ipfw.h
  head/sys/netinet/in.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 Dec 28 10:19:53 2009	(r201121)
+++ head/sys/net/if_bridge.c	Mon Dec 28 10:47:04 2009	(r201122)
@@ -3041,13 +3041,17 @@ 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) {
-		struct dn_pkt_tag *dn_tag;
+		struct m_tag *mtag;
 
 		error = -1;
-		dn_tag = ip_dn_claim_tag(*mp);
-		if (dn_tag == NULL) {
+		mtag = m_tag_find(*mp, PACKET_TAG_DUMMYNET, NULL);
+		if (mtag == NULL) {
 			args.slot = 0;
 		} else {
+			struct dn_pkt_tag *dn_tag;
+
+			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 */
 				goto ipfwpass;
@@ -3081,7 +3085,7 @@ bridge_pfil(struct mbuf **mp, struct ifn
 			 * packet will return to us via bridge_dummynet().
 			 */
 			args.oif = ifp;
-			ip_dn_io_ptr(mp, DN_TO_IFB_FWD, &args);
+			ip_dn_io_ptr(mp, DIR_FWD | PROTO_IFB, &args);
 			return (error);
 		}
 

Modified: head/sys/net/if_ethersubr.c
==============================================================================
--- head/sys/net/if_ethersubr.c	Mon Dec 28 10:19:53 2009	(r201121)
+++ head/sys/net/if_ethersubr.c	Mon Dec 28 10:47:04 2009	(r201122)
@@ -467,13 +467,16 @@ ether_ipfw_chk(struct mbuf **m0, struct 
 	struct mbuf *m;
 	int i;
 	struct ip_fw_args args;
-	struct dn_pkt_tag *dn_tag;
+	struct m_tag *mtag;
 
-	dn_tag = ip_dn_claim_tag(*m0);
-
-	if (dn_tag == NULL) {
+	mtag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL);
+	if (mtag == NULL) {
 		args.slot = 0;
 	} else {
+		struct dn_pkt_tag *dn_tag;
+
+		mtag->m_tag_id = PACKET_TAG_NONE;
+		dn_tag = (struct dn_pkt_tag *)(mtag + 1);
 		if (dn_tag->slot != 0 && V_fw_one_pass)
 			/* dummynet packet, already partially processed */
 			return (1);
@@ -532,6 +535,7 @@ ether_ipfw_chk(struct mbuf **m0, struct 
 		return 1;
 
 	if (ip_dn_io_ptr && (i == IP_FW_DUMMYNET)) {
+		int dir;
 		/*
 		 * Pass the pkt to dummynet, which consumes it.
 		 * If shared, make a copy and keep the original.
@@ -547,7 +551,8 @@ ether_ipfw_chk(struct mbuf **m0, struct 
 			 */
 			*m0 = NULL ;
 		}
-		ip_dn_io_ptr(&m, dst ? DN_TO_ETH_OUT: DN_TO_ETH_DEMUX, &args);
+		dir = PROTO_LAYER2 | (dst ? DIR_OUT : DIR_IN);
+		ip_dn_io_ptr(&m, dir, &args);
 		return 0;
 	}
 	/*

Modified: head/sys/netgraph/ng_ipfw.c
==============================================================================
--- head/sys/netgraph/ng_ipfw.c	Mon Dec 28 10:19:53 2009	(r201121)
+++ head/sys/netgraph/ng_ipfw.c	Mon Dec 28 10:47:04 2009	(r201122)
@@ -234,7 +234,7 @@ ng_ipfw_rcvdata(hook_p hook, item_p item
 	};
 
 	switch (ngit->dir) {
-	case NG_IPFW_OUT:
+	case DIR_OUT:
 	    {
 		struct ip *ip;
 
@@ -249,7 +249,7 @@ ng_ipfw_rcvdata(hook_p hook, item_p item
 
 		return ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
 	    }
-	case NG_IPFW_IN:
+	case DIR_IN:
 		ip_input(m);
 		return (0);
 	default:
@@ -298,7 +298,7 @@ ng_ipfw_input(struct mbuf **m0, int dir,
 		ngit->rule_id = fwa->rule_id;
 		ngit->chain_id = fwa->chain_id;
 		ngit->dir = dir;
-		ngit->ifp = fwa->oif;
+//		ngit->ifp = fwa->oif; /* XXX do we use it ? */
 		m_tag_prepend(m, &ngit->mt);
 
 	} else

Modified: head/sys/netgraph/ng_ipfw.h
==============================================================================
--- head/sys/netgraph/ng_ipfw.h	Mon Dec 28 10:19:53 2009	(r201121)
+++ head/sys/netgraph/ng_ipfw.h	Mon Dec 28 10:47:04 2009	(r201122)
@@ -26,27 +26,7 @@
  * $FreeBSD$
  */
 
+#ifndef _NG_IPFW_H
+#define _NG_IPFW_H
 #define NG_IPFW_NODE_TYPE    "ipfw"
-#define NGM_IPFW_COOKIE      1105988990
-
-#ifdef _KERNEL
-
-typedef int ng_ipfw_input_t(struct mbuf **, int, struct ip_fw_args *, int);
-extern	ng_ipfw_input_t	*ng_ipfw_input_p;
-#define	NG_IPFW_LOADED	(ng_ipfw_input_p != NULL)
-
-struct ng_ipfw_tag {
-	struct m_tag	mt;		/* tag header */
-	uint32_t	slot;		/* slot for next rule */
-	uint32_t	rulenum;	/* matching rule number */
-	uint32_t	rule_id;	/* matching rule id */
-	uint32_t	chain_id;	/* ruleset id */
-	struct ifnet	*ifp;		/* interface, for ip_output */
-	int		dir;
-#define	NG_IPFW_OUT	0
-#define	NG_IPFW_IN	1
-};
-
-#define	TAGSIZ	(sizeof(struct ng_ipfw_tag) - sizeof(struct m_tag))
-
-#endif /* _KERNEL */
+#endif /* _NG_IPFW_H */

Modified: head/sys/netinet/in.h
==============================================================================
--- head/sys/netinet/in.h	Mon Dec 28 10:19:53 2009	(r201121)
+++ head/sys/netinet/in.h	Mon Dec 28 10:47:04 2009	(r201122)
@@ -734,6 +734,32 @@ void	 in_ifdetach(struct ifnet *);
 #define	sintosa(sin)	((struct sockaddr *)(sin))
 #define	ifatoia(ifa)	((struct in_ifaddr *)(ifa))
 
+/*
+ * Historically, BSD keeps ip_len and ip_off in host format
+ * when doing layer 3 processing, and this often requires
+ * to translate the format back and forth.
+ * To make the process explicit, we define a couple of macros
+ * that also take into account the fact that at some point
+ * we may want to keep those fields always in net format.
+ */
+
+#if (BYTE_ORDER == BIG_ENDIAN) || defined(HAVE_NET_IPLEN)
+#define SET_NET_IPLEN(p)	do {} while (0)
+#define SET_HOST_IPLEN(p)	do {} while (0)
+#else
+#define SET_NET_IPLEN(p)	do {		\
+	struct ip *h_ip = (p);			\
+	h_ip->ip_len = htons(h_ip->ip_len);	\
+	h_ip->ip_off = htons(h_ip->ip_off);	\
+	} while (0)
+
+#define SET_HOST_IPLEN(p)	do {		\
+	struct ip *h_ip = (p);			\
+	h_ip->ip_len = ntohs(h_ip->ip_len);	\
+	h_ip->ip_off = ntohs(h_ip->ip_off);	\
+	} while (0)
+#endif /* !HAVE_NET_IPLEN */
+
 #endif /* _KERNEL */
 
 /* INET6 stuff */

Modified: head/sys/netinet/ip_dummynet.h
==============================================================================
--- head/sys/netinet/ip_dummynet.h	Mon Dec 28 10:19:53 2009	(r201121)
+++ head/sys/netinet/ip_dummynet.h	Mon Dec 28 10:47:04 2009	(r201122)
@@ -110,21 +110,19 @@ struct dn_heap {
  * them that carries their dummynet state.  This is used within
  * the dummynet code as well as outside when checking for special
  * processing requirements.
+ * Note that the first part is the reinject info and is common to
+ * 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 */
+
+    /* second part, dummynet specific */
     int dn_dir;			/* action when packet comes out. */
-#define DN_TO_IP_OUT	1
-#define DN_TO_IP_IN	2
-/* Obsolete: #define DN_TO_BDG_FWD	3 */
-#define DN_TO_ETH_DEMUX	4
-#define DN_TO_ETH_OUT	5
-#define DN_TO_IP6_IN	6
-#define DN_TO_IP6_OUT	7
-#define DN_TO_IFB_FWD	8
+				/* see ip_fw_private.h */
 
     dn_key output_time;		/* when the pkt is due for delivery	*/
     struct ifnet *ifp;		/* interface, for ip_output		*/
@@ -377,21 +375,4 @@ struct dn_pipe_max {
 
 SLIST_HEAD(dn_pipe_head, dn_pipe);
 
-#ifdef _KERNEL
-
-/*
- * Return the dummynet tag; if any.
- * Make sure that the dummynet tag is not reused by lower layers.
- */
-static __inline struct dn_pkt_tag *
-ip_dn_claim_tag(struct mbuf *m)
-{
-	struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
-	if (mtag != NULL) {
-		mtag->m_tag_id = PACKET_TAG_NONE;
-		return ((struct dn_pkt_tag *)(mtag + 1));
-	} else
-		return (NULL);
-}
-#endif
 #endif /* _IP_DUMMYNET_H */

Modified: head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- head/sys/netinet/ipfw/ip_dummynet.c	Mon Dec 28 10:19:53 2009	(r201121)
+++ head/sys/netinet/ipfw/ip_dummynet.c	Mon Dec 28 10:47:04 2009	(r201122)
@@ -551,7 +551,6 @@ transmit_event(struct dn_pipe *pipe, str
 }
 
 #define div64(a, b)	((int64_t)(a) / (int64_t)(b))
-#define DN_TO_DROP	0xffff
 /*
  * Compute how many ticks we have to wait before being able to send
  * a packet. This is computed as the "wire time" for the packet
@@ -589,7 +588,7 @@ compute_extra_bits(struct mbuf *pkt, str
 	if (index >= p->loss_level) {
 		struct dn_pkt_tag *dt = dn_tag_get(pkt);
 		if (dt)
-			dt->dn_dir = DN_TO_DROP;
+			dt->dn_dir = DIR_DROP;
 	}
 	return extra_bits;
 }
@@ -964,49 +963,48 @@ dummynet_task(void *context, int pending
 static void
 dummynet_send(struct mbuf *m)
 {
-	struct dn_pkt_tag *pkt;
 	struct mbuf *n;
-	struct ip *ip;
-	int dst;
 
 	for (; m != NULL; m = n) {
+		struct ifnet *ifp;
+		int dst;
+
 		n = m->m_nextpkt;
 		m->m_nextpkt = NULL;
 		if (m_tag_first(m) == NULL) {
-			pkt = NULL; /* probably unnecessary */
-			dst = DN_TO_DROP;
+			dst = DIR_DROP;
 		} else {
-			pkt = dn_tag_get(m);
+			struct dn_pkt_tag *pkt = dn_tag_get(m);
 			dst = pkt->dn_dir;
+			ifp = pkt->ifp;
 		}
 
 		switch (dst) {
-		case DN_TO_IP_OUT:
+		case DIR_OUT:
 			ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
 			break ;
-		case DN_TO_IP_IN :
-			ip = mtod(m, struct ip *);
-			ip->ip_len = htons(ip->ip_len);
-			ip->ip_off = htons(ip->ip_off);
+		case DIR_IN :
+			/* put header in network format for ip_input() */
+			SET_NET_IPLEN(mtod(m, struct ip *));
 			netisr_dispatch(NETISR_IP, m);
 			break;
 #ifdef INET6
-		case DN_TO_IP6_IN:
+		case DIR_IN | PROTO_IPV6:
 			netisr_dispatch(NETISR_IPV6, m);
 			break;
 
-		case DN_TO_IP6_OUT:
+		case DIR_OUT | PROTO_IPV6:
 			ip6_output(m, NULL, NULL, IPV6_FORWARDING, NULL, NULL, NULL);
 			break;
 #endif
-		case DN_TO_IFB_FWD:
+		case DIR_FWD | PROTO_IFB: /* DN_TO_IFB_FWD: */
 			if (bridge_dn_p != NULL)
-				((*bridge_dn_p)(m, pkt->ifp));
+				((*bridge_dn_p)(m, ifp));
 			else
 				printf("dummynet: if_bridge not loaded\n");
 
 			break;
-		case DN_TO_ETH_DEMUX:
+		case DIR_IN | PROTO_LAYER2: /* DN_TO_ETH_DEMUX: */
 			/*
 			 * The Ethernet code assumes the Ethernet header is
 			 * contiguous in the first mbuf header.
@@ -1020,17 +1018,17 @@ dummynet_send(struct mbuf *m)
 			}
 			ether_demux(m->m_pkthdr.rcvif, m);
 			break;
-		case DN_TO_ETH_OUT:
-			ether_output_frame(pkt->ifp, m);
+		case DIR_OUT | PROTO_LAYER2: /* N_TO_ETH_OUT: */
+			ether_output_frame(ifp, m);
 			break;
 
-		case DN_TO_DROP:
+		case DIR_DROP:
 			/* drop the packet after some time */
 			dn_free_pkt(m);
 			break;
 
 		default:
-			printf("dummynet: bad switch %d!\n", pkt->dn_dir);
+			printf("dummynet: bad switch %d!\n", dst);
 			dn_free_pkt(m);
 			break;
 		}
@@ -1545,8 +1543,8 @@ dummynet_io(struct mbuf **m0, int dir, s
 		}
 	}
 done:
-	if (head == m && dir != DN_TO_IFB_FWD && dir != DN_TO_ETH_DEMUX &&
-	    dir != DN_TO_ETH_OUT) {	/* Fast io. */
+	if (head == m && (dir & PROTO_LAYER2) == 0 ) {
+		/* Fast io. */
 		io_pkt_fast++;
 		if (m->m_nextpkt != NULL)
 			printf("dummynet: fast io: pkt chain detected!\n");
@@ -1810,13 +1808,15 @@ config_pipe(struct dn_pipe *p)
 			pipe->idle_heap.size = pipe->idle_heap.elements = 0;
 			pipe->idle_heap.offset =
 			    offsetof(struct dn_flow_queue, heap_pos);
-		} else
+		} else {
 			/* Flush accumulated credit for all queues. */
-			for (i = 0; i <= pipe->fs.rq_size; i++)
+			for (i = 0; i <= pipe->fs.rq_size; i++) {
 				for (q = pipe->fs.rq[i]; q; q = q->next) {
 					q->numbytes = p->burst +
 					    (io_fast ? p->bandwidth : 0);
 				}
+			}
+		}
 
 		pipe->bandwidth = p->bandwidth;
 		pipe->burst = p->burst;

Modified: head/sys/netinet/ipfw/ip_fw2.c
==============================================================================
--- head/sys/netinet/ipfw/ip_fw2.c	Mon Dec 28 10:19:53 2009	(r201121)
+++ head/sys/netinet/ipfw/ip_fw2.c	Mon Dec 28 10:47:04 2009	(r201122)
@@ -75,7 +75,6 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ip_fw.h>
 #include <netinet/ipfw/ip_fw_private.h>
 #include <netinet/ip_divert.h>
-#include <netinet/ip_dummynet.h>
 #include <netinet/ip_carp.h>
 #include <netinet/pim.h>
 #include <netinet/tcp_var.h>
@@ -83,8 +82,6 @@ __FBSDID("$FreeBSD$");
 #include <netinet/udp_var.h>
 #include <netinet/sctp.h>
 
-#include <netgraph/ng_ipfw.h>
-
 #include <netinet/ip6.h>
 #include <netinet/icmp6.h>
 #ifdef INET6
@@ -591,7 +588,7 @@ send_reject6(struct ip_fw_args *args, in
  * sends a reject message, consuming the mbuf passed as an argument.
  */
 static void
-send_reject(struct ip_fw_args *args, int code, int ip_len, struct ip *ip)
+send_reject(struct ip_fw_args *args, int code, int iplen, struct ip *ip)
 {
 
 #if 0
@@ -607,8 +604,7 @@ send_reject(struct ip_fw_args *args, int
 	if (code != ICMP_REJECT_RST) { /* Send an ICMP unreach */
 		/* We need the IP header in host order for icmp_error(). */
 		if (args->eh != NULL) {
-			ip->ip_len = ntohs(ip->ip_len);
-			ip->ip_off = ntohs(ip->ip_off);
+			SET_HOST_IPLEN(ip);
 		}
 		icmp_error(args->m, ICMP_UNREACH, code, 0L, 0);
 	} else if (args->f_id.proto == IPPROTO_TCP) {
@@ -851,12 +847,12 @@ ipfw_chk(struct ip_fw_args *args)
 	 * src_ip, dst_ip	ip addresses, in NETWORK format.
 	 *	Only valid for IPv4 packets.
 	 */
-	u_int8_t proto;
-	u_int16_t src_port = 0, dst_port = 0;	/* NOTE: host format	*/
+	uint8_t proto;
+	uint16_t src_port = 0, dst_port = 0;	/* NOTE: host format	*/
 	struct in_addr src_ip, dst_ip;		/* NOTE: network format	*/
-	u_int16_t ip_len=0;
+	uint16_t iplen=0;
 	int pktlen;
-	u_int16_t	etype = 0;	/* Host order stored ether type */
+	uint16_t	etype = 0;	/* Host order stored ether type */
 
 	/*
 	 * dyn_dir = MATCH_UNKNOWN when rules unchecked,
@@ -1094,14 +1090,17 @@ do {								\
 		proto = ip->ip_p;
 		src_ip = ip->ip_src;
 		dst_ip = ip->ip_dst;
-		if (args->eh != NULL) { /* layer 2 packets are as on the wire */
-			offset = ntohs(ip->ip_off) & IP_OFFMASK;
-			ip_len = ntohs(ip->ip_len);
-		} else {
+#ifndef HAVE_NET_IPLEN
+		if (args->eh == NULL) { /* on l3 these are in host format */
 			offset = ip->ip_off & IP_OFFMASK;
-			ip_len = ip->ip_len;
+			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);
 		}
-		pktlen = ip_len < pktlen ? ip_len : pktlen;
+		pktlen = iplen < pktlen ? iplen : pktlen;
 
 		if (offset == 0) {
 			switch (proto) {
@@ -1144,6 +1143,7 @@ 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) {
 		/*
@@ -1355,27 +1355,29 @@ do {								\
 			case O_IP_SRC_LOOKUP:
 			case O_IP_DST_LOOKUP:
 				if (is_ipv4) {
-				    uint32_t a =
+				    uint32_t key =
 					(cmd->opcode == O_IP_DST_LOOKUP) ?
 					    dst_ip.s_addr : src_ip.s_addr;
 				    uint32_t v = 0;
 
 				    if (cmdlen > F_INSN_SIZE(ipfw_insn_u32)) {
-					/* generic lookup */
+					/* generic lookup. The key must be
+					 * in 32bit big-endian format.
+					 */
 					v = ((ipfw_insn_u32 *)cmd)->d[1];
 					if (v == 0)
-					    a = dst_ip.s_addr;
+					    key = dst_ip.s_addr;
 					else if (v == 1)
-					    a = src_ip.s_addr;
+					    key = src_ip.s_addr;
 					else if (offset != 0)
 					    break;
 					else if (proto != IPPROTO_TCP &&
 						proto != IPPROTO_UDP)
 					    break;
 					else if (v == 2)
-					    a = dst_port;
+					    key = htonl(dst_port);
 					else if (v == 3)
-					    a = src_port;
+					    key = htons(src_port);
 					else if (v == 4 || v == 5) {
 					    check_uidgid(
 						(ipfw_insn_u32 *)cmd,
@@ -1384,14 +1386,15 @@ do {								\
 						src_ip, src_port, &ucred_cache,
 						&ucred_lookup, args->inp);
 					    if (v == 4 /* O_UID */)
-						a = ucred_cache->cr_uid;
+						key = ucred_cache->cr_uid;
 					    else if (v == 5 /* O_JAIL */)
-						a = ucred_cache->cr_prison->pr_id;
+						key = ucred_cache->cr_prison->pr_id;
+					    key = htonl(key);
 					} else
 					    break;
 				    }
-				    match = ipfw_lookup_table(chain, cmd->arg1, a,
-					&v);
+				    match = ipfw_lookup_table(chain,
+					cmd->arg1, key, &v);
 				    if (!match)
 					break;
 				    if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
@@ -1514,7 +1517,7 @@ do {								\
 				    int i;
 
 				    if (cmd->opcode == O_IPLEN)
-					x = ip_len;
+					x = iplen;
 				    else if (cmd->opcode == O_IPTTL)
 					x = ip->ip_ttl;
 				    else /* must be IPID */
@@ -1549,7 +1552,7 @@ do {								\
 				    int i;
 
 				    tcp = TCP(ulp);
-				    x = ip_len -
+				    x = iplen -
 					((ip->ip_hl + tcp->th_off) << 2);
 				    if (cmdlen == 1) {
 					match = (cmd->arg1 == x);
@@ -2022,7 +2025,7 @@ do {								\
 				     is_icmp_query(ICMP(ulp))) &&
 				    !(m->m_flags & (M_BCAST|M_MCAST)) &&
 				    !IN_MULTICAST(ntohl(dst_ip.s_addr))) {
-					send_reject(args, cmd->arg1, ip_len, ip);
+					send_reject(args, cmd->arg1, iplen, ip);
 					m = args->m;
 				}
 				/* FALLTHROUGH */
@@ -2124,8 +2127,13 @@ do {								\
 				f->bcnt += pktlen;
 				l = 0;	/* in any case exit inner loop */
 
-				ip_off = (args->eh != NULL) ?
-					ntohs(ip->ip_off) : ip->ip_off;
+#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 */
 				if ((ip_off & (IP_MF | IP_OFFMASK)) == 0)
 				    break;
@@ -2135,8 +2143,7 @@ do {								\
 				 * from layer2.
 				 */
 				if (args->eh != NULL) {
-				    ip->ip_len = ntohs(ip->ip_len);
-				    ip->ip_off = ntohs(ip->ip_off);
+					SET_HOST_IPLEN(ip);
 				}
 
 				args->m = m = ip_reass(m);
@@ -2153,9 +2160,10 @@ do {								\
 
 				    ip = mtod(m, struct ip *);
 				    hlen = ip->ip_hl << 2;
-				    /* revert len & off for layer2 pkts */
-				    if (args->eh != NULL)
-					ip->ip_len = htons(ip->ip_len);
+				    /* revert len. & off to net format if needed */
+				    if (args->eh != NULL) {
+					SET_NET_IPLEN(ip);
+				    }
 				    ip->ip_sum = 0;
 				    if (hlen == sizeof(struct ip))
 					ip->ip_sum = in_cksum_hdr(ip);
@@ -2364,7 +2372,7 @@ vnet_ipfw_init(const void *unused)
 	 */
 	V_ip_fw_ctl_ptr = ipfw_ctl;
 	V_ip_fw_chk_ptr = ipfw_chk;
-	error = ipfw_attach_hooks();
+	error = ipfw_attach_hooks(1);
 	return (error);
 }
 
@@ -2384,10 +2392,7 @@ vnet_ipfw_uninit(const void *unused)
 	 * Then grab, release and grab again the WLOCK so we make
 	 * sure the update is propagated and nobody will be in.
 	 */
-	ipfw_unhook();
-#ifdef INET6
-	ipfw6_unhook();
-#endif
+	(void)ipfw_attach_hooks(0 /* detach */);
 	V_ip_fw_chk_ptr = NULL;
 	V_ip_fw_ctl_ptr = NULL;
 	IPFW_UH_WLOCK(chain);

Modified: head/sys/netinet/ipfw/ip_fw_dynamic.c
==============================================================================
--- head/sys/netinet/ipfw/ip_fw_dynamic.c	Mon Dec 28 10:19:53 2009	(r201121)
+++ head/sys/netinet/ipfw/ip_fw_dynamic.c	Mon Dec 28 10:47:04 2009	(r201122)
@@ -1002,7 +1002,11 @@ 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 Dec 28 10:19:53 2009	(r201121)
+++ head/sys/netinet/ipfw/ip_fw_log.c	Mon Dec 28 10:47:04 2009	(r201122)
@@ -87,6 +87,12 @@ __FBSDID("$FreeBSD$");
 #define SNPARGS(buf, len) buf + len, sizeof(buf) > len ? sizeof(buf) - len : 0
 #define SNP(buf) buf, sizeof(buf)
 
+#ifdef WITHOUT_BPF
+void
+ipfw_log_bpf(int onoff)
+{
+}
+#else /* !WITHOUT_BPF */
 static struct ifnet *log_if;	/* hook to attach to bpf */
 
 /* we use this dummy function for all ifnet callbacks */
@@ -128,6 +134,7 @@ ipfw_log_bpf(int onoff)
 		log_if = NULL;
 	}
 }
+#endif /* !WITHOUT_BPF */
 
 /*
  * We enter here when we have a rule with O_LOG.
@@ -138,12 +145,12 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
     struct mbuf *m, struct ifnet *oif, u_short offset, uint32_t tablearg,
     struct ip *ip)
 {
-	struct ether_header *eh = args->eh;
 	char *action;
 	int limit_reached = 0;
 	char action2[40], proto[128], fragment[32];
 
 	if (V_fw_verbose == 0) {
+#ifndef WITHOUT_BPF
 		struct m_hdr mh;
 
 		if (log_if == NULL || log_if->if_bpf == NULL)
@@ -160,16 +167,15 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
 			mh.mh_data = "DDDDDDSSSSSS\x08\x00";
 			if (args->f_id.addr_type == 4) {
 				/* restore wire format */
-				ip->ip_off = ntohs(ip->ip_off);
-				ip->ip_len = ntohs(ip->ip_len);
+				SET_NET_IPLEN(ip);
 			}
 		}
 		BPF_MTAP(log_if, (struct mbuf *)&mh);
 		if (args->eh == NULL && args->f_id.addr_type == 4) {
 			/* restore host format */
-			ip->ip_off = htons(ip->ip_off);
-			ip->ip_len = htons(ip->ip_len);
+			SET_HOST_IPLEN(ip);
 		}
+#endif /* !WITHOUT_BPF */
 		return;
 	}
 	/* the old 'log' function */
@@ -404,12 +410,15 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
 #endif
 		{
 			int ip_off, ip_len;
-			if (eh != NULL) { /* layer 2 packets are as on the wire */
-				ip_off = ntohs(ip->ip_off);
-				ip_len = ntohs(ip->ip_len);
-			} else {
+#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))
 				snprintf(SNPARGS(fragment, 0),

Modified: head/sys/netinet/ipfw/ip_fw_nat.c
==============================================================================
--- head/sys/netinet/ipfw/ip_fw_nat.c	Mon Dec 28 10:19:53 2009	(r201121)
+++ head/sys/netinet/ipfw/ip_fw_nat.c	Mon Dec 28 10:47:04 2009	(r201122)
@@ -29,14 +29,11 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/condvar.h>
 #include <sys/eventhandler.h>
 #include <sys/malloc.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/module.h>
-#include <sys/priv.h>
-#include <sys/proc.h>
 #include <sys/rwlock.h>
 
 #define        IPFW_INTERNAL   /* Access to protected data structures in ip_fw.h. */
@@ -223,8 +220,7 @@ ipfw_nat(struct ip_fw_args *args, struct
 	}
 	ip = mtod(mcl, struct ip *);
 	if (args->eh == NULL) {
-		ip->ip_len = htons(ip->ip_len);
-		ip->ip_off = htons(ip->ip_off);
+		SET_NET_IPLEN(ip);
 	}
 
 	/*
@@ -302,11 +298,11 @@ ipfw_nat(struct ip_fw_args *args, struct
 		struct udphdr 	*uh;
 		u_short cksum;
 
-		ip->ip_len = ntohs(ip->ip_len);
+		/* XXX check if ip_len can stay in net format */
 		cksum = in_pseudo(
 		    ip->ip_src.s_addr,
 		    ip->ip_dst.s_addr,
-		    htons(ip->ip_p + ip->ip_len - (ip->ip_hl << 2))
+		    htons(ip->ip_p + ntohs(ip->ip_len) - (ip->ip_hl << 2))
 		);
 
 		switch (ip->ip_p) {
@@ -333,14 +329,10 @@ ipfw_nat(struct ip_fw_args *args, struct
 			in_delayed_cksum(mcl);
 			mcl->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
 		}
-		ip->ip_len = htons(ip->ip_len);
 	}
-
 	if (args->eh == NULL) {
-		ip->ip_len = ntohs(ip->ip_len);
-		ip->ip_off = ntohs(ip->ip_off);
+		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 Dec 28 10:19:53 2009	(r201121)
+++ head/sys/netinet/ipfw/ip_fw_pfil.c	Mon Dec 28 10:47:04 2009	(r201122)
@@ -46,9 +46,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/lock.h>
 #include <sys/rwlock.h>
 #include <sys/socket.h>
-#include <sys/socketvar.h>
 #include <sys/sysctl.h>
-#include <sys/ucred.h>
 
 #include <net/if.h>
 #include <net/route.h>
@@ -64,8 +62,6 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ip_divert.h>
 #include <netinet/ip_dummynet.h>
 
-#include <netgraph/ng_ipfw.h>
-
 #include <machine/in_cksum.h>
 
 static VNET_DEFINE(int, fw_enable) = 1;
@@ -85,9 +81,7 @@ ip_divert_packet_t *ip_divert_ptr = NULL
 ng_ipfw_input_t *ng_ipfw_input_p = NULL;
 
 /* Forward declarations. */
-static int	ipfw_divert(struct mbuf **, int, int);
-#define	DIV_DIR_IN	1
-#define	DIV_DIR_OUT	0
+static void	ipfw_divert(struct mbuf **, int, int);
 
 #ifdef SYSCTL_NODE
 SYSCTL_DECL(_net_inet_ip_fw);
@@ -102,162 +96,32 @@ SYSCTL_VNET_PROC(_net_inet6_ip6_fw, OID_
 #endif /* INET6 */
 #endif /* SYSCTL_NODE */
 
-int
-ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
-    struct inpcb *inp)
-{
-	struct ip_fw_args args;
-	struct ng_ipfw_tag *ng_tag;
-	struct m_tag *dn_tag;
-	int ipfw = 0;
-	int divert;
-	int tee;
-#ifdef IPFIREWALL_FORWARD
-	struct m_tag *fwd_tag;
-#endif
-
-	KASSERT(dir == PFIL_IN, ("ipfw_check_in wrong direction!"));
-
-	bzero(&args, sizeof(args));
-
-	ng_tag = (struct ng_ipfw_tag *)m_tag_locate(*m0, NGM_IPFW_COOKIE, 0,
-	    NULL);
-	if (ng_tag != NULL) {
-		KASSERT(ng_tag->dir == NG_IPFW_IN,
-		    ("ng_ipfw tag with wrong direction"));
-		args.slot = ng_tag->slot;
-		args.rulenum = ng_tag->rulenum;
-		args.rule_id = ng_tag->rule_id;
-		args.chain_id = ng_tag->chain_id;
-		m_tag_delete(*m0, (struct m_tag *)ng_tag);
-	}
-
-again:
-	dn_tag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL);
-	if (dn_tag != NULL){
-		struct dn_pkt_tag *dt;
-
-		dt = (struct dn_pkt_tag *)(dn_tag+1);
-		args.slot = dt->slot;
-		args.rulenum = dt->rulenum;
-		args.rule_id = dt->rule_id;
-		args.chain_id = dt->chain_id;
-		m_tag_delete(*m0, dn_tag);
-	}
-
-	args.m = *m0;
-	args.inp = inp;
-	tee = 0;
-
-	if (V_fw_one_pass == 0 || args.slot == 0) {
-		ipfw = ipfw_chk(&args);
-		*m0 = args.m;
-	} else
-		ipfw = IP_FW_PASS;
-		
-	KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL",
-	    __func__));
-
-	switch (ipfw) {
-	case IP_FW_PASS:
-		if (args.next_hop == NULL)
-			goto pass;
-
-#ifdef IPFIREWALL_FORWARD
-		fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD,
-				sizeof(struct sockaddr_in), M_NOWAIT);
-		if (fwd_tag == NULL)
-			goto drop;
-		bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in));
-		m_tag_prepend(*m0, fwd_tag);
-
-		if (in_localip(args.next_hop->sin_addr))
-			(*m0)->m_flags |= M_FASTFWD_OURS;
-		goto pass;
-#endif
-		break;			/* not reached */
-
-	case IP_FW_DENY:
-		goto drop;
-		break;			/* not reached */
-
-	case IP_FW_DUMMYNET:
-		if (ip_dn_io_ptr == NULL)
-			goto drop;
-		if (mtod(*m0, struct ip *)->ip_v == 4)
-			ip_dn_io_ptr(m0, DN_TO_IP_IN, &args);
-		else if (mtod(*m0, struct ip *)->ip_v == 6)
-			ip_dn_io_ptr(m0, DN_TO_IP6_IN, &args);
-		if (*m0 != NULL)
-			goto again;
-		return 0;		/* packet consumed */
-
-	case IP_FW_TEE:
-		tee = 1;
-		/* fall through */
-
-	case IP_FW_DIVERT:
-		divert = ipfw_divert(m0, DIV_DIR_IN, tee);
-		if (divert) {
-			*m0 = NULL;
-			return 0;	/* packet consumed */
-		} else {
-			args.slot = 0;
-			goto again;	/* continue with packet */
-		}
-
-	case IP_FW_NGTEE:
-		if (!NG_IPFW_LOADED)
-			goto drop;
-		(void)ng_ipfw_input_p(m0, NG_IPFW_IN, &args, 1);
-		goto again;		/* continue with packet */
-
-	case IP_FW_NETGRAPH:
-		if (!NG_IPFW_LOADED)
-			goto drop;
-		return ng_ipfw_input_p(m0, NG_IPFW_IN, &args, 0);
-		
-	case IP_FW_NAT:
-		goto again;		/* continue with packet */
-
-	case IP_FW_REASS:
-		goto again;
-
-	default:
-		KASSERT(0, ("%s: unknown retval", __func__));
-	}
-
-drop:
-	if (*m0)
-		m_freem(*m0);
-	*m0 = NULL;
-	return (EACCES);
-pass:
-	return 0;	/* not filtered */
-}
-
-int
-ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
+/*
+ * The pfilter hook to pass packets to ipfw_chk and then to
+ * dummynet, divert, netgraph or other modules.
+ * The packet may be consumed.
+ */
+static int
+ipfw_check_hook(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
     struct inpcb *inp)
 {
 	struct ip_fw_args args;
 	struct ng_ipfw_tag *ng_tag;
 	struct m_tag *dn_tag;
-	int ipfw = 0;
-	int divert;
-	int tee;
+	int ipfw;
+	int ret;
 #ifdef IPFIREWALL_FORWARD
 	struct m_tag *fwd_tag;
 #endif
 
-	KASSERT(dir == PFIL_OUT, ("ipfw_check_out wrong direction!"));
-
+	/* convert dir to IPFW values */
+	dir = (dir == PFIL_IN) ? DIR_IN : DIR_OUT;
 	bzero(&args, sizeof(args));
 
 	ng_tag = (struct ng_ipfw_tag *)m_tag_locate(*m0, NGM_IPFW_COOKIE, 0,
 	    NULL);
 	if (ng_tag != NULL) {
-		KASSERT(ng_tag->dir == NG_IPFW_OUT,
+		KASSERT(ng_tag->dir == dir,
 		    ("ng_ipfw tag with wrong direction"));
 		args.slot = ng_tag->slot;
 		args.rulenum = ng_tag->rulenum;
@@ -280,9 +144,8 @@ again:
 	}
 
 	args.m = *m0;
-	args.oif = ifp;
+	args.oif = dir == DIR_OUT ? ifp : NULL;
 	args.inp = inp;
-	tee = 0;
 
 	if (V_fw_one_pass == 0 || args.slot == 0) {
 		ipfw = ipfw_chk(&args);
@@ -293,255 +156,209 @@ again:
 	KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL",
 	    __func__));
 
+	/* breaking out of the switch means drop */
+	ret = 0;	/* default return value for pass */
 	switch (ipfw) {
 	case IP_FW_PASS:
+		/* next_hop may be set by ipfw_chk */
                 if (args.next_hop == NULL)
-                        goto pass;
-#ifdef IPFIREWALL_FORWARD
-		/* Overwrite existing tag. */
-		fwd_tag = m_tag_find(*m0, PACKET_TAG_IPFORWARD, NULL);
-		if (fwd_tag == NULL) {
+                        break; /* pass */
+#ifndef IPFIREWALL_FORWARD
+		ret = EACCES;
+#else
+		/* Incoming packets should not be tagged so we do not
+		 * m_tag_find. Outgoing packets may be tagged, so we
+		 * reuse the tag if present.
+		 */
+		fwd_tag = (dir == DIR_IN) ? NULL :
+			m_tag_find(*m0, PACKET_TAG_IPFORWARD, NULL);
+		if (fwd_tag != NULL) {
+			m_tag_unlink(*m0, fwd_tag);
+		} else {
 			fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD,
 				sizeof(struct sockaddr_in), M_NOWAIT);
-			if (fwd_tag == NULL)
-				goto drop;
-		} else
-			m_tag_unlink(*m0, fwd_tag);
+			if (fwd_tag == NULL) {
+				ret = EACCES;
+				break; /* i.e. drop */
+			}
+		}
 		bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in));
 		m_tag_prepend(*m0, fwd_tag);
 
 		if (in_localip(args.next_hop->sin_addr))
 			(*m0)->m_flags |= M_FASTFWD_OURS;
-		goto pass;
 #endif

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


More information about the svn-src-head mailing list