Slightly re-worked bpf(4) code associated with bridging: if we have a

destination interface as a member of our bridge or this is a unicast packet,
push it through the bpf(4) machinery.

For broadcast or multicast packets, don't bother with the bpf(4) because it will
be re-injected into ether_input. We do this before we pass the packets through
the pfil(9) framework, as it is possible that pfil(9) will drop the packet or
possibly modify it, making it very difficult to debug firewall issues on the
bridge.

Further, implemented IFF_MONITOR for bridge interfaces. This does much the same
thing that it does for regular network interfaces: it pushes the packet to any
bpf(4) peers and then returns. This bypasses all of the bridge machinery,
saving mutex acquisitions, list traversals, and other operations performed by
the bridging code.

This change to the bridging code is useful in situations where individuals use a
bridge to multiplex RX/TX signals from two interfaces, as is required by some
network taps for de-multiplexing links and transmitting the RX/TX signals
out through two separate interfaces. This behaviour is quite common for network
taps monitoring links, especially for certain manufacturers.

Reviewed by:	thompsa
MFC after:	1 month
Sponsored by:	Seccuris Labs
This commit is contained in:
Christian S.J. Peron 2006-03-03 05:58:18 +00:00
parent a7f12baaca
commit 6f75ef188b

View File

@ -1799,6 +1799,18 @@ bridge_forward(struct bridge_softc *sc, struct mbuf *m)
dst_if = NULL;
}
/*
* If we have a destination interface which is a member of our bridge,
* OR this is a unicast packet, push it through the bpf(4) machinery.
* For broadcast or multicast packets, don't bother because it will
* be reinjected into ether_input. We do this before we pass the packets
* through the pfil(9) framework, as it is possible that pfil(9) will
* drop the packet, or possibly modify it, making it difficult to debug
* firewall issues on the bridge.
*/
if (dst_if != NULL || (m->m_flags & (M_BCAST | M_MCAST)) == 0)
BPF_MTAP(ifp, m);
/* run the packet filter */
if (PFIL_HOOKED(&inet_pfil_hook)
#ifdef INET6
@ -1814,13 +1826,6 @@ bridge_forward(struct bridge_softc *sc, struct mbuf *m)
}
if (dst_if == NULL) {
/*
* Tap off packets passing the bridge. Broadcast packets will
* already be tapped as they are reinjected into ether_input.
*/
if ((m->m_flags & (M_BCAST|M_MCAST)) == 0)
BPF_MTAP(ifp, m);
bridge_broadcast(sc, src_if, m, 1);
return;
}
@ -1852,9 +1857,6 @@ bridge_forward(struct bridge_softc *sc, struct mbuf *m)
}
}
/* tap off packets passing the bridge */
BPF_MTAP(ifp, m);
BRIDGE_UNLOCK(sc);
if (PFIL_HOOKED(&inet_pfil_hook)
@ -1891,6 +1893,20 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
bifp = sc->sc_ifp;
/*
* Implement support for bridge monitoring. If this flag has been
* set on this interface, discard the packet once we push it through
* the bpf(4) machinery, but before we do, increment the byte and
* packet counters associated with this interface.
*/
if ((bifp->if_flags & IFF_MONITOR) != 0) {
m->m_pkthdr.rcvif = bifp;
BPF_MTAP(bifp, m);
bifp->if_ipackets++;
bifp->if_ibytes += m->m_pkthdr.len;
m_free(m);
return (NULL);
}
BRIDGE_LOCK(sc);
bif = bridge_lookup_member_if(sc, ifp);
if (bif == NULL) {