From owner-freebsd-pf@FreeBSD.ORG Mon May 8 18:30:08 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 532CF16A401; Mon, 8 May 2006 18:30:08 +0000 (UTC) (envelope-from dhartmei@insomnia.benzedrine.cx) Received: from insomnia.benzedrine.cx (insomnia.benzedrine.cx [62.65.145.30]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2360843D45; Mon, 8 May 2006 18:30:03 +0000 (GMT) (envelope-from dhartmei@insomnia.benzedrine.cx) Received: from insomnia.benzedrine.cx (dhartmei@localhost [127.0.0.1]) by insomnia.benzedrine.cx (8.13.4/8.13.4) with ESMTP id k48ITiBO025253 (version=TLSv1/SSLv3 cipher=DHE-DSS-AES256-SHA bits=256 verify=NO); Mon, 8 May 2006 20:29:44 +0200 (MEST) Received: (from dhartmei@localhost) by insomnia.benzedrine.cx (8.13.4/8.12.10/Submit) id k48IRNx5031786; Mon, 8 May 2006 20:27:23 +0200 (MEST) Date: Mon, 8 May 2006 20:27:23 +0200 From: Daniel Hartmeier To: Adam McDougall Message-ID: <20060508182723.GG9739@insomnia.benzedrine.cx> 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> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20060508154929.GS30200@egr.msu.edu> User-Agent: Mutt/1.5.10i 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: Mon, 08 May 2006 18:30:08 -0000 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;