]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netkey/keysock.c
1 /* $KAME: keysock.c,v 1.13 2000/03/25 07:24:13 sumikawa Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 /* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/sysctl.h>
40 #include <sys/mcache.h>
41 #include <sys/malloc.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/domain.h>
45 #include <sys/protosw.h>
46 #include <sys/errno.h>
48 #include <kern/locks.h>
50 #include <net/raw_cb.h>
51 #include <net/route.h>
53 #include <net/pfkeyv2.h>
54 #include <netkey/keydb.h>
55 #include <netkey/key.h>
56 #include <netkey/keysock.h>
57 #include <netkey/key_debug.h>
59 extern lck_mtx_t
*raw_mtx
;
60 extern void key_init(struct protosw
*, struct domain
*);
62 struct sockaddr key_dst
= { 2, PF_KEY
, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,} };
63 struct sockaddr key_src
= { 2, PF_KEY
, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,} };
65 static void key_dinit(struct domain
*);
66 static int key_sendup0(struct rawcb
*, struct mbuf
*, int);
68 struct pfkeystat pfkeystat
;
70 static struct domain
*keydomain
= NULL
;
72 extern lck_mtx_t
*pfkey_stat_mutex
;
79 /* No variable argument support? */
80 key_output(struct mbuf
*m
, struct socket
*so
)
83 key_output(struct mbuf
*m
, ...)
85 key_output(m
, va_alist
)
98 so
= va_arg(ap
, struct socket
*);
103 panic("key_output: NULL pointer was passed.\n");
105 socket_unlock(so
, 0);
106 lck_mtx_lock(pfkey_stat_mutex
);
107 pfkeystat
.out_total
++;
108 pfkeystat
.out_bytes
+= m
->m_pkthdr
.len
;
109 lck_mtx_unlock(pfkey_stat_mutex
);
111 len
= m
->m_pkthdr
.len
;
112 if (len
< sizeof(struct sadb_msg
)) {
114 printf("key_output: Invalid message length.\n");
116 PFKEY_STAT_INCREMENT(pfkeystat
.out_tooshort
);
121 if (m
->m_len
< sizeof(struct sadb_msg
)) {
122 if ((m
= m_pullup(m
, sizeof(struct sadb_msg
))) == 0) {
124 printf("key_output: can't pullup mbuf\n");
126 PFKEY_STAT_INCREMENT(pfkeystat
.out_nomem
);
132 if ((m
->m_flags
& M_PKTHDR
) == 0)
133 panic("key_output: not M_PKTHDR ??");
136 KEYDEBUG(KEYDEBUG_KEY_DUMP
, kdebug_mbuf(m
));
137 #endif /* defined(IPSEC_DEBUG) */
139 msg
= mtod(m
, struct sadb_msg
*);
140 PFKEY_STAT_INCREMENT(pfkeystat
.out_msgtype
[msg
->sadb_msg_type
]);
141 if (len
!= PFKEY_UNUNIT64(msg
->sadb_msg_len
)) {
143 printf("key_output: Invalid message length.\n");
145 PFKEY_STAT_INCREMENT(pfkeystat
.out_invlen
);
150 error
= key_parse(m
, so
);
161 * send message to the socket.
164 key_sendup0(rp
, m
, promisc
)
172 struct sadb_msg
*pmsg
;
174 M_PREPEND(m
, sizeof(struct sadb_msg
), M_NOWAIT
);
175 if (m
&& m
->m_len
< sizeof(struct sadb_msg
))
176 m
= m_pullup(m
, sizeof(struct sadb_msg
));
179 printf("key_sendup0: cannot pullup\n");
181 PFKEY_STAT_INCREMENT(pfkeystat
.in_nomem
);
185 m
->m_pkthdr
.len
+= sizeof(*pmsg
);
187 pmsg
= mtod(m
, struct sadb_msg
*);
188 bzero(pmsg
, sizeof(*pmsg
));
189 pmsg
->sadb_msg_version
= PF_KEY_V2
;
190 pmsg
->sadb_msg_type
= SADB_X_PROMISC
;
191 pmsg
->sadb_msg_len
= PFKEY_UNIT64(m
->m_pkthdr
.len
);
194 PFKEY_STAT_INCREMENT(pfkeystat
.in_msgtype
[pmsg
->sadb_msg_type
]);
197 if (!sbappendaddr(&rp
->rcb_socket
->so_rcv
, (struct sockaddr
*)&key_src
,
200 printf("key_sendup0: sbappendaddr failed\n");
202 PFKEY_STAT_INCREMENT(pfkeystat
.in_nomem
);
205 sorwakeup(rp
->rcb_socket
);
211 /* so can be NULL if target != KEY_SENDUP_ONE */
213 key_sendup_mbuf(so
, m
, target
)
225 panic("key_sendup_mbuf: NULL pointer was passed.\n");
226 if (so
== NULL
&& target
== KEY_SENDUP_ONE
)
227 panic("key_sendup_mbuf: NULL pointer was passed.\n");
229 lck_mtx_lock(pfkey_stat_mutex
);
230 pfkeystat
.in_total
++;
231 pfkeystat
.in_bytes
+= m
->m_pkthdr
.len
;
232 lck_mtx_unlock(pfkey_stat_mutex
);
233 if (m
->m_len
< sizeof(struct sadb_msg
)) {
235 m
= m_pullup(m
, sizeof(struct sadb_msg
));
237 PFKEY_STAT_INCREMENT(pfkeystat
.in_nomem
);
241 /* don't bother pulling it up just for stats */
244 if (m
->m_len
>= sizeof(struct sadb_msg
)) {
245 struct sadb_msg
*msg
;
246 msg
= mtod(m
, struct sadb_msg
*);
247 PFKEY_STAT_INCREMENT(pfkeystat
.in_msgtype
[msg
->sadb_msg_type
]);
250 lck_mtx_lock(raw_mtx
);
251 LIST_FOREACH(rp
, &rawcb_list
, list
)
253 if (rp
->rcb_proto
.sp_family
!= PF_KEY
)
255 if (rp
->rcb_proto
.sp_protocol
256 && rp
->rcb_proto
.sp_protocol
!= PF_KEY_V2
) {
260 kp
= (struct keycb
*)rp
;
262 socket_lock(rp
->rcb_socket
, 1);
264 * If you are in promiscuous mode, and when you get broadcasted
265 * reply, you'll get two PF_KEY messages.
266 * (based on pf_key@inner.net message on 14 Oct 1998)
268 if (((struct keycb
*)rp
)->kp_promisc
) {
269 if ((n
= m_copy(m
, 0, (int)M_COPYALL
)) != NULL
) {
270 (void)key_sendup0(rp
, n
, 1);
275 /* the exact target will be processed later */
276 if (so
&& sotorawcb(so
) == rp
) {
277 socket_unlock(rp
->rcb_socket
, 1);
284 /* the statement has no effect */
289 case KEY_SENDUP_REGISTERED
:
290 if (kp
->kp_registered
)
294 PFKEY_STAT_INCREMENT(pfkeystat
.in_msgtarget
[target
]);
297 socket_unlock(rp
->rcb_socket
, 1);
301 sendup
= 0; // clear for next iteration
303 if ((n
= m_copy(m
, 0, (int)M_COPYALL
)) == NULL
) {
305 printf("key_sendup: m_copy fail\n");
308 PFKEY_STAT_INCREMENT(pfkeystat
.in_nomem
);
309 socket_unlock(rp
->rcb_socket
, 1);
310 lck_mtx_unlock(raw_mtx
);
315 * ignore error even if queue is full. PF_KEY does not
316 * guarantee the delivery of the message.
317 * this is important when target == KEY_SENDUP_ALL.
319 key_sendup0(rp
, n
, 0);
320 socket_unlock(rp
->rcb_socket
, 1);
324 lck_mtx_unlock(raw_mtx
);
327 error
= key_sendup0(sotorawcb(so
), m
, 0);
328 socket_unlock(so
, 1);
339 * derived from net/rtsock.c:rts_abort()
342 key_abort(struct socket
*so
)
345 error
= raw_usrreqs
.pru_abort(so
);
351 * derived from net/rtsock.c:rts_attach()
354 key_attach(struct socket
*so
, int proto
, struct proc
*p
)
359 if (sotorawcb(so
) != 0)
360 return EISCONN
; /* XXX panic? */
361 kp
= (struct keycb
*)_MALLOC(sizeof *kp
, M_PCB
, M_WAITOK
); /* XXX */
364 bzero(kp
, sizeof *kp
);
366 so
->so_pcb
= (caddr_t
)kp
;
367 kp
->kp_promisc
= kp
->kp_registered
= 0;
368 kp
->kp_raw
.rcb_laddr
= &key_src
;
369 kp
->kp_raw
.rcb_faddr
= &key_dst
;
371 error
= raw_usrreqs
.pru_attach(so
, proto
, p
);
372 kp
= (struct keycb
*)sotorawcb(so
);
375 so
->so_pcb
= (caddr_t
) 0;
376 so
->so_flags
|= SOF_PCBCLEARING
;
377 printf("key_usrreq: key_usrreq results %d\n", error
);
381 /* so is already locked when calling key_attach */
382 if (kp
->kp_raw
.rcb_proto
.sp_protocol
== PF_KEY
) /* XXX: AF_KEY */
386 so
->so_options
|= SO_USELOOPBACK
;
393 * derived from net/rtsock.c:rts_bind()
396 key_bind(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
399 error
= raw_usrreqs
.pru_bind(so
, nam
, p
); /* xxx just EINVAL */
405 * derived from net/rtsock.c:rts_connect()
408 key_connect(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
411 error
= raw_usrreqs
.pru_connect(so
, nam
, p
); /* XXX just EINVAL */
417 * derived from net/rtsock.c:rts_detach()
420 key_detach(struct socket
*so
)
422 struct keycb
*kp
= (struct keycb
*)sotorawcb(so
);
426 if (kp
->kp_raw
.rcb_proto
.sp_protocol
== PF_KEY
) /* XXX: AF_KEY */
429 socket_unlock(so
, 0);
433 error
= raw_usrreqs
.pru_detach(so
);
439 * derived from net/rtsock.c:key_disconnect()
442 key_disconnect(struct socket
*so
)
445 error
= raw_usrreqs
.pru_disconnect(so
);
451 * derived from net/rtsock.c:rts_peeraddr()
454 key_peeraddr(struct socket
*so
, struct sockaddr
**nam
)
457 error
= raw_usrreqs
.pru_peeraddr(so
, nam
);
463 * derived from net/rtsock.c:rts_send()
466 key_send(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*nam
,
467 struct mbuf
*control
, struct proc
*p
)
470 error
= raw_usrreqs
.pru_send(so
, flags
, m
, nam
, control
, p
);
476 * derived from net/rtsock.c:rts_shutdown()
479 key_shutdown(struct socket
*so
)
482 error
= raw_usrreqs
.pru_shutdown(so
);
488 * derived from net/rtsock.c:rts_sockaddr()
491 key_sockaddr(struct socket
*so
, struct sockaddr
**nam
)
494 error
= raw_usrreqs
.pru_sockaddr(so
, nam
);
498 static struct pr_usrreqs key_usrreqs
= {
499 .pru_abort
= key_abort
,
500 .pru_attach
= key_attach
,
501 .pru_bind
= key_bind
,
502 .pru_connect
= key_connect
,
503 .pru_detach
= key_detach
,
504 .pru_disconnect
= key_disconnect
,
505 .pru_peeraddr
= key_peeraddr
,
506 .pru_send
= key_send
,
507 .pru_shutdown
= key_shutdown
,
508 .pru_sockaddr
= key_sockaddr
,
509 .pru_sosend
= sosend
,
510 .pru_soreceive
= soreceive
,
514 SYSCTL_NODE(_net
, PF_KEY
, key
, CTLFLAG_RW
|CTLFLAG_LOCKED
, 0, "Key Family");
517 * Definitions of protocols supported in the KEY domain.
520 extern struct domain keydomain_s
;
522 static struct protosw keysw
[] = {
525 .pr_protocol
= PF_KEY_V2
,
526 .pr_flags
= PR_ATOMIC
|PR_ADDR
,
527 .pr_output
= key_output
,
528 .pr_ctlinput
= raw_ctlinput
,
530 .pr_usrreqs
= &key_usrreqs
,
534 static int key_proto_count
= (sizeof (keysw
) / sizeof (struct protosw
));
536 struct domain keydomain_s
= {
537 .dom_family
= PF_KEY
,
539 .dom_init
= key_dinit
,
540 .dom_maxrtkey
= sizeof (struct key_cb
),
544 key_dinit(struct domain
*dp
)
549 VERIFY(!(dp
->dom_flags
& DOM_INITIALIZED
));
550 VERIFY(keydomain
== NULL
);
554 for (i
= 0, pr
= &keysw
[0]; i
< key_proto_count
; i
++, pr
++)
555 net_add_proto(pr
, dp
, 1);