keysock.c revision 185571
1/*	$FreeBSD: head/sys/netipsec/keysock.c 185571 2008-12-02 21:37:28Z bz $	*/
2/*	$KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $	*/
3
4/*-
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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.
19 *
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
30 * SUCH DAMAGE.
31 */
32
33#include "opt_ipsec.h"
34
35/* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
36
37#include <sys/types.h>
38#include <sys/param.h>
39#include <sys/domain.h>
40#include <sys/errno.h>
41#include <sys/kernel.h>
42#include <sys/lock.h>
43#include <sys/malloc.h>
44#include <sys/mbuf.h>
45#include <sys/mutex.h>
46#include <sys/priv.h>
47#include <sys/protosw.h>
48#include <sys/signalvar.h>
49#include <sys/socket.h>
50#include <sys/socketvar.h>
51#include <sys/sysctl.h>
52#include <sys/systm.h>
53#include <sys/vimage.h>
54
55#include <net/if.h>
56#include <net/raw_cb.h>
57#include <net/route.h>
58#include <net/vnet.h>
59
60#include <netinet/in.h>
61
62#include <net/pfkeyv2.h>
63#include <netipsec/key.h>
64#include <netipsec/keysock.h>
65#include <netipsec/key_debug.h>
66#include <netipsec/ipsec.h>
67
68#include <machine/stdarg.h>
69
70#ifdef VIMAGE_GLOBALS
71static struct key_cb key_cb;
72struct pfkeystat pfkeystat;
73#endif
74
75static struct sockaddr key_src = { 2, PF_KEY };
76
77static int key_sendup0 __P((struct rawcb *, struct mbuf *, int));
78
79/*
80 * key_output()
81 */
82int
83key_output(struct mbuf *m, struct socket *so)
84{
85	INIT_VNET_IPSEC(curvnet);
86	struct sadb_msg *msg;
87	int len, error = 0;
88
89	if (m == 0)
90		panic("%s: NULL pointer was passed.\n", __func__);
91
92	V_pfkeystat.out_total++;
93	V_pfkeystat.out_bytes += m->m_pkthdr.len;
94
95	len = m->m_pkthdr.len;
96	if (len < sizeof(struct sadb_msg)) {
97		V_pfkeystat.out_tooshort++;
98		error = EINVAL;
99		goto end;
100	}
101
102	if (m->m_len < sizeof(struct sadb_msg)) {
103		if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
104			V_pfkeystat.out_nomem++;
105			error = ENOBUFS;
106			goto end;
107		}
108	}
109
110	M_ASSERTPKTHDR(m);
111
112	KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
113
114	msg = mtod(m, struct sadb_msg *);
115	V_pfkeystat.out_msgtype[msg->sadb_msg_type]++;
116	if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
117		V_pfkeystat.out_invlen++;
118		error = EINVAL;
119		goto end;
120	}
121
122	error = key_parse(m, so);
123	m = NULL;
124end:
125	if (m)
126		m_freem(m);
127	return error;
128}
129
130/*
131 * send message to the socket.
132 */
133static int
134key_sendup0(rp, m, promisc)
135	struct rawcb *rp;
136	struct mbuf *m;
137	int promisc;
138{
139	INIT_VNET_IPSEC(curvnet);
140	int error;
141
142	if (promisc) {
143		struct sadb_msg *pmsg;
144
145		M_PREPEND(m, sizeof(struct sadb_msg), M_DONTWAIT);
146		if (m && m->m_len < sizeof(struct sadb_msg))
147			m = m_pullup(m, sizeof(struct sadb_msg));
148		if (!m) {
149			V_pfkeystat.in_nomem++;
150			m_freem(m);
151			return ENOBUFS;
152		}
153		m->m_pkthdr.len += sizeof(*pmsg);
154
155		pmsg = mtod(m, struct sadb_msg *);
156		bzero(pmsg, sizeof(*pmsg));
157		pmsg->sadb_msg_version = PF_KEY_V2;
158		pmsg->sadb_msg_type = SADB_X_PROMISC;
159		pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
160		/* pid and seq? */
161
162		V_pfkeystat.in_msgtype[pmsg->sadb_msg_type]++;
163	}
164
165	if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src,
166	    m, NULL)) {
167		V_pfkeystat.in_nomem++;
168		m_freem(m);
169		error = ENOBUFS;
170	} else
171		error = 0;
172	sorwakeup(rp->rcb_socket);
173	return error;
174}
175
176/* XXX this interface should be obsoleted. */
177int
178key_sendup(so, msg, len, target)
179	struct socket *so;
180	struct sadb_msg *msg;
181	u_int len;
182	int target;	/*target of the resulting message*/
183{
184	INIT_VNET_IPSEC(curvnet);
185	struct mbuf *m, *n, *mprev;
186	int tlen;
187
188	/* sanity check */
189	if (so == 0 || msg == 0)
190		panic("%s: NULL pointer was passed.\n", __func__);
191
192	KEYDEBUG(KEYDEBUG_KEY_DUMP,
193		printf("%s: \n", __func__);
194		kdebug_sadb(msg));
195
196	/*
197	 * we increment statistics here, just in case we have ENOBUFS
198	 * in this function.
199	 */
200	V_pfkeystat.in_total++;
201	V_pfkeystat.in_bytes += len;
202	V_pfkeystat.in_msgtype[msg->sadb_msg_type]++;
203
204	/*
205	 * Get mbuf chain whenever possible (not clusters),
206	 * to save socket buffer.  We'll be generating many SADB_ACQUIRE
207	 * messages to listening key sockets.  If we simply allocate clusters,
208	 * sbappendaddr() will raise ENOBUFS due to too little sbspace().
209	 * sbspace() computes # of actual data bytes AND mbuf region.
210	 *
211	 * TODO: SADB_ACQUIRE filters should be implemented.
212	 */
213	tlen = len;
214	m = mprev = NULL;
215	while (tlen > 0) {
216		if (tlen == len) {
217			MGETHDR(n, M_DONTWAIT, MT_DATA);
218			if (n == NULL) {
219				V_pfkeystat.in_nomem++;
220				return ENOBUFS;
221			}
222			n->m_len = MHLEN;
223		} else {
224			MGET(n, M_DONTWAIT, MT_DATA);
225			if (n == NULL) {
226				V_pfkeystat.in_nomem++;
227				return ENOBUFS;
228			}
229			n->m_len = MLEN;
230		}
231		if (tlen >= MCLBYTES) {	/*XXX better threshold? */
232			MCLGET(n, M_DONTWAIT);
233			if ((n->m_flags & M_EXT) == 0) {
234				m_free(n);
235				m_freem(m);
236				V_pfkeystat.in_nomem++;
237				return ENOBUFS;
238			}
239			n->m_len = MCLBYTES;
240		}
241
242		if (tlen < n->m_len)
243			n->m_len = tlen;
244		n->m_next = NULL;
245		if (m == NULL)
246			m = mprev = n;
247		else {
248			mprev->m_next = n;
249			mprev = n;
250		}
251		tlen -= n->m_len;
252		n = NULL;
253	}
254	m->m_pkthdr.len = len;
255	m->m_pkthdr.rcvif = NULL;
256	m_copyback(m, 0, len, (caddr_t)msg);
257
258	/* avoid duplicated statistics */
259	V_pfkeystat.in_total--;
260	V_pfkeystat.in_bytes -= len;
261	V_pfkeystat.in_msgtype[msg->sadb_msg_type]--;
262
263	return key_sendup_mbuf(so, m, target);
264}
265
266/* so can be NULL if target != KEY_SENDUP_ONE */
267int
268key_sendup_mbuf(so, m, target)
269	struct socket *so;
270	struct mbuf *m;
271	int target;
272{
273	INIT_VNET_NET(curvnet);
274	INIT_VNET_IPSEC(curvnet);
275	struct mbuf *n;
276	struct keycb *kp;
277	int sendup;
278	struct rawcb *rp;
279	int error = 0;
280
281	if (m == NULL)
282		panic("key_sendup_mbuf: NULL pointer was passed.\n");
283	if (so == NULL && target == KEY_SENDUP_ONE)
284		panic("%s: NULL pointer was passed.\n", __func__);
285
286	V_pfkeystat.in_total++;
287	V_pfkeystat.in_bytes += m->m_pkthdr.len;
288	if (m->m_len < sizeof(struct sadb_msg)) {
289		m = m_pullup(m, sizeof(struct sadb_msg));
290		if (m == NULL) {
291			V_pfkeystat.in_nomem++;
292			return ENOBUFS;
293		}
294	}
295	if (m->m_len >= sizeof(struct sadb_msg)) {
296		struct sadb_msg *msg;
297		msg = mtod(m, struct sadb_msg *);
298		V_pfkeystat.in_msgtype[msg->sadb_msg_type]++;
299	}
300	mtx_lock(&rawcb_mtx);
301	LIST_FOREACH(rp, &V_rawcb_list, list)
302	{
303		if (rp->rcb_proto.sp_family != PF_KEY)
304			continue;
305		if (rp->rcb_proto.sp_protocol
306		 && rp->rcb_proto.sp_protocol != PF_KEY_V2) {
307			continue;
308		}
309
310		kp = (struct keycb *)rp;
311
312		/*
313		 * If you are in promiscuous mode, and when you get broadcasted
314		 * reply, you'll get two PF_KEY messages.
315		 * (based on pf_key@inner.net message on 14 Oct 1998)
316		 */
317		if (((struct keycb *)rp)->kp_promisc) {
318			if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
319				(void)key_sendup0(rp, n, 1);
320				n = NULL;
321			}
322		}
323
324		/* the exact target will be processed later */
325		if (so && sotorawcb(so) == rp)
326			continue;
327
328		sendup = 0;
329		switch (target) {
330		case KEY_SENDUP_ONE:
331			/* the statement has no effect */
332			if (so && sotorawcb(so) == rp)
333				sendup++;
334			break;
335		case KEY_SENDUP_ALL:
336			sendup++;
337			break;
338		case KEY_SENDUP_REGISTERED:
339			if (kp->kp_registered)
340				sendup++;
341			break;
342		}
343		V_pfkeystat.in_msgtarget[target]++;
344
345		if (!sendup)
346			continue;
347
348		if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
349			m_freem(m);
350			V_pfkeystat.in_nomem++;
351			mtx_unlock(&rawcb_mtx);
352			return ENOBUFS;
353		}
354
355		if ((error = key_sendup0(rp, n, 0)) != 0) {
356			m_freem(m);
357			mtx_unlock(&rawcb_mtx);
358			return error;
359		}
360
361		n = NULL;
362	}
363
364	if (so) {
365		error = key_sendup0(sotorawcb(so), m, 0);
366		m = NULL;
367	} else {
368		error = 0;
369		m_freem(m);
370	}
371	mtx_unlock(&rawcb_mtx);
372	return error;
373}
374
375/*
376 * key_abort()
377 * derived from net/rtsock.c:rts_abort()
378 */
379static void
380key_abort(struct socket *so)
381{
382	raw_usrreqs.pru_abort(so);
383}
384
385/*
386 * key_attach()
387 * derived from net/rtsock.c:rts_attach()
388 */
389static int
390key_attach(struct socket *so, int proto, struct thread *td)
391{
392	INIT_VNET_IPSEC(curvnet);
393	struct keycb *kp;
394	int error;
395
396	KASSERT(so->so_pcb == NULL, ("key_attach: so_pcb != NULL"));
397
398	if (td != NULL) {
399		error = priv_check(td, PRIV_NET_RAW);
400		if (error)
401			return error;
402	}
403
404	/* XXX */
405	kp = malloc(sizeof *kp, M_PCB, M_WAITOK | M_ZERO);
406	if (kp == 0)
407		return ENOBUFS;
408
409	so->so_pcb = (caddr_t)kp;
410	error = raw_attach(so, proto);
411	kp = (struct keycb *)sotorawcb(so);
412	if (error) {
413		free(kp, M_PCB);
414		so->so_pcb = (caddr_t) 0;
415		return error;
416	}
417
418	kp->kp_promisc = kp->kp_registered = 0;
419
420	if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
421		V_key_cb.key_count++;
422	V_key_cb.any_count++;
423	soisconnected(so);
424	so->so_options |= SO_USELOOPBACK;
425
426	return 0;
427}
428
429/*
430 * key_bind()
431 * derived from net/rtsock.c:rts_bind()
432 */
433static int
434key_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
435{
436  return EINVAL;
437}
438
439/*
440 * key_close()
441 * derived from net/rtsock.c:rts_close().
442 */
443static void
444key_close(struct socket *so)
445{
446
447	raw_usrreqs.pru_close(so);
448}
449
450/*
451 * key_connect()
452 * derived from net/rtsock.c:rts_connect()
453 */
454static int
455key_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
456{
457	return EINVAL;
458}
459
460/*
461 * key_detach()
462 * derived from net/rtsock.c:rts_detach()
463 */
464static void
465key_detach(struct socket *so)
466{
467	INIT_VNET_IPSEC(curvnet);
468	struct keycb *kp = (struct keycb *)sotorawcb(so);
469
470	KASSERT(kp != NULL, ("key_detach: kp == NULL"));
471	if (kp->kp_raw.rcb_proto.sp_protocol
472	    == PF_KEY) /* XXX: AF_KEY */
473		V_key_cb.key_count--;
474	V_key_cb.any_count--;
475
476	key_freereg(so);
477	raw_usrreqs.pru_detach(so);
478}
479
480/*
481 * key_disconnect()
482 * derived from net/rtsock.c:key_disconnect()
483 */
484static int
485key_disconnect(struct socket *so)
486{
487	return(raw_usrreqs.pru_disconnect(so));
488}
489
490/*
491 * key_peeraddr()
492 * derived from net/rtsock.c:rts_peeraddr()
493 */
494static int
495key_peeraddr(struct socket *so, struct sockaddr **nam)
496{
497	return(raw_usrreqs.pru_peeraddr(so, nam));
498}
499
500/*
501 * key_send()
502 * derived from net/rtsock.c:rts_send()
503 */
504static int
505key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
506	 struct mbuf *control, struct thread *td)
507{
508	return(raw_usrreqs.pru_send(so, flags, m, nam, control, td));
509}
510
511/*
512 * key_shutdown()
513 * derived from net/rtsock.c:rts_shutdown()
514 */
515static int
516key_shutdown(struct socket *so)
517{
518	return(raw_usrreqs.pru_shutdown(so));
519}
520
521/*
522 * key_sockaddr()
523 * derived from net/rtsock.c:rts_sockaddr()
524 */
525static int
526key_sockaddr(struct socket *so, struct sockaddr **nam)
527{
528	return(raw_usrreqs.pru_sockaddr(so, nam));
529}
530
531struct pr_usrreqs key_usrreqs = {
532	.pru_abort =		key_abort,
533	.pru_attach =		key_attach,
534	.pru_bind =		key_bind,
535	.pru_connect =		key_connect,
536	.pru_detach =		key_detach,
537	.pru_disconnect =	key_disconnect,
538	.pru_peeraddr =		key_peeraddr,
539	.pru_send =		key_send,
540	.pru_shutdown =		key_shutdown,
541	.pru_sockaddr =		key_sockaddr,
542	.pru_close =		key_close,
543};
544
545/* sysctl */
546SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
547
548/*
549 * Definitions of protocols supported in the KEY domain.
550 */
551
552extern struct domain keydomain;
553
554struct protosw keysw[] = {
555{
556	.pr_type =		SOCK_RAW,
557	.pr_domain =		&keydomain,
558	.pr_protocol =		PF_KEY_V2,
559	.pr_flags =		PR_ATOMIC|PR_ADDR,
560	.pr_output =		key_output,
561	.pr_ctlinput =		raw_ctlinput,
562	.pr_init =		raw_init,
563	.pr_usrreqs =		&key_usrreqs
564}
565};
566
567static void
568key_init0(void)
569{
570	INIT_VNET_IPSEC(curvnet);
571
572	bzero((caddr_t)&V_key_cb, sizeof(V_key_cb));
573	ipsec_init();
574	key_init();
575}
576
577struct domain keydomain = {
578	.dom_family =		PF_KEY,
579	.dom_name =		"key",
580	.dom_init =		key_init0,
581	.dom_protosw =		keysw,
582	.dom_protoswNPROTOSW =	&keysw[sizeof(keysw)/sizeof(keysw[0])]
583};
584
585DOMAIN_SET(key);
586