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