summaryrefslogtreecommitdiff
path: root/sys/net/if_bridge.c
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2021-03-01 11:05:44 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2021-03-01 11:05:44 +0000
commitf34d4b2beb1d31a0fd5b37fc76cbf03834be8a7d (patch)
tree8f718d3a9d07a08b49389d6486c238111b1d802a /sys/net/if_bridge.c
parente2cabf3b47ab75eb968195e43fb2218e2e1d2e56 (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.c54
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;