]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet6/nd6_send.c
xnu-4903.270.47.tar.gz
[apple/xnu.git] / bsd / netinet6 / nd6_send.c
index 916607bd6368e1a733d81a211b19868e2135a5c9..cd59d78dd461143efecd7e0e149a157fc6e69e77 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2013-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
 #include <netinet6/ip6_var.h>
 #include <netinet6/nd6.h>
 
-SYSCTL_DECL(_net_inet6);       /* Note: Not in any common header. */
+#if CONFIG_MACF
+#include <sys/kauth.h>
+#include <security/mac_framework.h>
+#endif
 
-SYSCTL_NODE(_net_inet6, OID_AUTO, send, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
-       "IPv6 Secure Neighbor Discovery");
+SYSCTL_DECL(_net_inet6);        /* Note: Not in any common header. */
 
-static int nd6_send_opmode = ND6_SEND_OPMODE_DISABLED;
+SYSCTL_NODE(_net_inet6, OID_AUTO, send, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
+    "IPv6 Secure Neighbor Discovery");
 
-SYSCTL_INT(_net_inet6_send, OID_AUTO, opstate, CTLFLAG_RD | CTLFLAG_LOCKED,
-       &nd6_send_opstate, 0, "current SEND operating state");
+static int nd6_send_opmode = ND6_SEND_OPMODE_CGA_QUIET;
+SYSCTL_INT(_net_inet6_send, OID_AUTO, opmode, CTLFLAG_RW | CTLFLAG_LOCKED,
+    &nd6_send_opmode, 0, "configured SEND operating mode");
 
 int nd6_send_opstate = ND6_SEND_OPMODE_DISABLED;
-SYSCTL_INT(_net_inet6_send, OID_AUTO, opmode, CTLFLAG_RW | CTLFLAG_LOCKED,
-       &nd6_send_opmode, 0, "configured SEND operating mode");
+SYSCTL_INT(_net_inet6_send, OID_AUTO, opstate, CTLFLAG_RD | CTLFLAG_LOCKED,
+    &nd6_send_opstate, 0, "current SEND operating state");
 
 static int sysctl_cga_parameters SYSCTL_HANDLER_ARGS;
 
 SYSCTL_PROC(_net_inet6_send, OID_AUTO, cga_parameters,
-       CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0,
-       sysctl_cga_parameters, "S,nd6_send_nodecfg", "");
+    CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0,
+    sysctl_cga_parameters, "S,nd6_send_nodecfg", "");
 
 /*
  * The size of the buffer is sufficient to contain a public key, its size in
@@ -68,9 +72,9 @@ SYSCTL_PROC(_net_inet6_send, OID_AUTO, cga_parameters,
  * scope. This interface is not a public API, so we don't anticipate that the
  * userland and the kernel will be mismatched between ILP32 and LP64.
  */
-#define        SYSCTL_CGA_PARAMETERS_BUFFER_SIZE \
-       2 * (sizeof (u_int16_t) + IN6_CGA_KEY_MAXSIZE) + \
-       sizeof (struct in6_cga_prepare)
+#define SYSCTL_CGA_PARAMETERS_BUFFER_SIZE \
+       (2 * (sizeof (u_int16_t) + IN6_CGA_KEY_MAXSIZE) + \
+       sizeof (struct in6_cga_prepare))
 
 static int
 sysctl_cga_parameters SYSCTL_HANDLER_ARGS
@@ -84,26 +88,39 @@ sysctl_cga_parameters SYSCTL_HANDLER_ARGS
        int error;
        char *buffer;
        u_int16_t u16;
+#if CONFIG_MACF
+       kauth_cred_t cred;
+#endif
 
        namelen = arg2;
        if (namelen != 0) {
                log(LOG_ERR, "%s: name length err [len=%u]\n", __func__,
                    namelen);
-               return (EINVAL);
+               return EINVAL;
        }
 
        if (req->newlen > SYSCTL_CGA_PARAMETERS_BUFFER_SIZE) {
                log(LOG_ERR, "%s: input buffer size error [len=%u]\n", __func__,
                    req->newlen);
-               return (EINVAL);
+               return EINVAL;
+       }
+
+#if CONFIG_MACF
+       cred = kauth_cred_proc_ref(current_proc());
+       error = mac_system_check_info(cred, "net.inet6.send.cga_parameters");
+       kauth_cred_unref(&cred);
+       if (error != 0) {
+               log(LOG_ERR, "%s: mac_system_check_info denied.\n", __func__);
+               return EPERM;
        }
+#endif
 
        MALLOC(buffer, char *, SYSCTL_CGA_PARAMETERS_BUFFER_SIZE, M_IP6CGA,
-           M_WAITOK);
+           M_WAITOK | M_ZERO);
        if (buffer == NULL) {
                log(LOG_ERR, "%s: could not allocate marshaling buffer.\n",
                    __func__);
-               return (ENOMEM);
+               return ENOMEM;
        }
 
        in6_cga_node_lock();
