]> git.saurik.com Git - apple/network_cmds.git/blobdiff - ifconfig.tproj/af_inet6.c
network_cmds-606.40.2.tar.gz
[apple/network_cmds.git] / ifconfig.tproj / af_inet6.c
index 54d039a1f66d4dc2d3f120b36916fb1157307e37..c32c5c0bbb3e5e2cc72519bafdc6c246b0a63a33 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * Copyright (c) 2009-2017, 2020 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
 /*
  * Copyright (c) 1983, 1993
  *     The Regents of the University of California.  All rights reserved.
  * SUCH DAMAGE.
  */
 
-#ifndef lint
-static const char rcsid[] =
-  "$FreeBSD: src/sbin/ifconfig/af_inet6.c,v 1.6.6.1 2008/11/25 02:59:29 kensmith Exp $";
-#endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
@@ -38,6 +62,7 @@ static const char rcsid[] =
 #include <net/if.h>
 
 #include <err.h>
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -56,6 +81,10 @@ static const char rcsid[] =
 
 #include "ifconfig.h"
 
+#define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \
+       "\004IFDISABLED\005DONT_SET_IFROUTE\006PROXY_PREFIXES" \
+       "\007IGNORE_NA\010INSECURE\011REPLICATED\012DAD"
+
 static struct in6_ifreq in6_ridreq;
 static struct in6_aliasreq in6_addreq = 
   { { 0 }, 
@@ -82,6 +111,29 @@ setifprefixlen(const char *addr, int dummy __unused, int s,
        explicit_prefix = 1;
 }
 
+static void
+setnd6flags(const char *dummyaddr __unused, int d, int s,
+    const struct afswtch *afp)
+{
+       struct in6_ndireq nd;
+       int error;
+
+       memset(&nd, 0, sizeof(nd));
+       strlcpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
+       error = ioctl(s, SIOCGIFINFO_IN6, &nd);
+       if (error) {
+               warn("ioctl(SIOCGIFINFO_IN6)");
+               return;
+       }
+       if (d < 0)
+               nd.ndi.flags &= ~(-d);
+       else
+               nd.ndi.flags |= d;
+       error = ioctl(s, SIOCSIFINFO_FLAGS, (caddr_t)&nd);
+       if (error)
+               warn("ioctl(SIOCSIFINFO_FLAGS)");
+}
+
 static void
 setip6flags(const char *dummyaddr __unused, int flag, int dummysoc __unused,
     const struct afswtch *afp)
@@ -195,7 +247,7 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
        if (sin == NULL)
                return;
 
-       strncpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name));
+       strlcpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name));
        if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
                warn("socket(AF_INET6,SOCK_DGRAM)");
                return;
@@ -277,6 +329,8 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
                printf("anycast ");
        if ((flags6 & IN6_IFF_TENTATIVE) != 0)
                printf("tentative ");
+       if ((flags6 & IN6_IFF_OPTIMISTIC) != 0)
+               printf("optimistic ");
        if ((flags6 & IN6_IFF_DUPLICATED) != 0)
                printf("duplicated ");
        if ((flags6 & IN6_IFF_DETACHED) != 0)
@@ -287,6 +341,12 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
                printf("autoconf ");
        if ((flags6 & IN6_IFF_TEMPORARY) != 0)
                printf("temporary ");
+       if ((flags6 & IN6_IFF_DYNAMIC) != 0)
+               printf("dynamic ");
+       if ((flags6 & IN6_IFF_SECURED) != 0)
+               printf("secured ");
+       if ((flags6 & IN6_IFF_CLAT46) != 0)
+               printf("clat46 ");
 
         if (scopeid)
                printf("scopeid 0x%x ", scopeid);
@@ -412,19 +472,19 @@ sec2str(time_t total)
 
                if (days) {
                        first = 0;
-                       p += sprintf(p, "%dd", days);
+                       p += snprintf(p, sizeof(result) - (p - result), "%dd", days);
                }
                if (!first || hours) {
                        first = 0;
-                       p += sprintf(p, "%dh", hours);
+                       p += snprintf(p, sizeof(result) - (p - result), "%dh", hours);
                }
                if (!first || mins) {
                        first = 0;
-                       p += sprintf(p, "%dm", mins);
+                       p += snprintf(p, sizeof(result) - (p - result), "%dm", mins);
                }
-               sprintf(p, "%ds", secs);
+               snprintf(p, sizeof(result) - (p - result), "%ds", secs);
        } else
-               sprintf(result, "%lu", (unsigned long)total);
+               snprintf(result, sizeof(result), "%lu", (unsigned long)total);
 
        return(result);
 }
