summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2021-05-26 06:44:29 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2021-05-26 06:44:29 +0000
commitb39d959eafed7e50c4a8a463a55b8ace28a969cd (patch)
treec7cc47b58c32b2a84e333ded33546d2e0594b640 /sys/net
parent5a0beaf267f61004b0e7a5376afe4549dbf9e8f5 (diff)
add support for pf divert-to on tpmr, like what was done for veb(4).
when a divert-to rule applies to a packet, pf doesnt take the packet away and shove it in the socket directly. pf marks the packet, and then ip (or ipv6) input processing looks at the mark and picks the local socket to queue it on. because tpmr operates at layer 2, ip input has no chance to look at the packet and let the divert socket steal it. bridge(4) and now veb(4) handle this by checking if the packet has the pf divert to mark set on it and calls ip input if it's set. this copies the semantic to tpmr.
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if_tpmr.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/sys/net/if_tpmr.c b/sys/net/if_tpmr.c
index 981a7d5a09b..753379a446b 100644
--- a/sys/net/if_tpmr.c
+++ b/sys/net/if_tpmr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_tpmr.c,v 1.24 2021/03/05 06:44:09 dlg Exp $ */
+/* $OpenBSD: if_tpmr.c,v 1.25 2021/05/26 06:44:28 dlg Exp $ */
/*
* Copyright (c) 2019 The University of Queensland
@@ -247,15 +247,20 @@ tpmr_pf(struct ifnet *ifp0, int dir, struct mbuf *m)
{
struct ether_header *eh, copy;
sa_family_t af = AF_UNSPEC;
+ void (*ip_input)(struct ifnet *, struct mbuf *) = NULL;
eh = mtod(m, struct ether_header *);
switch (ntohs(eh->ether_type)) {
case ETHERTYPE_IP:
af = AF_INET;
+ ip_input = ipv4_input;
break;
+#ifdef INET6
case ETHERTYPE_IPV6:
af = AF_INET6;
+ ip_input = ipv6_input;
break;
+#endif
default:
return (m);
}
@@ -270,6 +275,11 @@ tpmr_pf(struct ifnet *ifp0, int dir, struct mbuf *m)
if (m == NULL)
return (NULL);
+ if (dir == PF_IN && ISSET(m->m_pkthdr.pf.flags, PF_TAG_DIVERTED)) {
+ (*ip_input)(ifp0, m);
+ return (NULL);
+ }
+
m = m_prepend(m, sizeof(*eh), M_DONTWAIT);
if (m == NULL)
return (NULL);