summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/if_ether.c57
1 files changed, 46 insertions, 11 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index b72d3aaaf8b..c811b72d526 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ether.c,v 1.35 2001/12/08 06:15:15 jason Exp $ */
+/* $OpenBSD: if_ether.c,v 1.36 2002/02/15 15:27:17 jason Exp $ */
/* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */
/*
@@ -44,6 +44,8 @@
#ifdef INET
+#include "bridge.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
@@ -450,7 +452,10 @@ in_arpinput(m)
struct ether_header *eh;
register struct llinfo_arp *la = 0;
register struct rtentry *rt;
- struct in_ifaddr *ia, *maybe_ia = 0;
+ struct in_ifaddr *ia;
+#if NBRIDGE > 0
+ struct in_ifaddr *bridge_ia = NULL;
+#endif
struct sockaddr_dl *sdl;
struct sockaddr sa;
struct in_addr isaddr, itaddr, myaddr;
@@ -467,21 +472,51 @@ in_arpinput(m)
goto out;
}
#endif
- bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof(isaddr));
+
bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, sizeof(itaddr));
+ bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof(isaddr));
+
TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
- if (ia->ia_ifp == &ac->ac_if ||
- (ia->ia_ifp->if_bridge &&
- ia->ia_ifp->if_bridge == ac->ac_if.if_bridge)) {
- maybe_ia = ia;
- if (itaddr.s_addr == ia->ia_addr.sin_addr.s_addr ||
- isaddr.s_addr == ia->ia_addr.sin_addr.s_addr)
+ if (itaddr.s_addr != ia->ia_addr.sin_addr.s_addr)
+ continue;
+
+ if (ia->ia_ifp == m->m_pkthdr.rcvif)
+ break;
+#if NBRIDGE > 0
+ /*
+ * If the interface we received the packet on
+ * is part of a bridge, check to see if we need
+ * to "bridge" the packet to ourselves at this
+ * layer. Note we still prefer a perfect match,
+ * but allow this weaker match if necessary.
+ */
+ if (m->m_pkthdr.rcvif->if_bridge != NULL &&
+ m->m_pkthdr.rcvif->if_bridge == ia->ia_ifp->if_bridge)
+ bridge_ia = ia;
+#endif
+ }
+
+#if NBRIDGE > 0
+ if (ia == NULL && bridge_ia != NULL) {
+ ia = bridge_ia;
+ ac = (struct arpcom *)bridge_ia->ia_ifp;
+ }
+#endif
+
+ if (ia == NULL) {
+ TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
+ if (itaddr.s_addr != ia->ia_addr.sin_addr.s_addr)
+ continue;
+ if (ia->ia_ifp == m->m_pkthdr.rcvif)
break;
}
}
- if (maybe_ia == 0)
+
+ if (ia == NULL)
goto out;
- myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr;
+
+ myaddr = ia->ia_addr.sin_addr;
+
if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
sizeof (ea->arp_sha)))
goto out; /* it's from me, ignore it. */