summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2019-08-05 03:56:31 +0000
committerdlg <dlg@openbsd.org>2019-08-05 03:56:31 +0000
commitde0dfb644a6ae5a0ca9592b5a89c580f9aed2a72 (patch)
treeba5d5e4923e5bd2dffab2fd33f565e84bfbfac95
parentpay some lip service to TPMR compliance according to 802.1Q-2018 (diff)
downloadwireguard-openbsd-de0dfb644a6ae5a0ca9592b5a89c580f9aed2a72.tar.xz
wireguard-openbsd-de0dfb644a6ae5a0ca9592b5a89c580f9aed2a72.zip
run pf against ip packets coming in and out of the two ports.
the idea and a good chunk of the implementation is copied from bridge(4). note that IP packets inside "service delimited" traffic, ie, vlan, svlan, or bpe encapsulated traffic, are not considered IP and will therefore not be given to pf to look at. if you want to filter that you'll need to configure vlan/svlan/bpe interfaces to get past their headers, and then configure them with their own tpmrs. hopefully the interface input handlers were established in the right order.
-rw-r--r--sys/net/if_tpmr.c67
1 files changed, 63 insertions, 4 deletions
diff --git a/sys/net/if_tpmr.c b/sys/net/if_tpmr.c
index 9b3caf551fb..654a3d8e3fc 100644
--- a/sys/net/if_tpmr.c
+++ b/sys/net/if_tpmr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_tpmr.c,v 1.2 2019/08/05 01:55:38 dlg Exp $ */
+/* $OpenBSD: if_tpmr.c,v 1.3 2019/08/05 03:56:31 dlg Exp $ */
/*
* Copyright (c) 2019 The University of Queensland
@@ -24,6 +24,7 @@
*/
#include "bpfilter.h"
+#include "pf.h"
#include "vlan.h"
#include <sys/param.h>
@@ -55,6 +56,10 @@
#include <net/bpf.h>
#endif
+#if NPF > 0
+#include <net/pfvar.h>
+#endif
+
#if NVLAN > 0
#include <net/if_vlan_var.h>
#endif
@@ -232,6 +237,46 @@ tpmr_8021q_filter(const struct mbuf *m)
return (0);
}
+#if NPF > 0
+static struct mbuf *
+tpmr_pf(struct ifnet *ifp0, int dir, struct mbuf *m)
+{
+ struct ether_header *eh, copy;
+ sa_family_t af = AF_UNSPEC;
+
+ eh = mtod(m, struct ether_header *);
+ switch (ntohs(eh->ether_type)) {
+ case ETHERTYPE_IP:
+ af = AF_INET;
+ break;
+ case ETHERTYPE_IPV6:
+ af = AF_INET6;
+ break;
+ default:
+ return (m);
+ }
+
+ copy = *eh;
+ m_adj(m, sizeof(*eh));
+
+ if (pf_test(af, dir, ifp0, &m) != PF_PASS) {
+ m_freem(m);
+ return (NULL);
+ }
+
+ m = m_prepend(m, sizeof(*eh), M_DONTWAIT);
+ if (m == NULL)
+ return (NULL);
+
+ /* checksum? */
+
+ eh = mtod(m, struct ether_header *);
+ *eh = copy;
+
+ return (m);
+}
+#endif /* NPF > 0 */
+
static int
tpmr_input(struct ifnet *ifp0, struct mbuf *m, void *cookie)
{
@@ -261,12 +306,19 @@ tpmr_input(struct ifnet *ifp0, struct mbuf *m, void *cookie)
}
#endif
+ if (!ISSET(ifp->if_flags, IFF_LINK0) &&
+ tpmr_8021q_filter(m))
+ goto drop;
+
+#if NPF > 0
+ if (!ISSET(ifp->if_flags, IFF_LINK1) &&
+ (m = tpmr_pf(ifp0, PF_IN, m)) == NULL)
+ return (1);
+#endif
+
len = m->m_pkthdr.len;
counters_pkt(ifp->if_counters, ifc_ipackets, ifc_ibytes, len);
- if (!ISSET(ifp->if_flags, IFF_LINK0) && tpmr_8021q_filter(m))
- goto drop;
-
#if NBPFILTER > 0
if_bpf = ifp->if_bpf;
if (if_bpf) {
@@ -281,6 +333,13 @@ tpmr_input(struct ifnet *ifp0, struct mbuf *m, void *cookie)
m_freem(m);
else {
struct ifnet *ifpn = pn->p_ifp0;
+
+#if NPF > 0
+ if (!ISSET(ifp->if_flags, IFF_LINK1) &&
+ (m = tpmr_pf(ifpn, PF_OUT, m)) == NULL)
+ ;
+ else
+#endif
if ((*ifpn->if_enqueue)(ifpn, m))
counters_inc(ifp->if_counters, ifc_oerrors);
else {