diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index 0870e6589bc7..9fee24e11e4d 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -248,6 +248,11 @@ the system will not attempt to transmit messages through that interface. If possible, the interface will be reset to disable reception as well. This action does not automatically disable routes using the interface. +.It Cm eui64 +(Inet6 only.) +Fill interface index +.Pq lowermost 64bit of an IPv6 address +automatically. .\" .It Cm ipdst .\" This is used to specify an Internet host who is willing to receive .\" ip packets encapsulating NS packets bound for a remote network. diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index 62ccdc264763..9f37f9903aed 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -98,6 +98,7 @@ static const char rcsid[] = #include #include #include +#include #include "ifconfig.h" @@ -175,6 +176,7 @@ c_func setip6flags; c_func setip6pltime; c_func setip6vltime; c_func2 setip6lifetime; +c_func setip6eui64; #endif c_func setifipdst; c_func setifflags, setifmetric, setifmtu, setifcap; @@ -222,6 +224,7 @@ struct cmd { { "-autoconf", -IN6_IFF_AUTOCONF, setip6flags }, { "pltime", NEXTARG, setip6pltime }, { "vltime", NEXTARG, setip6vltime }, + { "eui64", 0, setip6eui64 }, #endif { "range", NEXTARG, setatrange }, { "phase", NEXTARG, setatphase }, @@ -898,6 +901,40 @@ setip6lifetime(const char *cmd, const char *val, int s, in6_addreq.ifra_lifetime.ia6t_pltime = newval; } } + +void +setip6eui64(const char *cmd, int dummy __unused, int s, + const struct afswtch *afp) +{ + struct ifaddrs *ifap, *ifa; + const struct sockaddr_in6 *sin6 = NULL; + const struct in6_addr *lladdr = NULL; + struct in6_addr *in6; + + if (afp->af_af != AF_INET6) + errx(EXIT_FAILURE, "%s not allowed for the AF", cmd); + in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr; + if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0) + errx(EXIT_FAILURE, "interface index is already filled"); + if (getifaddrs(&ifap) != 0) + err(EXIT_FAILURE, "getifaddrs"); + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (ifa->ifa_addr->sa_family == AF_INET6 && + strcmp(ifa->ifa_name, name) == 0) { + sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr; + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + lladdr = &sin6->sin6_addr; + break; + } + } + } + if (!lladdr) + errx(EXIT_FAILURE, "could not determine link local address"); + + memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8); + + freeifaddrs(ifap); +} #endif void