1240116Smarcel/*	$NetBSD: keysock.c,v 1.53 2009/05/09 11:36:17 mlelstv Exp $	*/
2240116Smarcel/*	$KAME: keysock.c,v 1.32 2003/08/22 05:45:08 itojun Exp $	*/
3240116Smarcel
4240116Smarcel/*
5240116Smarcel * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6240116Smarcel * All rights reserved.
7240116Smarcel *
8240116Smarcel * Redistribution and use in source and binary forms, with or without
9240116Smarcel * modification, are permitted provided that the following conditions
10240116Smarcel * are met:
11240116Smarcel * 1. Redistributions of source code must retain the above copyright
12240116Smarcel *    notice, this list of conditions and the following disclaimer.
13240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright
14240116Smarcel *    notice, this list of conditions and the following disclaimer in the
15240116Smarcel *    documentation and/or other materials provided with the distribution.
16240116Smarcel * 3. Neither the name of the project nor the names of its contributors
17240116Smarcel *    may be used to endorse or promote products derived from this software
18240116Smarcel *    without specific prior written permission.
19240116Smarcel *
20240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21240116Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22240116Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23240116Smarcel * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24240116Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25240116Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26275988Sngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27240116Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28240116Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29240116Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30240116Smarcel * SUCH DAMAGE.
31240116Smarcel */
32240116Smarcel
33240116Smarcel#include <sys/cdefs.h>
34240116Smarcel__KERNEL_RCSID(0, "$NetBSD: keysock.c,v 1.53 2009/05/09 11:36:17 mlelstv Exp $");
35240116Smarcel
36240116Smarcel#include "opt_inet.h"
37240116Smarcel
38240116Smarcel/* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
39240116Smarcel
40240116Smarcel#include <sys/param.h>
41240116Smarcel#include <sys/systm.h>
42240116Smarcel#include <sys/kernel.h>
43240116Smarcel#include <sys/mbuf.h>
44240116Smarcel#include <sys/socket.h>
45240116Smarcel#include <sys/socketvar.h>
46240116Smarcel#include <sys/domain.h>
47240116Smarcel#include <sys/protosw.h>
48240116Smarcel#include <sys/errno.h>
49#include <sys/proc.h>
50#include <sys/queue.h>
51
52#include <net/raw_cb.h>
53#include <net/route.h>
54#include <netinet/in.h>
55
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>
62
63struct sockaddr key_dst = { .sa_len = 2, .sa_family = PF_KEY, };
64struct sockaddr key_src = { .sa_len = 2, .sa_family = PF_KEY, };
65
66static int key_receive(struct socket *, struct mbuf **, struct uio *,
67	struct mbuf **, struct mbuf **, int *);
68
69static int key_sendup0(struct rawcb *, struct mbuf *, int, int);
70
71static int
72key_receive(struct socket *so, struct mbuf **paddr, struct uio *uio,
73	struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
74{
75	struct rawcb *rp = sotorawcb(so);
76	struct keycb *kp = (struct keycb *)rp;
77	int error;
78
79	error = (*kp->kp_receive)(so, paddr, uio, mp0, controlp, flagsp);
80
81	/*
82	 * now we might have enough receive buffer space.
83	 * pull packets from kp_queue as many as possible.
84	 */
85	mutex_enter(softnet_lock);
86	KERNEL_LOCK(1, NULL);
87	while (/*CONSTCOND*/ 1) {
88		struct mbuf *m;
89
90		m = kp->kp_queue;
91		if (m == NULL || sbspace(&so->so_rcv) < m->m_pkthdr.len)
92			break;
93		kp->kp_queue = m->m_nextpkt;
94		m->m_nextpkt = NULL; /* safety */
95		if (key_sendup0(rp, m, 0, 1))
96			break;
97	}
98	KERNEL_UNLOCK_ONE(NULL);
99	mutex_exit(softnet_lock);
100
101	return error;
102}
103
104/*
105 * key_usrreq()
106 * derived from net/rtsock.c:route_usrreq()
107 */
108int
109key_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, struct mbuf *control, struct lwp *l)
110{
111	int error = 0;
112	struct keycb *kp = (struct keycb *)sotorawcb(so);
113	int s;
114
115	s = splsoftnet();
116	if (req == PRU_ATTACH) {
117		sosetlock(so);
118		kp = (struct keycb *)malloc(sizeof(*kp), M_PCB,
119		    M_WAITOK|M_ZERO);
120		so->so_pcb = (void *)kp;
121		kp->kp_receive = so->so_receive;
122		so->so_receive = key_receive;
123	}
124	if (req == PRU_DETACH && kp) {
125		int af = kp->kp_raw.rcb_proto.sp_protocol;
126		struct mbuf *n;
127
128		if (af == PF_KEY)
129			key_cb.key_count--;
130		key_cb.any_count--;
131
132		key_freereg(so);
133
134		while (kp->kp_queue) {
135			n = kp->kp_queue->m_nextpkt;
136			kp->kp_queue->m_nextpkt = NULL;
137			m_freem(kp->kp_queue);
138			kp->kp_queue = n;
139		}
140	}
141
142	error = raw_usrreq(so, req, m, nam, control, l);
143	m = control = NULL;	/* reclaimed in raw_usrreq */
144	kp = (struct keycb *)sotorawcb(so);
145	if (req == PRU_ATTACH && kp) {
146		int af = kp->kp_raw.rcb_proto.sp_protocol;
147		if (error) {
148			PFKEY_STATINC(PFKEY_STAT_SOCKERR);
149			free((void *)kp, M_PCB);
150			so->so_pcb = (void *) 0;
151			splx(s);
152			return (error);
153		}
154
155		kp->kp_promisc = kp->kp_registered = 0;
156
157		if (af == PF_KEY)
158			key_cb.key_count++;
159		key_cb.any_count++;
160		kp->kp_raw.rcb_laddr = &key_src;
161		kp->kp_raw.rcb_faddr = &key_dst;
162		soisconnected(so);
163		so->so_options |= SO_USELOOPBACK;
164	}
165	splx(s);
166	return (error);
167}
168
169/*
170 * key_output()
171 */
172int
173key_output(struct mbuf *m, ...)
174{
175	struct sadb_msg *msg;
176	int len, error = 0;
177	int s;
178	struct socket *so;
179	va_list ap;
180
181	va_start(ap, m);
182	so = va_arg(ap, struct socket *);
183	va_end(ap);
184
185	if (m == 0)
186		panic("key_output: NULL pointer was passed.");
187
188	{
189		uint64_t *ps = PFKEY_STAT_GETREF();
190		ps[PFKEY_STAT_OUT_TOTAL]++;
191		ps[PFKEY_STAT_OUT_BYTES] += m->m_pkthdr.len;
192		PFKEY_STAT_PUTREF();
193	}
194
195	len = m->m_pkthdr.len;
196	if (len < sizeof(struct sadb_msg)) {
197		PFKEY_STATINC(PFKEY_STAT_OUT_TOOSHORT);
198		error = EINVAL;
199		goto end;
200	}
201
202	if (m->m_len < sizeof(struct sadb_msg)) {
203		if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
204			PFKEY_STATINC(PFKEY_STAT_OUT_NOMEM);
205			error = ENOBUFS;
206			goto end;
207		}
208	}
209
210	if ((m->m_flags & M_PKTHDR) == 0)
211		panic("key_output: not M_PKTHDR ??");
212
213	KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
214
215	msg = mtod(m, struct sadb_msg *);
216	PFKEY_STATINC(PFKEY_STAT_OUT_MSGTYPE + msg->sadb_msg_type);
217	if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
218		PFKEY_STATINC(PFKEY_STAT_OUT_INVLEN);
219		error = EINVAL;
220		goto end;
221	}
222
223	/*XXX giant lock*/
224	s = splsoftnet();
225	error = key_parse(m, so);
226	m = NULL;
227	splx(s);
228end:
229	if (m)
230		m_freem(m);
231	return error;
232}
233
234/*
235 * send message to the socket.
236 */
237static int
238key_sendup0(struct rawcb *rp, struct mbuf *m, int promisc, int canwait)
239{
240	struct keycb *kp = (struct keycb *)rp;
241	struct mbuf *n;
242	int error = 0;
243
244	if (promisc) {
245		struct sadb_msg *pmsg;
246
247		M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT);
248		if (m && m->m_len < sizeof(struct sadb_msg))
249			m = m_pullup(m, sizeof(struct sadb_msg));
250		if (!m) {
251			PFKEY_STATINC(PFKEY_STAT_OUT_NOMEM);
252			return ENOBUFS;
253		}
254		m->m_pkthdr.len += sizeof(*pmsg);
255
256		pmsg = mtod(m, struct sadb_msg *);
257		memset(pmsg, 0, sizeof(*pmsg));
258		pmsg->sadb_msg_version = PF_KEY_V2;
259		pmsg->sadb_msg_type = SADB_X_PROMISC;
260		pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
261		/* pid and seq? */
262
263		PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE + pmsg->sadb_msg_type);
264	}
265
266	if (canwait) {
267		if (kp->kp_queue) {
268			for (n = kp->kp_queue; n && n->m_nextpkt;
269			    n = n->m_nextpkt)
270				;
271			n->m_nextpkt = m;
272			m = kp->kp_queue;
273			kp->kp_queue = NULL;
274		} else
275			m->m_nextpkt = NULL;	/* just for safety */
276	} else
277		m->m_nextpkt = NULL;
278
279	for (; m && error == 0; m = n) {
280		n = m->m_nextpkt;
281
282		if (canwait &&
283		    sbspace(&rp->rcb_socket->so_rcv) < m->m_pkthdr.len) {
284			error = EAGAIN;
285			goto recovery;
286		}
287
288		m->m_nextpkt = NULL;
289
290		if (!sbappendaddr(&rp->rcb_socket->so_rcv,
291		    (struct sockaddr *)&key_src, m, NULL)) {
292			PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
293			error = ENOBUFS;
294			goto recovery;
295		} else {
296			sorwakeup(rp->rcb_socket);
297			error = 0;
298		}
299	}
300	return (error);
301
302recovery:
303	if (kp->kp_queue) {
304		/*
305		 * kp_queue != NULL implies !canwait.
306		 */
307		KASSERT(!canwait);
308		KASSERT(m->m_nextpkt == NULL);
309		/*
310		 * insert m to the head of queue, as normally mbuf on the queue
311		 * is less important than others.
312		 */
313		if (m) {
314			m->m_nextpkt = kp->kp_queue;
315			kp->kp_queue = m;
316		}
317	} else {
318		/* recover the queue */
319		if (!m) {
320			/* first ENOBUFS case */
321			kp->kp_queue = n;
322		} else {
323			kp->kp_queue = m;
324			m->m_nextpkt = n;
325		}
326	}
327	return (error);
328}
329
330/* so can be NULL if target != KEY_SENDUP_ONE */
331int
332key_sendup_mbuf(struct socket *so, struct mbuf *m, int target)
333{
334	struct mbuf *n;
335	struct keycb *kp;
336	int sendup;
337	struct rawcb *rp;
338	int error = 0;
339	int canwait;
340
341	if (m == NULL)
342		panic("key_sendup_mbuf: NULL pointer was passed.");
343	if (so == NULL && target == KEY_SENDUP_ONE)
344		panic("key_sendup_mbuf: NULL pointer was passed.");
345
346	canwait = target & KEY_SENDUP_CANWAIT;
347	target &= ~KEY_SENDUP_CANWAIT;
348
349	{
350		uint64_t *ps = PFKEY_STAT_GETREF();
351		ps[PFKEY_STAT_IN_TOTAL]++;
352		ps[PFKEY_STAT_IN_BYTES] += m->m_pkthdr.len;
353		PFKEY_STAT_PUTREF();
354	}
355	if (m->m_len < sizeof(struct sadb_msg)) {
356		m = m_pullup(m, sizeof(struct sadb_msg));
357		if (m == NULL) {
358			PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
359			return ENOBUFS;
360		}
361	}
362	if (m->m_len >= sizeof(struct sadb_msg)) {
363		struct sadb_msg *msg;
364		msg = mtod(m, struct sadb_msg *);
365		PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type);
366	}
367
368	for (rp = rawcb.lh_first; rp; rp = rp->rcb_list.le_next)
369	{
370		if (rp->rcb_proto.sp_family != PF_KEY)
371			continue;
372		if (rp->rcb_proto.sp_protocol &&
373		    rp->rcb_proto.sp_protocol != PF_KEY_V2) {
374			continue;
375		}
376
377		kp = (struct keycb *)rp;
378
379		/*
380		 * If you are in promiscuous mode, and when you get broadcasted
381		 * reply, you'll get two PF_KEY messages.
382		 * (based on pf_key@inner.net message on 14 Oct 1998)
383		 */
384		if (((struct keycb *)rp)->kp_promisc) {
385			if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
386				(void)key_sendup0(rp, n, 1, canwait);
387				n = NULL;
388			}
389		}
390
391		/* the exact target will be processed later */
392		if (so && sotorawcb(so) == rp)
393			continue;
394
395		sendup = 0;
396		switch (target) {
397		case KEY_SENDUP_ONE:
398			/* the statement has no effect */
399			if (so && sotorawcb(so) == rp)
400				sendup++;
401			break;
402		case KEY_SENDUP_ALL:
403			sendup++;
404			break;
405		case KEY_SENDUP_REGISTERED:
406			if (kp->kp_registered)
407				sendup++;
408			break;
409		}
410		PFKEY_STATINC(PFKEY_STAT_IN_MSGTARGET + target);
411
412		if (!sendup)
413			continue;
414
415		if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
416			m_freem(m);
417			PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
418			return ENOBUFS;
419		}
420
421		/*
422		 * ignore error even if queue is full.  PF_KEY does not
423		 * guarantee the delivery of the message.
424		 * this is important when target == KEY_SENDUP_ALL.
425		 */
426		key_sendup0(rp, n, 0, canwait);
427
428		n = NULL;
429	}
430
431	if (so) {
432		error = key_sendup0(sotorawcb(so), m, 0, canwait);
433		m = NULL;
434	} else {
435		error = 0;
436		m_freem(m);
437	}
438	return error;
439}
440
441
442/*
443 * Definitions of protocols supported in the KEY domain.
444 */
445
446DOMAIN_DEFINE(keydomain);
447
448PR_WRAP_USRREQ(key_usrreq)
449
450#define	key_usrreq	key_usrreq_wrapper
451
452const struct protosw keysw[] = {
453{ .pr_type = SOCK_RAW,
454  .pr_domain = &keydomain,
455  .pr_protocol = PF_KEY_V2,
456  .pr_flags = PR_ATOMIC|PR_ADDR,
457  .pr_input = 0,
458  .pr_output = key_output,
459  .pr_ctlinput = raw_ctlinput,
460  .pr_ctloutput = 0,
461  .pr_usrreq = key_usrreq,
462  .pr_init = raw_init,
463  .pr_fasttimo = 0,
464  .pr_slowtimo = 0,
465  .pr_drain = 0,
466}
467};
468
469struct domain keydomain = {
470	.dom_family = PF_KEY,
471    	.dom_name = "key",
472	.dom_init = key_init,
473	.dom_protosw = keysw,
474	.dom_protoswNPROTOSW = &keysw[sizeof(keysw)/sizeof(keysw[0])],
475};
476