]>
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 lck_mtx_t
*sadb_mutex
;
60 extern void key_init(void);
62 struct sockaddr key_dst
= { 2, PF_KEY
, };
63 struct sockaddr key_src
= { 2, PF_KEY
, };
65 static int key_sendup0(struct rawcb
*, struct mbuf
*, int);
67 struct pfkeystat pfkeystat
;
74 /* No variable argument support? */
75 key_output(struct mbuf
*m
, struct socket
*so
)
78 key_output(struct mbuf
*m
, ...)
80 key_output(m
, va_alist
)
93 so
= va_arg(ap
, struct socket
*);
98 panic("key_output: NULL pointer was passed.\n");
100 socket_unlock(so
, 0);
101 lck_mtx_lock(sadb_mutex
);
102 pfkeystat
.out_total
++;
103 pfkeystat
.out_bytes
+= m
->m_pkthdr
.len
;
105 len
= m
->m_pkthdr
.len
;
106 if (len
< sizeof(struct sadb_msg
)) {
108 printf("key_output: Invalid message length.\n");
110 pfkeystat
.out_tooshort
++;
115 if (m
->m_len
< sizeof(struct sadb_msg
)) {
116 if ((m
= m_pullup(m
, sizeof(struct sadb_msg
))) == 0) {
118 printf("key_output: can't pullup mbuf\n");
120 pfkeystat
.out_nomem
++;
126 if ((m
->m_flags
& M_PKTHDR
) == 0)
127 panic("key_output: not M_PKTHDR ??");
130 KEYDEBUG(KEYDEBUG_KEY_DUMP
, kdebug_mbuf(m
));
131 #endif /* defined(IPSEC_DEBUG) */
133 msg
= mtod(m
, struct sadb_msg
*);
134 pfkeystat
.out_msgtype
[msg
->sadb_msg_type
]++;
135 if (len
!= PFKEY_UNUNIT64(msg
->sadb_msg_len
)) {
137 printf("key_output: Invalid message length.\n");
139 pfkeystat
.out_invlen
++;
144 error
= key_parse(m
, so
);
150 lck_mtx_unlock(sadb_mutex
);
156 * send message to the socket.
159 key_sendup0(rp
, m
, promisc
)
166 lck_mtx_assert(sadb_mutex
, LCK_MTX_ASSERT_OWNED
);
168 struct sadb_msg
*pmsg
;
170 M_PREPEND(m
, sizeof(struct sadb_msg
), M_NOWAIT
);
171 if (m
&& m
->m_len
< sizeof(struct sadb_msg
))
172 m
= m_pullup(m
, sizeof(struct sadb_msg
));
175 printf("key_sendup0: cannot pullup\n");
177 pfkeystat
.in_nomem
++;
181 m
->m_pkthdr
.len
+= sizeof(*pmsg
);
183 pmsg
= mtod(m
, struct sadb_msg
*);
184 bzero(pmsg
, sizeof(*pmsg
));
185 pmsg
->sadb_msg_version
= PF_KEY_V2
;
186 pmsg
->sadb_msg_type
= SADB_X_PROMISC
;
187 pmsg
->sadb_msg_len
= PFKEY_UNIT64(m
->m_pkthdr
.len
);
190 pfkeystat
.in_msgtype
[pmsg
->sadb_msg_type
]++;
193 if (!sbappendaddr(&rp
->rcb_socket
->so_rcv
, (struct sockaddr
*)&key_src
,
196 printf("key_sendup0: sbappendaddr failed\n");
198 pfkeystat
.in_nomem
++;
201 sorwakeup(rp
->rcb_socket
);
207 /* so can be NULL if target != KEY_SENDUP_ONE */
209 key_sendup_mbuf(so
, m
, target
)
220 lck_mtx_assert(sadb_mutex
, LCK_MTX_ASSERT_OWNED
);
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 pfkeystat
.in_total
++;
227 pfkeystat
.in_bytes
+= m
->m_pkthdr
.len
;
228 if (m
->m_len
< sizeof(struct sadb_msg
)) {
230 m
= m_pullup(m
, sizeof(struct sadb_msg
));
232 pfkeystat
.in_nomem
++;
236 /* don't bother pulling it up just for stats */
239 if (m
->m_len
>= sizeof(struct sadb_msg
)) {
240 struct sadb_msg
*msg
;
241 msg
= mtod(m
, struct sadb_msg
*);
242 pfkeystat
.in_msgtype
[msg
->sadb_msg_type
]++;
245 lck_mtx_lock(raw_mtx
);
246 LIST_FOREACH(rp
, &rawcb_list
, list
)
248 if (rp
->rcb_proto
.sp_family
!= PF_KEY
)
250 if (rp
->rcb_proto
.sp_protocol
251 && rp
->rcb_proto
.sp_protocol
!= PF_KEY_V2
) {
255 kp
= (struct keycb
*)rp
;
257 socket_lock(rp
->rcb_socket
, 1);
259 * If you are in promiscuous mode, and when you get broadcasted
260 * reply, you'll get two PF_KEY messages.
261 * (based on pf_key@inner.net message on 14 Oct 1998)
263 if (((struct keycb
*)rp
)->kp_promisc
) {
264 if ((n
= m_copy(m
, 0, (int)M_COPYALL
)) != NULL
) {
265 (void)key_sendup0(rp
, n
, 1);
270 /* the exact target will be processed later */
271 if (so
&& sotorawcb(so
) == rp
) {
272 socket_unlock(rp
->rcb_socket
, 1);
279 /* the statement has no effect */
284 case KEY_SENDUP_REGISTERED
:
285 if (kp
->kp_registered
)
289 pfkeystat
.in_msgtarget
[target
]++;
292 socket_unlock(rp
->rcb_socket
, 1);
296 sendup
= 0; // clear for next iteration
298 if ((n
= m_copy(m
, 0, (int)M_COPYALL
)) == NULL
) {
300 printf("key_sendup: m_copy fail\n");
303 pfkeystat
.in_nomem
++;
304 socket_unlock(rp
->rcb_socket
, 1);
305 lck_mtx_unlock(raw_mtx
);
310 * ignore error even if queue is full. PF_KEY does not
311 * guarantee the delivery of the message.
312 * this is important when target == KEY_SENDUP_ALL.
314 key_sendup0(rp
, n
, 0);
315 socket_unlock(rp
->rcb_socket
, 1);
319 lck_mtx_unlock(raw_mtx
);
322 error
= key_sendup0(sotorawcb(so
), m
, 0);
323 socket_unlock(so
, 1);
334 * derived from net/rtsock.c:rts_abort()
337 key_abort(struct socket
*so
)
340 error
= raw_usrreqs
.pru_abort(so
);
346 * derived from net/rtsock.c:rts_attach()
349 key_attach(struct socket
*so
, int proto
, struct proc
*p
)
354 if (sotorawcb(so
) != 0)
355 return EISCONN
; /* XXX panic? */
356 kp
= (struct keycb
*)_MALLOC(sizeof *kp
, M_PCB
, M_WAITOK
); /* XXX */
359 bzero(kp
, sizeof *kp
);
361 so
->so_pcb
= (caddr_t
)kp
;
362 kp
->kp_promisc
= kp
->kp_registered
= 0;
363 kp
->kp_raw
.rcb_laddr
= &key_src
;
364 kp
->kp_raw
.rcb_faddr
= &key_dst
;
366 error
= raw_usrreqs
.pru_attach(so
, proto
, p
);
367 kp
= (struct keycb
*)sotorawcb(so
);
370 so
->so_pcb
= (caddr_t
) 0;
371 so
->so_flags
|= SOF_PCBCLEARING
;
372 printf("key_usrreq: key_usrreq results %d\n", error
);
377 if (kp
->kp_raw
.rcb_proto
.sp_protocol
== PF_KEY
) /* XXX: AF_KEY */
381 so
->so_options
|= SO_USELOOPBACK
;
382 socket_unlock(so
, 1);
389 * derived from net/rtsock.c:rts_bind()
392 key_bind(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
395 error
= raw_usrreqs
.pru_bind(so
, nam
, p
); /* xxx just EINVAL */
401 * derived from net/rtsock.c:rts_connect()
404 key_connect(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
407 error
= raw_usrreqs
.pru_connect(so
, nam
, p
); /* XXX just EINVAL */
413 * derived from net/rtsock.c:rts_detach()
416 key_detach(struct socket
*so
)
418 struct keycb
*kp
= (struct keycb
*)sotorawcb(so
);
422 if (kp
->kp_raw
.rcb_proto
.sp_protocol
== PF_KEY
) /* XXX: AF_KEY */
425 socket_unlock(so
, 0);
426 lck_mtx_lock(sadb_mutex
);
428 lck_mtx_unlock(sadb_mutex
);
431 error
= raw_usrreqs
.pru_detach(so
);
437 * derived from net/rtsock.c:key_disconnect()
440 key_disconnect(struct socket
*so
)
443 error
= raw_usrreqs
.pru_disconnect(so
);
449 * derived from net/rtsock.c:rts_peeraddr()
452 key_peeraddr(struct socket
*so
, struct sockaddr
**nam
)
455 error
= raw_usrreqs
.pru_peeraddr(so
, nam
);
461 * derived from net/rtsock.c:rts_send()
464 key_send(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*nam
,
465 struct mbuf
*control
, struct proc
*p
)
468 error
= raw_usrreqs
.pru_send(so
, flags
, m
, nam
, control
, p
);
474 * derived from net/rtsock.c:rts_shutdown()
477 key_shutdown(struct socket
*so
)
480 error
= raw_usrreqs
.pru_shutdown(so
);
486 * derived from net/rtsock.c:rts_sockaddr()
489 key_sockaddr(struct socket
*so
, struct sockaddr
**nam
)
492 error
= raw_usrreqs
.pru_sockaddr(so
, nam
);
496 struct pr_usrreqs key_usrreqs
= {
497 key_abort
, pru_accept_notsupp
, key_attach
, key_bind
,
499 pru_connect2_notsupp
, pru_control_notsupp
, key_detach
,
500 key_disconnect
, pru_listen_notsupp
, key_peeraddr
,
502 pru_rcvoob_notsupp
, key_send
, pru_sense_null
, key_shutdown
,
503 key_sockaddr
, sosend
, soreceive
, pru_sopoll_notsupp
507 SYSCTL_NODE(_net
, PF_KEY
, key
, CTLFLAG_RW
, 0, "Key Family");
510 * Definitions of protocols supported in the KEY domain.
513 extern struct domain keydomain
;
515 struct protosw keysw
[] = {
516 { SOCK_RAW
, &keydomain
, PF_KEY_V2
, PR_ATOMIC
|PR_ADDR
,
517 0, key_output
, raw_ctlinput
, 0,
526 struct domain keydomain
=
527 { PF_KEY
, "key", key_domain_init
, 0, 0,
530 sizeof(struct key_cb
), 0