summaryrefslogtreecommitdiffstats
path: root/sys/netinet/if_ether.c
diff options
context:
space:
mode:
authorqingli <qingli@FreeBSD.org>2009-09-15 18:39:27 +0000
committerqingli <qingli@FreeBSD.org>2009-09-15 18:39:27 +0000
commit620c678111a81c88256575cb8a1e9fff36f90003 (patch)
treef50f5518fb647bef794e9da234b34b5d84ab6bff /sys/netinet/if_ether.c
parent25c88f593e7faf26360fd688f8afb5b1993cb864 (diff)
downloadFreeBSD-src-620c678111a81c88256575cb8a1e9fff36f90003.zip
FreeBSD-src-620c678111a81c88256575cb8a1e9fff36f90003.tar.gz
This patch enables the node to respond to ARP requests for
configured proxy ARP entries. Reviewed by: bz MFC after: immediately
Diffstat (limited to 'sys/netinet/if_ether.c')
-rw-r--r--sys/netinet/if_ether.c100
1 files changed, 54 insertions, 46 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index 941a93b..be62921 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -714,62 +714,70 @@ reply:
} else {
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);
+ IF_AFDATA_LOCK(ifp);
+ lle = lla_lookup(LLTABLE(ifp), 0, (struct sockaddr *)&sin);
+ IF_AFDATA_UNLOCK(ifp);
- if (lle != NULL) {
+ if ((lle != NULL) && (lle->la_flags & LLE_PUB)) {
(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;
+ } else {
+
+ if (lle != NULL)
+ LLE_RUNLOCK(lle);
+
+ 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;
+ }
+ 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);
+ (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
+ (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
+
+ /*
+ * 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);
- 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
+ }
}
if (itaddr.s_addr == myaddr.s_addr &&
OpenPOWER on IntegriCloud