1 /* $NetBSD: keysock.c,v 1.52 2009/03/18 16:00:23 cegger Exp $ */
2 /* $KAME: keysock.c,v 1.32 2003/08/22 05:45:08 itojun Exp $ */
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: keysock.c,v 1.52 2009/03/18 16:00:23 cegger Exp $");
38 /* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
46 #include <sys/domain.h>
47 #include <sys/protosw.h>
48 #include <sys/errno.h>
50 #include <sys/queue.h>
52 #include <net/raw_cb.h>
53 #include <net/route.h>
54 #include <netinet/in.h>
56 #include <net/pfkeyv2.h>
57 #include <netkey/keydb.h>
58 #include <netkey/key.h>
59 #include <netkey/keysock.h>
60 #include <netkey/key_debug.h>
61 #include <netkey/key_private.h>
63 #include <machine/stdarg.h>
65 struct sockaddr key_dst
= { .sa_len
= 2, .sa_family
= PF_KEY
, };
66 struct sockaddr key_src
= { .sa_len
= 2, .sa_family
= PF_KEY
, };
68 static int key_receive(struct socket
*, struct mbuf
**, struct uio
*,
69 struct mbuf
**, struct mbuf
**, int *);
71 static int key_sendup0(struct rawcb
*, struct mbuf
*, int, int);
74 key_receive(struct socket
*so
, struct mbuf
**paddr
, struct uio
*uio
,
75 struct mbuf
**mp0
, struct mbuf
**controlp
, int *flagsp
)
77 struct rawcb
*rp
= sotorawcb(so
);
78 struct keycb
*kp
= (struct keycb
*)rp
;
81 error
= (*kp
->kp_receive
)(so
, paddr
, uio
, mp0
, controlp
, flagsp
);
84 * now we might have enough receive buffer space.
85 * pull packets from kp_queue as many as possible.
87 mutex_enter(softnet_lock
);
89 while (/*CONSTCOND*/ 1) {
93 if (m
== NULL
|| sbspace(&so
->so_rcv
) < m
->m_pkthdr
.len
)
95 kp
->kp_queue
= m
->m_nextpkt
;
96 m
->m_nextpkt
= NULL
; /* safety */
97 if (key_sendup0(rp
, m
, 0, 1))
100 KERNEL_UNLOCK_ONE(NULL
);
101 mutex_exit(softnet_lock
);
108 * derived from net/rtsock.c:route_usrreq()
111 key_usrreq(struct socket
*so
, int req
, struct mbuf
*m
, struct mbuf
*nam
, struct mbuf
*control
, struct lwp
*l
)
114 struct keycb
*kp
= (struct keycb
*)sotorawcb(so
);
118 if (req
== PRU_ATTACH
) {
120 kp
= (struct keycb
*)malloc(sizeof(*kp
), M_PCB
,
122 so
->so_pcb
= (void *)kp
;
123 kp
->kp_receive
= so
->so_receive
;
124 so
->so_receive
= key_receive
;
126 if (req
== PRU_DETACH
&& kp
) {
127 int af
= kp
->kp_raw
.rcb_proto
.sp_protocol
;
136 while (kp
->kp_queue
) {
137 n
= kp
->kp_queue
->m_nextpkt
;
138 kp
->kp_queue
->m_nextpkt
= NULL
;
139 m_freem(kp
->kp_queue
);
144 error
= raw_usrreq(so
, req
, m
, nam
, control
, l
);
145 m
= control
= NULL
; /* reclaimed in raw_usrreq */
146 kp
= (struct keycb
*)sotorawcb(so
);
147 if (req
== PRU_ATTACH
&& kp
) {
148 int af
= kp
->kp_raw
.rcb_proto
.sp_protocol
;
150 PFKEY_STATINC(PFKEY_STAT_SOCKERR
);
151 free((void *)kp
, M_PCB
);
152 so
->so_pcb
= (void *) 0;
157 kp
->kp_promisc
= kp
->kp_registered
= 0;
162 kp
->kp_raw
.rcb_laddr
= &key_src
;
163 kp
->kp_raw
.rcb_faddr
= &key_dst
;
165 so
->so_options
|= SO_USELOOPBACK
;
175 key_output(struct mbuf
*m
, ...)
177 struct sadb_msg
*msg
;
184 so
= va_arg(ap
, struct socket
*);
188 panic("key_output: NULL pointer was passed.");
191 uint64_t *ps
= PFKEY_STAT_GETREF();
192 ps
[PFKEY_STAT_OUT_TOTAL
]++;
193 ps
[PFKEY_STAT_OUT_BYTES
] += m
->m_pkthdr
.len
;
197 len
= m
->m_pkthdr
.len
;
198 if (len
< sizeof(struct sadb_msg
)) {
199 PFKEY_STATINC(PFKEY_STAT_OUT_TOOSHORT
);
204 if (m
->m_len
< sizeof(struct sadb_msg
)) {
205 if ((m
= m_pullup(m
, sizeof(struct sadb_msg
))) == 0) {
206 PFKEY_STATINC(PFKEY_STAT_OUT_NOMEM
);
212 if ((m
->m_flags
& M_PKTHDR
) == 0)
213 panic("key_output: not M_PKTHDR ??");
215 KEYDEBUG(KEYDEBUG_KEY_DUMP
, kdebug_mbuf(m
));
217 msg
= mtod(m
, struct sadb_msg
*);
218 PFKEY_STATINC(PFKEY_STAT_OUT_MSGTYPE
+ msg
->sadb_msg_type
);
219 if (len
!= PFKEY_UNUNIT64(msg
->sadb_msg_len
)) {
220 PFKEY_STATINC(PFKEY_STAT_OUT_INVLEN
);
227 error
= key_parse(m
, so
);
237 * send message to the socket.
240 key_sendup0(struct rawcb
*rp
, struct mbuf
*m
, int promisc
, int canwait
)
242 struct keycb
*kp
= (struct keycb
*)rp
;
247 struct sadb_msg
*pmsg
;
249 M_PREPEND(m
, sizeof(struct sadb_msg
), M_NOWAIT
);
250 if (m
&& m
->m_len
< sizeof(struct sadb_msg
))
251 m
= m_pullup(m
, sizeof(struct sadb_msg
));
253 PFKEY_STATINC(PFKEY_STAT_OUT_NOMEM
);
256 m
->m_pkthdr
.len
+= sizeof(*pmsg
);
258 pmsg
= mtod(m
, struct sadb_msg
*);
259 memset(pmsg
, 0, sizeof(*pmsg
));
260 pmsg
->sadb_msg_version
= PF_KEY_V2
;
261 pmsg
->sadb_msg_type
= SADB_X_PROMISC
;
262 pmsg
->sadb_msg_len
= PFKEY_UNIT64(m
->m_pkthdr
.len
);
265 PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE
+ pmsg
->sadb_msg_type
);
270 for (n
= kp
->kp_queue
; n
&& n
->m_nextpkt
;
277 m
->m_nextpkt
= NULL
; /* just for safety */
281 for (; m
&& error
== 0; m
= n
) {
285 sbspace(&rp
->rcb_socket
->so_rcv
) < m
->m_pkthdr
.len
) {
292 if (!sbappendaddr(&rp
->rcb_socket
->so_rcv
,
293 (struct sockaddr
*)&key_src
, m
, NULL
)) {
294 PFKEY_STATINC(PFKEY_STAT_IN_NOMEM
);
298 sorwakeup(rp
->rcb_socket
);
307 * kp_queue != NULL implies !canwait.
310 KASSERT(m
->m_nextpkt
== NULL
);
312 * insert m to the head of queue, as normally mbuf on the queue
313 * is less important than others.
316 m
->m_nextpkt
= kp
->kp_queue
;
320 /* recover the queue */
322 /* first ENOBUFS case */
332 /* so can be NULL if target != KEY_SENDUP_ONE */
334 key_sendup_mbuf(struct socket
*so
, struct mbuf
*m
, int target
)
344 panic("key_sendup_mbuf: NULL pointer was passed.");
345 if (so
== NULL
&& target
== KEY_SENDUP_ONE
)
346 panic("key_sendup_mbuf: NULL pointer was passed.");
348 canwait
= target
& KEY_SENDUP_CANWAIT
;
349 target
&= ~KEY_SENDUP_CANWAIT
;
352 uint64_t *ps
= PFKEY_STAT_GETREF();
353 ps
[PFKEY_STAT_IN_TOTAL
]++;
354 ps
[PFKEY_STAT_IN_BYTES
] += m
->m_pkthdr
.len
;
357 if (m
->m_len
< sizeof(struct sadb_msg
)) {
358 m
= m_pullup(m
, sizeof(struct sadb_msg
));
360 PFKEY_STATINC(PFKEY_STAT_IN_NOMEM
);
364 if (m
->m_len
>= sizeof(struct sadb_msg
)) {
365 struct sadb_msg
*msg
;
366 msg
= mtod(m
, struct sadb_msg
*);
367 PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE
+ msg
->sadb_msg_type
);
370 for (rp
= rawcb
.lh_first
; rp
; rp
= rp
->rcb_list
.le_next
)
372 if (rp
->rcb_proto
.sp_family
!= PF_KEY
)
374 if (rp
->rcb_proto
.sp_protocol
&&
375 rp
->rcb_proto
.sp_protocol
!= PF_KEY_V2
) {
379 kp
= (struct keycb
*)rp
;
382 * If you are in promiscuous mode, and when you get broadcasted
383 * reply, you'll get two PF_KEY messages.
384 * (based on pf_key@inner.net message on 14 Oct 1998)
386 if (((struct keycb
*)rp
)->kp_promisc
) {
387 if ((n
= m_copy(m
, 0, (int)M_COPYALL
)) != NULL
) {
388 (void)key_sendup0(rp
, n
, 1, canwait
);
393 /* the exact target will be processed later */
394 if (so
&& sotorawcb(so
) == rp
)
400 /* the statement has no effect */
401 if (so
&& sotorawcb(so
) == rp
)
407 case KEY_SENDUP_REGISTERED
:
408 if (kp
->kp_registered
)
412 PFKEY_STATINC(PFKEY_STAT_IN_MSGTARGET
+ target
);
417 if ((n
= m_copy(m
, 0, (int)M_COPYALL
)) == NULL
) {
419 PFKEY_STATINC(PFKEY_STAT_IN_NOMEM
);
424 * ignore error even if queue is full. PF_KEY does not
425 * guarantee the delivery of the message.
426 * this is important when target == KEY_SENDUP_ALL.
428 key_sendup0(rp
, n
, 0, canwait
);
434 error
= key_sendup0(sotorawcb(so
), m
, 0, canwait
);
445 * Definitions of protocols supported in the KEY domain.
448 DOMAIN_DEFINE(keydomain
);
450 PR_WRAP_USRREQ(key_usrreq
)
452 #define key_usrreq key_usrreq_wrapper
454 const struct protosw keysw
[] = {
455 { .pr_type
= SOCK_RAW
,
456 .pr_domain
= &keydomain
,
457 .pr_protocol
= PF_KEY_V2
,
458 .pr_flags
= PR_ATOMIC
|PR_ADDR
,
460 .pr_output
= key_output
,
461 .pr_ctlinput
= raw_ctlinput
,
463 .pr_usrreq
= key_usrreq
,
471 struct domain keydomain
= {
472 .dom_family
= PF_KEY
,
474 .dom_init
= key_init
,
475 .dom_protosw
= keysw
,
476 .dom_protoswNPROTOSW
= &keysw
[sizeof(keysw
)/sizeof(keysw
[0])],