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