summaryrefslogtreecommitdiffstats
path: root/sys/netinet/if_ether.c
diff options
context:
space:
mode:
authorqingli <qingli@FreeBSD.org>2008-12-19 11:07:34 +0000
committerqingli <qingli@FreeBSD.org>2008-12-19 11:07:34 +0000
commite1a252e123d00883dfdada1b4a1567a5fbb1414f (patch)
treeee357c191fa777901e4866e2c359cbba69c5bb80 /sys/netinet/if_ether.c
parent468571c1c0a807043a39f0cd88fa41b543e03e9f (diff)
downloadFreeBSD-src-e1a252e123d00883dfdada1b4a1567a5fbb1414f.zip
FreeBSD-src-e1a252e123d00883dfdada1b4a1567a5fbb1414f.tar.gz
The proxy-arp code was broken and responds to ARP
requests for addresses that are not proxied locally.
Diffstat (limited to 'sys/netinet/if_ether.c')
-rw-r--r--sys/netinet/if_ether.c109
1 files changed, 52 insertions, 57 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index 7bea5aa..1b03fb3 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -660,69 +660,64 @@ reply:
(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
(void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
} else {
- if (la == NULL) {
- if (!V_arp_proxyall)
- goto drop;
-
- sin.sin_addr = itaddr;
- /* XXX MRT use table 0 for arp reply */
- rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
- if (!rt)
- goto drop;
- /*
- * Don't send proxies for nodes on the same interface
- * as this one came out of, or we'll get into a fight
- * over who claims what Ether address.
- */
- if (rt->rt_ifp == ifp) {
- RTFREE_LOCKED(rt);
- goto drop;
- }
- (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
- (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
+ struct llentry *lle = NULL;
+
+ if (!V_arp_proxyall)
+ goto drop;
+
+ sin.sin_addr = itaddr;
+ /* XXX MRT use table 0 for arp reply */
+ rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
+ if (!rt)
+ goto drop;
+
+ /*
+ * Don't send proxies for nodes on the same interface
+ * as this one came out of, or we'll get into a fight
+ * over who claims what Ether address.
+ */
+ if (!rt->rt_ifp || rt->rt_ifp == ifp) {
RTFREE_LOCKED(rt);
+ goto drop;
+ }
+ IF_AFDATA_LOCK(rt->rt_ifp);
+ lle = lla_lookup(LLTABLE(rt->rt_ifp), 0, (struct sockaddr *)&sin);
+ IF_AFDATA_UNLOCK(rt->rt_ifp);
+ RTFREE_LOCKED(rt);
- /*
- * Also check that the node which sent the ARP packet
- * is on the the interface we expect it to be on. This
- * avoids ARP chaos if an interface is connected to the
- * wrong network.
- */
- sin.sin_addr = isaddr;
-
- /* XXX MRT use table 0 for arp checks */
- rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
- if (!rt)
- goto drop;
- if (rt->rt_ifp != ifp) {
- log(LOG_INFO, "arp_proxy: ignoring request"
- " from %s via %s, expecting %s\n",
- inet_ntoa(isaddr), ifp->if_xname,
- rt->rt_ifp->if_xname);
- RTFREE_LOCKED(rt);
- goto drop;
- }
+ if (lle != NULL) {
+ (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
+ (void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln);
+ LLE_RUNLOCK(lle);
+ } else
+ goto drop;
+
+ /*
+ * Also check that the node which sent the ARP packet
+ * is on the the interface we expect it to be on. This
+ * avoids ARP chaos if an interface is connected to the
+ * wrong network.
+ */
+ sin.sin_addr = isaddr;
+
+ /* XXX MRT use table 0 for arp checks */
+ rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
+ if (!rt)
+ goto drop;
+ if (rt->rt_ifp != ifp) {
+ log(LOG_INFO, "arp_proxy: ignoring request"
+ " from %s via %s, expecting %s\n",
+ inet_ntoa(isaddr), ifp->if_xname,
+ rt->rt_ifp->if_xname);
RTFREE_LOCKED(rt);
+ goto drop;
+ }
+ RTFREE_LOCKED(rt);
#ifdef DEBUG_PROXY
- printf("arp: proxying for %s\n",
- inet_ntoa(itaddr));
+ printf("arp: proxying for %s\n",
+ inet_ntoa(itaddr));
#endif
- } else {
- /*
- * Return proxied ARP replies only on the interface
- * or bridge cluster where this network resides.
- * Otherwise we may conflict with the host we are
- * proxying for.
- */
- if (la->lle_tbl->llt_ifp != ifp &&
- (la->lle_tbl->llt_ifp->if_bridge != ifp->if_bridge ||
- ifp->if_bridge == NULL)) {
- goto drop;
- }
- (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
- (void)memcpy(ar_sha(ah), &la->ll_addr, ah->ar_hln);
- }
}
if (la != NULL)
OpenPOWER on IntegriCloud