summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2014-10-07 11:16:23 +0000
committerdlg <dlg@openbsd.org>2014-10-07 11:16:23 +0000
commitad7bdc7f72d0b375583701cc3ac25cd800b4f86d (patch)
tree19bf5f4db5257cd4b6c2e59060874d021d2488d2
parentUse L1_S_V7_AP instead of L1_S_AP for the v7 case (diff)
downloadwireguard-openbsd-ad7bdc7f72d0b375583701cc3ac25cd800b4f86d.tar.xz
wireguard-openbsd-ad7bdc7f72d0b375583701cc3ac25cd800b4f86d.zip
when running bpf on an outgoing vlan interface that doesnt have a
parent that doesnt offload the tag insertion, we need to chop the vlan subheader out before the filter is run, not after. this moves the mbuf surgery out from the bpf layer into the vlan layer. ok henning@ jmatthew@
-rw-r--r--sys/net/bpf.c50
-rw-r--r--sys/net/bpf.h3
-rw-r--r--sys/net/if_vlan.c41
3 files changed, 39 insertions, 55 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index bbe921edcbf..e8ccf7b833e 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bpf.c,v 1.109 2014/09/23 00:26:11 dlg Exp $ */
+/* $OpenBSD: bpf.c,v 1.110 2014/10/07 11:16:23 dlg Exp $ */
/* $NetBSD: bpf.c,v 1.33 1997/02/21 23:59:35 thorpej Exp $ */
/*
@@ -92,7 +92,6 @@ void bpf_ifname(struct ifnet *, struct ifreq *);
void _bpf_mtap(caddr_t, struct mbuf *, u_int,
void (*)(const void *, void *, size_t));
void bpf_mcopy(const void *, void *, size_t);
-void bpf_mcopy_stripvlan(const void *, void *, size_t);
int bpf_movein(struct uio *, u_int, struct mbuf **,
struct sockaddr *, struct bpf_insn *);
void bpf_attachd(struct bpf_d *, struct bpf_if *);
@@ -1160,46 +1159,6 @@ bpf_mcopy(const void *src_arg, void *dst_arg, size_t len)
}
/*
- * Copy an ethernet frame from an mbuf chain into a buffer, strip the
- * vlan header bits
- */
-void
-bpf_mcopy_stripvlan(const void *src_arg, void *dst_arg, size_t len)
-{
-#if NVLAN > 0
- const struct mbuf *m;
- u_int count, copied = 0, hdrdone = 0;
- u_char *dst;
- struct ether_vlan_header *evh;
-
- m = src_arg;
- dst = dst_arg;
- evh = dst_arg;
- while (len > 0) {
- if (m == 0)
- panic("bpf_mcopy_stripvlan");
- count = min(m->m_len, len);
- bcopy(mtod(m, caddr_t), (caddr_t)dst, count);
- m = m->m_next;
- dst += count;
- len -= count;
- copied += count;
- if (!hdrdone && copied >= sizeof(struct ether_vlan_header) &&
- (ntohs(evh->evl_encap_proto) == ETHERTYPE_VLAN ||
- ntohs(evh->evl_encap_proto) == ETHERTYPE_QINQ)) {
- /* move up by 4 bytes, overwrite encap_proto + tag */
- memmove(&evh->evl_encap_proto, &evh->evl_proto, copied -
- offsetof(struct ether_vlan_header, evl_proto));
- dst -= (offsetof(struct ether_vlan_header, evl_proto) -
- offsetof(struct ether_vlan_header,
- evl_encap_proto)); /* long expression for "4" */
- hdrdone = 1;
- }
- }
-#endif
-}
-
-/*
* like bpf_mtap, but copy fn can be given. used by various bpf_mtap*
*/
void
@@ -1251,13 +1210,6 @@ bpf_mtap(caddr_t arg, struct mbuf *m, u_int direction)
_bpf_mtap(arg, m, direction, NULL);
}
-/* like bpf_mtap, but strip the vlan header, leave regular ethernet hdr */
-void
-bpf_mtap_stripvlan(caddr_t arg, struct mbuf *m, u_int direction)
-{
- _bpf_mtap(arg, m, direction, bpf_mcopy_stripvlan);
-}
-
/*
* Incoming linkage from device drivers, where we have a mbuf chain
* but need to prepend some arbitrary header from a linear buffer.
diff --git a/sys/net/bpf.h b/sys/net/bpf.h
index 6bbb73c9fd5..f733ef7de4c 100644
--- a/sys/net/bpf.h
+++ b/sys/net/bpf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bpf.h,v 1.46 2014/07/10 09:46:29 henning Exp $ */
+/* $OpenBSD: bpf.h,v 1.47 2014/10/07 11:16:23 dlg Exp $ */
/* $NetBSD: bpf.h,v 1.15 1996/12/13 07:57:33 mikel Exp $ */
/*
@@ -272,7 +272,6 @@ struct bpf_dltlist {
int bpf_validate(struct bpf_insn *, int);
int bpf_tap(caddr_t, u_char *, u_int, u_int);
void bpf_mtap(caddr_t, struct mbuf *, u_int);
-void bpf_mtap_stripvlan(caddr_t, struct mbuf *, u_int);
void bpf_mtap_hdr(caddr_t, caddr_t, u_int, struct mbuf *, u_int,
void (*)(const void *, void *, size_t));
void bpf_mtap_af(caddr_t, u_int32_t, struct mbuf *, u_int);
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index a5779f26f10..46be6d779c4 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_vlan.c,v 1.108 2014/07/12 18:44:22 tedu Exp $ */
+/* $OpenBSD: if_vlan.c,v 1.109 2014/10/07 11:16:23 dlg Exp $ */
/*
* Copyright 1998 Massachusetts Institute of Technology
@@ -212,9 +212,42 @@ vlan_start(struct ifnet *ifp)
}
#if NBPFILTER > 0
- if (ifp->if_bpf)
- bpf_mtap_stripvlan(ifp->if_bpf, m, BPF_DIRECTION_OUT);
-#endif
+ if (ifp->if_bpf) {
+ if ((p->if_capabilities & IFCAP_VLAN_HWTAGGING) &&
+ (ifv->ifv_type == ETHERTYPE_VLAN))
+ bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+ else {
+ struct mbuf *m0;
+ u_int off;
+ struct m_hdr mh;
+ struct {
+ uint8_t dst[ETHER_ADDR_LEN];
+ uint8_t src[ETHER_ADDR_LEN];
+ } hdr;
+
+ /* copy the ether addresses off the front */
+ m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr);
+
+ /* find the ethertype after the vlan subhdr*/
+ m0 = m_getptr(m,
+ offsetof(struct ether_vlan_header,
+ evl_proto), &off);
+ KASSERT(m0 != NULL);
+
+ /* pretend the vlan subhdr isnt there */
+ mh.mh_flags = 0;
+ mh.mh_data = mtod(m0, caddr_t) + off;
+ mh.mh_len = m0->m_len - off;
+ mh.mh_next = m0->m_next;
+
+ /* dst+src + ethertype == ethernet header */
+ bpf_mtap_hdr(ifp->if_bpf,
+ (caddr_t)&hdr, sizeof(hdr),
+ (struct mbuf *)&mh, BPF_DIRECTION_OUT,
+ NULL);
+ }
+ }
+#endif /* NBPFILTER > 0 */
/*
* Send it, precisely as ether_output() would have.