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