2 * Copyright (c) 2013 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/types.h>
30 #include <sys/malloc.h>
32 #include <sys/sysctl.h>
33 #include <sys/syslog.h>
35 #include <libkern/crypto/sha1.h>
39 #include <netinet/in.h>
40 #include <netinet6/in6_var.h>
41 #include <netinet/ip6.h>
42 #include <netinet6/ip6_var.h>
43 #include <netinet6/nd6.h>
45 SYSCTL_DECL(_net_inet6
); /* Note: Not in any common header. */
47 SYSCTL_NODE(_net_inet6
, OID_AUTO
, send
, CTLFLAG_RW
| CTLFLAG_LOCKED
, 0,
48 "IPv6 Secure Neighbor Discovery");
50 static int nd6_send_opmode
= ND6_SEND_OPMODE_DISABLED
;
52 SYSCTL_INT(_net_inet6_send
, OID_AUTO
, opstate
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
53 &nd6_send_opstate
, 0, "current SEND operating state");
55 int nd6_send_opstate
= ND6_SEND_OPMODE_DISABLED
;
56 SYSCTL_INT(_net_inet6_send
, OID_AUTO
, opmode
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
57 &nd6_send_opmode
, 0, "configured SEND operating mode");
59 static int sysctl_cga_parameters SYSCTL_HANDLER_ARGS
;
61 SYSCTL_PROC(_net_inet6_send
, OID_AUTO
, cga_parameters
,
62 CTLTYPE_OPAQUE
| CTLFLAG_RW
| CTLFLAG_LOCKED
, 0, 0,
63 sysctl_cga_parameters
, "S,nd6_send_nodecfg", "");
66 * The size of the buffer is sufficient to contain a public key, its size in
67 * machine binary type for the kernel, and the CGA precalc for the global
68 * scope. This interface is not a public API, so we don't anticipate that the
69 * userland and the kernel will be mismatched between ILP32 and LP64.
71 #define SYSCTL_CGA_PARAMETERS_BUFFER_SIZE \
72 2 * (sizeof (u_int16_t) + IN6_CGA_KEY_MAXSIZE) + \
73 sizeof (struct in6_cga_prepare)
76 sysctl_cga_parameters SYSCTL_HANDLER_ARGS
78 #pragma unused(oidp, arg1)
82 struct in6_cga_nodecfg cfg
;
90 log(LOG_ERR
, "%s: name length err [len=%u]\n", __func__
,
95 if (req
->newlen
> SYSCTL_CGA_PARAMETERS_BUFFER_SIZE
) {
96 log(LOG_ERR
, "%s: input buffer size error [len=%u]\n", __func__
,
101 MALLOC(buffer
, char *, SYSCTL_CGA_PARAMETERS_BUFFER_SIZE
, M_IP6CGA
,
103 if (buffer
== NULL
) {
104 log(LOG_ERR
, "%s: could not allocate marshaling buffer.\n",
111 if (req
->oldptr
!= USER_ADDR_NULL
&& req
->oldlen
> 0) {
113 fin
= &buffer
[SYSCTL_CGA_PARAMETERS_BUFFER_SIZE
];
114 if (req
->oldlen
< SYSCTL_CGA_PARAMETERS_BUFFER_SIZE
)
115 fin
= &buffer
[req
->oldlen
];
118 iov
= &cfg
.cga_pubkey
;
119 if (iov
->iov_len
> 0) {
120 VERIFY(iov
->iov_len
< UINT16_MAX
);
122 if (&oldp
[sizeof (cfg
.cga_prepare
)] <= fin
)
123 bcopy(&cfg
.cga_prepare
, oldp
,
124 sizeof (cfg
.cga_prepare
));
125 oldp
+= sizeof (cfg
.cga_prepare
);
127 if (&oldp
[sizeof (u16
)] < fin
) {
128 u16
= (u_int16_t
) iov
->iov_len
;
129 bcopy(&u16
, oldp
, sizeof (u16
));
131 oldp
+= sizeof (u16
);
133 if (&oldp
[iov
->iov_len
] < fin
)
134 bcopy(iov
->iov_base
, oldp
, iov
->iov_len
);
135 oldp
+= iov
->iov_len
;
138 req
->oldlen
= oldp
- buffer
;
139 log(LOG_ERR
, "%s: marshalled data too large.\n",
146 error
= SYSCTL_OUT(req
, buffer
, oldp
- buffer
);
151 if (req
->newptr
== USER_ADDR_NULL
)
154 error
= proc_suser(current_proc());
158 if (req
->newlen
== 0) {
160 nd6_send_opstate
= ND6_SEND_OPMODE_DISABLED
;
164 error
= SYSCTL_IN(req
, buffer
, req
->newlen
);
169 fin
= &buffer
[req
->newlen
];
171 bzero(&cfg
, sizeof cfg
);
173 if (&newp
[sizeof (cfg
.cga_prepare
)] <= fin
)
174 bcopy(newp
, &cfg
.cga_prepare
, sizeof (cfg
.cga_prepare
));
175 newp
+= sizeof (cfg
.cga_prepare
);
177 iov
= &cfg
.cga_privkey
;
178 if (&newp
[sizeof (u16
)] < fin
) {
179 bcopy(newp
, &u16
, sizeof (u16
));
182 if (iov
->iov_len
> IN6_CGA_KEY_MAXSIZE
) {
187 newp
+= sizeof (u16
);
189 iov
->iov_base
= newp
;
190 newp
+= iov
->iov_len
;
192 iov
= &cfg
.cga_pubkey
;
193 if (&newp
[sizeof (u16
)] < fin
) {
194 bcopy(newp
, &u16
, sizeof (u16
));
197 if (iov
->iov_len
> IN6_CGA_KEY_MAXSIZE
) {
202 newp
+= sizeof (u16
);
204 iov
->iov_base
= newp
;
205 newp
+= iov
->iov_len
;
208 log(LOG_ERR
, "%s: input too large [octets=%ld].\n", __func__
,
214 error
= in6_cga_start(&cfg
);
216 nd6_send_opstate
= nd6_send_opmode
;
218 log(LOG_ERR
, "%s: in6_cga_start error=%d.\n", __func__
,
222 in6_cga_node_unlock();
223 FREE(buffer
, M_IP6CGA
);