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