Sync usage with man page.
[netbsd-mini2440.git] / sys / netipsec / keysock.c
blob1b94d095af20c7bd2b7f03e905b5d98499002a7c
1 /* $NetBSD: keysock.c,v 1.17 2009/03/14 14:46:10 dsl 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 $ */
5 /*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
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.
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.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: keysock.c,v 1.17 2009/03/14 14:46:10 dsl Exp $");
37 #include "opt_ipsec.h"
39 /* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
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>
55 #include <net/raw_cb.h>
56 #include <net/route.h>
58 #include <net/pfkeyv2.h>
59 #include <netipsec/key.h>
60 #include <netipsec/keysock.h>
61 #include <netipsec/key_debug.h>
63 #include <netipsec/ipsec_osdep.h>
64 #include <netipsec/ipsec_private.h>
66 #include <machine/stdarg.h>
68 typedef int pr_output_t (struct mbuf *, struct socket *);
70 struct key_cb {
71 int key_count;
72 int any_count;
74 static struct key_cb key_cb;
76 static struct sockaddr key_dst = {
77 .sa_len = 2,
78 .sa_family = PF_KEY,
80 static struct sockaddr key_src = {
81 .sa_len = 2,
82 .sa_family = PF_KEY,
86 static int key_sendup0(struct rawcb *, struct mbuf *, int, int);
88 int key_registered_sb_max = (NMBCLUSTERS * MHLEN); /* XXX arbitrary */
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
97 * key_output()
99 int
100 key_output(struct mbuf *m, ...)
102 struct sadb_msg *msg;
103 int len, error = 0;
104 int s;
105 struct socket *so;
106 va_list ap;
108 va_start(ap, m);
109 so = va_arg(ap, struct socket *);
110 va_end(ap);
112 if (m == 0)
113 panic("key_output: NULL pointer was passed");
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();
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;
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;
137 if ((m->m_flags & M_PKTHDR) == 0)
138 panic("key_output: not M_PKTHDR ??");
140 KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
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;
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;
162 * send message to the socket.
164 static int
165 key_sendup0(
166 struct rawcb *rp,
167 struct mbuf *m,
168 int promisc,
169 int sbprio
172 int error;
173 int ok;
175 if (promisc) {
176 struct sadb_msg *pmsg;
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 m_freem(m);
184 return ENOBUFS;
186 m->m_pkthdr.len += sizeof(*pmsg);
188 pmsg = mtod(m, struct sadb_msg *);
189 memset(pmsg, 0, sizeof(*pmsg));
190 pmsg->sadb_msg_version = PF_KEY_V2;
191 pmsg->sadb_msg_type = SADB_X_PROMISC;
192 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
193 /* pid and seq? */
195 PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE + pmsg->sadb_msg_type);
198 if (sbprio == 0)
199 ok = sbappendaddr(&rp->rcb_socket->so_rcv,
200 (struct sockaddr *)&key_src, m, NULL);
201 else
202 ok = sbappendaddrchain(&rp->rcb_socket->so_rcv,
203 (struct sockaddr *)&key_src, m, sbprio);
205 if (!ok) {
206 PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
207 m_freem(m);
208 error = ENOBUFS;
209 } else
210 error = 0;
211 sorwakeup(rp->rcb_socket);
212 return error;
215 /* XXX this interface should be obsoleted. */
217 key_sendup(struct socket *so, struct sadb_msg *msg, u_int len,
218 int target) /*target of the resulting message*/
220 struct mbuf *m, *n, *mprev;
221 int tlen;
223 /* sanity check */
224 if (so == 0 || msg == 0)
225 panic("key_sendup: NULL pointer was passed");
227 KEYDEBUG(KEYDEBUG_KEY_DUMP,
228 printf("key_sendup: \n");
229 kdebug_sadb(msg));
232 * we increment statistics here, just in case we have ENOBUFS
233 * in this function.
236 uint64_t *ps = PFKEY_STAT_GETREF();
237 ps[PFKEY_STAT_IN_TOTAL]++;
238 ps[PFKEY_STAT_IN_BYTES] += len;
239 ps[PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type]++;
240 PFKEY_STAT_PUTREF();
244 * Get mbuf chain whenever possible (not clusters),
245 * to save socket buffer. We'll be generating many SADB_ACQUIRE
246 * messages to listening key sockets. If we simply allocate clusters,
247 * sbappendaddr() will raise ENOBUFS due to too little sbspace().
248 * sbspace() computes # of actual data bytes AND mbuf region.
250 * TODO: SADB_ACQUIRE filters should be implemented.
252 tlen = len;
253 m = mprev = NULL;
254 while (tlen > 0) {
255 if (tlen == len) {
256 MGETHDR(n, M_DONTWAIT, MT_DATA);
257 n->m_len = MHLEN;
258 } else {
259 MGET(n, M_DONTWAIT, MT_DATA);
260 n->m_len = MLEN;
262 if (!n) {
263 PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
264 return ENOBUFS;
266 if (tlen >= MCLBYTES) { /*XXX better threshold? */
267 MCLGET(n, M_DONTWAIT);
268 if ((n->m_flags & M_EXT) == 0) {
269 m_free(n);
270 m_freem(m);
271 PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
272 return ENOBUFS;
274 n->m_len = MCLBYTES;
277 if (tlen < n->m_len)
278 n->m_len = tlen;
279 n->m_next = NULL;
280 if (m == NULL)
281 m = mprev = n;
282 else {
283 mprev->m_next = n;
284 mprev = n;
286 tlen -= n->m_len;
287 n = NULL;
289 m->m_pkthdr.len = len;
290 m->m_pkthdr.rcvif = NULL;
291 m_copyback(m, 0, len, msg);
293 /* avoid duplicated statistics */
295 uint64_t *ps = PFKEY_STAT_GETREF();
296 ps[PFKEY_STAT_IN_TOTAL]--;
297 ps[PFKEY_STAT_IN_BYTES] -= len;
298 ps[PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type]--;
299 PFKEY_STAT_PUTREF();
302 return key_sendup_mbuf(so, m, target);
305 /* so can be NULL if target != KEY_SENDUP_ONE */
307 key_sendup_mbuf(struct socket *so, struct mbuf *m,
308 int target/*, sbprio */)
310 struct mbuf *n;
311 struct keycb *kp;
312 int sendup;
313 struct rawcb *rp;
314 int error = 0;
315 int sbprio = 0; /* XXX should be a parameter */
317 if (m == NULL)
318 panic("key_sendup_mbuf: NULL pointer was passed");
319 if (so == NULL && target == KEY_SENDUP_ONE)
320 panic("key_sendup_mbuf: NULL pointer was passed");
323 * RFC 2367 says ACQUIRE and other kernel-generated messages
324 * are special. We treat all KEY_SENDUP_REGISTERED messages
325 * as special, delivering them to all registered sockets
326 * even if the socket is at or above its so->so_rcv.sb_max limits.
327 * The only constraint is that the so_rcv data fall below
328 * key_registered_sb_max.
329 * Doing that check here avoids reworking every key_sendup_mbuf()
330 * in the short term. . The rework will be done after a technical
331 * conensus that this approach is appropriate.
333 if (target == KEY_SENDUP_REGISTERED) {
334 sbprio = SB_PRIO_BESTEFFORT;
338 uint64_t *ps = PFKEY_STAT_GETREF();
339 ps[PFKEY_STAT_IN_TOTAL]++;
340 ps[PFKEY_STAT_IN_BYTES] += m->m_pkthdr.len;
341 PFKEY_STAT_PUTREF();
343 if (m->m_len < sizeof(struct sadb_msg)) {
344 #if 1
345 m = m_pullup(m, sizeof(struct sadb_msg));
346 if (m == NULL) {
347 PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
348 return ENOBUFS;
350 #else
351 /* don't bother pulling it up just for stats */
352 #endif
354 if (m->m_len >= sizeof(struct sadb_msg)) {
355 struct sadb_msg *msg;
356 msg = mtod(m, struct sadb_msg *);
357 PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type);
360 LIST_FOREACH(rp, &rawcb_list, rcb_list)
362 struct socket * kso = rp->rcb_socket;
363 if (rp->rcb_proto.sp_family != PF_KEY)
364 continue;
365 if (rp->rcb_proto.sp_protocol
366 && rp->rcb_proto.sp_protocol != PF_KEY_V2) {
367 continue;
370 kp = (struct keycb *)rp;
373 * If you are in promiscuous mode, and when you get broadcasted
374 * reply, you'll get two PF_KEY messages.
375 * (based on pf_key@inner.net message on 14 Oct 1998)
377 if (((struct keycb *)rp)->kp_promisc) {
378 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
379 (void)key_sendup0(rp, n, 1, 0);
380 n = NULL;
384 /* the exact target will be processed later */
385 if (so && sotorawcb(so) == rp)
386 continue;
388 sendup = 0;
389 switch (target) {
390 case KEY_SENDUP_ONE:
391 /* the statement has no effect */
392 if (so && sotorawcb(so) == rp)
393 sendup++;
394 break;
395 case KEY_SENDUP_ALL:
396 sendup++;
397 break;
398 case KEY_SENDUP_REGISTERED:
399 if (kp->kp_registered) {
400 if (kso->so_rcv.sb_cc <= key_registered_sb_max)
401 sendup++;
402 else
403 printf("keysock: "
404 "registered sendup dropped, "
405 "sb_cc %ld max %d\n",
406 kso->so_rcv.sb_cc,
407 key_registered_sb_max);
409 break;
411 PFKEY_STATINC(PFKEY_STAT_IN_MSGTARGET + target);
413 if (!sendup)
414 continue;
416 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
417 m_freem(m);
418 PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
419 return ENOBUFS;
422 if ((error = key_sendup0(rp, n, 0, 0)) != 0) {
423 m_freem(m);
424 return error;
427 n = NULL;
430 /* The 'later' time for processing the exact target has arrived */
431 if (so) {
432 error = key_sendup0(sotorawcb(so), m, 0, sbprio);
433 m = NULL;
434 } else {
435 error = 0;
436 m_freem(m);
438 return error;
441 #ifdef __FreeBSD__
444 * key_abort()
445 * derived from net/rtsock.c:rts_abort()
447 static int
448 key_abort(struct socket *so)
450 int s, error;
451 s = splnet(); /* FreeBSD */
452 error = raw_usrreqs.pru_abort(so);
453 splx(s);
454 return error;
458 * key_attach()
459 * derived from net/rtsock.c:rts_attach()
461 static int
462 key_attach(struct socket *so, int proto, struct proc *td)
464 struct keycb *kp;
465 int s, error;
467 if (sotorawcb(so) != 0)
468 return EISCONN; /* XXX panic? */
469 kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK|M_ZERO); /* XXX */
470 if (kp == 0)
471 return ENOBUFS;
474 * The spl[soft]net() is necessary to block protocols from sending
475 * error notifications (like RTM_REDIRECT or RTM_LOSING) while
476 * this PCB is extant but incompletely initialized.
477 * Probably we should try to do more of this work beforehand and
478 * eliminate the spl.
480 s = splnet(); /* FreeBSD */
481 so->so_pcb = kp;
482 error = raw_usrreqs.pru_attach(so, proto, td);
483 kp = (struct keycb *)sotorawcb(so);
484 if (error) {
485 free(kp, M_PCB);
486 so->so_pcb = NULL;
487 splx(s);
488 return error;
491 kp->kp_promisc = kp->kp_registered = 0;
493 if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
494 key_cb.key_count++;
495 key_cb.any_count++;
496 kp->kp_raw.rcb_laddr = &key_src;
497 kp->kp_raw.rcb_faddr = &key_dst;
498 soisconnected(so);
499 so->so_options |= SO_USELOOPBACK;
501 splx(s);
502 return 0;
506 * key_bind()
507 * derived from net/rtsock.c:rts_bind()
509 static int
510 key_bind(struct socket *so, struct sockaddr *nam, struct proc *td)
512 int s, error;
513 s = splnet(); /* FreeBSD */
514 error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */
515 splx(s);
516 return error;
520 * key_connect()
521 * derived from net/rtsock.c:rts_connect()
523 static int
524 key_connect(struct socket *so, struct sockaddr *nam, struct proc *td)
526 int s, error;
527 s = splnet(); /* FreeBSD */
528 error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */
529 splx(s);
530 return error;
534 * key_detach()
535 * derived from net/rtsock.c:rts_detach()
537 static int
538 key_detach(struct socket *so)
540 struct keycb *kp = (struct keycb *)sotorawcb(so);
541 int s, error;
543 s = splnet(); /* FreeBSD */
544 if (kp != 0) {
545 if (kp->kp_raw.rcb_proto.sp_protocol
546 == PF_KEY) /* XXX: AF_KEY */
547 key_cb.key_count--;
548 key_cb.any_count--;
550 key_freereg(so);
552 error = raw_usrreqs.pru_detach(so);
553 splx(s);
554 return error;
558 * key_disconnect()
559 * derived from net/rtsock.c:key_disconnect()
561 static int
562 key_disconnect(struct socket *so)
564 int s, error;
565 s = splnet(); /* FreeBSD */
566 error = raw_usrreqs.pru_disconnect(so);
567 splx(s);
568 return error;
572 * key_peeraddr()
573 * derived from net/rtsock.c:rts_peeraddr()
575 static int
576 key_peeraddr(struct socket *so, struct sockaddr **nam)
578 int s, error;
579 s = splnet(); /* FreeBSD */
580 error = raw_usrreqs.pru_peeraddr(so, nam);
581 splx(s);
582 return error;
586 * key_send()
587 * derived from net/rtsock.c:rts_send()
589 static int
590 key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
591 struct mbuf *control, struct proc *td)
593 int s, error;
594 s = splnet(); /* FreeBSD */
595 error = raw_usrreqs.pru_send(so, flags, m, nam, control, td);
596 splx(s);
597 return error;
601 * key_shutdown()
602 * derived from net/rtsock.c:rts_shutdown()
604 static int
605 key_shutdown(struct socket *so)
607 int s, error;
608 s = splnet(); /* FreeBSD */
609 error = raw_usrreqs.pru_shutdown(so);
610 splx(s);
611 return error;
615 * key_sockaddr()
616 * derived from net/rtsock.c:rts_sockaddr()
618 static int
619 key_sockaddr(struct socket *so, struct sockaddr **nam)
621 int s, error;
622 s = splnet(); /* FreeBSD */
623 error = raw_usrreqs.pru_sockaddr(so, nam);
624 splx(s);
625 return error;
627 #else /*!__FreeBSD__ -- traditional proto_usrreq() switch */
630 * key_usrreq()
631 * derived from net/rtsock.c:route_usrreq()
634 key_usrreq(struct socket *so, int req,struct mbuf *m, struct mbuf *nam,
635 struct mbuf *control, struct lwp *l)
637 int error = 0;
638 struct keycb *kp = (struct keycb *)sotorawcb(so);
639 int s;
641 s = splsoftnet();
642 if (req == PRU_ATTACH) {
643 kp = (struct keycb *)malloc(sizeof(*kp), M_PCB, M_WAITOK);
644 sosetlock(so);
645 so->so_pcb = kp;
646 if (so->so_pcb)
647 memset(so->so_pcb, 0, sizeof(*kp));
649 if (req == PRU_DETACH && kp) {
650 int af = kp->kp_raw.rcb_proto.sp_protocol;
651 if (af == PF_KEY) /* XXX: AF_KEY */
652 key_cb.key_count--;
653 key_cb.any_count--;
655 key_freereg(so);
658 error = raw_usrreq(so, req, m, nam, control, l);
659 m = control = NULL; /* reclaimed in raw_usrreq */
660 kp = (struct keycb *)sotorawcb(so);
661 if (req == PRU_ATTACH && kp) {
662 int af = kp->kp_raw.rcb_proto.sp_protocol;
663 if (error) {
664 PFKEY_STATINC(PFKEY_STAT_SOCKERR);
665 free(kp, M_PCB);
666 so->so_pcb = NULL;
667 splx(s);
668 return (error);
671 kp->kp_promisc = kp->kp_registered = 0;
673 if (af == PF_KEY) /* XXX: AF_KEY */
674 key_cb.key_count++;
675 key_cb.any_count++;
676 kp->kp_raw.rcb_laddr = &key_src;
677 kp->kp_raw.rcb_faddr = &key_dst;
678 soisconnected(so);
679 so->so_options |= SO_USELOOPBACK;
681 splx(s);
682 return (error);
684 #endif /*!__FreeBSD__*/
686 /* sysctl */
687 #ifdef SYSCTL_NODE
688 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
689 #endif /* SYSCTL_NODE */
692 * Definitions of protocols supported in the KEY domain.
695 #ifdef __FreeBSD__
696 extern struct domain keydomain;
698 struct pr_usrreqs key_usrreqs = {
699 key_abort, pru_accept_notsupp, key_attach, key_bind,
700 key_connect,
701 pru_connect2_notsupp, pru_control_notsupp, key_detach,
702 key_disconnect, pru_listen_notsupp, key_peeraddr,
703 pru_rcvd_notsupp,
704 pru_rcvoob_notsupp, key_send, pru_sense_null, key_shutdown,
705 key_sockaddr, sosend, soreceive, sopoll
708 struct protosw keysw[] = {
709 { SOCK_RAW, &keydomain, PF_KEY_V2, PR_ATOMIC|PR_ADDR,
710 0, (pr_output_t *)key_output, raw_ctlinput, 0,
712 raw_init, 0, 0, 0,
713 &key_usrreqs
717 static void
718 key_init0(void)
720 memset(&key_cb, 0, sizeof(key_cb));
721 key_init();
724 struct domain keydomain =
725 { PF_KEY, "key", key_init0, 0, 0,
726 keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] };
728 DOMAIN_SET(key);
730 #else /* !__FreeBSD__ */
732 DOMAIN_DEFINE(keydomain);
734 const struct protosw keysw[] = {
736 .pr_type = SOCK_RAW,
737 .pr_domain = &keydomain,
738 .pr_protocol = PF_KEY_V2,
739 .pr_flags = PR_ATOMIC|PR_ADDR,
740 .pr_output = key_output,
741 .pr_ctlinput = raw_ctlinput,
742 .pr_usrreq = key_usrreq,
743 .pr_init = raw_init,
747 struct domain keydomain = {
748 .dom_family = PF_KEY,
749 .dom_name = "key",
750 .dom_init = key_init,
751 .dom_protosw = keysw,
752 .dom_protoswNPROTOSW = &keysw[__arraycount(keysw)],
755 #endif