keysock.c revision 1.23 1 /* $NetBSD: keysock.c,v 1.23 2014/05/19 02:51:25 rmind 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.23 2014/05/19 02:51:25 rmind 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/kmem.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 (at) 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 static int
627 key_attach(struct socket *so, int proto)
628 {
629 struct keycb *kp;
630 int s, error;
631
632 KASSERT(sotorawcb(so) == NULL);
633 kp = kmem_zalloc(sizeof(*kp), KM_SLEEP);
634 so->so_pcb = kp;
635
636 s = splsoftnet();
637 error = raw_attach(so, proto);
638 if (error) {
639 PFKEY_STATINC(PFKEY_STAT_SOCKERR);
640 kmem_free(kp, sizeof(*kp));
641 so->so_pcb = NULL;
642 goto out;
643 }
644
645 kp->kp_promisc = kp->kp_registered = 0;
646
647 if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
648 key_cb.key_count++;
649 key_cb.any_count++;
650 kp->kp_raw.rcb_laddr = &key_src;
651 kp->kp_raw.rcb_faddr = &key_dst;
652 soisconnected(so);
653 so->so_options |= SO_USELOOPBACK;
654 out:
655 KASSERT(solocked(so));
656 splx(s);
657 return error;
658 }
659
660 static void
661 key_detach(struct socket *so)
662 {
663 struct keycb *kp = (struct keycb *)sotorawcb(so);
664 int s;
665
666 KASSERT(solocked(so));
667 KASSERT(kp != NULL);
668
669 s = splsoftnet();
670 if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
671 key_cb.key_count--;
672 key_cb.any_count--;
673 key_freereg(so);
674 raw_detach(so);
675 splx(s);
676 }
677
678 /*
679 * key_usrreq()
680 * derived from net/rtsock.c:route_usrreq()
681 */
682 static int
683 key_usrreq(struct socket *so, int req,struct mbuf *m, struct mbuf *nam,
684 struct mbuf *control, struct lwp *l)
685 {
686 int s, error = 0;
687
688 KASSERT(req != PRU_ATTACH);
689 KASSERT(req != PRU_DETACH);
690
691 s = splsoftnet();
692 error = raw_usrreq(so, req, m, nam, control, l);
693 m = control = NULL; /* reclaimed in raw_usrreq */
694 splx(s);
695
696 return error;
697 }
698 #endif /*!__FreeBSD__*/
699
700 /* sysctl */
701 #ifdef SYSCTL_NODE
702 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
703 #endif /* SYSCTL_NODE */
704
705 /*
706 * Definitions of protocols supported in the KEY domain.
707 */
708
709 #ifdef __FreeBSD__
710 extern struct domain keydomain;
711
712 struct pr_usrreqs key_usrreqs = {
713 key_abort, pru_accept_notsupp, key_attach, key_bind,
714 key_connect,
715 pru_connect2_notsupp, pru_control_notsupp, key_detach,
716 key_disconnect, pru_listen_notsupp, key_peeraddr,
717 pru_rcvd_notsupp,
718 pru_rcvoob_notsupp, key_send, pru_sense_null, key_shutdown,
719 key_sockaddr, sosend, soreceive, sopoll
720 };
721
722 struct protosw keysw[] = {
723 { SOCK_RAW, &keydomain, PF_KEY_V2, PR_ATOMIC|PR_ADDR,
724 0, (pr_output_t *)key_output, raw_ctlinput, 0,
725 0,
726 raw_init, 0, 0, 0,
727 &key_usrreqs
728 }
729 };
730
731 static void
732 key_init0(void)
733 {
734 memset(&key_cb, 0, sizeof(key_cb));
735 key_init();
736 }
737
738 struct domain keydomain =
739 { PF_KEY, "key", key_init0, 0, 0,
740 keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] };
741
742 DOMAIN_SET(key);
743
744 #else /* !__FreeBSD__ */
745
746 DOMAIN_DEFINE(keydomain);
747
748 PR_WRAP_USRREQ(key_usrreq)
749
750 #define key_usrreq key_usrreq_wrapper
751
752 const struct pr_usrreqs key_usrreqs = {
753 .pr_attach = key_attach,
754 .pr_detach = key_detach,
755 .pr_generic = key_usrreq,
756 };
757
758 const struct protosw keysw[] = {
759 {
760 .pr_type = SOCK_RAW,
761 .pr_domain = &keydomain,
762 .pr_protocol = PF_KEY_V2,
763 .pr_flags = PR_ATOMIC|PR_ADDR,
764 .pr_output = key_output,
765 .pr_ctlinput = raw_ctlinput,
766 .pr_usrreqs = &key_usrreqs,
767 .pr_init = raw_init,
768 }
769 };
770
771 struct domain keydomain = {
772 .dom_family = PF_KEY,
773 .dom_name = "key",
774 .dom_init = key_init,
775 .dom_protosw = keysw,
776 .dom_protoswNPROTOSW = &keysw[__arraycount(keysw)],
777 };
778
779 #endif
780