broken ip checksum after frag reassemble of nfs READDIR?

Adam McDougall mcdouga9 at egr.msu.edu
Fri May 12 21:19:35 UTC 2006


Thanks, that does seem to work.  I can now use UDP NFS because the
checksum is valid.  I am also testing it alongside the bridge fragmentation
patch and that works as well.  I'm pretty sure these two patches remove
the roadblocks from me putting it into production in bridging mode!

On Mon, May 08, 2006 at 08:27:23PM +0200, Daniel Hartmeier wrote:

  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