From 3f18959cf6cf4543a19d1073d6f53b142e2f46e7 Mon Sep 17 00:00:00 2001 From: philip Date: Mon, 18 Aug 2008 09:06:11 +0000 Subject: Fix ARP in bridging scenarios where the bridge shares its MAC address with one of its members (see my r180140). Pointy hat to: philip Submitted by: Eygene Ryabinkin MFC after: 3 days --- sys/netinet/if_ether.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 6f489a2..558db3b 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -592,7 +592,7 @@ in_arpinput(struct mbuf *m) u_int8_t *enaddr = NULL; int op, rif_len; int req_len; - int bridged = 0; + int bridged = 0, is_bridge = 0; u_int fibnum; u_int goodfib = 0; int firstpass = 1; @@ -606,6 +606,8 @@ in_arpinput(struct mbuf *m) if (ifp->if_bridge) bridged = 1; + if (ifp->if_type == IFT_BRIDGE) + is_bridge = 1; req_len = arphdr_len2(ifp->if_addrlen, sizeof(struct in_addr)); if (m->m_len < req_len && (m = m_pullup(m, req_len)) == NULL) { @@ -646,6 +648,27 @@ in_arpinput(struct mbuf *m) (ia->ia_ifp == ifp)) && isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) goto match; + +#define BDG_MEMBER_MATCHES_ARP(addr, ifp, ia) \ + (ia->ia_ifp->if_bridge == ifp->if_softc && \ + !bcmp(IF_LLADDR(ia->ia_ifp), IF_LLADDR(ifp), ifp->if_addrlen) && \ + addr == ia->ia_addr.sin_addr.s_addr) + /* + * Check the case when bridge shares its MAC address with + * some of its children, so packets are claimed by bridge + * itself (bridge_input() does it first), but they are really + * meant to be destined to the bridge member. + */ + if (is_bridge) { + LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { + if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) { + ifp = ia->ia_ifp; + goto match; + } + } + } +#undef BDG_MEMBER_MATCHES_ARP + /* * No match, use the first inet address on the receive interface * as a dummy address for the rest of the function. -- cgit v1.1