]> git.saurik.com Git - apple/xnu.git/blame - bsd/netkey/keysock.c
xnu-4903.221.2.tar.gz
[apple/xnu.git] / bsd / netkey / keysock.c
CommitLineData
39037602
A
1/*
2 * Copyright (c) 2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
1c79356b
A
29/* $KAME: keysock.c,v 1.13 2000/03/25 07:24:13 sumikawa Exp $ */
30
31/*
32 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
33 * All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. Neither the name of the project nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 */
59
1c79356b
A
60/* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
61
1c79356b
A
62#include <sys/types.h>
63#include <sys/param.h>
64#include <sys/systm.h>
65#include <sys/kernel.h>
1c79356b 66#include <sys/sysctl.h>
1c79356b 67#include <sys/mbuf.h>
39236c6e 68#include <sys/mcache.h>
1c79356b 69#include <sys/malloc.h>
1c79356b
A
70#include <sys/socket.h>
71#include <sys/socketvar.h>
72#include <sys/domain.h>
73#include <sys/protosw.h>
74#include <sys/errno.h>
1c79356b 75
91447636 76#include <kern/locks.h>
1c79356b
A
77
78#include <net/raw_cb.h>
79#include <net/route.h>
80
81#include <net/pfkeyv2.h>
82#include <netkey/keydb.h>
83#include <netkey/key.h>
84#include <netkey/keysock.h>
85#include <netkey/key_debug.h>
86
91447636 87extern lck_mtx_t *raw_mtx;
39236c6e 88extern void key_init(struct protosw *, struct domain *);
91447636 89
2d21ac55
A
90struct sockaddr key_dst = { 2, PF_KEY, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,} };
91struct sockaddr key_src = { 2, PF_KEY, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,} };
1c79356b 92
39236c6e 93static void key_dinit(struct domain *);
91447636 94static int key_sendup0(struct rawcb *, struct mbuf *, int);
1c79356b
A
95
96struct pfkeystat pfkeystat;
97
39236c6e 98static struct domain *keydomain = NULL;
2d21ac55
A
99
100extern lck_mtx_t *pfkey_stat_mutex;
101
1c79356b 102/*
9bccf70c 103 * key_output()
1c79356b 104 */
1c79356b 105int
9bccf70c
A
106#ifdef __APPLE__
107/* No variable argument support? */
108key_output(struct mbuf *m, struct socket *so)
1c79356b 109#else
9bccf70c
A
110#if __STDC__
111key_output(struct mbuf *m, ...)
1c79356b 112#else
9bccf70c
A
113key_output(m, va_alist)
114 struct mbuf *m;
115 va_dcl
1c79356b 116#endif
1c79356b 117#endif
1c79356b 118{
9bccf70c 119 struct sadb_msg *msg;
1c79356b 120 int len, error = 0;
9bccf70c
A
121#ifndef __APPLE__
122 struct socket *so;
123 va_list ap;
124
125 va_start(ap, m);
126 so = va_arg(ap, struct socket *);
127 va_end(ap);
128#endif
1c79356b
A
129
130 if (m == 0)
131 panic("key_output: NULL pointer was passed.\n");
132
91447636 133 socket_unlock(so, 0);
2d21ac55 134 lck_mtx_lock(pfkey_stat_mutex);
1c79356b
A
135 pfkeystat.out_total++;
136 pfkeystat.out_bytes += m->m_pkthdr.len;
2d21ac55 137 lck_mtx_unlock(pfkey_stat_mutex);
1c79356b
A
138
139 len = m->m_pkthdr.len;
140 if (len < sizeof(struct sadb_msg)) {
141#if IPSEC_DEBUG
142 printf("key_output: Invalid message length.\n");
143#endif
2d21ac55 144 PFKEY_STAT_INCREMENT(pfkeystat.out_tooshort);
1c79356b
A
145 error = EINVAL;
146 goto end;
147 }
148
149 if (m->m_len < sizeof(struct sadb_msg)) {
150 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
151#if IPSEC_DEBUG
152 printf("key_output: can't pullup mbuf\n");
153#endif
2d21ac55 154 PFKEY_STAT_INCREMENT(pfkeystat.out_nomem);
1c79356b
A
155 error = ENOBUFS;
156 goto end;
157 }
158 }
159
160 if ((m->m_flags & M_PKTHDR) == 0)
161 panic("key_output: not M_PKTHDR ??");
162
9bccf70c 163#if IPSEC_DEBUG
1c79356b
A
164 KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
165#endif /* defined(IPSEC_DEBUG) */
166
167 msg = mtod(m, struct sadb_msg *);
2d21ac55 168 PFKEY_STAT_INCREMENT(pfkeystat.out_msgtype[msg->sadb_msg_type]);
1c79356b
A
169 if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
170#if IPSEC_DEBUG
171 printf("key_output: Invalid message length.\n");
172#endif
2d21ac55 173 PFKEY_STAT_INCREMENT(pfkeystat.out_invlen);
1c79356b
A
174 error = EINVAL;
175 goto end;
176 }
177
9bccf70c
A
178 error = key_parse(m, so);
179 m = NULL;
91447636 180
1c79356b 181end:
9bccf70c
A
182 if (m)
183 m_freem(m);
91447636 184 socket_lock(so, 0);
9bccf70c 185 return error;
1c79356b
A
186}
187
188/*
189 * send message to the socket.
190 */
191static int
39037602 192key_sendup0(struct rawcb *rp, struct mbuf *m, int promisc)
1c79356b 193{
9bccf70c
A
194 int error;
195
1c79356b
A
196 if (promisc) {
197 struct sadb_msg *pmsg;
198
3e170ce0 199 M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT, 1);
1c79356b
A
200 if (m && m->m_len < sizeof(struct sadb_msg))
201 m = m_pullup(m, sizeof(struct sadb_msg));
202 if (!m) {
203#if IPSEC_DEBUG
204 printf("key_sendup0: cannot pullup\n");
205#endif
2d21ac55 206 PFKEY_STAT_INCREMENT(pfkeystat.in_nomem);
1c79356b
A
207 m_freem(m);
208 return ENOBUFS;
209 }
210 m->m_pkthdr.len += sizeof(*pmsg);
211
212 pmsg = mtod(m, struct sadb_msg *);
213 bzero(pmsg, sizeof(*pmsg));
214 pmsg->sadb_msg_version = PF_KEY_V2;
215 pmsg->sadb_msg_type = SADB_X_PROMISC;
216 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
217 /* pid and seq? */
218
2d21ac55 219 PFKEY_STAT_INCREMENT(pfkeystat.in_msgtype[pmsg->sadb_msg_type]);
1c79356b
A
220 }
221
9bccf70c 222 if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src,
91447636 223 m, NULL, &error)) {
1c79356b
A
224#if IPSEC_DEBUG
225 printf("key_sendup0: sbappendaddr failed\n");
226#endif
2d21ac55 227 PFKEY_STAT_INCREMENT(pfkeystat.in_nomem);
91447636
A
228 }
229 else {
230 sorwakeup(rp->rcb_socket);
231 }
9bccf70c 232 return error;
1c79356b
A
233}
234
1c79356b 235
9bccf70c 236/* so can be NULL if target != KEY_SENDUP_ONE */
1c79356b 237int
39037602 238key_sendup_mbuf(struct socket *so, struct mbuf *m, int target)
1c79356b
A
239{
240 struct mbuf *n;
241 struct keycb *kp;
242 int sendup;
243 struct rawcb *rp;
9bccf70c 244 int error = 0;
1c79356b 245
9bccf70c
A
246 if (m == NULL)
247 panic("key_sendup_mbuf: NULL pointer was passed.\n");
248 if (so == NULL && target == KEY_SENDUP_ONE)
1c79356b
A
249 panic("key_sendup_mbuf: NULL pointer was passed.\n");
250
2d21ac55 251 lck_mtx_lock(pfkey_stat_mutex);
1c79356b
A
252 pfkeystat.in_total++;
253 pfkeystat.in_bytes += m->m_pkthdr.len;
2d21ac55 254 lck_mtx_unlock(pfkey_stat_mutex);
1c79356b
A
255 if (m->m_len < sizeof(struct sadb_msg)) {
256#if 1
257 m = m_pullup(m, sizeof(struct sadb_msg));
258 if (m == NULL) {
2d21ac55 259 PFKEY_STAT_INCREMENT(pfkeystat.in_nomem);
1c79356b
A
260 return ENOBUFS;
261 }
262#else
263 /* don't bother pulling it up just for stats */
264#endif
265 }
266 if (m->m_len >= sizeof(struct sadb_msg)) {
267 struct sadb_msg *msg;
268 msg = mtod(m, struct sadb_msg *);
2d21ac55 269 PFKEY_STAT_INCREMENT(pfkeystat.in_msgtype[msg->sadb_msg_type]);
1c79356b 270 }
91447636
A
271
272 lck_mtx_lock(raw_mtx);
1c79356b 273 LIST_FOREACH(rp, &rawcb_list, list)
1c79356b
A
274 {
275 if (rp->rcb_proto.sp_family != PF_KEY)
276 continue;
277 if (rp->rcb_proto.sp_protocol
278 && rp->rcb_proto.sp_protocol != PF_KEY_V2) {
279 continue;
280 }
281
282 kp = (struct keycb *)rp;
91447636
A
283
284 socket_lock(rp->rcb_socket, 1);
1c79356b
A
285 /*
286 * If you are in promiscuous mode, and when you get broadcasted
287 * reply, you'll get two PF_KEY messages.
288 * (based on pf_key@inner.net message on 14 Oct 1998)
289 */
290 if (((struct keycb *)rp)->kp_promisc) {
291 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
292 (void)key_sendup0(rp, n, 1);
293 n = NULL;
294 }
295 }
296
297 /* the exact target will be processed later */
91447636
A
298 if (so && sotorawcb(so) == rp) {
299 socket_unlock(rp->rcb_socket, 1);
1c79356b 300 continue;
91447636 301 }
1c79356b
A
302
303 sendup = 0;
304 switch (target) {
305 case KEY_SENDUP_ONE:
306 /* the statement has no effect */
1c79356b
A
307 break;
308 case KEY_SENDUP_ALL:
309 sendup++;
310 break;
311 case KEY_SENDUP_REGISTERED:
312 if (kp->kp_registered)
313 sendup++;
314 break;
315 }
2d21ac55 316 PFKEY_STAT_INCREMENT(pfkeystat.in_msgtarget[target]);
1c79356b 317
91447636
A
318 if (!sendup) {
319 socket_unlock(rp->rcb_socket, 1);
1c79356b 320 continue;
91447636
A
321 }
322 else
323 sendup = 0; // clear for next iteration
1c79356b
A
324
325 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
326#if IPSEC_DEBUG
327 printf("key_sendup: m_copy fail\n");
328#endif
329 m_freem(m);
2d21ac55 330 PFKEY_STAT_INCREMENT(pfkeystat.in_nomem);
91447636
A
331 socket_unlock(rp->rcb_socket, 1);
332 lck_mtx_unlock(raw_mtx);
1c79356b
A
333 return ENOBUFS;
334 }
335
91447636
A
336 /*
337 * ignore error even if queue is full. PF_KEY does not
338 * guarantee the delivery of the message.
339 * this is important when target == KEY_SENDUP_ALL.
340 */
341 key_sendup0(rp, n, 0);
342 socket_unlock(rp->rcb_socket, 1);
1c79356b
A
343 n = NULL;
344 }
345
91447636 346 lck_mtx_unlock(raw_mtx);
9bccf70c 347 if (so) {
91447636 348 socket_lock(so, 1);
9bccf70c 349 error = key_sendup0(sotorawcb(so), m, 0);
91447636 350 socket_unlock(so, 1);
9bccf70c
A
351 m = NULL;
352 } else {
353 error = 0;
354 m_freem(m);
355 }
1c79356b
A
356 return error;
357}
358
1c79356b
A
359/*
360 * key_abort()
361 * derived from net/rtsock.c:rts_abort()
362 */
363static int
364key_abort(struct socket *so)
365{
91447636 366 int error;
1c79356b 367 error = raw_usrreqs.pru_abort(so);
1c79356b
A
368 return error;
369}
370
371/*
372 * key_attach()
373 * derived from net/rtsock.c:rts_attach()
374 */
375static int
376key_attach(struct socket *so, int proto, struct proc *p)
377{
378 struct keycb *kp;
91447636 379 int error;
1c79356b
A
380
381 if (sotorawcb(so) != 0)
382 return EISCONN; /* XXX panic? */
3e170ce0
A
383 kp = (struct keycb *)_MALLOC(sizeof (*kp), M_PCB,
384 M_WAITOK | M_ZERO); /* XXX */
1c79356b
A
385 if (kp == 0)
386 return ENOBUFS;
1c79356b 387
1c79356b 388 so->so_pcb = (caddr_t)kp;
91447636
A
389 kp->kp_promisc = kp->kp_registered = 0;
390 kp->kp_raw.rcb_laddr = &key_src;
391 kp->kp_raw.rcb_faddr = &key_dst;
392
1c79356b
A
393 error = raw_usrreqs.pru_attach(so, proto, p);
394 kp = (struct keycb *)sotorawcb(so);
395 if (error) {
396 _FREE(kp, M_PCB);
397 so->so_pcb = (caddr_t) 0;
91447636 398 so->so_flags |= SOF_PCBCLEARING;
1c79356b
A
399 printf("key_usrreq: key_usrreq results %d\n", error);
400 return error;
401 }
402
37839358 403 /* so is already locked when calling key_attach */
1c79356b
A
404 if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
405 key_cb.key_count++;
406 key_cb.any_count++;
1c79356b
A
407 soisconnected(so);
408 so->so_options |= SO_USELOOPBACK;
409
1c79356b
A
410 return 0;
411}
412
413/*
414 * key_bind()
415 * derived from net/rtsock.c:rts_bind()
416 */
417static int
418key_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
419{
91447636 420 int error;
1c79356b 421 error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */
1c79356b
A
422 return error;
423}
424
425/*
426 * key_connect()
427 * derived from net/rtsock.c:rts_connect()
428 */
429static int
430key_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
431{
91447636 432 int error;
1c79356b 433 error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */
1c79356b
A
434 return error;
435}
436
437/*
438 * key_detach()
439 * derived from net/rtsock.c:rts_detach()
440 */
441static int
442key_detach(struct socket *so)
443{
444 struct keycb *kp = (struct keycb *)sotorawcb(so);
91447636 445 int error;
1c79356b 446
1c79356b 447 if (kp != 0) {
91447636 448 if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
1c79356b
A
449 key_cb.key_count--;
450 key_cb.any_count--;
91447636 451 socket_unlock(so, 0);
1c79356b 452 key_freereg(so);
91447636 453 socket_lock(so, 0);
1c79356b
A
454 }
455 error = raw_usrreqs.pru_detach(so);
1c79356b
A
456 return error;
457}
458
459/*
460 * key_disconnect()
461 * derived from net/rtsock.c:key_disconnect()
462 */
463static int
464key_disconnect(struct socket *so)
465{
91447636 466 int error;
1c79356b 467 error = raw_usrreqs.pru_disconnect(so);
1c79356b
A
468 return error;
469}
470
471/*
472 * key_peeraddr()
473 * derived from net/rtsock.c:rts_peeraddr()
474 */
475static int
476key_peeraddr(struct socket *so, struct sockaddr **nam)
477{
91447636 478 int error;
1c79356b 479 error = raw_usrreqs.pru_peeraddr(so, nam);
1c79356b
A
480 return error;
481}
482
483/*
484 * key_send()
485 * derived from net/rtsock.c:rts_send()
486 */
487static int
488key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
489 struct mbuf *control, struct proc *p)
490{
91447636 491 int error;
1c79356b 492 error = raw_usrreqs.pru_send(so, flags, m, nam, control, p);
1c79356b
A
493 return error;
494}
495
496/*
497 * key_shutdown()
498 * derived from net/rtsock.c:rts_shutdown()
499 */
500static int
501key_shutdown(struct socket *so)
502{
91447636 503 int error;
1c79356b 504 error = raw_usrreqs.pru_shutdown(so);
1c79356b
A
505 return error;
506}
507
508/*
509 * key_sockaddr()
510 * derived from net/rtsock.c:rts_sockaddr()
511 */
512static int
513key_sockaddr(struct socket *so, struct sockaddr **nam)
514{
91447636 515 int error;
1c79356b 516 error = raw_usrreqs.pru_sockaddr(so, nam);
1c79356b
A
517 return error;
518}
519
39236c6e
A
520static struct pr_usrreqs key_usrreqs = {
521 .pru_abort = key_abort,
522 .pru_attach = key_attach,
523 .pru_bind = key_bind,
524 .pru_connect = key_connect,
525 .pru_detach = key_detach,
526 .pru_disconnect = key_disconnect,
527 .pru_peeraddr = key_peeraddr,
528 .pru_send = key_send,
529 .pru_shutdown = key_shutdown,
530 .pru_sockaddr = key_sockaddr,
531 .pru_sosend = sosend,
532 .pru_soreceive = soreceive,
1c79356b 533};
1c79356b 534
1c79356b 535/* sysctl */
2d21ac55 536SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Key Family");
1c79356b
A
537
538/*
539 * Definitions of protocols supported in the KEY domain.
540 */
541
39236c6e
A
542extern struct domain keydomain_s;
543
544static struct protosw keysw[] = {
545{
546 .pr_type = SOCK_RAW,
547 .pr_protocol = PF_KEY_V2,
548 .pr_flags = PR_ATOMIC|PR_ADDR,
549 .pr_output = key_output,
550 .pr_ctlinput = raw_ctlinput,
551 .pr_init = key_init,
552 .pr_usrreqs = &key_usrreqs,
1c79356b
A
553}
554};
555
39236c6e
A
556static int key_proto_count = (sizeof (keysw) / sizeof (struct protosw));
557
558struct domain keydomain_s = {
559 .dom_family = PF_KEY,
560 .dom_name = "key",
561 .dom_init = key_dinit,
562 .dom_maxrtkey = sizeof (struct key_cb),
2d21ac55 563};
1c79356b 564
39236c6e
A
565static void
566key_dinit(struct domain *dp)
567{
568 struct protosw *pr;
569 int i;
570
571 VERIFY(!(dp->dom_flags & DOM_INITIALIZED));
572 VERIFY(keydomain == NULL);
573
574 keydomain = dp;
575
576 for (i = 0, pr = &keysw[0]; i < key_proto_count; i++, pr++)
577 net_add_proto(pr, dp, 1);
578}