From owner-freebsd-pf@FreeBSD.ORG Sun Apr 16 05:30:47 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 4278816A401 for ; Sun, 16 Apr 2006 05:30:47 +0000 (UTC) (envelope-from thompsa@freebsd.org) Received: from dbmail-mx1.orcon.net.nz (loadbalancer1.orcon.net.nz [219.88.242.3]) by mx1.FreeBSD.org (Postfix) with ESMTP id 46D5A43D46 for ; Sun, 16 Apr 2006 05:30:45 +0000 (GMT) (envelope-from thompsa@freebsd.org) Received-SPF: none Received: from heff.fud.org.nz (60-234-149-201.bitstream.orcon.net.nz [60.234.149.201]) by dbmail-mx1.orcon.net.nz (8.13.6/8.13.6/Debian-1) with SMTP id k3G5VGYE000606; Sun, 16 Apr 2006 17:31:17 +1200 Received: by heff.fud.org.nz (Postfix, from userid 1001) id CD1D71CC37; Sun, 16 Apr 2006 17:30:23 +1200 (NZST) Date: Sun, 16 Apr 2006 17:30:23 +1200 From: Andrew Thompson To: Daniel Hartmeier Message-ID: <20060416053023.GD56603@heff.fud.org.nz> 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> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="qMm9M+Fa2AknHoGS" Content-Disposition: inline In-Reply-To: <20060405130645.GB5683@insomnia.benzedrine.cx> User-Agent: Mutt/1.5.11 X-Virus-Scanned: ClamAV version 0.88, clamav-milter version 0.87 on dbmail-mx1.orcon.net.nz X-Virus-Status: Clean Cc: 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: Sun, 16 Apr 2006 05:30:47 -0000 --qMm9M+Fa2AknHoGS Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Wed, Apr 05, 2006 at 03:06:45PM +0200, Daniel Hartmeier wrote: > On Wed, Apr 05, 2006 at 02:41:09PM +0200, Max Laier wrote: > > > The other big problem that just crossed my mind: Reassembly in the bridge > > path!? It doesn't look like the current bridge code on either OS is ready to > > deal with packets > MTU coming out of the filter. The question here is > > probably how much IP processing we want to do in the bridge code? > > OpenBSD's bridge does, see bridge_fragment(). IIRC, we slightly adjusted > ip_fragment() so it could be called from there, and not too much code > had to be duplicated. > Here is a patch that adds fragmenting, largely based on whats in OpenBSD. I didnt bring over bridge_send_icmp_err() as we can only get a large packet to fragment by reassembling a previous fragment, checking for DF and sending an icmp doesnt apply to us. Can I get a review, esp. the traversal of the mbufs. cheers, Andrew --qMm9M+Fa2AknHoGS Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="bridge_frag.diff" Index: ../../net/if_bridge.c =================================================================== RCS file: /home/ncvs/src/sys/net/if_bridge.c,v retrieving revision 1.58 diff -u -p -r1.58 if_bridge.c --- ../../net/if_bridge.c 26 Mar 2006 20:52:47 -0000 1.58 +++ ../../net/if_bridge.c 16 Apr 2006 05:23:03 -0000 @@ -263,6 +263,8 @@ static int bridge_ip_checkbasic(struct m # ifdef INET6 static int bridge_ip6_checkbasic(struct mbuf **mp); # endif /* INET6 */ +static int bridge_fragment(struct ifnet *, struct mbuf *, + struct ether_header *, int, struct llc *); SYSCTL_DECL(_net_link); SYSCTL_NODE(_net_link, IFT_BRIDGE, bridge, CTLFLAG_RW, 0, "Bridge"); @@ -1497,13 +1499,21 @@ bridge_stop(struct ifnet *ifp, int disab __inline void bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m) { - int len, err; + int len, err = 0; short mflags; + struct mbuf *m0; len = m->m_pkthdr.len; mflags = m->m_flags; - IFQ_ENQUEUE(&dst_ifp->if_snd, m, err); + for (; m; m = m0) { + m0 = m->m_nextpkt; + m->m_nextpkt = NULL; + + if (err == 0) + IFQ_ENQUEUE(&dst_ifp->if_snd, m, err); + } + if (err == 0) { sc->sc_ifp->if_opackets++; @@ -2761,13 +2771,24 @@ ipfwpass: error = pfil_run_hooks(&inet_pfil_hook, mp, bifp, dir, NULL); - /* Restore ip and the fields ntohs()'d. */ - if (*mp != NULL && error == 0) { - ip = mtod(*mp, struct ip *); - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); + if (*mp == NULL || error != 0) /* filter may consume */ + break; + + /* check if we need to fragment the packet */ + if (pfil_member && ifp != NULL && dir == PFIL_OUT) { + i = (*mp)->m_pkthdr.len; + if (i > ifp->if_mtu) { + error = bridge_fragment(ifp, *mp, &eh2, snap, + &llc1); + return error; + } } + /* Restore ip and the fields ntohs()'d. */ + ip = mtod(*mp, struct ip *); + ip->ip_len = htons(ip->ip_len); + ip->ip_off = htons(ip->ip_off); + break; # ifdef INET6 case ETHERTYPE_IPV6 : @@ -2979,3 +3000,59 @@ bad: return -1; } # endif /* INET6 */ + +/* + * bridge_fragment: + * + * Return a fragmented mbuf chain. + */ +static int +bridge_fragment(struct ifnet *ifp, struct mbuf *m, struct ether_header *eh, + int hassnap, struct llc *llc) +{ + struct mbuf *m0; + int error = -1; + struct ip *ip; + + if (m->m_len < sizeof(struct ip) && + (m = m_pullup(m, sizeof(struct ip))) == NULL) + goto dropit; + ip = mtod(m, struct ip *); + + error = ip_fragment(ip, &m, ifp->if_mtu, ifp->if_hwassist, + CSUM_DELAY_IP); + if (error) + goto dropit; + + /* walk the chain and re-add the Ethernet header */ + for (m0 = m; m0; m0 = m0->m_nextpkt) { + if (error == 0) { + if (hassnap) { + M_PREPEND(m0, sizeof(struct llc), M_DONTWAIT); + if (m0 == NULL) { + error = ENOBUFS; + continue; + } + bcopy(llc, mtod(m0, caddr_t), + sizeof(struct llc)); + } + M_PREPEND(m0, ETHER_HDR_LEN, M_DONTWAIT); + if (m0 == NULL) { + error = ENOBUFS; + continue; + } + bcopy(eh, mtod(m0, caddr_t), ETHER_HDR_LEN); + } else + m_freem(m); + } + + if (error == 0) + ipstat.ips_fragmented++; + + return (error); + +dropit: + if (m != NULL) + m_freem(m); + return (error); +} --qMm9M+Fa2AknHoGS--