diff options
author | 2014-10-07 11:16:23 +0000 | |
---|---|---|
committer | 2014-10-07 11:16:23 +0000 | |
commit | ad7bdc7f72d0b375583701cc3ac25cd800b4f86d (patch) | |
tree | 19bf5f4db5257cd4b6c2e59060874d021d2488d2 | |
parent | Use L1_S_V7_AP instead of L1_S_AP for the v7 case (diff) | |
download | wireguard-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.c | 50 | ||||
-rw-r--r-- | sys/net/bpf.h | 3 | ||||
-rw-r--r-- | sys/net/if_vlan.c | 41 |
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. |