@@ -111,27 +128,30 @@ sysctl_cga_parameters SYSCTL_HANDLER_ARGS
        if (req->oldptr != USER_ADDR_NULL && req->oldlen > 0) {
                oldp = buffer;
                fin = &buffer[SYSCTL_CGA_PARAMETERS_BUFFER_SIZE];
-               if (req->oldlen < SYSCTL_CGA_PARAMETERS_BUFFER_SIZE)
+               if (req->oldlen < SYSCTL_CGA_PARAMETERS_BUFFER_SIZE) {
                        fin = &buffer[req->oldlen];
+               }
 
                in6_cga_query(&cfg);
                iov = &cfg.cga_pubkey;
                if (iov->iov_len > 0) {
                        VERIFY(iov->iov_len < UINT16_MAX);
 
-                       if (&oldp[sizeof (cfg.cga_prepare)] <= fin)
+                       if (&oldp[sizeof(cfg.cga_prepare)] <= fin) {
                                bcopy(&cfg.cga_prepare, oldp,
-                                   sizeof (cfg.cga_prepare));
-                       oldp += sizeof (cfg.cga_prepare);
+                                   sizeof(cfg.cga_prepare));
+                       }
+                       oldp += sizeof(cfg.cga_prepare);
 
-                       if (&oldp[sizeof (u16)] < fin) {
+                       if (&oldp[sizeof(u16)] < fin) {
                                u16 = (u_int16_t) iov->iov_len;
-                               bcopy(&u16, oldp, sizeof (u16));
+                               bcopy(&u16, oldp, sizeof(u16));
                        }
-                       oldp += sizeof (u16);
+                       oldp += sizeof(u16);
 
-                       if (&oldp[iov->iov_len] < fin)
+                       if (&oldp[iov->iov_len] < fin) {
                                bcopy(iov->iov_base, oldp, iov->iov_len);
+                       }
                        oldp += iov->iov_len;
 
                        if (oldp > fin) {
@@ -144,16 +164,19 @@ sysctl_cga_parameters SYSCTL_HANDLER_ARGS
                }
 
                error = SYSCTL_OUT(req, buffer, oldp - buffer);
-               if (error)
+               if (error) {
                        goto done;
+               }
        }
 
-       if (req->newptr == USER_ADDR_NULL)
+       if (req->newptr == USER_ADDR_NULL) {
                goto done;
+       }
 
        error = proc_suser(current_proc());
-       if (error)
+       if (error) {
                goto done;
+       }
 
        if (req->newlen == 0) {
                in6_cga_stop();
@@ -162,21 +185,23 @@ sysctl_cga_parameters SYSCTL_HANDLER_ARGS
        }
 
        error = SYSCTL_IN(req, buffer, req->newlen);
-       if (error)
+       if (error) {
                goto done;
+       }
 
        newp = buffer;
        fin = &buffer[req->newlen];
 
        bzero(&cfg, sizeof cfg);
 
-       if (&newp[sizeof (cfg.cga_prepare)] <= fin)
-               bcopy(newp, &cfg.cga_prepare, sizeof (cfg.cga_prepare));
-       newp += sizeof (cfg.cga_prepare);
+       if (&newp[sizeof(cfg.cga_prepare)] <= fin) {
+               bcopy(newp, &cfg.cga_prepare, sizeof(cfg.cga_prepare));
+       }
+       newp += sizeof(cfg.cga_prepare);
 
        iov = &cfg.cga_privkey;
-       if (&newp[sizeof (u16)] < fin) {
-               bcopy(newp, &u16, sizeof (u16));
+       if (&newp[sizeof(u16)] < fin) {
+               bcopy(newp, &u16, sizeof(u16));
                iov->iov_len = u16;
 
                if (iov->iov_len > IN6_CGA_KEY_MAXSIZE) {
@@ -184,14 +209,14 @@ sysctl_cga_parameters SYSCTL_HANDLER_ARGS
                        goto done;
                }
        }
-       newp += sizeof (u16);
+       newp += sizeof(u16);
 
        iov->iov_base = newp;
        newp += iov->iov_len;
 
        iov = &cfg.cga_pubkey;
-       if (&newp[sizeof (u16)] < fin) {
-               bcopy(newp, &u16, sizeof (u16));
+       if (&newp[sizeof(u16)] < fin) {
+               bcopy(newp, &u16, sizeof(u16));
                iov->iov_len = u16;
 
                if (iov->iov_len > IN6_CGA_KEY_MAXSIZE) {
@@ -199,7 +224,7 @@ sysctl_cga_parameters SYSCTL_HANDLER_ARGS
                        goto done;
                }
        }
-       newp += sizeof (u16);
+       newp += sizeof(u16);
 
        iov->iov_base = newp;
        newp += iov->iov_len;
@@ -212,16 +237,17 @@ sysctl_cga_parameters SYSCTL_HANDLER_ARGS
        }
 
        error = in6_cga_start(&cfg);
-       if (!error)
+       if (!error) {
                nd6_send_opstate = nd6_send_opmode;
-       else
+       } else {
                log(LOG_ERR, "%s: in6_cga_start error=%d.\n", __func__,
                    error);
+       }
 
 done:
        in6_cga_node_unlock();
        FREE(buffer, M_IP6CGA);
-       return (error);
+       return error;
 }
 
 /* End of file */