From eca3015e0d58ef1f08f95f9897ac01331edb9a48 Mon Sep 17 00:00:00 2001 From: Claudio Jeker Date: Tue, 6 Jan 2009 21:23:19 +0000 Subject: Send broadcast and multicast traffic not only out on all bridge interfaces but also up into the network stack on all interfaces. Multicast addresses are bound to interfaces and without this local sockets did not see packets that entered the bridge on a different interface. This should help IPv6. OK naddy@ --- sys/net/if_bridge.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'sys/net/if_bridge.c') diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index b28f4746e77..1d14ec1c3c9 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.c,v 1.173 2008/10/16 19:12:51 naddy Exp $ */ +/* $OpenBSD: if_bridge.c,v 1.174 2009/01/06 21:23:18 claudio Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -122,6 +122,8 @@ void bridge_start(struct ifnet *); void bridgeintr_frame(struct bridge_softc *, struct mbuf *); void bridge_broadcast(struct bridge_softc *, struct ifnet *, struct ether_header *, struct mbuf *); +void bridge_localbroadcast(struct bridge_softc *, struct ifnet *, + struct ether_header *, struct mbuf *); void bridge_span(struct bridge_softc *, struct ether_header *, struct mbuf *); void bridge_stop(struct bridge_softc *); @@ -1578,6 +1580,8 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *ifp, if (bridge_filterrule(&p->bif_brlout, eh, m) == BRL_ACTION_BLOCK) continue; + bridge_localbroadcast(sc, dst_if, eh, m); + /* If last one, reuse the passed-in mbuf */ if (LIST_NEXT(p, next) == LIST_END(&sc->sc_iflist)) { mc = m; @@ -1636,6 +1640,40 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *ifp, m_freem(m); } +void +bridge_localbroadcast(struct bridge_softc *sc, struct ifnet *ifp, + struct ether_header *eh, struct mbuf *m) +{ + struct mbuf *m1; + u_int16_t etype; + +#ifdef INET + /* + * quick optimisation, don't send packets up the stack if no + * corresponding address has been specified. + */ + etype = ntohs(eh->ether_type); + if (!(m->m_flags & M_VLANTAG) && etype == ETHERTYPE_IP) { + struct in_ifaddr *ia; + IFP_TO_IA(ifp, ia); + if (!ia) + return; + } +#endif + + m1 = m_copym2(m, 0, M_COPYALL, M_DONTWAIT); + if (m1 == NULL) { + sc->sc_if.if_oerrors++; + return; + } + m_adj(m1, ETHER_HDR_LEN); + + /* fixup header a bit */ + m1->m_flags |= M_PROTO1; + m1->m_pkthdr.rcvif = ifp; + ether_input(ifp, eh, m1); +} + void bridge_span(struct bridge_softc *sc, struct ether_header *eh, struct mbuf *morig) -- cgit v1.2.3