broken ip checksum after frag reassemble of nfs READDIR?

Daniel Hartmeier daniel at benzedrine.cx
Mon May 8 18:30:08 UTC 2006


On Mon, May 08, 2006 at 11:49:30AM -0400, Adam McDougall wrote:

> Could someone possibly produce a patch to force if_bridge to 
> recalculate the checksum on every packet so I can test that as well?
> To me, the extra load on the firewall is less important than breaking
> packets I am trying to pass.  

Try the patch below, the first one is against -current and the second
against 6.0-stable. It compiles, but is otherwise untested.

I'm not sure if the potential m_pullup() is needed, but better safe than
sorry. Maybe Andrew can comment.

Daniel


Index: if_bridge.c
===================================================================
RCS file: /pub/tmp/cvs/freebsd/src/sys/net/if_bridge.c,v
retrieving revision 1.59
diff -u -r1.59 if_bridge.c
--- if_bridge.c	29 Apr 2006 05:37:25 -0000	1.59
+++ if_bridge.c	8 May 2006 18:17:40 -0000
@@ -2590,7 +2590,7 @@
 static int
 bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
 {
-	int snap, error, i;
+	int snap, error, i, hlen;
 	struct ether_header *eh1, eh2;
 	struct ip_fw_args args;
 	struct ip *ip;
@@ -2787,8 +2787,25 @@
 
 		/* Restore ip and the fields ntohs()'d. */
 		ip = mtod(*mp, struct ip *);
+		if (ip == NULL)
+			goto bad;
+		hlen = ip->ip_hl << 2;
+		if (hlen < sizeof(struct ip))
+			goto bad;
+		if (hlen > (*mp)->m_len) {
+			if ((*mp = m_pullup(*mp, hlen)) == 0)
+				goto bad;
+			ip = mtod(*mp, struct ip *);
+			if (ip == NULL)
+				goto bad;
+		}
 		ip->ip_len = htons(ip->ip_len);
 		ip->ip_off = htons(ip->ip_off);
+		ip->ip_sum = 0;
+		if (hlen == sizeof(struct ip))
+			ip->ip_sum = in_cksum_hdr(ip);
+		else
+			ip->ip_sum = in_cksum(*mp, hlen);
 
 		break;
 # ifdef INET6



Index: if_bridge.c
===================================================================
RCS file: /pub/tmp/cvs/freebsd/src/sys/net/if_bridge.c,v
retrieving revision 1.11.2.12.2.4
diff -u -r1.11.2.12.2.4 if_bridge.c
--- if_bridge.c	25 Jan 2006 10:01:26 -0000	1.11.2.12.2.4
+++ if_bridge.c	8 May 2006 18:21:03 -0000
@@ -2281,7 +2281,7 @@
 static int bridge_pfil(struct mbuf **mp, struct ifnet *bifp,
 		struct ifnet *ifp, int dir)
 {
-	int snap, error, i;
+	int snap, error, i, hlen;
 	struct ether_header *eh1, eh2;
 	struct ip_fw_args args;
 	struct ip *ip;
@@ -2459,8 +2459,25 @@
 		/* Restore ip and the fields ntohs()'d. */
 		if (*mp != NULL && error == 0) {
 			ip = mtod(*mp, struct ip *);
+			if (ip == NULL)
+				goto bad;
+			hlen = ip->ip_hl << 2;
+	 		if (hlen < sizeof(struct ip))
+	 			goto bad;
+	 		if (hlen > (*mp)->m_len) {
+	 			if ((*mp = m_pullup(*mp, hlen)) == 0)
+	 				goto bad;
+	 			ip = mtod(*mp, struct ip *);
+	 			if (ip == NULL)
+	 				goto bad;
+	 		}
 			ip->ip_len = htons(ip->ip_len);
 			ip->ip_off = htons(ip->ip_off);
+	 		ip->ip_sum = 0;
+	 		if (hlen == sizeof(struct ip))
+	 			ip->ip_sum = in_cksum_hdr(ip);
+	 		else
+	 			ip->ip_sum = in_cksum(*mp, hlen);
 		}
 
 		break;


More information about the freebsd-pf mailing list