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@
-/* $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>
{
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
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);
}
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);