]> 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 2fedbb3428e35fd3eb59ac3b1d5bec8e28e995cc..c32c5c0bbb3e5e2cc72519bafdc6c246b0a63a33 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2017 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2017, 2020 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -119,7 +119,7 @@ setnd6flags(const char *dummyaddr __unused, int d, int s,
        int error;
 
        memset(&nd, 0, sizeof(nd));
-       strncpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
+       strlcpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
        error = ioctl(s, SIOCGIFINFO_IN6, &nd);
        if (error) {
                warn("ioctl(SIOCGIFINFO_IN6)");
@@ -247,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;
@@ -510,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;
@@ -541,7 +541,7 @@ nd6_status(int s)
        int error;
 
        memset(&nd, 0, sizeof(nd));
-       strncpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
+       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)");
@@ -567,7 +567,7 @@ 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);
@@ -576,19 +576,109 @@ 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));
-       strncpy(ifr.ifr_name, name, IFNAMSIZ);
-       ifr.ifr_intval = enable;
+       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),
@@ -635,6 +725,7 @@ static struct afswtch af_inet6 = {
        .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_ridreq,