@@ -450,7 +510,7 @@ in6_status_tunnel(int s)
        const struct sockaddr *sa = (const struct sockaddr *) &in6_ifr.ifr_addr;
 
        memset(&in6_ifr, 0, sizeof(in6_ifr));
-       strncpy(in6_ifr.ifr_name, name, IFNAMSIZ);
+       strlcpy(in6_ifr.ifr_name, name, sizeof(in6_ifr.ifr_name));
 
        if (ioctl(s, SIOCGIFPSRCADDR_IN6, (caddr_t)&in6_ifr) < 0)
                return;
@@ -473,13 +533,41 @@ in6_status_tunnel(int s)
        printf("\ttunnel inet6 %s --> %s\n", src, dst);
 }
 
+static void
+nd6_status(int s)
+{
+       struct in6_ndireq nd;
+       int s6;
+       int error;
+
+       memset(&nd, 0, sizeof(nd));
+       strlcpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
+       if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+               if (errno != EPROTONOSUPPORT)
+                       warn("socket(AF_INET6, SOCK_DGRAM)");
+               return;
+       }
+       error = ioctl(s6, SIOCGIFINFO_IN6, &nd);
+       if (error) {
+               if (errno != EPFNOSUPPORT && errno != EINVAL)
+                       warn("ioctl(SIOCGIFINFO_IN6)");
+               close(s6);
+               return;
+       }
+       close(s6);
+       if (nd.ndi.flags == 0)
+               return;
+       printb("\tnd6 options", (unsigned int)nd.ndi.flags, ND6BITS);
+       putchar('\n');
+}
+
 static void
 in6_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres)
 {
        struct in6_aliasreq in6_addreq; 
 
        memset(&in6_addreq, 0, sizeof(in6_addreq));
-       strncpy(in6_addreq.ifra_name, name, IFNAMSIZ);
+       strlcpy(in6_addreq.ifra_name, name, sizeof(in6_addreq.ifra_name));
        memcpy(&in6_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len);
        memcpy(&in6_addreq.ifra_dstaddr, dstres->ai_addr,
            dstres->ai_addr->sa_len);
@@ -488,18 +576,142 @@ in6_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres)
                warn("SIOCSIFPHYADDR_IN6");
 }
 
