]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netkey/keysock.c
2 * Copyright (c) 2016 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 /* $KAME: keysock.c,v 1.13 2000/03/25 07:24:13 sumikawa Exp $ */
32 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
33 * All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
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.
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
60 /* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
62 #include <sys/types.h>
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/kernel.h>
66 #include <sys/sysctl.h>
68 #include <sys/mcache.h>
69 #include <sys/malloc.h>
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>
76 #include <kern/locks.h>
78 #include <net/raw_cb.h>
79 #include <net/route.h>
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>
87 extern lck_mtx_t
*raw_mtx
;
88 extern void key_init(struct protosw
*, struct domain
*);
90 struct sockaddr key_dst
= { 2, PF_KEY
, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,} };
91 struct sockaddr key_src
= { 2, PF_KEY
, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,} };
93 static void key_dinit(struct domain
*);
94 static int key_sendup0(struct rawcb
*, struct mbuf
*, int);
96 struct pfkeystat pfkeystat
;
98 static struct domain
*keydomain
= NULL
;
100 extern lck_mtx_t
*pfkey_stat_mutex
;
107 /* No variable argument support? */
108 key_output(struct mbuf
*m
, struct socket
*so
)
111 key_output(struct mbuf
*m
, ...)
113 key_output(m
, va_alist
)
119 struct sadb_msg
*msg
;
126 so
= va_arg(ap
, struct socket
*);
131 panic("key_output: NULL pointer was passed.\n");
133 socket_unlock(so
, 0);
134 lck_mtx_lock(pfkey_stat_mutex
);
135 pfkeystat
.out_total
++;
136 pfkeystat
.out_bytes
+= m
->m_pkthdr
.len
;
137 lck_mtx_unlock(pfkey_stat_mutex
);
139 len
= m
->m_pkthdr
.len
;
140 if (len
< sizeof(struct sadb_msg
)) {
142 printf("key_output: Invalid message length.\n");
144 PFKEY_STAT_INCREMENT(pfkeystat
.out_tooshort
);
149 if (m
->m_len
< sizeof(struct sadb_msg
)) {
150 if ((m
= m_pullup(m
, sizeof(struct sadb_msg
))) == 0) {
152 printf("key_output: can't pullup mbuf\n");
154 PFKEY_STAT_INCREMENT(pfkeystat
.out_nomem
);
160 if ((m
->m_flags
& M_PKTHDR
) == 0)
161 panic("key_output: not M_PKTHDR ??");
164 KEYDEBUG(KEYDEBUG_KEY_DUMP
, kdebug_mbuf(m
));
165 #endif /* defined(IPSEC_DEBUG) */
167 msg
= mtod(m
, struct sadb_msg
*);
168 PFKEY_STAT_INCREMENT(pfkeystat
.out_msgtype
[msg
->sadb_msg_type
]);
169 if (len
!= PFKEY_UNUNIT64(msg
->sadb_msg_len
)) {
171 printf("key_output: Invalid message length.\n");
173 PFKEY_STAT_INCREMENT(pfkeystat
.out_invlen
);
178 error
= key_parse(m
, so
);
189 * send message to the socket.
192 key_sendup0(struct rawcb
*rp
, struct mbuf
*m
, int promisc
)
197 struct sadb_msg
*pmsg
;
199 M_PREPEND(m
, sizeof(struct sadb_msg
), M_NOWAIT
, 1);
200 if (m
&& m
->m_len
< sizeof(struct sadb_msg
))
201 m
= m_pullup(m
, sizeof(struct sadb_msg
));
204 printf("key_sendup0: cannot pullup\n");
206 PFKEY_STAT_INCREMENT(pfkeystat
.in_nomem
);
210 m
->m_pkthdr
.len
+= sizeof(*pmsg
);
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
);
219 PFKEY_STAT_INCREMENT(pfkeystat
.in_msgtype
[pmsg
->sadb_msg_type
]);
222 if (!sbappendaddr(&rp
->rcb_socket
->so_rcv
, (struct sockaddr
*)&key_src
,
225 printf("key_sendup0: sbappendaddr failed\n");
227 PFKEY_STAT_INCREMENT(pfkeystat
.in_nomem
);
230 sorwakeup(rp
->rcb_socket
);
236 /* so can be NULL if target != KEY_SENDUP_ONE */
238 key_sendup_mbuf(struct socket
*so
, struct mbuf
*m
, int target
)
247 panic("key_sendup_mbuf: NULL pointer was passed.\n");
248 if (so
== NULL
&& target
== KEY_SENDUP_ONE
)
249 panic("key_sendup_mbuf: NULL pointer was passed.\n");
251 lck_mtx_lock(pfkey_stat_mutex
);
252 pfkeystat
.in_total
++;
253 pfkeystat
.in_bytes
+= m
->m_pkthdr
.len
;
254 lck_mtx_unlock(pfkey_stat_mutex
);
255 if (m
->m_len
< sizeof(struct sadb_msg
)) {
257 m
= m_pullup(m
, sizeof(struct sadb_msg
));
259 PFKEY_STAT_INCREMENT(pfkeystat
.in_nomem
);
263 /* don't bother pulling it up just for stats */
266 if (m
->m_len
>= sizeof(struct sadb_msg
)) {
267 struct sadb_msg
*msg
;
268 msg
= mtod(m
, struct sadb_msg
*);
269 PFKEY_STAT_INCREMENT(pfkeystat
.in_msgtype
[msg
->sadb_msg_type
]);
272 lck_mtx_lock(raw_mtx
);
273 LIST_FOREACH(rp
, &rawcb_list
, list
)
275 if (rp
->rcb_proto
.sp_family
!= PF_KEY
)
277 if (rp
->rcb_proto
.sp_protocol
278 && rp
->rcb_proto
.sp_protocol
!= PF_KEY_V2
) {
282 kp
= (struct keycb
*)rp
;
284 socket_lock(rp
->rcb_socket
, 1);
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)
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);
297 /* the exact target will be processed later */
298 if (so
&& sotorawcb(so
) == rp
) {
299 socket_unlock(rp
->rcb_socket
, 1);
306 /* the statement has no effect */
311 case KEY_SENDUP_REGISTERED
:
312 if (kp
->kp_registered
)
316 PFKEY_STAT_INCREMENT(pfkeystat
.in_msgtarget
[target
]);
319 socket_unlock(rp
->rcb_socket
, 1);
323 sendup
= 0; // clear for next iteration
325 if ((n
= m_copy(m
, 0, (int)M_COPYALL
)) == NULL
) {
327 printf("key_sendup: m_copy fail\n");
330 PFKEY_STAT_INCREMENT(pfkeystat
.in_nomem
);
331 socket_unlock(rp
->rcb_socket
, 1);
332 lck_mtx_unlock(raw_mtx
);
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.
341 key_sendup0(rp
, n
, 0);
342 socket_unlock(rp
->rcb_socket
, 1);
346 lck_mtx_unlock(raw_mtx
);
349 error
= key_sendup0(sotorawcb(so
), m
, 0);
350 socket_unlock(so
, 1);
361 * derived from net/rtsock.c:rts_abort()
364 key_abort(struct socket
*so
)
367 error
= raw_usrreqs
.pru_abort(so
);
373 * derived from net/rtsock.c:rts_attach()
376 key_attach(struct socket
*so
, int proto
, struct proc
*p
)
381 if (sotorawcb(so
) != 0)
382 return EISCONN
; /* XXX panic? */
383 kp
= (struct keycb
*)_MALLOC(sizeof (*kp
), M_PCB
,
384 M_WAITOK
| M_ZERO
); /* XXX */
388 so
->so_pcb
= (caddr_t
)kp
;
389 kp
->kp_promisc
= kp
->kp_registered
= 0;
390 kp
->kp_raw
.rcb_laddr
= &key_src
;
391 kp
->kp_raw
.rcb_faddr
= &key_dst
;
393 error
= raw_usrreqs
.pru_attach(so
, proto
, p
);
394 kp
= (struct keycb
*)sotorawcb(so
);
397 so
->so_pcb
= (caddr_t
) 0;
398 so
->so_flags
|= SOF_PCBCLEARING
;
399 printf("key_usrreq: key_usrreq results %d\n", error
);
403 /* so is already locked when calling key_attach */
404 if (kp
->kp_raw
.rcb_proto
.sp_protocol
== PF_KEY
) /* XXX: AF_KEY */
408 so
->so_options
|= SO_USELOOPBACK
;
415 * derived from net/rtsock.c:rts_bind()
418 key_bind(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
421 error
= raw_usrreqs
.pru_bind(so
, nam
, p
); /* xxx just EINVAL */
427 * derived from net/rtsock.c:rts_connect()
430 key_connect(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
433 error
= raw_usrreqs
.pru_connect(so
, nam
, p
); /* XXX just EINVAL */
439 * derived from net/rtsock.c:rts_detach()
442 key_detach(struct socket
*so
)
444 struct keycb
*kp
= (struct keycb
*)sotorawcb(so
);
448 if (kp
->kp_raw
.rcb_proto
.sp_protocol
== PF_KEY
) /* XXX: AF_KEY */
451 socket_unlock(so
, 0);
455 error
= raw_usrreqs
.pru_detach(so
);
461 * derived from net/rtsock.c:key_disconnect()
464 key_disconnect(struct socket
*so
)
467 error
= raw_usrreqs
.pru_disconnect(so
);
473 * derived from net/rtsock.c:rts_peeraddr()
476 key_peeraddr(struct socket
*so
, struct sockaddr
**nam
)
479 error
= raw_usrreqs
.pru_peeraddr(so
, nam
);
485 * derived from net/rtsock.c:rts_send()
488 key_send(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*nam
,
489 struct mbuf
*control
, struct proc
*p
)
492 error
= raw_usrreqs
.pru_send(so
, flags
, m
, nam
, control
, p
);
498 * derived from net/rtsock.c:rts_shutdown()
501 key_shutdown(struct socket
*so
)
504 error
= raw_usrreqs
.pru_shutdown(so
);
510 * derived from net/rtsock.c:rts_sockaddr()
513 key_sockaddr(struct socket
*so
, struct sockaddr
**nam
)
516 error
= raw_usrreqs
.pru_sockaddr(so
, nam
);
520 static 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
,
536 SYSCTL_NODE(_net
, PF_KEY
, key
, CTLFLAG_RW
|CTLFLAG_LOCKED
, 0, "Key Family");
539 * Definitions of protocols supported in the KEY domain.
542 extern struct domain keydomain_s
;
544 static struct protosw keysw
[] = {
547 .pr_protocol
= PF_KEY_V2
,
548 .pr_flags
= PR_ATOMIC
|PR_ADDR
,
549 .pr_output
= key_output
,
550 .pr_ctlinput
= raw_ctlinput
,
552 .pr_usrreqs
= &key_usrreqs
,
556 static int key_proto_count
= (sizeof (keysw
) / sizeof (struct protosw
));
558 struct domain keydomain_s
= {
559 .dom_family
= PF_KEY
,
561 .dom_init
= key_dinit
,
562 .dom_maxrtkey
= sizeof (struct key_cb
),
566 key_dinit(struct domain
*dp
)
571 VERIFY(!(dp
->dom_flags
& DOM_INITIALIZED
));
572 VERIFY(keydomain
== NULL
);
576 for (i
= 0, pr
= &keysw
[0]; i
< key_proto_count
; i
++, pr
++)
577 net_add_proto(pr
, dp
, 1);