summaryrefslogtreecommitdiffstats
path: root/usr.sbin/arp/arp.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/arp/arp.c')
-rw-r--r--usr.sbin/arp/arp.c50
1 files changed, 34 insertions, 16 deletions
diff --git a/usr.sbin/arp/arp.c b/usr.sbin/arp/arp.c
index c8ef3e9..4154c3a1 100644
--- a/usr.sbin/arp/arp.c
+++ b/usr.sbin/arp/arp.c
@@ -370,7 +370,6 @@ set(int argc, char **argv)
if (addr->sin_addr.s_addr != dst->sin_addr.s_addr)
break;
if (sdl->sdl_family == AF_LINK &&
- (rtm->rtm_flags & RTF_LLINFO) &&
!(rtm->rtm_flags & RTF_GATEWAY) &&
valid_type(sdl->sdl_type) )
break;
@@ -426,25 +425,46 @@ delete(char *host, int do_proxy)
struct sockaddr_inarp *addr, *dst;
struct rt_msghdr *rtm;
struct sockaddr_dl *sdl;
+ struct sockaddr_dl sdl_m;
dst = getaddr(host);
if (dst == NULL)
return (1);
dst->sin_other = do_proxy;
+
+ /*
+ * setup the data structure to notify the kernel
+ * it is the ARP entry the RTM_GET is interested
+ * in
+ */
+ bzero(&sdl_m, sizeof(sdl_m));
+ sdl_m.sdl_len = sizeof(sdl_m);
+ sdl_m.sdl_family = AF_LINK;
+
for (;;) { /* try twice */
- rtm = rtmsg(RTM_GET, dst, NULL);
+ 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 &&
- sdl->sdl_family == AF_LINK &&
- (rtm->rtm_flags & RTF_LLINFO) &&
+
+ /*
+ * With the new L2/L3 restructure, the route
+ * returned is a prefix route. The important
+ * piece of information from the previous
+ * RTM_GET is the interface index. In the
+ * case of ECMP, the kernel will traverse
+ * the route group for the given entry.
+ */
+ if (sdl->sdl_family == AF_LINK &&
!(rtm->rtm_flags & RTF_GATEWAY) &&
- valid_type(sdl->sdl_type) )
- break; /* found it */
+ valid_type(sdl->sdl_type) ) {
+ addr->sin_addr.s_addr = dst->sin_addr.s_addr;
+ break;
+ }
+
if (dst->sin_other & SIN_PROXY) {
fprintf(stderr, "delete: cannot locate %s\n",host);
return (1);
@@ -478,7 +498,11 @@ search(u_long addr, action_fn *action)
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_FLAGS;
+#ifdef RTF_LLINFO
mib[5] = RTF_LLINFO;
+#else
+ mib[5] = 0;
+#endif
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
err(1, "route-sysctl-estimate");
if (needed == 0) /* empty table */
@@ -563,15 +587,9 @@ print_entry(struct sockaddr_dl *sdl,
printf(" permanent");
if (addr->sin_other & SIN_PROXY)
printf(" published (proxy only)");
- if (rtm->rtm_addrs & RTA_NETMASK) {
- addr = (struct sockaddr_inarp *)
- (SA_SIZE(sdl) + (char *)sdl);
- if (addr->sin_addr.s_addr == 0xffffffff)
- printf(" published");
- if (addr->sin_len != 8)
- printf("(weird)");
- }
- switch(sdl->sdl_type) {
+ if (rtm->rtm_flags & RTF_ANNOUNCE)
+ printf(" published");
+ switch(sdl->sdl_type) {
case IFT_ETHER:
printf(" [ethernet]");
break;
OpenPOWER on IntegriCloud