+#ifndef IPV6_ROUTER_MODE_EXCLUSIVE
+#define IPV6_ROUTER_MODE_DISABLED       0
+#define IPV6_ROUTER_MODE_EXCLUSIVE      1
+#define IPV6_ROUTER_MODE_HYBRID         2
+#endif /* IPV6_ROUTER_MODE_EXCLUSIVE */
+
+static void
+in6_set_router(int s, int enable)
+{
+       struct ifreq ifr;
+
+       bzero(&ifr, sizeof (ifr));
+       strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       ifr.ifr_intval = (enable == 0)
+               ? IPV6_ROUTER_MODE_DISABLED
+               : IPV6_ROUTER_MODE_EXCLUSIVE;
+
+       if (ioctl(s, SIOCSETROUTERMODE_IN6, &ifr) < 0)
+               warn("SIOCSETROUTERMODE_IN6");
+}
+
+static int
+routermode_from_string(char * str, int *mode_p)
+{
+       int     success = 1;
+
+       if (strcasecmp(str, "exclusive") == 0 ||
+           strcasecmp(str, "enabled") == 0) {
+               *mode_p = IPV6_ROUTER_MODE_EXCLUSIVE;
+       } else if (strcasecmp(str, "hybrid") == 0) {
+               *mode_p = IPV6_ROUTER_MODE_HYBRID;
+       } else if (strcasecmp(str, "disabled") == 0) {
+               *mode_p = IPV6_ROUTER_MODE_DISABLED;
+       } else {
+               success = 0;
+       }
+       return (success);
+}
+
+static const char *
+routermode_string(int mode)
+{
+       const char *    str;
+
+       switch (mode) {
+       case IPV6_ROUTER_MODE_EXCLUSIVE:
+               str = "enabled";
+               break;
+       case IPV6_ROUTER_MODE_HYBRID:
+               str = "hybrid";
+               break;
+       case IPV6_ROUTER_MODE_DISABLED:
+               str = "disabled";
+               break;
+       default:
+               str = "<unknown>";
+               break;
+       }
+       return str;
+}
+
+static int
+in6_routermode(int s, int argc, char *const*argv)
+{
+       struct in6_ifreq        ifr;
+       int                     ret;
+
+       bzero(&ifr, sizeof (ifr));
+       strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       if (argc == 0) {
+               ret = 0;
+#ifndef SIOCGETROUTERMODE_IN6
+#define SIOCGETROUTERMODE_IN6   _IOWR('i', 137, struct in6_ifreq)
+#endif /* SIOCGETROUTERMODE_IN6 */
+               if (ioctl(s, SIOCGETROUTERMODE_IN6, &ifr) < 0) {
+                       if (argv != NULL) {
+                               warn("SIOCGETROUTERMODE_IN6");
+                       }
+               } else {
+                       /* argv is NULL if we're called from status() */
+                       printf("%s%s\n",
+                              (argv == NULL) ? "\troutermode6: " : "",
+                              routermode_string(ifr.ifr_intval));
+               }
+               ret = 0;
+       } else {
+               int mode;
+
+               if (routermode_from_string(argv[0], &mode) == 0) {
+                       errx(EXIT_FAILURE,
+                            "mode '%s' invalid, must be one of "
+                            "disabled, exclusive, or hybrid",
+                            argv[0]);
+               }
+               ifr.ifr_intval = mode;
+               if (ioctl(s, SIOCSETROUTERMODE_IN6, &ifr) < 0) {
+                       warn("SIOCSETROUTERMODE_IN6");
+               }
+               ret = 1;
+       }
+       return ret;
+}
+
 static struct cmd inet6_cmds[] = {
        DEF_CMD_ARG("prefixlen",                        setifprefixlen),
        DEF_CMD("anycast",      IN6_IFF_ANYCAST,        setip6flags),
        DEF_CMD("tentative",    IN6_IFF_TENTATIVE,      setip6flags),
        DEF_CMD("-tentative",   -IN6_IFF_TENTATIVE,     setip6flags),
+       /* RFC 4429, section 3.1, says:
+        * "Optimistic DAD SHOULD NOT be used for manually entered
+        * addresses."
+        * it's not a MUST...
+        */
+       DEF_CMD("optimistic",   IN6_IFF_OPTIMISTIC,     setip6flags),
+       DEF_CMD("-optimistic",  -IN6_IFF_OPTIMISTIC,    setip6flags),
        DEF_CMD("deprecated",   IN6_IFF_DEPRECATED,     setip6flags),
        DEF_CMD("-deprecated", -IN6_IFF_DEPRECATED,     setip6flags),
        DEF_CMD("autoconf",     IN6_IFF_AUTOCONF,       setip6flags),
        DEF_CMD("-autoconf",    -IN6_IFF_AUTOCONF,      setip6flags),
+       DEF_CMD("nud",          ND6_IFF_PERFORMNUD,     setnd6flags),
+       DEF_CMD("-nud",         -ND6_IFF_PERFORMNUD,    setnd6flags),
+       DEF_CMD("ifdisabled",   ND6_IFF_IFDISABLED,     setnd6flags),
+       DEF_CMD("-ifdisabled",  -ND6_IFF_IFDISABLED,    setnd6flags),
+       DEF_CMD("replicated",   ND6_IFF_REPLICATED,     setnd6flags),
+       DEF_CMD("-replicated",  -ND6_IFF_REPLICATED,    setnd6flags),
+       DEF_CMD("proxy_prefixes", ND6_IFF_PROXY_PREFIXES,       setnd6flags),
+       DEF_CMD("-proxy_prefixes", -ND6_IFF_PROXY_PREFIXES,     setnd6flags),
+       DEF_CMD("insecure",     ND6_IFF_INSECURE,       setnd6flags),
+       DEF_CMD("-insecure",    -ND6_IFF_INSECURE,      setnd6flags),
        DEF_CMD_ARG("pltime",                           setip6pltime),
        DEF_CMD_ARG("vltime",                           setip6vltime),
        DEF_CMD("eui64",        0,                      setip6eui64),
+       DEF_CMD("secured",      IN6_IFF_SECURED,        setip6flags),
+       DEF_CMD("-secured",     -IN6_IFF_SECURED,       setip6flags),
+       DEF_CMD("dad",          ND6_IFF_DAD,            setnd6flags),
+       DEF_CMD("-dad",         -ND6_IFF_DAD,           setnd6flags),
 };
 
 static struct afswtch af_inet6 = {
@@ -508,12 +720,15 @@ static struct afswtch af_inet6 = {
        .af_status      = in6_status,
        .af_getaddr     = in6_getaddr,
        .af_getprefix   = in6_getprefix,
+       .af_other_status = nd6_status,
        .af_postproc    = in6_postproc,
        .af_status_tunnel = in6_status_tunnel,
        .af_settunnel   = in6_set_tunnel,
+       .af_setrouter   = in6_set_router,
+       .af_routermode  = in6_routermode,
        .af_difaddr     = SIOCDIFADDR_IN6,
        .af_aifaddr     = SIOCAIFADDR_IN6,
-       .af_ridreq      = &in6_addreq,
+       .af_ridreq      = &in6_ridreq,
        .af_addreq      = &in6_addreq,
 };