From 48fe76d737cd7b17b3c8436d6591aa3893afc29e Mon Sep 17 00:00:00 2001 From: kevans Date: Wed, 29 May 2019 01:08:30 +0000 Subject: [PATCH] if_bridge(4): Complete bpf auditing of local traffic over the bridge There were two remaining "gaps" in auditing local bridge traffic with bpf(4): Locally originated outbound traffic from a member interface is invisible to the bridge's bpf(4) interface. Inbound traffic locally destined to a member interface is invisible to the member's bpf(4) interface -- this traffic has no chance after bridge_input to otherwise pass it over, and it wasn't originally received on this interface. I call these "gaps" because they don't affect conventional bridge setups. Alas, being able to establish an audit trail of all locally destined traffic for setups that can function like this is useful in some scenarios. Reviewed by: kp MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D19757 --- sys/net/if_bridge.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index f293f136f58b..3a5e1f3d8968 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -2000,7 +2000,7 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, struct rtentry *rt) { struct ether_header *eh; - struct ifnet *dst_if; + struct ifnet *bifp, *dst_if; struct bridge_softc *sc; uint16_t vlan; @@ -2015,13 +2015,14 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, vlan = VLANTAGOF(m); BRIDGE_LOCK(sc); + bifp = sc->sc_ifp; /* * If bridge is down, but the original output interface is up, * go ahead and send out that interface. Otherwise, the packet * is dropped below. */ - if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { + if ((bifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { dst_if = ifp; goto sendunicast; } @@ -2034,6 +2035,9 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, dst_if = NULL; else dst_if = bridge_rtlookup(sc, eh->ether_dhost, vlan); + /* Tap any traffic not passing back out the originating interface */ + if (dst_if != ifp) + ETHER_BPF_MTAP(bifp, m); if (dst_if == NULL) { struct bridge_iflist *bif; struct mbuf *mc; @@ -2071,7 +2075,7 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, } else { mc = m_copypacket(m, M_NOWAIT); if (mc == NULL) { - if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1); + if_inc_counter(bifp, IFCOUNTER_OERRORS, 1); continue; } } @@ -2450,6 +2454,8 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) return (NULL); \ } \ } \ + if ((iface) != bifp) \ + ETHER_BPF_MTAP(iface, m); \ BRIDGE_UNLOCK(sc); \ return (m); \ } \