keysock.c revision 1.16
1/*	$NetBSD: keysock.c,v 1.16 2008/04/24 11:38:38 ad Exp $	*/
2/*	$FreeBSD: src/sys/netipsec/keysock.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $	*/
3/*	$KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $	*/
4
5/*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__KERNEL_RCSID(0, "$NetBSD: keysock.c,v 1.16 2008/04/24 11:38:38 ad Exp $");
36
37#include "opt_ipsec.h"
38
39/* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
40
41#include <sys/types.h>
42#include <sys/param.h>
43#include <sys/domain.h>
44#include <sys/errno.h>
45#include <sys/kernel.h>
46#include <sys/malloc.h>
47#include <sys/mbuf.h>
48#include <sys/protosw.h>
49#include <sys/signalvar.h>
50#include <sys/socket.h>
51#include <sys/socketvar.h>
52#include <sys/sysctl.h>
53#include <sys/systm.h>
54
55#include <net/raw_cb.h>
56#include <net/route.h>
57
58#include <net/pfkeyv2.h>
59#include <netipsec/key.h>
60#include <netipsec/keysock.h>
61#include <netipsec/key_debug.h>
62
63#include <netipsec/ipsec_osdep.h>
64#include <netipsec/ipsec_private.h>
65
66#include <machine/stdarg.h>
67
68typedef int	pr_output_t (struct mbuf *, struct socket *);
69
70struct key_cb {
71	int key_count;
72	int any_count;
73};
74static struct key_cb key_cb;
75
76static struct sockaddr key_dst = {
77    .sa_len = 2,
78    .sa_family = PF_KEY,
79};
80static struct sockaddr key_src = {
81    .sa_len = 2,
82    .sa_family = PF_KEY,
83};
84
85
86static int key_sendup0 __P((struct rawcb *, struct mbuf *, int, int));
87
88int key_registered_sb_max = (NMBCLUSTERS * MHLEN); /* XXX arbitrary */
89
90/* XXX sysctl */
91#ifdef __FreeBSD__
92SYSCTL_INT(_net_key, OID_AUTO, registered_sbmax, CTLFLAG_RD,
93    &key_registered_sb_max , 0, "Maximum kernel-to-user PFKEY datagram size");
94#endif
95
96/*
97 * key_output()
98 */
99int
100key_output(struct mbuf *m, ...)
101{
102	struct sadb_msg *msg;
103	int len, error = 0;
104	int s;
105	struct socket *so;
106	va_list ap;
107
108	va_start(ap, m);
109	so = va_arg(ap, struct socket *);
110	va_end(ap);
111
112	if (m == 0)
113		panic("key_output: NULL pointer was passed");
114
115	{
116		uint64_t *ps = PFKEY_STAT_GETREF();
117		ps[PFKEY_STAT_OUT_TOTAL]++;
118		ps[PFKEY_STAT_OUT_BYTES] += m->m_pkthdr.len;
119		PFKEY_STAT_PUTREF();
120	}
121
122	len = m->m_pkthdr.len;
123	if (len < sizeof(struct sadb_msg)) {
124		PFKEY_STATINC(PFKEY_STAT_OUT_TOOSHORT);
125		error = EINVAL;
126		goto end;
127	}
128
129	if (m->m_len < sizeof(struct sadb_msg)) {
130		if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
131			PFKEY_STATINC(PFKEY_STAT_OUT_NOMEM);
132			error = ENOBUFS;
133			goto end;
134		}
135	}
136
137	if ((m->m_flags & M_PKTHDR) == 0)
138		panic("key_output: not M_PKTHDR ??");
139
140	KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
141
142	msg = mtod(m, struct sadb_msg *);
143	PFKEY_STATINC(PFKEY_STAT_OUT_MSGTYPE + msg->sadb_msg_type);
144	if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
145		PFKEY_STATINC(PFKEY_STAT_OUT_INVLEN);
146		error = EINVAL;
147		goto end;
148	}
149
150	/*XXX giant lock*/
151	s = splsoftnet();
152	error = key_parse(m, so);
153	m = NULL;
154	splx(s);
155end:
156	if (m)
157		m_freem(m);
158	return error;
159}
160
161/*
162 * send message to the socket.
163 */
164static int
165key_sendup0(
166    struct rawcb *rp,
167    struct mbuf *m,
168    int promisc,
169    int sbprio
170)
171{
172	int error;
173	int ok;
174
175	if (promisc) {
176		struct sadb_msg *pmsg;
177
178		M_PREPEND(m, sizeof(struct sadb_msg), M_DONTWAIT);
179		if (m && m->m_len < sizeof(struct sadb_msg))
180			m = m_pullup(m, sizeof(struct sadb_msg));
181		if (!m) {
182			PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
183			m_freem(m);
184			return ENOBUFS;
185		}
186		m->m_pkthdr.len += sizeof(*pmsg);
187
188		pmsg = mtod(m, struct sadb_msg *);
189		bzero(pmsg, sizeof(*pmsg));
190		pmsg->sadb_msg_version = PF_KEY_V2;
191		pmsg->sadb_msg_type = SADB_X_PROMISC;
192		pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
193		/* pid and seq? */
194
195		PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE + pmsg->sadb_msg_type);
196	}
197
198	if (sbprio == 0)
199		ok = sbappendaddr(&rp->rcb_socket->so_rcv,
200			       (struct sockaddr *)&key_src, m, NULL);
201	else
202		ok = sbappendaddrchain(&rp->rcb_socket->so_rcv,
203			       (struct sockaddr *)&key_src, m, sbprio);
204
205	  if (!ok) {
206		PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
207		m_freem(m);
208		error = ENOBUFS;
209	} else
210		error = 0;
211	sorwakeup(rp->rcb_socket);
212	return error;
213}
214
215/* XXX this interface should be obsoleted. */
216int
217key_sendup(struct socket *so, struct sadb_msg *msg, u_int len,
218	   int target)	/*target of the resulting message*/
219{
220	struct mbuf *m, *n, *mprev;
221	int tlen;
222
223	/* sanity check */
224	if (so == 0 || msg == 0)
225		panic("key_sendup: NULL pointer was passed");
226
227	KEYDEBUG(KEYDEBUG_KEY_DUMP,
228		printf("key_sendup: \n");
229		kdebug_sadb(msg));
230
231	/*
232	 * we increment statistics here, just in case we have ENOBUFS
233	 * in this function.
234	 */
235	{
236		uint64_t *ps = PFKEY_STAT_GETREF();
237		ps[PFKEY_STAT_IN_TOTAL]++;
238		ps[PFKEY_STAT_IN_BYTES] += len;
239		ps[PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type]++;
240		PFKEY_STAT_PUTREF();
241	}
242
243	/*
244	 * Get mbuf chain whenever possible (not clusters),
245	 * to save socket buffer.  We'll be generating many SADB_ACQUIRE
246	 * messages to listening key sockets.  If we simply allocate clusters,
247	 * sbappendaddr() will raise ENOBUFS due to too little sbspace().
248	 * sbspace() computes # of actual data bytes AND mbuf region.
249	 *
250	 * TODO: SADB_ACQUIRE filters should be implemented.
251	 */
252	tlen = len;
253	m = mprev = NULL;
254	while (tlen > 0) {
255		if (tlen == len) {
256			MGETHDR(n, M_DONTWAIT, MT_DATA);
257			n->m_len = MHLEN;
258		} else {
259			MGET(n, M_DONTWAIT, MT_DATA);
260			n->m_len = MLEN;
261		}
262		if (!n) {
263			PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
264			return ENOBUFS;
265		}
266		if (tlen >= MCLBYTES) {	/*XXX better threshold? */
267			MCLGET(n, M_DONTWAIT);
268			if ((n->m_flags & M_EXT) == 0) {
269				m_free(n);
270				m_freem(m);
271				PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
272				return ENOBUFS;
273			}
274			n->m_len = MCLBYTES;
275		}
276
277		if (tlen < n->m_len)
278			n->m_len = tlen;
279		n->m_next = NULL;
280		if (m == NULL)
281			m = mprev = n;
282		else {
283			mprev->m_next = n;
284			mprev = n;
285		}
286		tlen -= n->m_len;
287		n = NULL;
288	}
289	m->m_pkthdr.len = len;
290	m->m_pkthdr.rcvif = NULL;
291	m_copyback(m, 0, len, msg);
292
293	/* avoid duplicated statistics */
294	{
295		uint64_t *ps = PFKEY_STAT_GETREF();
296		ps[PFKEY_STAT_IN_TOTAL]--;
297		ps[PFKEY_STAT_IN_BYTES] -= len;
298		ps[PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type]--;
299		PFKEY_STAT_PUTREF();
300	}
301
302	return key_sendup_mbuf(so, m, target);
303}
304
305/* so can be NULL if target != KEY_SENDUP_ONE */
306int
307key_sendup_mbuf(struct socket *so, struct mbuf *m,
308		int target/*, sbprio */)
309{
310	struct mbuf *n;
311	struct keycb *kp;
312	int sendup;
313	struct rawcb *rp;
314	int error = 0;
315	int sbprio = 0; /* XXX should be a parameter */
316
317	if (m == NULL)
318		panic("key_sendup_mbuf: NULL pointer was passed");
319	if (so == NULL && target == KEY_SENDUP_ONE)
320		panic("key_sendup_mbuf: NULL pointer was passed");
321
322	/*
323	 * RFC 2367 says ACQUIRE and other kernel-generated messages
324	 * are special. We treat all KEY_SENDUP_REGISTERED messages
325	 * as special, delivering them to all registered sockets
326	 * even if the socket is at or above its so->so_rcv.sb_max limits.
327	 * The only constraint is that the  so_rcv data fall below
328	 * key_registered_sb_max.
329	 * Doing that check here avoids reworking every key_sendup_mbuf()
330	 * in the short term. . The rework will be done after a technical
331	 * conensus that this approach is appropriate.
332 	 */
333	if (target == KEY_SENDUP_REGISTERED) {
334		sbprio = SB_PRIO_BESTEFFORT;
335	}
336
337	{
338		uint64_t *ps = PFKEY_STAT_GETREF();
339		ps[PFKEY_STAT_IN_TOTAL]++;
340		ps[PFKEY_STAT_IN_BYTES] += m->m_pkthdr.len;
341		PFKEY_STAT_PUTREF();
342	}
343	if (m->m_len < sizeof(struct sadb_msg)) {
344#if 1
345		m = m_pullup(m, sizeof(struct sadb_msg));
346		if (m == NULL) {
347			PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
348			return ENOBUFS;
349		}
350#else
351		/* don't bother pulling it up just for stats */
352#endif
353	}
354	if (m->m_len >= sizeof(struct sadb_msg)) {
355		struct sadb_msg *msg;
356		msg = mtod(m, struct sadb_msg *);
357		PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type);
358	}
359
360	LIST_FOREACH(rp, &rawcb_list, rcb_list)
361	{
362		struct socket * kso = rp->rcb_socket;
363		if (rp->rcb_proto.sp_family != PF_KEY)
364			continue;
365		if (rp->rcb_proto.sp_protocol
366		 && rp->rcb_proto.sp_protocol != PF_KEY_V2) {
367			continue;
368		}
369
370		kp = (struct keycb *)rp;
371
372		/*
373		 * If you are in promiscuous mode, and when you get broadcasted
374		 * reply, you'll get two PF_KEY messages.
375		 * (based on pf_key@inner.net message on 14 Oct 1998)
376		 */
377		if (((struct keycb *)rp)->kp_promisc) {
378			if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
379				(void)key_sendup0(rp, n, 1, 0);
380				n = NULL;
381			}
382		}
383
384		/* the exact target will be processed later */
385		if (so && sotorawcb(so) == rp)
386			continue;
387
388		sendup = 0;
389		switch (target) {
390		case KEY_SENDUP_ONE:
391			/* the statement has no effect */
392			if (so && sotorawcb(so) == rp)
393				sendup++;
394			break;
395		case KEY_SENDUP_ALL:
396			sendup++;
397			break;
398		case KEY_SENDUP_REGISTERED:
399			if (kp->kp_registered) {
400				if (kso->so_rcv.sb_cc <= key_registered_sb_max)
401					sendup++;
402			  	else
403			  		printf("keysock: "
404					       "registered sendup dropped, "
405					       "sb_cc %ld max %d\n",
406					       kso->so_rcv.sb_cc,
407					       key_registered_sb_max);
408			}
409			break;
410		}
411		PFKEY_STATINC(PFKEY_STAT_IN_MSGTARGET + target);
412
413		if (!sendup)
414			continue;
415
416		if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
417			m_freem(m);
418			PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
419			return ENOBUFS;
420		}
421
422		if ((error = key_sendup0(rp, n, 0, 0)) != 0) {
423			m_freem(m);
424			return error;
425		}
426
427		n = NULL;
428	}
429
430	/* The 'later' time for processing the exact target has arrived */
431	if (so) {
432		error = key_sendup0(sotorawcb(so), m, 0, sbprio);
433		m = NULL;
434	} else {
435		error = 0;
436		m_freem(m);
437	}
438	return error;
439}
440
441#ifdef __FreeBSD__
442
443/*
444 * key_abort()
445 * derived from net/rtsock.c:rts_abort()
446 */
447static int
448key_abort(struct socket *so)
449{
450	int s, error;
451	s = splnet(); 	/* FreeBSD */
452	error = raw_usrreqs.pru_abort(so);
453	splx(s);
454	return error;
455}
456
457/*
458 * key_attach()
459 * derived from net/rtsock.c:rts_attach()
460 */
461static int
462key_attach(struct socket *so, int proto, struct proc *td)
463{
464	struct keycb *kp;
465	int s, error;
466
467	if (sotorawcb(so) != 0)
468		return EISCONN;	/* XXX panic? */
469	kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK|M_ZERO); /* XXX */
470	if (kp == 0)
471		return ENOBUFS;
472
473	/*
474	 * The spl[soft]net() is necessary to block protocols from sending
475	 * error notifications (like RTM_REDIRECT or RTM_LOSING) while
476	 * this PCB is extant but incompletely initialized.
477	 * Probably we should try to do more of this work beforehand and
478	 * eliminate the spl.
479	 */
480	s = splnet();	/* FreeBSD */
481	so->so_pcb = kp;
482	error = raw_usrreqs.pru_attach(so, proto, td);
483	kp = (struct keycb *)sotorawcb(so);
484	if (error) {
485		free(kp, M_PCB);
486		so->so_pcb = NULL;
487		splx(s);
488		return error;
489	}
490
491	kp->kp_promisc = kp->kp_registered = 0;
492
493	if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
494		key_cb.key_count++;
495	key_cb.any_count++;
496	kp->kp_raw.rcb_laddr = &key_src;
497	kp->kp_raw.rcb_faddr = &key_dst;
498	soisconnected(so);
499	so->so_options |= SO_USELOOPBACK;
500
501	splx(s);
502	return 0;
503}
504
505/*
506 * key_bind()
507 * derived from net/rtsock.c:rts_bind()
508 */
509static int
510key_bind(struct socket *so, struct sockaddr *nam, struct proc *td)
511{
512	int s, error;
513	s = splnet();	/* FreeBSD */
514	error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */
515	splx(s);
516	return error;
517}
518
519/*
520 * key_connect()
521 * derived from net/rtsock.c:rts_connect()
522 */
523static int
524key_connect(struct socket *so, struct sockaddr *nam, struct proc *td)
525{
526	int s, error;
527	s = splnet();	/* FreeBSD */
528	error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */
529	splx(s);
530	return error;
531}
532
533/*
534 * key_detach()
535 * derived from net/rtsock.c:rts_detach()
536 */
537static int
538key_detach(struct socket *so)
539{
540	struct keycb *kp = (struct keycb *)sotorawcb(so);
541	int s, error;
542
543	s = splnet();	/* FreeBSD */
544	if (kp != 0) {
545		if (kp->kp_raw.rcb_proto.sp_protocol
546		    == PF_KEY) /* XXX: AF_KEY */
547			key_cb.key_count--;
548		key_cb.any_count--;
549
550		key_freereg(so);
551	}
552	error = raw_usrreqs.pru_detach(so);
553	splx(s);
554	return error;
555}
556
557/*
558 * key_disconnect()
559 * derived from net/rtsock.c:key_disconnect()
560 */
561static int
562key_disconnect(struct socket *so)
563{
564	int s, error;
565	s = splnet();	/* FreeBSD */
566	error = raw_usrreqs.pru_disconnect(so);
567	splx(s);
568	return error;
569}
570
571/*
572 * key_peeraddr()
573 * derived from net/rtsock.c:rts_peeraddr()
574 */
575static int
576key_peeraddr(struct socket *so, struct sockaddr **nam)
577{
578	int s, error;
579	s = splnet();	/* FreeBSD */
580	error = raw_usrreqs.pru_peeraddr(so, nam);
581	splx(s);
582	return error;
583}
584
585/*
586 * key_send()
587 * derived from net/rtsock.c:rts_send()
588 */
589static int
590key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
591	 struct mbuf *control, struct proc *td)
592{
593	int s, error;
594	s = splnet();	/* FreeBSD */
595	error = raw_usrreqs.pru_send(so, flags, m, nam, control, td);
596	splx(s);
597	return error;
598}
599
600/*
601 * key_shutdown()
602 * derived from net/rtsock.c:rts_shutdown()
603 */
604static int
605key_shutdown(struct socket *so)
606{
607	int s, error;
608	s = splnet();	/* FreeBSD */
609	error = raw_usrreqs.pru_shutdown(so);
610	splx(s);
611	return error;
612}
613
614/*
615 * key_sockaddr()
616 * derived from net/rtsock.c:rts_sockaddr()
617 */
618static int
619key_sockaddr(struct socket *so, struct sockaddr **nam)
620{
621	int s, error;
622	s = splnet();	/* FreeBSD */
623	error = raw_usrreqs.pru_sockaddr(so, nam);
624	splx(s);
625	return error;
626}
627#else /*!__FreeBSD__ -- traditional proto_usrreq() switch */
628
629/*
630 * key_usrreq()
631 * derived from net/rtsock.c:route_usrreq()
632 */
633int
634key_usrreq(struct socket *so, int req,struct mbuf *m, struct mbuf *nam,
635	   struct mbuf *control, struct lwp *l)
636{
637	int error = 0;
638	struct keycb *kp = (struct keycb *)sotorawcb(so);
639	int s;
640
641	s = splsoftnet();
642	if (req == PRU_ATTACH) {
643		kp = (struct keycb *)malloc(sizeof(*kp), M_PCB, M_WAITOK);
644		sosetlock(so);
645		so->so_pcb = kp;
646		if (so->so_pcb)
647			bzero(so->so_pcb, sizeof(*kp));
648	}
649	if (req == PRU_DETACH && kp) {
650		int af = kp->kp_raw.rcb_proto.sp_protocol;
651		if (af == PF_KEY) /* XXX: AF_KEY */
652			key_cb.key_count--;
653		key_cb.any_count--;
654
655		key_freereg(so);
656	}
657
658	error = raw_usrreq(so, req, m, nam, control, l);
659	m = control = NULL;	/* reclaimed in raw_usrreq */
660	kp = (struct keycb *)sotorawcb(so);
661	if (req == PRU_ATTACH && kp) {
662		int af = kp->kp_raw.rcb_proto.sp_protocol;
663		if (error) {
664			PFKEY_STATINC(PFKEY_STAT_SOCKERR);
665			free(kp, M_PCB);
666			so->so_pcb = NULL;
667			splx(s);
668			return (error);
669		}
670
671		kp->kp_promisc = kp->kp_registered = 0;
672
673		if (af == PF_KEY) /* XXX: AF_KEY */
674			key_cb.key_count++;
675		key_cb.any_count++;
676		kp->kp_raw.rcb_laddr = &key_src;
677		kp->kp_raw.rcb_faddr = &key_dst;
678		soisconnected(so);
679		so->so_options |= SO_USELOOPBACK;
680	}
681	splx(s);
682	return (error);
683}
684#endif /*!__FreeBSD__*/
685
686/* sysctl */
687#ifdef SYSCTL_NODE
688SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
689#endif /* SYSCTL_NODE */
690
691/*
692 * Definitions of protocols supported in the KEY domain.
693 */
694
695#ifdef __FreeBSD__
696extern struct domain keydomain;
697
698struct pr_usrreqs key_usrreqs = {
699	key_abort, pru_accept_notsupp, key_attach, key_bind,
700	key_connect,
701	pru_connect2_notsupp, pru_control_notsupp, key_detach,
702	key_disconnect, pru_listen_notsupp, key_peeraddr,
703	pru_rcvd_notsupp,
704	pru_rcvoob_notsupp, key_send, pru_sense_null, key_shutdown,
705	key_sockaddr, sosend, soreceive, sopoll
706};
707
708struct protosw keysw[] = {
709{ SOCK_RAW,	&keydomain,	PF_KEY_V2,	PR_ATOMIC|PR_ADDR,
710  0,		(pr_output_t *)key_output,	raw_ctlinput, 0,
711  0,
712  raw_init,	0,		0,		0,
713  &key_usrreqs
714}
715};
716
717static void
718key_init0(void)
719{
720	bzero(&key_cb, sizeof(key_cb));
721	key_init();
722}
723
724struct domain keydomain =
725    { PF_KEY, "key", key_init0, 0, 0,
726      keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] };
727
728DOMAIN_SET(key);
729
730#else /* !__FreeBSD__ */
731
732DOMAIN_DEFINE(keydomain);
733
734const struct protosw keysw[] = {
735    {
736	.pr_type = SOCK_RAW,
737	.pr_domain = &keydomain,
738	.pr_protocol = PF_KEY_V2,
739	.pr_flags = PR_ATOMIC|PR_ADDR,
740	.pr_output = key_output,
741	.pr_ctlinput = raw_ctlinput,
742	.pr_usrreq = key_usrreq,
743	.pr_init = raw_init,
744    }
745};
746
747struct domain keydomain = {
748    .dom_family = PF_KEY,
749    .dom_name = "key",
750    .dom_init = key_init,
751    .dom_protosw = keysw,
752    .dom_protoswNPROTOSW = &keysw[__arraycount(keysw)],
753};
754
755#endif
756