Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/arp Add an "auto" keyword to auto-determine the lin...



details:   https://anonhg.NetBSD.org/src/rev/1c455326a067
branches:  trunk
changeset: 324476:1c455326a067
user:      christos <christos%NetBSD.org@localhost>
date:      Fri Jul 06 00:50:05 2018 +0000

description:
Add an "auto" keyword to auto-determine the link address from the inet addr.

diffstat:

 usr.sbin/arp/arp.8 |  12 +++++++-
 usr.sbin/arp/arp.c |  68 +++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 70 insertions(+), 10 deletions(-)

diffs (156 lines):

diff -r 8ab574fa7df8 -r 1c455326a067 usr.sbin/arp/arp.8
--- a/usr.sbin/arp/arp.8        Thu Jul 05 19:46:58 2018 +0000
+++ b/usr.sbin/arp/arp.8        Fri Jul 06 00:50:05 2018 +0000
@@ -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 @@
 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
diff -r 8ab574fa7df8 -r 1c455326a067 usr.sbin/arp/arp.c
--- a/usr.sbin/arp/arp.c        Thu Jul 05 19:46:58 2018 +0000
+++ b/usr.sbin/arp/arp.c        Fri Jul 06 00:50:05 2018 +0000
@@ -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 @@
 #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 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 @@
 
        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 @@
                }
 
        }
+       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 @@
 {
        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 @@
 
        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;
+}



Home | Main Index | Thread Index | Old Index