diff options
author | Renato Botelho <renato@netgate.com> | 2016-10-06 07:51:32 -0300 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2016-10-06 07:51:32 -0300 |
commit | 32988844e41ba2dafefd4b0ca819b8c48ecbbb81 (patch) | |
tree | d807da3e73499e469ce777cac5c3c1854d09669e /sys | |
parent | 7a332daf8ec44bea09dd38a4026773c41caf9758 (diff) | |
download | FreeBSD-src-32988844e41ba2dafefd4b0ca819b8c48ecbbb81.zip FreeBSD-src-32988844e41ba2dafefd4b0ca819b8c48ecbbb81.tar.gz |
Revert "bridge: Fix fragment handling and memory leak"
This reverts commit 7a332daf8ec44bea09dd38a4026773c41caf9758.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/if_bridge.c | 86 |
1 files changed, 31 insertions, 55 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index b484191..3b723c1 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -333,7 +333,7 @@ static int bridge_ip_checkbasic(struct mbuf **mp); #ifdef INET6 static int bridge_ip6_checkbasic(struct mbuf **mp); #endif /* INET6 */ -static int bridge_fragment(struct ifnet *, struct mbuf **mp, +static int bridge_fragment(struct ifnet *, struct mbuf *, struct ether_header *, int, struct llc *); static void bridge_linkstate(struct ifnet *ifp); static void bridge_linkcheck(struct bridge_softc *sc); @@ -1921,7 +1921,6 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m) m->m_flags &= ~M_VLANTAG; } - M_ASSERTPKTHDR(m); /* We shouldn't transmit mbuf without pkthdr */ if ((err = dst_ifp->if_transmit(dst_ifp, m))) { m_freem(m0); if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1); @@ -3239,12 +3238,10 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir) break; /* check if we need to fragment the packet */ - /* bridge_fragment generates a mbuf chain of packets */ - /* that already include eth headers */ if (V_pfil_member && ifp != NULL && dir == PFIL_OUT) { i = (*mp)->m_pkthdr.len; if (i > ifp->if_mtu) { - error = bridge_fragment(ifp, mp, &eh2, snap, + error = bridge_fragment(ifp, *mp, &eh2, snap, &llc1); return (error); } @@ -3483,77 +3480,56 @@ bad: /* * bridge_fragment: * - * Fragment mbuf chain in multiple packets and prepend ethernet header. + * Return a fragmented mbuf chain. */ static int -bridge_fragment(struct ifnet *ifp, struct mbuf **mp, struct ether_header *eh, +bridge_fragment(struct ifnet *ifp, struct mbuf *m, struct ether_header *eh, int snap, struct llc *llc) { - struct mbuf *m = *mp, *nextpkt = NULL, *mprev = NULL, *mcur = NULL; + struct mbuf *m0; struct ip *ip; int error = -1; if (m->m_len < sizeof(struct ip) && (m = m_pullup(m, sizeof(struct ip))) == NULL) - goto dropit; + goto out; ip = mtod(m, struct ip *); m->m_pkthdr.csum_flags |= CSUM_IP; error = ip_fragment(ip, &m, ifp->if_mtu, ifp->if_hwassist); if (error) - goto dropit; + goto out; - /* - * Walk the chain and re-add the Ethernet header for - * each mbuf packet. - */ - for (mcur = m; mcur; mcur = mcur->m_nextpkt) { - nextpkt = mcur->m_nextpkt; - mcur->m_nextpkt = NULL; - if (snap) { - M_PREPEND(mcur, sizeof(struct llc), M_NOWAIT); - if (mcur == NULL) { + /* walk the chain and re-add the Ethernet header */ + for (m0 = m; m0; m0 = m0->m_nextpkt) { + if (error == 0) { + if (snap) { + M_PREPEND(m0, sizeof(struct llc), M_NOWAIT); + if (m0 == NULL) { + error = ENOBUFS; + continue; + } + bcopy(llc, mtod(m0, caddr_t), + sizeof(struct llc)); + } + M_PREPEND(m0, ETHER_HDR_LEN, M_NOWAIT); + if (m0 == NULL) { error = ENOBUFS; - if (mprev != NULL) - mprev->m_nextpkt = nextpkt; - goto dropit; + continue; } - bcopy(llc, mtod(mcur, caddr_t),sizeof(struct llc)); - } - - M_PREPEND(mcur, ETHER_HDR_LEN, M_NOWAIT); - if (mcur == NULL) { - error = ENOBUFS; - if (mprev != NULL) - mprev->m_nextpkt = nextpkt; - goto dropit; - } - bcopy(eh, mtod(mcur, caddr_t), ETHER_HDR_LEN); - - /* - * The previous two M_PREPEND could have inserted one or two - * mbufs in front so we have to update the previous packet's - * m_nextpkt. - */ - mcur->m_nextpkt = nextpkt; - if (mprev != NULL) - mprev->m_nextpkt = mcur; - else { - /* The first mbuf in the original chain needs to be - * updated. */ - *mp = mcur; - } - mprev = mcur; + bcopy(eh, mtod(m0, caddr_t), ETHER_HDR_LEN); + } else + m_freem(m); } - KMOD_IPSTAT_INC(ips_fragmented); + if (error == 0) + KMOD_IPSTAT_INC(ips_fragmented); + return (error); -dropit: - for (mcur = *mp; mcur; mcur = m) { /* droping the full packet chain */ - m = mcur->m_nextpkt; - m_freem(mcur); - } +out: + if (m != NULL) + m_freem(m); return (error); } |