summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorChristian Weisgerber <naddy@cvs.openbsd.org>2008-11-09 15:08:27 +0000
committerChristian Weisgerber <naddy@cvs.openbsd.org>2008-11-09 15:08:27 +0000
commit19e72e3b9f3138440f80b79260f2adaee85eae40 (patch)
tree291a75bc288930e303d106f2c4b3e8fb865415a0 /sys/net
parentbe7cd0fdfd40b4f306a204fdbb31aa7cdd7efec5 (diff)
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@
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/bpf.c51
-rw-r--r--sys/net/bpf.h3
2 files changed, 52 insertions, 2 deletions
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 <netinet/in.h>
#include <netinet/if_ether.h>
+#include "vlan.h"
+#if NVLAN > 0
+#include <net/if_vlan_var.h>
+#endif
+
#define BPF_BUFSIZE 32768
#define PRINET 26 /* interruptible */
@@ -1237,6 +1242,50 @@ bpf_mtap_af(caddr_t arg, u_int32_t af, struct mbuf *m, u_int direction)
}
/*
+ * 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),
* otherwise 0. "copy" is the routine called to do the actual data
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);