Module Name: src Committed By: christos Date: Fri Jul 6 00:50:05 UTC 2018
Modified Files: src/usr.sbin/arp: arp.8 arp.c Log Message: Add an "auto" keyword to auto-determine the link address from the inet addr. To generate a diff of this commit: cvs rdiff -u -r1.23 -r1.24 src/usr.sbin/arp/arp.8 cvs rdiff -u -r1.59 -r1.60 src/usr.sbin/arp/arp.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.sbin/arp/arp.8 diff -u src/usr.sbin/arp/arp.8:1.23 src/usr.sbin/arp/arp.8:1.24 --- src/usr.sbin/arp/arp.8:1.23 Mon Jul 8 00:31:12 2013 +++ src/usr.sbin/arp/arp.8 Thu Jul 5 20:50:05 2018 @@ -1,4 +1,4 @@ -.\" $NetBSD: arp.8,v 1.23 2013/07/08 04:31:12 apb Exp $ +.\" $NetBSD: arp.8,v 1.24 2018/07/06 00:50:05 christos Exp $ .\" .\" Copyright (c) 1985, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" from: @(#)arp.8 8.2 (Berkeley) 4/27/95 .\" -.Dd July 8, 2013 +.Dd July 5, 2018 .Dt ARP 8 .Os .Sh NAME @@ -132,11 +132,19 @@ server, responding to requests for .Ar hostname even though the host address is not its own. +.Pp If the word .Cm proxy is also given, the published entry will be a .Dq proxy only entry. +In this case the +.Ar ether_addr +can be given as +.Cm auto +in which case the interfaces on this host will be examined, +and if one of them is found to occupy the same subnet, its +Ethernet address will be used. .It Fl v Display verbose information when adding or deleting .Tn ARP Index: src/usr.sbin/arp/arp.c diff -u src/usr.sbin/arp/arp.c:1.59 src/usr.sbin/arp/arp.c:1.60 --- src/usr.sbin/arp/arp.c:1.59 Fri Jun 8 00:24:12 2018 +++ src/usr.sbin/arp/arp.c Thu Jul 5 20:50:05 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: arp.c,v 1.59 2018/06/08 04:24:12 nonaka Exp $ */ +/* $NetBSD: arp.c,v 1.60 2018/07/06 00:50:05 christos Exp $ */ /* * Copyright (c) 1984, 1993 @@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1984, 19 #if 0 static char sccsid[] = "@(#)arp.c 8.3 (Berkeley) 4/28/95"; #else -__RCSID("$NetBSD: arp.c,v 1.59 2018/06/08 04:24:12 nonaka Exp $"); +__RCSID("$NetBSD: arp.c,v 1.60 2018/07/06 00:50:05 christos Exp $"); #endif #endif /* not lint */ @@ -84,14 +84,14 @@ static void dump(uint32_t); static void delete(const char *, const char *); static void sdl_print(const struct sockaddr_dl *); static int getifname(u_int16_t, char *, size_t); -static int atosdl(const char *s, struct sockaddr_dl *sdl); +static int atosdl(const char *, struct sockaddr_dl *); static int file(const char *); static void get(const char *); static int getinetaddr(const char *, struct in_addr *); static int getsocket(void); -static struct rt_msghdr * - rtmsg(const int, const int, struct rt_msghdr *, - const struct sockaddr_inarp *, const struct sockaddr_dl *); +static int getetheraddr(struct in_addr, struct sockaddr_dl *); +static struct rt_msghdr * rtmsg(const int, const int, struct rt_msghdr *, + const struct sockaddr_inarp *, const struct sockaddr_dl *); static int set(int, char **); static void usage(void) __dead; @@ -278,7 +278,7 @@ set(int argc, char **argv) if (getinetaddr(host, &sin_m.sin_addr) == -1) return (1); - if (atosdl(eaddr, &sdl_m)) + if (!strcmp(eaddr, "auto") && atosdl(eaddr, &sdl_m)) warnx("invalid link-level address '%s'", eaddr); doing_proxy = flags = export_only = expire_time = 0; for (; argc-- > 0; argv++) { @@ -309,6 +309,10 @@ set(int argc, char **argv) } } + if (doing_proxy && !strcmp(eaddr, "auto")) { + if (getetheraddr(sin_m.sin_addr, &sdl_m) == -1) + return 1; + } tryagain: rtm = rtmsg(s, RTM_GET, NULL, &sin_m, &sdl_m); if (rtm == NULL) { @@ -706,7 +710,7 @@ getifname(u_int16_t ifindex, char *ifnam { int i; struct ifaddrs *addr; - const struct sockaddr_dl *sdl = NULL; + const struct sockaddr_dl *sdl; static struct ifaddrs* ifaddrs = NULL; if (ifaddrs == NULL) { @@ -729,3 +733,51 @@ getifname(u_int16_t ifindex, char *ifnam return -1; } + +static int +getetheraddr(struct in_addr ipaddr, struct sockaddr_dl *sdl) +{ + struct ifaddrs *ifaddrs, *addr; + in_addr_t ina, mask; + char ifname[IFNAMSIZ]; + + if (getifaddrs(&ifaddrs) != 0) { + warn("getifaddrs"); + return -1; + } + + for (addr = ifaddrs; addr; addr = addr->ifa_next) { + if (addr->ifa_addr == NULL || + addr->ifa_addr->sa_family != AF_INET) + continue; + if ((addr->ifa_flags & (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT| + IFF_LOOPBACK|IFF_NOARP)) != (IFF_UP|IFF_BROADCAST)) + continue; + + mask = ((struct sockaddr_in *)(void *)addr->ifa_netmask)->sin_addr.s_addr; + ina = ((struct sockaddr_in *)(void *)addr->ifa_addr)->sin_addr.s_addr; + if ((ipaddr.s_addr & mask) != (ina & mask)) + continue; + strlcpy(ifname, addr->ifa_name, sizeof(ifname)); + break; + } + if (addr == NULL) { + warnx("No interface matched %s", inet_ntoa(ipaddr)); + freeifaddrs(ifaddrs); + return -1; + } + + for (addr = ifaddrs; addr; addr = addr->ifa_next) { + if (addr->ifa_addr == NULL || + addr->ifa_addr->sa_family != AF_LINK) + continue; + if (strcmp(ifname, addr->ifa_name) != 0) + continue; + memcpy(sdl, addr->ifa_addr, sizeof(*sdl)); + freeifaddrs(ifaddrs); + return 0; + } + warnx("No link address for interface %s", ifname); + freeifaddrs(ifaddrs); + return -1; +}