From 19e72e3b9f3138440f80b79260f2adaee85eae40 Mon Sep 17 00:00:00 2001 From: Christian Weisgerber Date: Sun, 9 Nov 2008 15:08:27 +0000 Subject: Introduce bpf_mtap_ether(), which for the benefit of bpf listeners creates the VLAN encapsulation from the tag stored in the mbuf header. Idea from FreeBSD, input from claudio@ and canacar@. Switch all hardware VLAN enabled drivers to the new function. ok claudio@ --- sys/net/bpf.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- sys/net/bpf.h | 3 ++- 2 files changed, 52 insertions(+), 2 deletions(-) (limited to 'sys/net') diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 8f1781bf447..0172c5d8f85 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bpf.c,v 1.69 2008/09/17 20:10:37 chl Exp $ */ +/* $OpenBSD: bpf.c,v 1.70 2008/11/09 15:08:26 naddy Exp $ */ /* $NetBSD: bpf.c,v 1.33 1997/02/21 23:59:35 thorpej Exp $ */ /* @@ -59,6 +59,11 @@ #include #include +#include "vlan.h" +#if NVLAN > 0 +#include +#endif + #define BPF_BUFSIZE 32768 #define PRINET 26 /* interruptible */ @@ -1236,6 +1241,50 @@ bpf_mtap_af(caddr_t arg, u_int32_t af, struct mbuf *m, u_int direction) m->m_flags |= mh.mh_flags & M_FILDROP; } +/* + * Incoming linkage from device drivers, where we have a mbuf chain + * but need to prepend a VLAN encapsulation header. + * + * Con up a minimal dummy header to pacify bpf. Allocate (only) a + * struct m_hdr on the stack. This is safe as bpf only reads from the + * fields in this header that we initialize, and will not try to free + * it or keep a pointer to it. + */ +void +bpf_mtap_ether(caddr_t arg, struct mbuf *m, u_int direction) +{ +#if NVLAN > 0 + struct m_hdr mh; + struct ether_vlan_header evh; + + if ((m->m_flags & M_VLANTAG) == 0) +#endif + { + bpf_mtap(arg, m, direction); + return; + } + +#if NVLAN > 0 + bcopy(mtod(m, char *), &evh, ETHER_HDR_LEN); + evh.evl_proto = evh.evl_encap_proto; + evh.evl_encap_proto = htons(ETHERTYPE_VLAN); + evh.evl_tag = htons(m->m_pkthdr.ether_vtag); + m->m_len -= ETHER_HDR_LEN; + m->m_data += ETHER_HDR_LEN; + + mh.mh_flags = 0; + mh.mh_next = m; + mh.mh_len = sizeof(evh); + mh.mh_data = (caddr_t)&evh; + + bpf_mtap(arg, (struct mbuf *) &mh, direction); + m->m_flags |= mh.mh_flags & M_FILDROP; + + m->m_len += ETHER_HDR_LEN; + m->m_data -= ETHER_HDR_LEN; +#endif +} + /* * Move the packet data from interface memory (pkt) into the * store buffer. Return 1 if it's time to wakeup a listener (buffer full), diff --git a/sys/net/bpf.h b/sys/net/bpf.h index 88d0a7fbc7f..fcf4c2588ec 100644 --- a/sys/net/bpf.h +++ b/sys/net/bpf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bpf.h,v 1.35 2008/06/29 19:31:16 deraadt Exp $ */ +/* $OpenBSD: bpf.h,v 1.36 2008/11/09 15:08:26 naddy Exp $ */ /* $NetBSD: bpf.h,v 1.15 1996/12/13 07:57:33 mikel Exp $ */ /* @@ -273,6 +273,7 @@ int bpf_tap(caddr_t, u_char *, u_int, u_int); void bpf_mtap(caddr_t, struct mbuf *, u_int); void bpf_mtap_hdr(caddr_t, caddr_t, u_int, struct mbuf *, u_int); void bpf_mtap_af(caddr_t, u_int32_t, struct mbuf *, u_int); +void bpf_mtap_ether(caddr_t, struct mbuf *, u_int); void bpfattach(caddr_t *, struct ifnet *, u_int, u_int); void bpfdetach(struct ifnet *); void bpfilterattach(int); -- cgit v1.2.3