From owner-freebsd-pf@FreeBSD.ORG Fri May 12 21:19:33 2006 Return-Path: X-Original-To: freebsd-pf@freebsd.org Delivered-To: freebsd-pf@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 66D0316AF81; Fri, 12 May 2006 21:19:33 +0000 (UTC) (envelope-from mcdouga9@daemon.egr.msu.edu) Received: from daemon.egr.msu.edu (daemon.egr.msu.edu [35.9.44.65]) by mx1.FreeBSD.org (Postfix) with ESMTP id EFE3C43D46; Fri, 12 May 2006 21:19:32 +0000 (GMT) (envelope-from mcdouga9@daemon.egr.msu.edu) Received: by daemon.egr.msu.edu (Postfix, from userid 21281) id 650191CD33; Fri, 12 May 2006 17:19:32 -0400 (EDT) Date: Fri, 12 May 2006 17:19:32 -0400 From: Adam McDougall To: Daniel Hartmeier Message-ID: <20060512211932.GA9173@egr.msu.edu> References: <20060402054532.GF17711@egr.msu.edu> <20060404145704.GW2684@insomnia.benzedrine.cx> <20060404153443.GX2684@insomnia.benzedrine.cx> <200604051441.16865.max@love2party.net> <20060405130645.GB5683@insomnia.benzedrine.cx> <20060416053023.GD56603@heff.fud.org.nz> <20060508154929.GS30200@egr.msu.edu> <20060508182723.GG9739@insomnia.benzedrine.cx> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20060508182723.GG9739@insomnia.benzedrine.cx> User-Agent: Mutt/1.5.11 Cc: Andrew Thompson , freebsd-pf@freebsd.org Subject: Re: broken ip checksum after frag reassemble of nfs READDIR? X-BeenThere: freebsd-pf@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Technical discussion and general questions about packet filter \(pf\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 May 2006 21:19:35 -0000 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;