diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2021-05-26 06:44:29 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2021-05-26 06:44:29 +0000 |
commit | b39d959eafed7e50c4a8a463a55b8ace28a969cd (patch) | |
tree | c7cc47b58c32b2a84e333ded33546d2e0594b640 /sys/net | |
parent | 5a0beaf267f61004b0e7a5376afe4549dbf9e8f5 (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.c | 12 |
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); |