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