summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2023-11-23 23:45:11 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2023-11-23 23:45:11 +0000
commit4f592c123a8bb037be23d6d4204468b8edda3bcc (patch)
tree99235d7d30755808bb07b42121b978403538f27a /sys/net
parent0615daf9d387c9a48b49cb0eee470980c1ee3021 (diff)
avoid passing weird mbuf chains to pf when pushing out a veb.
pf expects the ip header to be in the first mbuf of the chain we pass to pf_test, but in some situations the ethernet header is the only data in the first mbuf. after we remove the ethernet header, the first mbuf had no data in it which confused pf. fix this by passing all packets to ip_check on output as well as input. ip input handlers do all the necessary m_pullups. found by Mark Patruck.
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if_veb.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/sys/net/if_veb.c b/sys/net/if_veb.c
index df405678fa3..cbdc3fb7d53 100644
--- a/sys/net/if_veb.c
+++ b/sys/net/if_veb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_veb.c,v 1.31 2023/05/16 14:32:54 jan Exp $ */
+/* $OpenBSD: if_veb.c,v 1.32 2023/11/23 23:45:10 dlg Exp $ */
/*
* Copyright (c) 2021 David Gwynne <dlg@openbsd.org>
@@ -612,6 +612,7 @@ veb_pf(struct ifnet *ifp0, int dir, struct mbuf *m)
{
struct ether_header *eh, copy;
const struct veb_pf_ip_family *fam;
+ int hlen;
/*
* pf runs on vport interfaces when they enter or leave the
@@ -640,11 +641,9 @@ veb_pf(struct ifnet *ifp0, int dir, struct mbuf *m)
copy = *eh;
m_adj(m, sizeof(*eh));
- if (dir == PF_IN) {
- m = (*fam->ip_check)(ifp0, m);
- if (m == NULL)
- return (NULL);
- }
+ m = (*fam->ip_check)(ifp0, m);
+ if (m == NULL)
+ return (NULL);
if (pf_test(fam->af, dir, ifp0, &m) != PF_PASS) {
m_freem(m);
@@ -660,12 +659,14 @@ veb_pf(struct ifnet *ifp0, int dir, struct mbuf *m)
return (NULL);
}
- m = m_prepend(m, sizeof(*eh), M_DONTWAIT);
+ hlen = roundup(sizeof(*eh), sizeof(long));
+ m = m_prepend(m, hlen, M_DONTWAIT);
if (m == NULL)
return (NULL);
/* checksum? */
+ m_adj(m, hlen - sizeof(*eh));
eh = mtod(m, struct ether_header *);
*eh = copy;