diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2021-05-26 02:38:02 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2021-05-26 02:38:02 +0000 |
commit | 5a0beaf267f61004b0e7a5376afe4549dbf9e8f5 (patch) | |
tree | 9c3c25b4117216e9db9c37f6b606927635778e1f /sys/net | |
parent | 1ed7fcc81f247d9050e3ff45536de76c0964954f (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.c | 12 |
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); |