summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2009-01-06 21:23:18 +0000
committerclaudio <claudio@openbsd.org>2009-01-06 21:23:18 +0000
commitd3d259ddac0b6cd0fd332bce72ed128be539877b (patch)
treed42577d71d531367fa65655d7f24bd0f796d0140
parentmake file update in queue_update_envelope atomic; ok gilles@ (diff)
downloadwireguard-openbsd-d3d259ddac0b6cd0fd332bce72ed128be539877b.tar.xz
wireguard-openbsd-d3d259ddac0b6cd0fd332bce72ed128be539877b.zip
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@
-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)
{