1105197Ssam/*	$FreeBSD$	*/
2105197Ssam/*	$KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $	*/
3105197Ssam
4139823Simp/*-
5105197Ssam * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6105197Ssam * All rights reserved.
7105197Ssam *
8105197Ssam * Redistribution and use in source and binary forms, with or without
9105197Ssam * modification, are permitted provided that the following conditions
10105197Ssam * are met:
11105197Ssam * 1. Redistributions of source code must retain the above copyright
12105197Ssam *    notice, this list of conditions and the following disclaimer.
13105197Ssam * 2. Redistributions in binary form must reproduce the above copyright
14105197Ssam *    notice, this list of conditions and the following disclaimer in the
15105197Ssam *    documentation and/or other materials provided with the distribution.
16105197Ssam * 3. Neither the name of the project nor the names of its contributors
17105197Ssam *    may be used to endorse or promote products derived from this software
18105197Ssam *    without specific prior written permission.
19105197Ssam *
20105197Ssam * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21105197Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22105197Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23105197Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24105197Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25105197Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26105197Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27105197Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28105197Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29105197Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30105197Ssam * SUCH DAMAGE.
31105197Ssam */
32105197Ssam
33105197Ssam#include "opt_ipsec.h"
34105197Ssam
35105197Ssam/* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
36105197Ssam
37105197Ssam#include <sys/types.h>
38105197Ssam#include <sys/param.h>
39105197Ssam#include <sys/domain.h>
40105197Ssam#include <sys/errno.h>
41105197Ssam#include <sys/kernel.h>
42130955Sbms#include <sys/lock.h>
43105197Ssam#include <sys/malloc.h>
44105197Ssam#include <sys/mbuf.h>
45130955Sbms#include <sys/mutex.h>
46173574Sbz#include <sys/priv.h>
47105197Ssam#include <sys/protosw.h>
48105197Ssam#include <sys/signalvar.h>
49105197Ssam#include <sys/socket.h>
50105197Ssam#include <sys/socketvar.h>
51105197Ssam#include <sys/sysctl.h>
52105197Ssam#include <sys/systm.h>
53105197Ssam
54183550Szec#include <net/if.h>
55105197Ssam#include <net/raw_cb.h>
56185571Sbz#include <net/vnet.h>
57105197Ssam
58183550Szec#include <netinet/in.h>
59183550Szec
60105197Ssam#include <net/pfkeyv2.h>
61105197Ssam#include <netipsec/key.h>
62105197Ssam#include <netipsec/keysock.h>
63105197Ssam#include <netipsec/key_debug.h>
64183550Szec#include <netipsec/ipsec.h>
65105197Ssam
66105197Ssam#include <machine/stdarg.h>
67105197Ssam
68195699Srwatsonstruct key_cb {
69195699Srwatson	int key_count;
70195699Srwatson	int any_count;
71195699Srwatson};
72215701Sdimstatic VNET_DEFINE(struct key_cb, key_cb);
73195727Srwatson#define	V_key_cb		VNET(key_cb)
74105197Ssam
75195699Srwatsonstatic struct sockaddr key_src = { 2, PF_KEY, };
76105197Ssam
77283902Saestatic int key_sendup0(struct rawcb *, struct mbuf *, int);
78105197Ssam
79253088SaeVNET_PCPUSTAT_DEFINE(struct pfkeystat, pfkeystat);
80253088SaeVNET_PCPUSTAT_SYSINIT(pfkeystat);
81195699Srwatson
82253088Sae#ifdef VIMAGE
83253088SaeVNET_PCPUSTAT_SYSUNINIT(pfkeystat);
84253088Sae#endif /* VIMAGE */
85253088Sae
86105197Ssam/*
87105197Ssam * key_output()
88105197Ssam */
89105197Ssamint
90154625Sbzkey_output(struct mbuf *m, struct socket *so)
91105197Ssam{
92105197Ssam	struct sadb_msg *msg;
93105197Ssam	int len, error = 0;
94105197Ssam
95105197Ssam	if (m == 0)
96120585Ssam		panic("%s: NULL pointer was passed.\n", __func__);
97105197Ssam
98252028Sae	PFKEYSTAT_INC(out_total);
99252028Sae	PFKEYSTAT_ADD(out_bytes, m->m_pkthdr.len);
100105197Ssam
101105197Ssam	len = m->m_pkthdr.len;
102105197Ssam	if (len < sizeof(struct sadb_msg)) {
103252028Sae		PFKEYSTAT_INC(out_tooshort);
104105197Ssam		error = EINVAL;
105105197Ssam		goto end;
106105197Ssam	}
107105197Ssam
108105197Ssam	if (m->m_len < sizeof(struct sadb_msg)) {
109105197Ssam		if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
110252028Sae			PFKEYSTAT_INC(out_nomem);
111105197Ssam			error = ENOBUFS;
112105197Ssam			goto end;
113105197Ssam		}
114105197Ssam	}
115105197Ssam
116113255Sdes	M_ASSERTPKTHDR(m);
117105197Ssam
118105197Ssam	KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
119105197Ssam
120105197Ssam	msg = mtod(m, struct sadb_msg *);
121252028Sae	PFKEYSTAT_INC(out_msgtype[msg->sadb_msg_type]);
122105197Ssam	if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
123252028Sae		PFKEYSTAT_INC(out_invlen);
124105197Ssam		error = EINVAL;
125105197Ssam		goto end;
126105197Ssam	}
127105197Ssam
128105197Ssam	error = key_parse(m, so);
129105197Ssam	m = NULL;
130105197Ssamend:
131105197Ssam	if (m)
132105197Ssam		m_freem(m);
133105197Ssam	return error;
134105197Ssam}
135105197Ssam
136105197Ssam/*
137105197Ssam * send message to the socket.
138105197Ssam */
139105197Ssamstatic int
140283902Saekey_sendup0(struct rawcb *rp, struct mbuf *m, int promisc)
141105197Ssam{
142105197Ssam	int error;
143105197Ssam
144105197Ssam	if (promisc) {
145105197Ssam		struct sadb_msg *pmsg;
146105197Ssam
147243882Sglebius		M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT);
148275825Sae		if (m == NULL) {
149252028Sae			PFKEYSTAT_INC(in_nomem);
150275825Sae			return (ENOBUFS);
151105197Ssam		}
152105197Ssam		pmsg = mtod(m, struct sadb_msg *);
153105197Ssam		bzero(pmsg, sizeof(*pmsg));
154105197Ssam		pmsg->sadb_msg_version = PF_KEY_V2;
155105197Ssam		pmsg->sadb_msg_type = SADB_X_PROMISC;
156105197Ssam		pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
157105197Ssam		/* pid and seq? */
158105197Ssam
159252028Sae		PFKEYSTAT_INC(in_msgtype[pmsg->sadb_msg_type]);
160105197Ssam	}
161105197Ssam
162185348Szec	if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src,
163105197Ssam	    m, NULL)) {
164252028Sae		PFKEYSTAT_INC(in_nomem);
165105197Ssam		m_freem(m);
166105197Ssam		error = ENOBUFS;
167105197Ssam	} else
168105197Ssam		error = 0;
169105197Ssam	sorwakeup(rp->rcb_socket);
170105197Ssam	return error;
171105197Ssam}
172105197Ssam
173105197Ssam/* XXX this interface should be obsoleted. */
174105197Ssamint
175283902Saekey_sendup(struct socket *so, struct sadb_msg *msg, u_int len, int target)
176105197Ssam{
177105197Ssam	struct mbuf *m, *n, *mprev;
178105197Ssam	int tlen;
179105197Ssam
180105197Ssam	/* sanity check */
181105197Ssam	if (so == 0 || msg == 0)
182120585Ssam		panic("%s: NULL pointer was passed.\n", __func__);
183105197Ssam
184105197Ssam	KEYDEBUG(KEYDEBUG_KEY_DUMP,
185120585Ssam		printf("%s: \n", __func__);
186105197Ssam		kdebug_sadb(msg));
187105197Ssam
188105197Ssam	/*
189105197Ssam	 * we increment statistics here, just in case we have ENOBUFS
190105197Ssam	 * in this function.
191105197Ssam	 */
192252028Sae	PFKEYSTAT_INC(in_total);
193252028Sae	PFKEYSTAT_ADD(in_bytes, len);
194252028Sae	PFKEYSTAT_INC(in_msgtype[msg->sadb_msg_type]);
195105197Ssam
196105197Ssam	/*
197105197Ssam	 * Get mbuf chain whenever possible (not clusters),
198105197Ssam	 * to save socket buffer.  We'll be generating many SADB_ACQUIRE
199105197Ssam	 * messages to listening key sockets.  If we simply allocate clusters,
200105197Ssam	 * sbappendaddr() will raise ENOBUFS due to too little sbspace().
201105197Ssam	 * sbspace() computes # of actual data bytes AND mbuf region.
202105197Ssam	 *
203105197Ssam	 * TODO: SADB_ACQUIRE filters should be implemented.
204105197Ssam	 */
205105197Ssam	tlen = len;
206105197Ssam	m = mprev = NULL;
207105197Ssam	while (tlen > 0) {
208105197Ssam		if (tlen == len) {
209243882Sglebius			MGETHDR(n, M_NOWAIT, MT_DATA);
210171133Sgnn			if (n == NULL) {
211252028Sae				PFKEYSTAT_INC(in_nomem);
212171133Sgnn				return ENOBUFS;
213171133Sgnn			}
214105197Ssam			n->m_len = MHLEN;
215105197Ssam		} else {
216243882Sglebius			MGET(n, M_NOWAIT, MT_DATA);
217171133Sgnn			if (n == NULL) {
218252028Sae				PFKEYSTAT_INC(in_nomem);
219171133Sgnn				return ENOBUFS;
220171133Sgnn			}
221105197Ssam			n->m_len = MLEN;
222105197Ssam		}
223105197Ssam		if (tlen >= MCLBYTES) {	/*XXX better threshold? */
224243882Sglebius			MCLGET(n, M_NOWAIT);
225105197Ssam			if ((n->m_flags & M_EXT) == 0) {
226105197Ssam				m_free(n);
227105197Ssam				m_freem(m);
228252028Sae				PFKEYSTAT_INC(in_nomem);
229105197Ssam				return ENOBUFS;
230105197Ssam			}
231105197Ssam			n->m_len = MCLBYTES;
232105197Ssam		}
233105197Ssam
234105197Ssam		if (tlen < n->m_len)
235105197Ssam			n->m_len = tlen;
236105197Ssam		n->m_next = NULL;
237105197Ssam		if (m == NULL)
238105197Ssam			m = mprev = n;
239105197Ssam		else {
240105197Ssam			mprev->m_next = n;
241105197Ssam			mprev = n;
242105197Ssam		}
243105197Ssam		tlen -= n->m_len;
244105197Ssam		n = NULL;
245105197Ssam	}
246105197Ssam	m->m_pkthdr.len = len;
247105197Ssam	m->m_pkthdr.rcvif = NULL;
248105197Ssam	m_copyback(m, 0, len, (caddr_t)msg);
249105197Ssam
250105197Ssam	/* avoid duplicated statistics */
251252028Sae	PFKEYSTAT_ADD(in_total, -1);
252252028Sae	PFKEYSTAT_ADD(in_bytes, -len);
253252028Sae	PFKEYSTAT_ADD(in_msgtype[msg->sadb_msg_type], -1);
254105197Ssam
255105197Ssam	return key_sendup_mbuf(so, m, target);
256105197Ssam}
257105197Ssam
258105197Ssam/* so can be NULL if target != KEY_SENDUP_ONE */
259105197Ssamint
260283902Saekey_sendup_mbuf(struct socket *so, struct mbuf *m, int target)
261105197Ssam{
262105197Ssam	struct mbuf *n;
263105197Ssam	struct keycb *kp;
264105197Ssam	int sendup;
265105197Ssam	struct rawcb *rp;
266105197Ssam	int error = 0;
267105197Ssam
268105197Ssam	if (m == NULL)
269105197Ssam		panic("key_sendup_mbuf: NULL pointer was passed.\n");
270105197Ssam	if (so == NULL && target == KEY_SENDUP_ONE)
271120585Ssam		panic("%s: NULL pointer was passed.\n", __func__);
272105197Ssam
273252028Sae	PFKEYSTAT_INC(in_total);
274252028Sae	PFKEYSTAT_ADD(in_bytes, m->m_pkthdr.len);
275105197Ssam	if (m->m_len < sizeof(struct sadb_msg)) {
276105197Ssam		m = m_pullup(m, sizeof(struct sadb_msg));
277105197Ssam		if (m == NULL) {
278252028Sae			PFKEYSTAT_INC(in_nomem);
279105197Ssam			return ENOBUFS;
280105197Ssam		}
281105197Ssam	}
282105197Ssam	if (m->m_len >= sizeof(struct sadb_msg)) {
283105197Ssam		struct sadb_msg *msg;
284105197Ssam		msg = mtod(m, struct sadb_msg *);
285252028Sae		PFKEYSTAT_INC(in_msgtype[msg->sadb_msg_type]);
286105197Ssam	}
287171133Sgnn	mtx_lock(&rawcb_mtx);
288181803Sbz	LIST_FOREACH(rp, &V_rawcb_list, list)
289105197Ssam	{
290105197Ssam		if (rp->rcb_proto.sp_family != PF_KEY)
291105197Ssam			continue;
292105197Ssam		if (rp->rcb_proto.sp_protocol
293105197Ssam		 && rp->rcb_proto.sp_protocol != PF_KEY_V2) {
294105197Ssam			continue;
295105197Ssam		}
296105197Ssam
297105197Ssam		kp = (struct keycb *)rp;
298105197Ssam
299105197Ssam		/*
300105197Ssam		 * If you are in promiscuous mode, and when you get broadcasted
301105197Ssam		 * reply, you'll get two PF_KEY messages.
302105197Ssam		 * (based on pf_key@inner.net message on 14 Oct 1998)
303105197Ssam		 */
304105197Ssam		if (((struct keycb *)rp)->kp_promisc) {
305105197Ssam			if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
306105197Ssam				(void)key_sendup0(rp, n, 1);
307105197Ssam				n = NULL;
308105197Ssam			}
309105197Ssam		}
310105197Ssam
311105197Ssam		/* the exact target will be processed later */
312105197Ssam		if (so && sotorawcb(so) == rp)
313105197Ssam			continue;
314105197Ssam
315105197Ssam		sendup = 0;
316105197Ssam		switch (target) {
317105197Ssam		case KEY_SENDUP_ONE:
318105197Ssam			/* the statement has no effect */
319105197Ssam			if (so && sotorawcb(so) == rp)
320105197Ssam				sendup++;
321105197Ssam			break;
322105197Ssam		case KEY_SENDUP_ALL:
323105197Ssam			sendup++;
324105197Ssam			break;
325105197Ssam		case KEY_SENDUP_REGISTERED:
326105197Ssam			if (kp->kp_registered)
327105197Ssam				sendup++;
328105197Ssam			break;
329105197Ssam		}
330252028Sae		PFKEYSTAT_INC(in_msgtarget[target]);
331105197Ssam
332105197Ssam		if (!sendup)
333105197Ssam			continue;
334105197Ssam
335105197Ssam		if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
336105197Ssam			m_freem(m);
337252028Sae			PFKEYSTAT_INC(in_nomem);
338171133Sgnn			mtx_unlock(&rawcb_mtx);
339105197Ssam			return ENOBUFS;
340105197Ssam		}
341105197Ssam
342105197Ssam		if ((error = key_sendup0(rp, n, 0)) != 0) {
343105197Ssam			m_freem(m);
344171133Sgnn			mtx_unlock(&rawcb_mtx);
345105197Ssam			return error;
346105197Ssam		}
347105197Ssam
348105197Ssam		n = NULL;
349105197Ssam	}
350105197Ssam
351105197Ssam	if (so) {
352105197Ssam		error = key_sendup0(sotorawcb(so), m, 0);
353105197Ssam		m = NULL;
354105197Ssam	} else {
355105197Ssam		error = 0;
356105197Ssam		m_freem(m);
357105197Ssam	}
358171133Sgnn	mtx_unlock(&rawcb_mtx);
359105197Ssam	return error;
360105197Ssam}
361105197Ssam
362105197Ssam/*
363105197Ssam * key_abort()
364105197Ssam * derived from net/rtsock.c:rts_abort()
365105197Ssam */
366157366Srwatsonstatic void
367105197Ssamkey_abort(struct socket *so)
368105197Ssam{
369157366Srwatson	raw_usrreqs.pru_abort(so);
370105197Ssam}
371105197Ssam
372105197Ssam/*
373105197Ssam * key_attach()
374105197Ssam * derived from net/rtsock.c:rts_attach()
375105197Ssam */
376105197Ssamstatic int
377105197Ssamkey_attach(struct socket *so, int proto, struct thread *td)
378105197Ssam{
379105197Ssam	struct keycb *kp;
380171133Sgnn	int error;
381105197Ssam
382171133Sgnn	KASSERT(so->so_pcb == NULL, ("key_attach: so_pcb != NULL"));
383171133Sgnn
384173689Sbz	if (td != NULL) {
385173689Sbz		error = priv_check(td, PRIV_NET_RAW);
386173689Sbz		if (error)
387173689Sbz			return error;
388173689Sbz	}
389173689Sbz
390171133Sgnn	/* XXX */
391184205Sdes	kp = malloc(sizeof *kp, M_PCB, M_WAITOK | M_ZERO);
392105197Ssam	if (kp == 0)
393105197Ssam		return ENOBUFS;
394105197Ssam
395105197Ssam	so->so_pcb = (caddr_t)kp;
396171133Sgnn	error = raw_attach(so, proto);
397105197Ssam	kp = (struct keycb *)sotorawcb(so);
398105197Ssam	if (error) {
399105197Ssam		free(kp, M_PCB);
400105197Ssam		so->so_pcb = (caddr_t) 0;
401105197Ssam		return error;
402105197Ssam	}
403105197Ssam
404105197Ssam	kp->kp_promisc = kp->kp_registered = 0;
405105197Ssam
406105197Ssam	if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
407181803Sbz		V_key_cb.key_count++;
408181803Sbz	V_key_cb.any_count++;
409105197Ssam	soisconnected(so);
410105197Ssam	so->so_options |= SO_USELOOPBACK;
411105197Ssam
412105197Ssam	return 0;
413105197Ssam}
414105197Ssam
415105197Ssam/*
416105197Ssam * key_bind()
417105197Ssam * derived from net/rtsock.c:rts_bind()
418105197Ssam */
419105197Ssamstatic int
420105197Ssamkey_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
421105197Ssam{
422171133Sgnn  return EINVAL;
423105197Ssam}
424105197Ssam
425105197Ssam/*
426160549Srwatson * key_close()
427160549Srwatson * derived from net/rtsock.c:rts_close().
428160549Srwatson */
429160549Srwatsonstatic void
430160566Sgnnkey_close(struct socket *so)
431160549Srwatson{
432160549Srwatson
433160549Srwatson	raw_usrreqs.pru_close(so);
434160549Srwatson}
435160549Srwatson
436160549Srwatson/*
437105197Ssam * key_connect()
438105197Ssam * derived from net/rtsock.c:rts_connect()
439105197Ssam */
440105197Ssamstatic int
441105197Ssamkey_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
442105197Ssam{
443171133Sgnn	return EINVAL;
444105197Ssam}
445105197Ssam
446105197Ssam/*
447105197Ssam * key_detach()
448105197Ssam * derived from net/rtsock.c:rts_detach()
449105197Ssam */
450157370Srwatsonstatic void
451105197Ssamkey_detach(struct socket *so)
452105197Ssam{
453105197Ssam	struct keycb *kp = (struct keycb *)sotorawcb(so);
454105197Ssam
455157370Srwatson	KASSERT(kp != NULL, ("key_detach: kp == NULL"));
456157370Srwatson	if (kp->kp_raw.rcb_proto.sp_protocol
457157370Srwatson	    == PF_KEY) /* XXX: AF_KEY */
458181803Sbz		V_key_cb.key_count--;
459181803Sbz	V_key_cb.any_count--;
460105197Ssam
461157370Srwatson	key_freereg(so);
462157370Srwatson	raw_usrreqs.pru_detach(so);
463105197Ssam}
464105197Ssam
465105197Ssam/*
466105197Ssam * key_disconnect()
467105197Ssam * derived from net/rtsock.c:key_disconnect()
468105197Ssam */
469105197Ssamstatic int
470105197Ssamkey_disconnect(struct socket *so)
471105197Ssam{
472171133Sgnn	return(raw_usrreqs.pru_disconnect(so));
473105197Ssam}
474105197Ssam
475105197Ssam/*
476105197Ssam * key_peeraddr()
477105197Ssam * derived from net/rtsock.c:rts_peeraddr()
478105197Ssam */
479105197Ssamstatic int
480105197Ssamkey_peeraddr(struct socket *so, struct sockaddr **nam)
481105197Ssam{
482171133Sgnn	return(raw_usrreqs.pru_peeraddr(so, nam));
483105197Ssam}
484105197Ssam
485105197Ssam/*
486105197Ssam * key_send()
487105197Ssam * derived from net/rtsock.c:rts_send()
488105197Ssam */
489105197Ssamstatic int
490105197Ssamkey_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
491105197Ssam	 struct mbuf *control, struct thread *td)
492105197Ssam{
493171133Sgnn	return(raw_usrreqs.pru_send(so, flags, m, nam, control, td));
494105197Ssam}
495105197Ssam
496105197Ssam/*
497105197Ssam * key_shutdown()
498105197Ssam * derived from net/rtsock.c:rts_shutdown()
499105197Ssam */
500105197Ssamstatic int
501105197Ssamkey_shutdown(struct socket *so)
502105197Ssam{
503171133Sgnn	return(raw_usrreqs.pru_shutdown(so));
504105197Ssam}
505105197Ssam
506105197Ssam/*
507105197Ssam * key_sockaddr()
508105197Ssam * derived from net/rtsock.c:rts_sockaddr()
509105197Ssam */
510105197Ssamstatic int
511105197Ssamkey_sockaddr(struct socket *so, struct sockaddr **nam)
512105197Ssam{
513171133Sgnn	return(raw_usrreqs.pru_sockaddr(so, nam));
514105197Ssam}
515105197Ssam
516105197Ssamstruct pr_usrreqs key_usrreqs = {
517137386Sphk	.pru_abort =		key_abort,
518137386Sphk	.pru_attach =		key_attach,
519137386Sphk	.pru_bind =		key_bind,
520137386Sphk	.pru_connect =		key_connect,
521137386Sphk	.pru_detach =		key_detach,
522137386Sphk	.pru_disconnect =	key_disconnect,
523137386Sphk	.pru_peeraddr =		key_peeraddr,
524137386Sphk	.pru_send =		key_send,
525137386Sphk	.pru_shutdown =		key_shutdown,
526137386Sphk	.pru_sockaddr =		key_sockaddr,
527160549Srwatson	.pru_close =		key_close,
528105197Ssam};
529105197Ssam
530105197Ssam/* sysctl */
531105197SsamSYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
532105197Ssam
533105197Ssam/*
534105197Ssam * Definitions of protocols supported in the KEY domain.
535105197Ssam */
536105197Ssam
537105197Ssamextern struct domain keydomain;
538105197Ssam
539105197Ssamstruct protosw keysw[] = {
540152242Sru{
541152242Sru	.pr_type =		SOCK_RAW,
542152242Sru	.pr_domain =		&keydomain,
543152242Sru	.pr_protocol =		PF_KEY_V2,
544152242Sru	.pr_flags =		PR_ATOMIC|PR_ADDR,
545154625Sbz	.pr_output =		key_output,
546152242Sru	.pr_ctlinput =		raw_ctlinput,
547152242Sru	.pr_init =		raw_init,
548152242Sru	.pr_usrreqs =		&key_usrreqs
549105197Ssam}
550105197Ssam};
551105197Ssam
552105197Ssamstatic void
553105197Ssamkey_init0(void)
554105197Ssam{
555185088Szec
556181803Sbz	bzero((caddr_t)&V_key_cb, sizeof(V_key_cb));
557105197Ssam	key_init();
558105197Ssam}
559105197Ssam
560152242Srustruct domain keydomain = {
561152242Sru	.dom_family =		PF_KEY,
562152242Sru	.dom_name =		"key",
563152242Sru	.dom_init =		key_init0,
564193731Szec#ifdef VIMAGE
565193731Szec	.dom_destroy =		key_destroy,
566193731Szec#endif
567152242Sru	.dom_protosw =		keysw,
568152242Sru	.dom_protoswNPROTOSW =	&keysw[sizeof(keysw)/sizeof(keysw[0])]
569152242Sru};
570105197Ssam
571195837SrwatsonVNET_DOMAIN_SET(key);
572