]>
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/malloc.h>
41 #include <sys/socket.h>
42 #include <sys/socketvar.h>
43 #include <sys/domain.h>
44 #include <sys/protosw.h>
45 #include <sys/errno.h>
47 #include <kern/locks.h>
49 #include <net/raw_cb.h>
50 #include <net/route.h>
52 #include <net/pfkeyv2.h>
53 #include <netkey/keydb.h>
54 #include <netkey/key.h>
55 #include <netkey/keysock.h>
56 #include <netkey/key_debug.h>
58 extern lck_mtx_t
*raw_mtx
;
59 extern void key_init(void) __attribute__((section("__TEXT, initcode")));
61 struct sockaddr key_dst
= { 2, PF_KEY
, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,} };
62 struct sockaddr key_src
= { 2, PF_KEY
, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,} };
64 static int key_sendup0(struct rawcb
*, struct mbuf
*, int);
66 struct pfkeystat pfkeystat
;
69 extern lck_mtx_t
*pfkey_stat_mutex
;
76 /* No variable argument support? */
77 key_output(struct mbuf
*m
, struct socket
*so
)
80 key_output(struct mbuf
*m
, ...)
82 key_output(m
, va_alist
)
95 so
= va_arg(ap
, struct socket
*);
100 panic("key_output: NULL pointer was passed.\n");
102 socket_unlock(so
, 0);
103 lck_mtx_lock(pfkey_stat_mutex
);
104 pfkeystat
.out_total
++;
105 pfkeystat
.out_bytes
+= m
->m_pkthdr
.len
;
106 lck_mtx_unlock(pfkey_stat_mutex
);
108 len
= m
->m_pkthdr
.len
;
109 if (len
< sizeof(struct sadb_msg
)) {
111 printf("key_output: Invalid message length.\n");
113 PFKEY_STAT_INCREMENT(pfkeystat
.out_tooshort
);
118 if (m
->m_len
< sizeof(struct sadb_msg
)) {
119 if ((m
= m_pullup(m
, sizeof(struct sadb_msg
))) == 0) {
121 printf("key_output: can't pullup mbuf\n");
123 PFKEY_STAT_INCREMENT(pfkeystat
.out_nomem
);
129 if ((m
->m_flags
& M_PKTHDR
) == 0)
130 panic("key_output: not M_PKTHDR ??");
133 KEYDEBUG(KEYDEBUG_KEY_DUMP
, kdebug_mbuf(m
));
134 #endif /* defined(IPSEC_DEBUG) */
136 msg
= mtod(m
, struct sadb_msg
*);
137 PFKEY_STAT_INCREMENT(pfkeystat
.out_msgtype
[msg
->sadb_msg_type
]);
138 if (len
!= PFKEY_UNUNIT64(msg
->sadb_msg_len
)) {
140 printf("key_output: Invalid message length.\n");
142 PFKEY_STAT_INCREMENT(pfkeystat
.out_invlen
);
147 error
= key_parse(m
, so
);
158 * send message to the socket.
161 key_sendup0(rp
, m
, promisc
)
169 struct sadb_msg
*pmsg
;
171 M_PREPEND(m
, sizeof(struct sadb_msg
), M_NOWAIT
);
172 if (m
&& m
->m_len
< sizeof(struct sadb_msg
))
173 m
= m_pullup(m
, sizeof(struct sadb_msg
));
176 printf("key_sendup0: cannot pullup\n");
178 PFKEY_STAT_INCREMENT(pfkeystat
.in_nomem
);
182 m
->m_pkthdr
.len
+= sizeof(*pmsg
);
184 pmsg
= mtod(m
, struct sadb_msg
*);
185 bzero(pmsg
, sizeof(*pmsg
));
186 pmsg
->sadb_msg_version
= PF_KEY_V2
;
187 pmsg
->sadb_msg_type
= SADB_X_PROMISC
;
188 pmsg
->sadb_msg_len
= PFKEY_UNIT64(m
->m_pkthdr
.len
);
191 PFKEY_STAT_INCREMENT(pfkeystat
.in_msgtype
[pmsg
->sadb_msg_type
]);
194 if (!sbappendaddr(&rp
->rcb_socket
->so_rcv
, (struct sockaddr
*)&key_src
,
197 printf("key_sendup0: sbappendaddr failed\n");
199 PFKEY_STAT_INCREMENT(pfkeystat
.in_nomem
);
202 sorwakeup(rp
->rcb_socket
);
208 /* so can be NULL if target != KEY_SENDUP_ONE */
210 key_sendup_mbuf(so
, m
, target
)
222 panic("key_sendup_mbuf: NULL pointer was passed.\n");
223 if (so
== NULL
&& target
== KEY_SENDUP_ONE
)
224 panic("key_sendup_mbuf: NULL pointer was passed.\n");
226 lck_mtx_lock(pfkey_stat_mutex
);
227 pfkeystat
.in_total
++;
228 pfkeystat
.in_bytes
+= m
->m_pkthdr
.len
;
229 lck_mtx_unlock(pfkey_stat_mutex
);
230 if (m
->m_len
< sizeof(struct sadb_msg
)) {
232 m
= m_pullup(m
, sizeof(struct sadb_msg
));
234 PFKEY_STAT_INCREMENT(pfkeystat
.in_nomem
);
238 /* don't bother pulling it up just for stats */
241 if (m
->m_len
>= sizeof(struct sadb_msg
)) {
242 struct sadb_msg
*msg
;
243 msg
= mtod(m
, struct sadb_msg
*);
244 PFKEY_STAT_INCREMENT(pfkeystat
.in_msgtype
[msg
->sadb_msg_type
]);
247 lck_mtx_lock(raw_mtx
);
248 LIST_FOREACH(rp
, &rawcb_list
, list
)
250 if (rp
->rcb_proto
.sp_family
!= PF_KEY
)
252 if (rp
->rcb_proto
.sp_protocol
253 && rp
->rcb_proto
.sp_protocol
!= PF_KEY_V2
) {
257 kp
= (struct keycb
*)rp
;
259 socket_lock(rp
->rcb_socket
, 1);
261 * If you are in promiscuous mode, and when you get broadcasted
262 * reply, you'll get two PF_KEY messages.
263 * (based on pf_key@inner.net message on 14 Oct 1998)
265 if (((struct keycb
*)rp
)->kp_promisc
) {
266 if ((n
= m_copy(m
, 0, (int)M_COPYALL
)) != NULL
) {
267 (void)key_sendup0(rp
, n
, 1);
272 /* the exact target will be processed later */
273 if (so
&& sotorawcb(so
) == rp
) {
274 socket_unlock(rp
->rcb_socket
, 1);
281 /* the statement has no effect */
286 case KEY_SENDUP_REGISTERED
:
287 if (kp
->kp_registered
)
291 PFKEY_STAT_INCREMENT(pfkeystat
.in_msgtarget
[target
]);
294 socket_unlock(rp
->rcb_socket
, 1);
298 sendup
= 0; // clear for next iteration
300 if ((n
= m_copy(m
, 0, (int)M_COPYALL
)) == NULL
) {
302 printf("key_sendup: m_copy fail\n");
305 PFKEY_STAT_INCREMENT(pfkeystat
.in_nomem
);
306 socket_unlock(rp
->rcb_socket
, 1);
307 lck_mtx_unlock(raw_mtx
);
312 * ignore error even if queue is full. PF_KEY does not
313 * guarantee the delivery of the message.
314 * this is important when target == KEY_SENDUP_ALL.
316 key_sendup0(rp
, n
, 0);
317 socket_unlock(rp
->rcb_socket
, 1);
321 lck_mtx_unlock(raw_mtx
);
324 error
= key_sendup0(sotorawcb(so
), m
, 0);
325 socket_unlock(so
, 1);
336 * derived from net/rtsock.c:rts_abort()
339 key_abort(struct socket
*so
)
342 error
= raw_usrreqs
.pru_abort(so
);
348 * derived from net/rtsock.c:rts_attach()
351 key_attach(struct socket
*so
, int proto
, struct proc
*p
)
356 if (sotorawcb(so
) != 0)
357 return EISCONN
; /* XXX panic? */
358 kp
= (struct keycb
*)_MALLOC(sizeof *kp
, M_PCB
, M_WAITOK
); /* XXX */
361 bzero(kp
, sizeof *kp
);
363 so
->so_pcb
= (caddr_t
)kp
;
364 kp
->kp_promisc
= kp
->kp_registered
= 0;
365 kp
->kp_raw
.rcb_laddr
= &key_src
;
366 kp
->kp_raw
.rcb_faddr
= &key_dst
;
368 error
= raw_usrreqs
.pru_attach(so
, proto
, p
);
369 kp
= (struct keycb
*)sotorawcb(so
);
372 so
->so_pcb
= (caddr_t
) 0;
373 so
->so_flags
|= SOF_PCBCLEARING
;
374 printf("key_usrreq: key_usrreq results %d\n", error
);
378 /* so is already locked when calling key_attach */
379 if (kp
->kp_raw
.rcb_proto
.sp_protocol
== PF_KEY
) /* XXX: AF_KEY */
383 so
->so_options
|= SO_USELOOPBACK
;
390 * derived from net/rtsock.c:rts_bind()
393 key_bind(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
396 error
= raw_usrreqs
.pru_bind(so
, nam
, p
); /* xxx just EINVAL */
402 * derived from net/rtsock.c:rts_connect()
405 key_connect(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
408 error
= raw_usrreqs
.pru_connect(so
, nam
, p
); /* XXX just EINVAL */
414 * derived from net/rtsock.c:rts_detach()
417 key_detach(struct socket
*so
)
419 struct keycb
*kp
= (struct keycb
*)sotorawcb(so
);
423 if (kp
->kp_raw
.rcb_proto
.sp_protocol
== PF_KEY
) /* XXX: AF_KEY */
426 socket_unlock(so
, 0);
430 error
= raw_usrreqs
.pru_detach(so
);
436 * derived from net/rtsock.c:key_disconnect()
439 key_disconnect(struct socket
*so
)
442 error
= raw_usrreqs
.pru_disconnect(so
);
448 * derived from net/rtsock.c:rts_peeraddr()
451 key_peeraddr(struct socket
*so
, struct sockaddr
**nam
)
454 error
= raw_usrreqs
.pru_peeraddr(so
, nam
);
460 * derived from net/rtsock.c:rts_send()
463 key_send(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*nam
,
464 struct mbuf
*control
, struct proc
*p
)
467 error
= raw_usrreqs
.pru_send(so
, flags
, m
, nam
, control
, p
);
473 * derived from net/rtsock.c:rts_shutdown()
476 key_shutdown(struct socket
*so
)
479 error
= raw_usrreqs
.pru_shutdown(so
);
485 * derived from net/rtsock.c:rts_sockaddr()
488 key_sockaddr(struct socket
*so
, struct sockaddr
**nam
)
491 error
= raw_usrreqs
.pru_sockaddr(so
, nam
);
495 struct pr_usrreqs key_usrreqs
= {
496 key_abort
, pru_accept_notsupp
, key_attach
, key_bind
,
498 pru_connect2_notsupp
, pru_control_notsupp
, key_detach
,
499 key_disconnect
, pru_listen_notsupp
, key_peeraddr
,
501 pru_rcvoob_notsupp
, key_send
, pru_sense_null
, key_shutdown
,
502 key_sockaddr
, sosend
, soreceive
, pru_sopoll_notsupp
506 SYSCTL_NODE(_net
, PF_KEY
, key
, CTLFLAG_RW
|CTLFLAG_LOCKED
, 0, "Key Family");
509 * Definitions of protocols supported in the KEY domain.
512 extern struct domain keydomain
;
514 struct protosw keysw
[] = {
515 { SOCK_RAW
, &keydomain
, PF_KEY_V2
, PR_ATOMIC
|PR_ADDR
,
516 NULL
, key_output
, raw_ctlinput
, NULL
,
518 key_init
, NULL
, NULL
, NULL
,
522 { NULL
, NULL
}, NULL
, { 0 }
526 struct domain keydomain
= { PF_KEY
, "key", key_domain_init
, NULL
, NULL
,
529 sizeof(struct key_cb
), 0, 0,