diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2021-03-01 11:05:44 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2021-03-01 11:05:44 +0000 |
commit | f34d4b2beb1d31a0fd5b37fc76cbf03834be8a7d (patch) | |
tree | 8f718d3a9d07a08b49389d6486c238111b1d802a /sys/net/if_bridge.c | |
parent | e2cabf3b47ab75eb968195e43fb2218e2e1d2e56 (diff) |
Refactor ip_fragment() and ip6_fragment(). Use a mbuf list to
simplify the handling of the fragment list. Now the functions
ip_fragment() and ip6_fragment() always consume the mbuf. They
free the mbuf and mbuf list in case of an error and take care about
the counter. Adjust the code a bit to make v4 and v6 look similar.
Fixes a potential mbuf leak when pf_route6() called pf_refragment6()
and it failed. Now the mbuf is always freed by ip6_fragment().
OK dlg@ mvs@
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r-- | sys/net/if_bridge.c | 54 |
1 files changed, 23 insertions, 31 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index bb91143b35d..3ec31ff993a 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.c,v 1.352 2021/02/25 02:48:21 dlg Exp $ */ +/* $OpenBSD: if_bridge.c,v 1.353 2021/03/01 11:05:42 bluhm Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -1853,7 +1853,7 @@ bridge_fragment(struct ifnet *brifp, struct ifnet *ifp, struct ether_header *eh, struct mbuf *m) { struct llc llc; - struct mbuf *m0; + struct mbuf_list fml; int error = 0; int hassnap = 0; u_int16_t etype; @@ -1911,40 +1911,32 @@ bridge_fragment(struct ifnet *brifp, struct ifnet *ifp, struct ether_header *eh, return; } - error = ip_fragment(m, ifp, ifp->if_mtu); - if (error) { - m = NULL; - goto dropit; - } + error = ip_fragment(m, &fml, ifp, ifp->if_mtu); + if (error) + return; - for (; m; m = m0) { - m0 = m->m_nextpkt; - m->m_nextpkt = NULL; - if (error == 0) { - if (hassnap) { - M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT); - if (m == NULL) { - error = ENOBUFS; - continue; - } - bcopy(&llc, mtod(m, caddr_t), - LLC_SNAPFRAMELEN); - } - M_PREPEND(m, sizeof(*eh), M_DONTWAIT); + while ((m = ml_dequeue(&fml)) != NULL) { + if (hassnap) { + M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT); if (m == NULL) { error = ENOBUFS; - continue; - } - bcopy(eh, mtod(m, caddr_t), sizeof(*eh)); - error = bridge_ifenqueue(brifp, ifp, m); - if (error) { - continue; + break; } - } else - m_freem(m); + bcopy(&llc, mtod(m, caddr_t), LLC_SNAPFRAMELEN); + } + M_PREPEND(m, sizeof(*eh), M_DONTWAIT); + if (m == NULL) { + error = ENOBUFS; + break; + } + bcopy(eh, mtod(m, caddr_t), sizeof(*eh)); + error = bridge_ifenqueue(brifp, ifp, m); + if (error) + break; } - - if (error == 0) + if (error) + ml_purge(&fml); + else ipstat_inc(ips_fragmented); return; |