summaryrefslogtreecommitdiffstats
path: root/usr.sbin/arp
diff options
context:
space:
mode:
authorqingli <qingli@FreeBSD.org>2009-12-30 21:35:34 +0000
committerqingli <qingli@FreeBSD.org>2009-12-30 21:35:34 +0000
commited965a92bc17f25c5049fbd529d10a9e94f8a3a7 (patch)
tree8e2dcb46479d9e8deaedba15ff39e4bf06edf8c9 /usr.sbin/arp
parent05e668091314a2bdc6f8d36ac2e8abf4c424a09a (diff)
downloadFreeBSD-src-ed965a92bc17f25c5049fbd529d10a9e94f8a3a7.zip
FreeBSD-src-ed965a92bc17f25c5049fbd529d10a9e94f8a3a7.tar.gz
The proxy arp entries could not be added into the system over the
IFF_POINTOPOINT link types. The reason was due to the routing entry returned from the kernel covering the remote end is of an interface type that does not support ARP. This patch fixes this problem by providing a hint to the kernel routing code, which indicates the prefix route instead of the PPP host route should be returned to the caller. Since a host route to the local end point is also added into the routing table, and there could be multiple such instantiations due to multiple PPP links can be created with the same local end IP address, this patch also fixes the loopback route installation failure problem observed prior to this patch. The reference count of loopback route to local end would be either incremented or decremented. The first instantiation would create the entry and the last removal would delete the route entry. MFC after: 5 days
Diffstat (limited to 'usr.sbin/arp')
-rw-r--r--usr.sbin/arp/arp.c64
1 files changed, 35 insertions, 29 deletions
diff --git a/usr.sbin/arp/arp.c b/usr.sbin/arp/arp.c
index 2982f48..61427d3 100644
--- a/usr.sbin/arp/arp.c
+++ b/usr.sbin/arp/arp.c
@@ -326,7 +326,6 @@ set(int argc, char **argv)
doing_proxy = 1;
if (argc && strncmp(argv[1], "only", 3) == 0) {
proxy_only = 1;
- dst->sin_other = SIN_PROXY;
argc--; argv++;
}
} else if (strncmp(argv[0], "blackhole", 9) == 0) {
@@ -365,33 +364,30 @@ set(int argc, char **argv)
sdl_m.sdl_alen = ETHER_ADDR_LEN;
}
}
- for (;;) { /* try at most twice */
- rtm = rtmsg(RTM_GET, dst, &sdl_m);
- if (rtm == NULL) {
- warn("%s", host);
- return (1);
- }
- addr = (struct sockaddr_inarp *)(rtm + 1);
- sdl = (struct sockaddr_dl *)(SA_SIZE(addr) + (char *)addr);
- if (addr->sin_addr.s_addr != dst->sin_addr.s_addr)
- break;
- if (sdl->sdl_family == AF_LINK &&
- !(rtm->rtm_flags & RTF_GATEWAY) &&
- valid_type(sdl->sdl_type) )
- break;
- if (doing_proxy == 0) {
- printf("set: can only proxy for %s\n", host);
- return (1);
- }
- if (dst->sin_other & SIN_PROXY) {
- printf("set: proxy entry exists for non 802 device\n");
- return (1);
- }
- dst->sin_other = SIN_PROXY;
- proxy_only = 1;
+
+ /*
+ * In the case a proxy-arp entry is being added for
+ * a remote end point, the RTF_ANNOUNCE flag in the
+ * RTM_GET command is an indication to the kernel
+ * routing code that the interface associated with
+ * the prefix route covering the local end of the
+ * PPP link should be returned, on which ARP applies.
+ */
+ rtm = rtmsg(RTM_GET, dst, &sdl_m);
+ if (rtm == NULL) {
+ warn("%s", host);
+ return (1);
+ }
+ addr = (struct sockaddr_inarp *)(rtm + 1);
+ sdl = (struct sockaddr_dl *)(SA_SIZE(addr) + (char *)addr);
+ if (addr->sin_addr.s_addr == dst->sin_addr.s_addr) {
+ printf("set: proxy entry exists for non 802 device\n");
+ return (1);
}
- if (sdl->sdl_family != AF_LINK) {
+ if ((sdl->sdl_family != AF_LINK) ||
+ (rtm->rtm_flags & RTF_GATEWAY) ||
+ !valid_type(sdl->sdl_type)) {
printf("cannot intuit interface index and type for %s\n", host);
return (1);
}
@@ -436,7 +432,11 @@ delete(char *host, int do_proxy)
dst = getaddr(host);
if (dst == NULL)
return (1);
- dst->sin_other = do_proxy;
+
+ /*
+ * Perform a regular entry delete first.
+ */
+ flags &= ~RTF_ANNOUNCE;
/*
* setup the data structure to notify the kernel
@@ -471,11 +471,16 @@ delete(char *host, int do_proxy)
break;
}
- if (dst->sin_other & SIN_PROXY) {
+ /*
+ * Regualar entry delete failed, now check if there
+ * is a proxy-arp entry to remove.
+ */
+ if (flags & RTF_ANNOUNCE) {
fprintf(stderr, "delete: cannot locate %s\n",host);
return (1);
}
- dst->sin_other = SIN_PROXY;
+
+ flags |= RTF_ANNOUNCE;
}
rtm->rtm_flags |= RTF_LLDATA;
if (rtmsg(RTM_DELETE, dst, NULL) != NULL) {
@@ -485,6 +490,7 @@ delete(char *host, int do_proxy)
return (1);
}
+
/*
* Search the arp table and do some action on matching entries
*/
OpenPOWER on IntegriCloud