keysock.c revision 253088
185587Sobrien/*	$FreeBSD: head/sys/netipsec/keysock.c 253088 2013-07-09 10:08:13Z ae $	*/
285587Sobrien/*	$KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $	*/
385587Sobrien
485587Sobrien/*-
585587Sobrien * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
685587Sobrien * All rights reserved.
785587Sobrien *
885587Sobrien * Redistribution and use in source and binary forms, with or without
985587Sobrien * modification, are permitted provided that the following conditions
1085587Sobrien * are met:
1185587Sobrien * 1. Redistributions of source code must retain the above copyright
1285587Sobrien *    notice, this list of conditions and the following disclaimer.
1385587Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1485587Sobrien *    notice, this list of conditions and the following disclaimer in the
1585587Sobrien *    documentation and/or other materials provided with the distribution.
1685587Sobrien * 3. Neither the name of the project nor the names of its contributors
1785587Sobrien *    may be used to endorse or promote products derived from this software
1885587Sobrien *    without specific prior written permission.
1985587Sobrien *
2085587Sobrien * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
2185587Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2285587Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2385587Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2485587Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25170331Srafan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2685587Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27201989Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28201989Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29201989Sru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3085587Sobrien * SUCH DAMAGE.
3185587Sobrien */
3285587Sobrien
3385587Sobrien#include "opt_ipsec.h"
3485587Sobrien
3585587Sobrien/* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
3685587Sobrien
3785587Sobrien#include <sys/types.h>
3885587Sobrien#include <sys/param.h>
39118194Sru#include <sys/domain.h>
4085587Sobrien#include <sys/errno.h>
4185587Sobrien#include <sys/kernel.h>
4285587Sobrien#include <sys/lock.h>
4385587Sobrien#include <sys/malloc.h>
4485587Sobrien#include <sys/mbuf.h>
4585587Sobrien#include <sys/mutex.h>
4685587Sobrien#include <sys/priv.h>
4785587Sobrien#include <sys/protosw.h>
4885587Sobrien#include <sys/signalvar.h>
4985587Sobrien#include <sys/socket.h>
50170331Srafan#include <sys/socketvar.h>
5185587Sobrien#include <sys/sysctl.h>
5285587Sobrien#include <sys/systm.h>
5385587Sobrien
54170331Srafan#include <net/if.h>
5585587Sobrien#include <net/raw_cb.h>
5685587Sobrien#include <net/route.h>
5785587Sobrien#include <net/vnet.h>
5885587Sobrien
5985587Sobrien#include <netinet/in.h>
6085587Sobrien
6185587Sobrien#include <net/pfkeyv2.h>
6285587Sobrien#include <netipsec/key.h>
6385587Sobrien#include <netipsec/keysock.h>
6485587Sobrien#include <netipsec/key_debug.h>
6585587Sobrien#include <netipsec/ipsec.h>
6685587Sobrien
6785587Sobrien#include <machine/stdarg.h>
6885587Sobrien
6985587Sobrienstruct key_cb {
7085587Sobrien	int key_count;
7185587Sobrien	int any_count;
7285587Sobrien};
7385587Sobrienstatic VNET_DEFINE(struct key_cb, key_cb);
7485587Sobrien#define	V_key_cb		VNET(key_cb)
7585587Sobrien
7685587Sobrienstatic struct sockaddr key_src = { 2, PF_KEY, };
7785587Sobrien
7885587Sobrienstatic int key_sendup0 __P((struct rawcb *, struct mbuf *, int));
7985587Sobrien
8085587SobrienVNET_PCPUSTAT_DEFINE(struct pfkeystat, pfkeystat);
8185587SobrienVNET_PCPUSTAT_SYSINIT(pfkeystat);
82107806Sobrien
8385587Sobrien#ifdef VIMAGE
8485587SobrienVNET_PCPUSTAT_SYSUNINIT(pfkeystat);
8585587Sobrien#endif /* VIMAGE */
8685587Sobrien
8785587Sobrien/*
8885587Sobrien * key_output()
8985587Sobrien */
9085587Sobrienint
9185587Sobrienkey_output(struct mbuf *m, struct socket *so)
9285587Sobrien{
9385587Sobrien	struct sadb_msg *msg;
9485587Sobrien	int len, error = 0;
9585587Sobrien
9685587Sobrien	if (m == 0)
9785587Sobrien		panic("%s: NULL pointer was passed.\n", __func__);
9885587Sobrien
9985587Sobrien	PFKEYSTAT_INC(out_total);
10090902Sdes	PFKEYSTAT_ADD(out_bytes, m->m_pkthdr.len);
10185587Sobrien
10285587Sobrien	len = m->m_pkthdr.len;
10385587Sobrien	if (len < sizeof(struct sadb_msg)) {
10485587Sobrien		PFKEYSTAT_INC(out_tooshort);
10585587Sobrien		error = EINVAL;
10685587Sobrien		goto end;
10785587Sobrien	}
10885587Sobrien
10985587Sobrien	if (m->m_len < sizeof(struct sadb_msg)) {
11085587Sobrien		if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
11185587Sobrien			PFKEYSTAT_INC(out_nomem);
11285587Sobrien			error = ENOBUFS;
11385587Sobrien			goto end;
11485587Sobrien		}
11585587Sobrien	}
11685587Sobrien
11785587Sobrien	M_ASSERTPKTHDR(m);
11885587Sobrien
11985587Sobrien	KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
12085587Sobrien
12185587Sobrien	msg = mtod(m, struct sadb_msg *);
12285587Sobrien	PFKEYSTAT_INC(out_msgtype[msg->sadb_msg_type]);
12385587Sobrien	if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
124107806Sobrien		PFKEYSTAT_INC(out_invlen);
12585587Sobrien		error = EINVAL;
12685587Sobrien		goto end;
12785587Sobrien	}
12885587Sobrien
12985587Sobrien	error = key_parse(m, so);
13085587Sobrien	m = NULL;
13185587Sobrienend:
13285587Sobrien	if (m)
13385587Sobrien		m_freem(m);
13485587Sobrien	return error;
13585587Sobrien}
13685587Sobrien
13785587Sobrien/*
13885587Sobrien * send message to the socket.
13985587Sobrien */
14085587Sobrienstatic int
14185587Sobrienkey_sendup0(rp, m, promisc)
14285587Sobrien	struct rawcb *rp;
143315582Spfg	struct mbuf *m;
14485587Sobrien	int promisc;
14585587Sobrien{
14685587Sobrien	int error;
14785587Sobrien
14885587Sobrien	if (promisc) {
14985587Sobrien		struct sadb_msg *pmsg;
15085587Sobrien
15185587Sobrien		M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT);
15285587Sobrien		if (m && m->m_len < sizeof(struct sadb_msg))
15385587Sobrien			m = m_pullup(m, sizeof(struct sadb_msg));
15485587Sobrien		if (!m) {
15585587Sobrien			PFKEYSTAT_INC(in_nomem);
15685587Sobrien			m_freem(m);
15785587Sobrien			return ENOBUFS;
15885587Sobrien		}
15985587Sobrien		m->m_pkthdr.len += sizeof(*pmsg);
16085587Sobrien
16185587Sobrien		pmsg = mtod(m, struct sadb_msg *);
16285587Sobrien		bzero(pmsg, sizeof(*pmsg));
163315582Spfg		pmsg->sadb_msg_version = PF_KEY_V2;
16485587Sobrien		pmsg->sadb_msg_type = SADB_X_PROMISC;
16585587Sobrien		pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
16685587Sobrien		/* pid and seq? */
16785587Sobrien
16885587Sobrien		PFKEYSTAT_INC(in_msgtype[pmsg->sadb_msg_type]);
16985587Sobrien	}
17085587Sobrien
17185587Sobrien	if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src,
17285587Sobrien	    m, NULL)) {
17385587Sobrien		PFKEYSTAT_INC(in_nomem);
17485587Sobrien		m_freem(m);
17585587Sobrien		error = ENOBUFS;
17685587Sobrien	} else
17785587Sobrien		error = 0;
17885587Sobrien	sorwakeup(rp->rcb_socket);
17985587Sobrien	return error;
18085587Sobrien}
18185587Sobrien
18285587Sobrien/* XXX this interface should be obsoleted. */
18385587Sobrienint
18485587Sobrienkey_sendup(so, msg, len, target)
18585587Sobrien	struct socket *so;
18685587Sobrien	struct sadb_msg *msg;
18785587Sobrien	u_int len;
18885587Sobrien	int target;	/*target of the resulting message*/
189170331Srafan{
19085587Sobrien	struct mbuf *m, *n, *mprev;
19185587Sobrien	int tlen;
19285587Sobrien
19385587Sobrien	/* sanity check */
19485587Sobrien	if (so == 0 || msg == 0)
19585587Sobrien		panic("%s: NULL pointer was passed.\n", __func__);
19685587Sobrien
19785587Sobrien	KEYDEBUG(KEYDEBUG_KEY_DUMP,
19885587Sobrien		printf("%s: \n", __func__);
19985587Sobrien		kdebug_sadb(msg));
20085587Sobrien
20185587Sobrien	/*
20285587Sobrien	 * we increment statistics here, just in case we have ENOBUFS
20385587Sobrien	 * in this function.
20485587Sobrien	 */
20585587Sobrien	PFKEYSTAT_INC(in_total);
20685587Sobrien	PFKEYSTAT_ADD(in_bytes, len);
20785587Sobrien	PFKEYSTAT_INC(in_msgtype[msg->sadb_msg_type]);
20885587Sobrien
20985587Sobrien	/*
21085587Sobrien	 * Get mbuf chain whenever possible (not clusters),
21185587Sobrien	 * to save socket buffer.  We'll be generating many SADB_ACQUIRE
21285587Sobrien	 * messages to listening key sockets.  If we simply allocate clusters,
21385587Sobrien	 * sbappendaddr() will raise ENOBUFS due to too little sbspace().
214170331Srafan	 * sbspace() computes # of actual data bytes AND mbuf region.
21585587Sobrien	 *
21685587Sobrien	 * TODO: SADB_ACQUIRE filters should be implemented.
21785587Sobrien	 */
21885587Sobrien	tlen = len;
21985587Sobrien	m = mprev = NULL;
22085587Sobrien	while (tlen > 0) {
22185587Sobrien		if (tlen == len) {
22285587Sobrien			MGETHDR(n, M_NOWAIT, MT_DATA);
22385587Sobrien			if (n == NULL) {
22485587Sobrien				PFKEYSTAT_INC(in_nomem);
22585587Sobrien				return ENOBUFS;
22685587Sobrien			}
22785587Sobrien			n->m_len = MHLEN;
22885587Sobrien		} else {
22985587Sobrien			MGET(n, M_NOWAIT, MT_DATA);
23085587Sobrien			if (n == NULL) {
23185587Sobrien				PFKEYSTAT_INC(in_nomem);
23285587Sobrien				return ENOBUFS;
23385587Sobrien			}
23485587Sobrien			n->m_len = MLEN;
23585587Sobrien		}
23685587Sobrien		if (tlen >= MCLBYTES) {	/*XXX better threshold? */
237224731Sru			MCLGET(n, M_NOWAIT);
23885587Sobrien			if ((n->m_flags & M_EXT) == 0) {
23985587Sobrien				m_free(n);
24085587Sobrien				m_freem(m);
24185587Sobrien				PFKEYSTAT_INC(in_nomem);
24285587Sobrien				return ENOBUFS;
24385587Sobrien			}
24485587Sobrien			n->m_len = MCLBYTES;
24585587Sobrien		}
24685587Sobrien
24785587Sobrien		if (tlen < n->m_len)
24885587Sobrien			n->m_len = tlen;
24985587Sobrien		n->m_next = NULL;
25085587Sobrien		if (m == NULL)
251224731Sru			m = mprev = n;
25285587Sobrien		else {
25385587Sobrien			mprev->m_next = n;
25485587Sobrien			mprev = n;
25585587Sobrien		}
25685587Sobrien		tlen -= n->m_len;
257224731Sru		n = NULL;
25885587Sobrien	}
25985587Sobrien	m->m_pkthdr.len = len;
260224731Sru	m->m_pkthdr.rcvif = NULL;
26185587Sobrien	m_copyback(m, 0, len, (caddr_t)msg);
26285587Sobrien
26385587Sobrien	/* avoid duplicated statistics */
26485587Sobrien	PFKEYSTAT_ADD(in_total, -1);
26585587Sobrien	PFKEYSTAT_ADD(in_bytes, -len);
26685587Sobrien	PFKEYSTAT_ADD(in_msgtype[msg->sadb_msg_type], -1);
26785587Sobrien
26885587Sobrien	return key_sendup_mbuf(so, m, target);
26985587Sobrien}
27085587Sobrien
27185587Sobrien/* so can be NULL if target != KEY_SENDUP_ONE */
27285587Sobrienint
27385587Sobrienkey_sendup_mbuf(so, m, target)
27485587Sobrien	struct socket *so;
27585587Sobrien	struct mbuf *m;
27685587Sobrien	int target;
27785587Sobrien{
27885587Sobrien	struct mbuf *n;
27985587Sobrien	struct keycb *kp;
28085587Sobrien	int sendup;
28185587Sobrien	struct rawcb *rp;
28285587Sobrien	int error = 0;
28385587Sobrien
28485587Sobrien	if (m == NULL)
28585587Sobrien		panic("key_sendup_mbuf: NULL pointer was passed.\n");
28685587Sobrien	if (so == NULL && target == KEY_SENDUP_ONE)
28785587Sobrien		panic("%s: NULL pointer was passed.\n", __func__);
28885587Sobrien
28985587Sobrien	PFKEYSTAT_INC(in_total);
29085587Sobrien	PFKEYSTAT_ADD(in_bytes, m->m_pkthdr.len);
291201989Sru	if (m->m_len < sizeof(struct sadb_msg)) {
292201989Sru		m = m_pullup(m, sizeof(struct sadb_msg));
293201989Sru		if (m == NULL) {
294201989Sru			PFKEYSTAT_INC(in_nomem);
295201989Sru			return ENOBUFS;
296201989Sru		}
297201989Sru	}
298201989Sru	if (m->m_len >= sizeof(struct sadb_msg)) {
299201989Sru		struct sadb_msg *msg;
300201989Sru		msg = mtod(m, struct sadb_msg *);
301201989Sru		PFKEYSTAT_INC(in_msgtype[msg->sadb_msg_type]);
302107806Sobrien	}
303107806Sobrien	mtx_lock(&rawcb_mtx);
30485587Sobrien	LIST_FOREACH(rp, &V_rawcb_list, list)
305201989Sru	{
30685587Sobrien		if (rp->rcb_proto.sp_family != PF_KEY)
30785587Sobrien			continue;
30885587Sobrien		if (rp->rcb_proto.sp_protocol
30985587Sobrien		 && rp->rcb_proto.sp_protocol != PF_KEY_V2) {
31085587Sobrien			continue;
31185587Sobrien		}
31285587Sobrien
31385587Sobrien		kp = (struct keycb *)rp;
31485587Sobrien
31585587Sobrien		/*
31685587Sobrien		 * If you are in promiscuous mode, and when you get broadcasted
317224731Sru		 * reply, you'll get two PF_KEY messages.
31885587Sobrien		 * (based on pf_key@inner.net message on 14 Oct 1998)
31985587Sobrien		 */
32085587Sobrien		if (((struct keycb *)rp)->kp_promisc) {
32185587Sobrien			if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
32285587Sobrien				(void)key_sendup0(rp, n, 1);
323224731Sru				n = NULL;
324201989Sru			}
32585587Sobrien		}
32685587Sobrien
32785587Sobrien		/* the exact target will be processed later */
32885587Sobrien		if (so && sotorawcb(so) == rp)
329201989Sru			continue;
330201989Sru
331201989Sru		sendup = 0;
332201989Sru		switch (target) {
333170331Srafan		case KEY_SENDUP_ONE:
33485587Sobrien			/* the statement has no effect */
335201989Sru			if (so && sotorawcb(so) == rp)
33685587Sobrien				sendup++;
33785587Sobrien			break;
33885587Sobrien		case KEY_SENDUP_ALL:
33985587Sobrien			sendup++;
34085587Sobrien			break;
341170331Srafan		case KEY_SENDUP_REGISTERED:
34285587Sobrien			if (kp->kp_registered)
34385587Sobrien				sendup++;
34485587Sobrien			break;
34585587Sobrien		}
34685587Sobrien		PFKEYSTAT_INC(in_msgtarget[target]);
34785587Sobrien
34885587Sobrien		if (!sendup)
34985587Sobrien			continue;
35085587Sobrien
35185587Sobrien		if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
352107806Sobrien			m_freem(m);
35385587Sobrien			PFKEYSTAT_INC(in_nomem);
35485587Sobrien			mtx_unlock(&rawcb_mtx);
35585587Sobrien			return ENOBUFS;
35685587Sobrien		}
35785587Sobrien
35885587Sobrien		if ((error = key_sendup0(rp, n, 0)) != 0) {
35985587Sobrien			m_freem(m);
36085587Sobrien			mtx_unlock(&rawcb_mtx);
36185587Sobrien			return error;
36285587Sobrien		}
363170331Srafan
36485587Sobrien		n = NULL;
36585587Sobrien	}
36685587Sobrien
36785587Sobrien	if (so) {
36885587Sobrien		error = key_sendup0(sotorawcb(so), m, 0);
36985587Sobrien		m = NULL;
37085587Sobrien	} else {
37185587Sobrien		error = 0;
37285587Sobrien		m_freem(m);
37385587Sobrien	}
37485587Sobrien	mtx_unlock(&rawcb_mtx);
37585587Sobrien	return error;
37685587Sobrien}
37785587Sobrien
378315582Spfg/*
37985587Sobrien * key_abort()
38085587Sobrien * derived from net/rtsock.c:rts_abort()
38185587Sobrien */
38285587Sobrienstatic void
38385587Sobrienkey_abort(struct socket *so)
38485587Sobrien{
38585587Sobrien	raw_usrreqs.pru_abort(so);
38685587Sobrien}
38785587Sobrien
38885587Sobrien/*
38985587Sobrien * key_attach()
39085587Sobrien * derived from net/rtsock.c:rts_attach()
39185587Sobrien */
39285587Sobrienstatic int
39385587Sobrienkey_attach(struct socket *so, int proto, struct thread *td)
39485587Sobrien{
39585587Sobrien	struct keycb *kp;
39685587Sobrien	int error;
39785587Sobrien
39885587Sobrien	KASSERT(so->so_pcb == NULL, ("key_attach: so_pcb != NULL"));
39985587Sobrien
400170331Srafan	if (td != NULL) {
40185587Sobrien		error = priv_check(td, PRIV_NET_RAW);
40285587Sobrien		if (error)
40385587Sobrien			return error;
40485587Sobrien	}
405170331Srafan
40685587Sobrien	/* XXX */
40785587Sobrien	kp = malloc(sizeof *kp, M_PCB, M_WAITOK | M_ZERO);
40885587Sobrien	if (kp == 0)
40985587Sobrien		return ENOBUFS;
41085587Sobrien
41185587Sobrien	so->so_pcb = (caddr_t)kp;
41285587Sobrien	error = raw_attach(so, proto);
41385587Sobrien	kp = (struct keycb *)sotorawcb(so);
41485587Sobrien	if (error) {
415170331Srafan		free(kp, M_PCB);
416170331Srafan		so->so_pcb = (caddr_t) 0;
417170331Srafan		return error;
418170331Srafan	}
41985587Sobrien
42085587Sobrien	kp->kp_promisc = kp->kp_registered = 0;
42185587Sobrien
42285587Sobrien	if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
42385587Sobrien		V_key_cb.key_count++;
42485587Sobrien	V_key_cb.any_count++;
42585587Sobrien	soisconnected(so);
42685587Sobrien	so->so_options |= SO_USELOOPBACK;
42785587Sobrien
42885587Sobrien	return 0;
42985587Sobrien}
43085587Sobrien
43185587Sobrien/*
43285587Sobrien * key_bind()
43385587Sobrien * derived from net/rtsock.c:rts_bind()
43485587Sobrien */
43585587Sobrienstatic int
43685587Sobrienkey_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
43785587Sobrien{
43885587Sobrien  return EINVAL;
43985587Sobrien}
44085587Sobrien
44185587Sobrien/*
44285587Sobrien * key_close()
44385587Sobrien * derived from net/rtsock.c:rts_close().
44485587Sobrien */
44585587Sobrienstatic void
44685587Sobrienkey_close(struct socket *so)
44785587Sobrien{
44885587Sobrien
44985587Sobrien	raw_usrreqs.pru_close(so);
45085587Sobrien}
45185587Sobrien
45285587Sobrien/*
45385587Sobrien * key_connect()
45485587Sobrien * derived from net/rtsock.c:rts_connect()
45585587Sobrien */
45685587Sobrienstatic int
45785587Sobrienkey_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
45885587Sobrien{
45985587Sobrien	return EINVAL;
46085587Sobrien}
46185587Sobrien
46285587Sobrien/*
46385587Sobrien * key_detach()
46485587Sobrien * derived from net/rtsock.c:rts_detach()
46585587Sobrien */
46685587Sobrienstatic void
46785587Sobrienkey_detach(struct socket *so)
46885587Sobrien{
46985587Sobrien	struct keycb *kp = (struct keycb *)sotorawcb(so);
47085587Sobrien
47185587Sobrien	KASSERT(kp != NULL, ("key_detach: kp == NULL"));
47285587Sobrien	if (kp->kp_raw.rcb_proto.sp_protocol
47385587Sobrien	    == PF_KEY) /* XXX: AF_KEY */
47485587Sobrien		V_key_cb.key_count--;
47585587Sobrien	V_key_cb.any_count--;
476107806Sobrien
47785587Sobrien	key_freereg(so);
47885587Sobrien	raw_usrreqs.pru_detach(so);
47985587Sobrien}
48085587Sobrien
48185587Sobrien/*
48285587Sobrien * key_disconnect()
48385587Sobrien * derived from net/rtsock.c:key_disconnect()
48485587Sobrien */
48585587Sobrienstatic int
486107806Sobrienkey_disconnect(struct socket *so)
48785587Sobrien{
48885587Sobrien	return(raw_usrreqs.pru_disconnect(so));
48985587Sobrien}
49085587Sobrien
49185587Sobrien/*
49285587Sobrien * key_peeraddr()
49385587Sobrien * derived from net/rtsock.c:rts_peeraddr()
49485587Sobrien */
495170331Srafanstatic int
49685587Sobrienkey_peeraddr(struct socket *so, struct sockaddr **nam)
49785587Sobrien{
49885587Sobrien	return(raw_usrreqs.pru_peeraddr(so, nam));
49985587Sobrien}
50085587Sobrien
50185587Sobrien/*
50285587Sobrien * key_send()
50385587Sobrien * derived from net/rtsock.c:rts_send()
50485587Sobrien */
50585587Sobrienstatic int
506107806Sobrienkey_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
50785587Sobrien	 struct mbuf *control, struct thread *td)
50885587Sobrien{
50985587Sobrien	return(raw_usrreqs.pru_send(so, flags, m, nam, control, td));
51085587Sobrien}
51185587Sobrien
51285587Sobrien/*
513125601Sru * key_shutdown()
514125601Sru * derived from net/rtsock.c:rts_shutdown()
515125601Sru */
516125601Srustatic int
517125601Srukey_shutdown(struct socket *so)
518125601Sru{
51985587Sobrien	return(raw_usrreqs.pru_shutdown(so));
52085587Sobrien}
52185587Sobrien
52285587Sobrien/*
52385587Sobrien * key_sockaddr()
52485587Sobrien * derived from net/rtsock.c:rts_sockaddr()
52585587Sobrien */
526170331Srafanstatic int
52785587Sobrienkey_sockaddr(struct socket *so, struct sockaddr **nam)
52885587Sobrien{
52985587Sobrien	return(raw_usrreqs.pru_sockaddr(so, nam));
53085587Sobrien}
53185587Sobrien
53285587Sobrienstruct pr_usrreqs key_usrreqs = {
53385587Sobrien	.pru_abort =		key_abort,
53485587Sobrien	.pru_attach =		key_attach,
53585587Sobrien	.pru_bind =		key_bind,
53685587Sobrien	.pru_connect =		key_connect,
53785587Sobrien	.pru_detach =		key_detach,
53885587Sobrien	.pru_disconnect =	key_disconnect,
53985587Sobrien	.pru_peeraddr =		key_peeraddr,
54085587Sobrien	.pru_send =		key_send,
54185587Sobrien	.pru_shutdown =		key_shutdown,
54285587Sobrien	.pru_sockaddr =		key_sockaddr,
54385587Sobrien	.pru_close =		key_close,
54485587Sobrien};
54585587Sobrien
54685587Sobrien/* sysctl */
54785587SobrienSYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
54885587Sobrien
54985587Sobrien/*
55085587Sobrien * Definitions of protocols supported in the KEY domain.
55185587Sobrien */
552315582Spfg
55385587Sobrienextern struct domain keydomain;
55485587Sobrien
55585587Sobrienstruct protosw keysw[] = {
55685587Sobrien{
55785587Sobrien	.pr_type =		SOCK_RAW,
55885587Sobrien	.pr_domain =		&keydomain,
55985587Sobrien	.pr_protocol =		PF_KEY_V2,
56085587Sobrien	.pr_flags =		PR_ATOMIC|PR_ADDR,
56185587Sobrien	.pr_output =		key_output,
56285587Sobrien	.pr_ctlinput =		raw_ctlinput,
56385587Sobrien	.pr_init =		raw_init,
56485587Sobrien	.pr_usrreqs =		&key_usrreqs
565107806Sobrien}
56685587Sobrien};
56785587Sobrien
56885587Sobrienstatic void
56985587Sobrienkey_init0(void)
57085587Sobrien{
57185587Sobrien
572125601Sru	bzero((caddr_t)&V_key_cb, sizeof(V_key_cb));
573125601Sru	key_init();
574125601Sru}
575125601Sru
576125601Srustruct domain keydomain = {
577125601Sru	.dom_family =		PF_KEY,
57885587Sobrien	.dom_name =		"key",
57985587Sobrien	.dom_init =		key_init0,
58085587Sobrien#ifdef VIMAGE
58185587Sobrien	.dom_destroy =		key_destroy,
58285587Sobrien#endif
58385587Sobrien	.dom_protosw =		keysw,
584170331Srafan	.dom_protoswNPROTOSW =	&keysw[sizeof(keysw)/sizeof(keysw[0])]
58585587Sobrien};
58685587Sobrien
58785587SobrienVNET_DOMAIN_SET(key);
58885587Sobrien