summaryrefslogtreecommitdiff
path: root/sys/net/if_bridge.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2009-01-06 21:23:19 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2009-01-06 21:23:19 +0000
commiteca3015e0d58ef1f08f95f9897ac01331edb9a48 (patch)
treec120d6d83c834848014d601fd78121ac47abcf06 /sys/net/if_bridge.c
parent57beca5400c36e5f3003e1652339d8c4b45bf7b3 (diff)
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@
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r--sys/net/if_bridge.c40
1 files changed, 39 insertions, 1 deletions
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;
@@ -1637,6 +1641,40 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *ifp,
}
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)
{