summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2021-05-26 02:38:02 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2021-05-26 02:38:02 +0000
commit5a0beaf267f61004b0e7a5376afe4549dbf9e8f5 (patch)
tree9c3c25b4117216e9db9c37f6b606927635778e1f /sys/net
parent1ed7fcc81f247d9050e3ff45536de76c0964954f (diff)
support divert-to when pf applies it to a packet.
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 veb operates at layer 2, ip input processing only occurred if the packet was destined to go into a vport interface. bridge(4) handles 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 veb. this allows divert-to to steal (take?) packets going over a veb and process them on a local socket. reported by ajacatot@
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if_veb.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/sys/net/if_veb.c b/sys/net/if_veb.c
index 6b141bfb5cf..32a01466940 100644
--- a/sys/net/if_veb.c
+++ b/sys/net/if_veb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_veb.c,v 1.16 2021/03/10 10:21:48 jsg Exp $ */
+/* $OpenBSD: if_veb.c,v 1.17 2021/05/26 02:38:01 dlg Exp $ */
/*
* Copyright (c) 2021 David Gwynne <dlg@openbsd.org>
@@ -500,6 +500,7 @@ veb_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;
/*
* pf runs on vport interfaces when they enter or leave the
@@ -515,10 +516,14 @@ veb_pf(struct ifnet *ifp0, int dir, struct mbuf *m)
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);
}
@@ -533,6 +538,11 @@ veb_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);