1 /* $NetBSD: keysock.c,v 1.3 2003/12/04 19:38:25 atatat 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.3 2003/12/04 19:38:25 atatat 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
65 #include <machine/stdarg.h>
66
67 typedef int pr_output_t (struct mbuf *, struct socket *);
68
69 struct key_cb {
70 int key_count;
71 int any_count;
72 };
73 static struct key_cb key_cb;
74
75 static struct sockaddr key_dst = { 2, PF_KEY, };
76 static struct sockaddr key_src = { 2, PF_KEY, };
77
78 static int key_sendup0 __P((struct rawcb *, struct mbuf *, int));
79
80 struct pfkeystat pfkeystat;
81
82 /*
83 * key_output()
84 */
85 int
86 #if __STDC__
87 key_output(struct mbuf *m, ...)
88 #else
89 key_output(m, va_alist)
90 struct mbuf *m;
91 va_dcl
92 #endif
93 {
94 struct sadb_msg *msg;
95 int len, error = 0;
96 int s;
97 struct socket *so;
98 va_list ap;
99
100 va_start(ap, m);
101 so = va_arg(ap, struct socket *);
102 va_end(ap);
103
104 if (m == 0)
105 panic("key_output: NULL pointer was passed.\n");
106
107 pfkeystat.out_total++;
108 pfkeystat.out_bytes += m->m_pkthdr.len;
109
110 len = m->m_pkthdr.len;
111 if (len < sizeof(struct sadb_msg)) {
112 pfkeystat.out_tooshort++;
113 error = EINVAL;
114 goto end;
115 }
116
117 if (m->m_len < sizeof(struct sadb_msg)) {
118 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
119 pfkeystat.out_nomem++;
120 error = ENOBUFS;
121 goto end;
122 }
123 }
124
125 if ((m->m_flags & M_PKTHDR) == 0)
126 panic("key_output: not M_PKTHDR ??");
127
128 KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
129
130 msg = mtod(m, struct sadb_msg *);
131 pfkeystat.out_msgtype[msg->sadb_msg_type]++;
132 if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
133 pfkeystat.out_invlen++;
134 error = EINVAL;
135 goto end;
136 }
137
138 /*XXX giant lock*/
139 s = splsoftnet();
140 error = key_parse(m, so);
141 m = NULL;
142 splx(s);
143 end:
144 if (m)
145 m_freem(m);
146 return error;
147 }
148
149 /*
150 * send message to the socket.
151 */
152 static int
153 key_sendup0(rp, m, promisc)
154 struct rawcb *rp;
155 struct mbuf *m;
156 int promisc;
157 {
158 int error;
159
160 if (promisc) {
161 struct sadb_msg *pmsg;
162
163 M_PREPEND(m, sizeof(struct sadb_msg), M_DONTWAIT);
164 if (m && m->m_len < sizeof(struct sadb_msg))
165 m = m_pullup(m, sizeof(struct sadb_msg));
166 if (!m) {
167 pfkeystat.in_nomem++;
168 m_freem(m);
169 return ENOBUFS;
170 }
171 m->m_pkthdr.len += sizeof(*pmsg);
172
173 pmsg = mtod(m, struct sadb_msg *);
174 bzero(pmsg, sizeof(*pmsg));
175 pmsg->sadb_msg_version = PF_KEY_V2;
176 pmsg->sadb_msg_type = SADB_X_PROMISC;
177 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
178 /* pid and seq? */
179
180 pfkeystat.in_msgtype[pmsg->sadb_msg_type]++;
181 }
182
183 if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src,
184 m, NULL)) {
185 pfkeystat.in_nomem++;
186 m_freem(m);
187 error = ENOBUFS;
188 } else
189 error = 0;
190 sorwakeup(rp->rcb_socket);
191 return error;
192 }
193
194 /* XXX this interface should be obsoleted. */
195 int
196 key_sendup(so, msg, len, target)
197 struct socket *so;
198 struct sadb_msg *msg;
199 u_int len;
200 int target; /*target of the resulting message*/
201 {
202 struct mbuf *m, *n, *mprev;
203 int tlen;
204
205 /* sanity check */
206 if (so == 0 || msg == 0)
207 panic("key_sendup: NULL pointer was passed.\n");
208
209 KEYDEBUG(KEYDEBUG_KEY_DUMP,
210 printf("key_sendup: \n");
211 kdebug_sadb(msg));
212
213 /*
214 * we increment statistics here, just in case we have ENOBUFS
215 * in this function.
216 */
217 pfkeystat.in_total++;
218 pfkeystat.in_bytes += len;
219 pfkeystat.in_msgtype[msg->sadb_msg_type]++;
220
221 /*
222 * Get mbuf chain whenever possible (not clusters),
223 * to save socket buffer. We'll be generating many SADB_ACQUIRE
224 * messages to listening key sockets. If we simply allocate clusters,
225 * sbappendaddr() will raise ENOBUFS due to too little sbspace().
226 * sbspace() computes # of actual data bytes AND mbuf region.
227 *
228 * TODO: SADB_ACQUIRE filters should be implemented.
229 */
230 tlen = len;
231 m = mprev = NULL;
232 while (tlen > 0) {
233 if (tlen == len) {
234 MGETHDR(n, M_DONTWAIT, MT_DATA);
235 n->m_len = MHLEN;
236 } else {
237 MGET(n, M_DONTWAIT, MT_DATA);
238 n->m_len = MLEN;
239 }
240 if (!n) {
241 pfkeystat.in_nomem++;
242 return ENOBUFS;
243 }
244 if (tlen >= MCLBYTES) { /*XXX better threshold? */
245 MCLGET(n, M_DONTWAIT);
246 if ((n->m_flags & M_EXT) == 0) {
247 m_free(n);
248 m_freem(m);
249 pfkeystat.in_nomem++;
250 return ENOBUFS;
251 }
252 n->m_len = MCLBYTES;
253 }
254
255 if (tlen < n->m_len)
256 n->m_len = tlen;
257 n->m_next = NULL;
258 if (m == NULL)
259 m = mprev = n;
260 else {
261 mprev->m_next = n;
262 mprev = n;
263 }
264 tlen -= n->m_len;
265 n = NULL;
266 }
267 m->m_pkthdr.len = len;
268 m->m_pkthdr.rcvif = NULL;
269 m_copyback(m, 0, len, (caddr_t)msg);
270
271 /* avoid duplicated statistics */
272 pfkeystat.in_total--;
273 pfkeystat.in_bytes -= len;
274 pfkeystat.in_msgtype[msg->sadb_msg_type]--;
275
276 return key_sendup_mbuf(so, m, target);
277 }
278
279 /* so can be NULL if target != KEY_SENDUP_ONE */
280 int
281 key_sendup_mbuf(so, m, target)
282 struct socket *so;
283 struct mbuf *m;
284 int target;
285 {
286 struct mbuf *n;
287 struct keycb *kp;
288 int sendup;
289 struct rawcb *rp;
290 int error = 0;
291
292 if (m == NULL)
293 panic("key_sendup_mbuf: NULL pointer was passed.\n");
294 if (so == NULL && target == KEY_SENDUP_ONE)
295 panic("key_sendup_mbuf: NULL pointer was passed.\n");
296
297 pfkeystat.in_total++;
298 pfkeystat.in_bytes += m->m_pkthdr.len;
299 if (m->m_len < sizeof(struct sadb_msg)) {
300 #if 1
301 m = m_pullup(m, sizeof(struct sadb_msg));
302 if (m == NULL) {
303 pfkeystat.in_nomem++;
304 return ENOBUFS;
305 }
306 #else
307 /* don't bother pulling it up just for stats */
308 #endif
309 }
310 if (m->m_len >= sizeof(struct sadb_msg)) {
311 struct sadb_msg *msg;
312 msg = mtod(m, struct sadb_msg *);
313 pfkeystat.in_msgtype[msg->sadb_msg_type]++;
314 }
315
316 LIST_FOREACH(rp, &rawcb_list, rcb_list)
317 {
318 if (rp->rcb_proto.sp_family != PF_KEY)
319 continue;
320 if (rp->rcb_proto.sp_protocol
321 && rp->rcb_proto.sp_protocol != PF_KEY_V2) {
322 continue;
323 }
324
325 kp = (struct keycb *)rp;
326
327 /*
328 * If you are in promiscuous mode, and when you get broadcasted
329 * reply, you'll get two PF_KEY messages.
330 * (based on pf_key@inner.net message on 14 Oct 1998)
331 */
332 if (((struct keycb *)rp)->kp_promisc) {
333 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
334 (void)key_sendup0(rp, n, 1);
335 n = NULL;
336 }
337 }
338
339 /* the exact target will be processed later */
340 if (so && sotorawcb(so) == rp)
341 continue;
342
343 sendup = 0;
344 switch (target) {
345 case KEY_SENDUP_ONE:
346 /* the statement has no effect */
347 if (so && sotorawcb(so) == rp)
348 sendup++;
349 break;
350 case KEY_SENDUP_ALL:
351 sendup++;
352 break;
353 case KEY_SENDUP_REGISTERED:
354 if (kp->kp_registered)
355 sendup++;
356 break;
357 }
358 pfkeystat.in_msgtarget[target]++;
359
360 if (!sendup)
361 continue;
362
363 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
364 m_freem(m);
365 pfkeystat.in_nomem++;
366 return ENOBUFS;
367 }
368
369 if ((error = key_sendup0(rp, n, 0)) != 0) {
370 m_freem(m);
371 return error;
372 }
373
374 n = NULL;
375 }
376
377 if (so) {
378 error = key_sendup0(sotorawcb(so), m, 0);
379 m = NULL;
380 } else {
381 error = 0;
382 m_freem(m);
383 }
384 return error;
385 }
386
387 #ifdef __FreeBSD__
388
389 /*
390 * key_abort()
391 * derived from net/rtsock.c:rts_abort()
392 */
393 static int
394 key_abort(struct socket *so)
395 {
396 int s, error;
397 s = splnet(); /* FreeBSD */
398 error = raw_usrreqs.pru_abort(so);
399 splx(s);
400 return error;
401 }
402
403 /*
404 * key_attach()
405 * derived from net/rtsock.c:rts_attach()
406 */
407 static int
408 key_attach(struct socket *so, int proto, struct proc *td)
409 {
410 struct keycb *kp;
411 int s, error;
412
413 if (sotorawcb(so) != 0)
414 return EISCONN; /* XXX panic? */
415 kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK|M_ZERO); /* XXX */
416 if (kp == 0)
417 return ENOBUFS;
418
419 /*
420 * The spl[soft]net() is necessary to block protocols from sending
421 * error notifications (like RTM_REDIRECT or RTM_LOSING) while
422 * this PCB is extant but incompletely initialized.
423 * Probably we should try to do more of this work beforehand and
424 * eliminate the spl.
425 */
426 s = splnet(); /* FreeBSD */
427 so->so_pcb = (caddr_t)kp;
428 error = raw_usrreqs.pru_attach(so, proto, td);
429 kp = (struct keycb *)sotorawcb(so);
430 if (error) {
431 free(kp, M_PCB);
432 so->so_pcb = (caddr_t) 0;
433 splx(s);
434 return error;
435 }
436
437 kp->kp_promisc = kp->kp_registered = 0;
438
439 if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
440 key_cb.key_count++;
441 key_cb.any_count++;
442 kp->kp_raw.rcb_laddr = &key_src;
443 kp->kp_raw.rcb_faddr = &key_dst;
444 soisconnected(so);
445 so->so_options |= SO_USELOOPBACK;
446
447 splx(s);
448 return 0;
449 }
450
451 /*
452 * key_bind()
453 * derived from net/rtsock.c:rts_bind()
454 */
455 static int
456 key_bind(struct socket *so, struct sockaddr *nam, struct proc *td)
457 {
458 int s, error;
459 s = splnet(); /* FreeBSD */
460 error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */
461 splx(s);
462 return error;
463 }
464
465 /*
466 * key_connect()
467 * derived from net/rtsock.c:rts_connect()
468 */
469 static int
470 key_connect(struct socket *so, struct sockaddr *nam, struct proc *td)
471 {
472 int s, error;
473 s = splnet(); /* FreeBSD */
474 error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */
475 splx(s);
476 return error;
477 }
478
479 /*
480 * key_detach()
481 * derived from net/rtsock.c:rts_detach()
482 */
483 static int
484 key_detach(struct socket *so)
485 {
486 struct keycb *kp = (struct keycb *)sotorawcb(so);
487 int s, error;
488
489 s = splnet(); /* FreeBSD */
490 if (kp != 0) {
491 if (kp->kp_raw.rcb_proto.sp_protocol
492 == PF_KEY) /* XXX: AF_KEY */
493 key_cb.key_count--;
494 key_cb.any_count--;
495
496 key_freereg(so);
497 }
498 error = raw_usrreqs.pru_detach(so);
499 splx(s);
500 return error;
501 }
502
503 /*
504 * key_disconnect()
505 * derived from net/rtsock.c:key_disconnect()
506 */
507 static int
508 key_disconnect(struct socket *so)
509 {
510 int s, error;
511 s = splnet(); /* FreeBSD */
512 error = raw_usrreqs.pru_disconnect(so);
513 splx(s);
514 return error;
515 }
516
517 /*
518 * key_peeraddr()
519 * derived from net/rtsock.c:rts_peeraddr()
520 */
521 static int
522 key_peeraddr(struct socket *so, struct sockaddr **nam)
523 {
524 int s, error;
525 s = splnet(); /* FreeBSD */
526 error = raw_usrreqs.pru_peeraddr(so, nam);
527 splx(s);
528 return error;
529 }
530
531 /*
532 * key_send()
533 * derived from net/rtsock.c:rts_send()
534 */
535 static int
536 key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
537 struct mbuf *control, struct proc *td)
538 {
539 int s, error;
540 s = splnet(); /* FreeBSD */
541 error = raw_usrreqs.pru_send(so, flags, m, nam, control, td);
542 splx(s);
543 return error;
544 }
545
546 /*
547 * key_shutdown()
548 * derived from net/rtsock.c:rts_shutdown()
549 */
550 static int
551 key_shutdown(struct socket *so)
552 {
553 int s, error;
554 s = splnet(); /* FreeBSD */
555 error = raw_usrreqs.pru_shutdown(so);
556 splx(s);
557 return error;
558 }
559
560 /*
561 * key_sockaddr()
562 * derived from net/rtsock.c:rts_sockaddr()
563 */
564 static int
565 key_sockaddr(struct socket *so, struct sockaddr **nam)
566 {
567 int s, error;
568 s = splnet(); /* FreeBSD */
569 error = raw_usrreqs.pru_sockaddr(so, nam);
570 splx(s);
571 return error;
572 }
573 #else /*!__FreeBSD__ -- traditional proto_usrreq() switch */
574
575 /*
576 * key_usrreq()
577 * derived from net/rtsock.c:route_usrreq()
578 */
579 int
580 key_usrreq(so, req, m, nam, control, p)
581 struct socket *so;
582 int req;
583 struct mbuf *m, *nam, *control;
584 struct proc *p;
585 {
586 int error = 0;
587 struct keycb *kp = (struct keycb *)sotorawcb(so);
588 int s;
589
590 s = splsoftnet();
591 if (req == PRU_ATTACH) {
592 kp = (struct keycb *)malloc(sizeof(*kp), M_PCB, M_WAITOK);
593 so->so_pcb = (caddr_t)kp;
594 if (so->so_pcb)
595 bzero(so->so_pcb, sizeof(*kp));
596 }
597 if (req == PRU_DETACH && kp) {
598 int af = kp->kp_raw.rcb_proto.sp_protocol;
599 if (af == PF_KEY) /* XXX: AF_KEY */
600 key_cb.key_count--;
601 key_cb.any_count--;
602
603 key_freereg(so);
604 }
605
606 error = raw_usrreq(so, req, m, nam, control, p);
607 m = control = NULL; /* reclaimed in raw_usrreq */
608 kp = (struct keycb *)sotorawcb(so);
609 if (req == PRU_ATTACH && kp) {
610 int af = kp->kp_raw.rcb_proto.sp_protocol;
611 if (error) {
612 pfkeystat.sockerr++;
613 free((caddr_t)kp, M_PCB);
614 so->so_pcb = (caddr_t) 0;
615 splx(s);
616 return (error);
617 }
618
619 kp->kp_promisc = kp->kp_registered = 0;
620
621 if (af == PF_KEY) /* XXX: AF_KEY */
622 key_cb.key_count++;
623 key_cb.any_count++;
624 kp->kp_raw.rcb_laddr = &key_src;
625 kp->kp_raw.rcb_faddr = &key_dst;
626 soisconnected(so);
627 so->so_options |= SO_USELOOPBACK;
628 }
629 splx(s);
630 return (error);
631 }
632 #endif /*!__FreeBSD__*/
633
634 /* sysctl */
635 #ifdef SYSCTL_NODE
636 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
637 #endif /* SYSCTL_NODE */
638
639 /*
640 * Definitions of protocols supported in the KEY domain.
641 */
642
643 /* This extern declaration is all that's common... */
644 extern struct domain keydomain;
645
646 #ifdef __FreeBSD__
647 struct pr_usrreqs key_usrreqs = {
648 key_abort, pru_accept_notsupp, key_attach, key_bind,
649 key_connect,
650 pru_connect2_notsupp, pru_control_notsupp, key_detach,
651 key_disconnect, pru_listen_notsupp, key_peeraddr,
652 pru_rcvd_notsupp,
653 pru_rcvoob_notsupp, key_send, pru_sense_null, key_shutdown,
654 key_sockaddr, sosend, soreceive, sopoll
655 };
656
657 struct protosw keysw[] = {
658 { SOCK_RAW, &keydomain, PF_KEY_V2, PR_ATOMIC|PR_ADDR,
659 0, (pr_output_t *)key_output, raw_ctlinput, 0,
660 0,
661 raw_init, 0, 0, 0,
662 &key_usrreqs
663 }
664 };
665
666 static void
667 key_init0(void)
668 {
669 bzero((caddr_t)&key_cb, sizeof(key_cb));
670 key_init();
671 }
672
673 struct domain keydomain =
674 { PF_KEY, "key", key_init0, 0, 0,
675 keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] };
676
677 DOMAIN_SET(key);
678
679 #else /* !__FreeBSD__ */
680
681
682 struct protosw keysw[] = {
683 { SOCK_RAW, &keydomain, PF_KEY_V2, PR_ATOMIC|PR_ADDR,
684 0, key_output, raw_ctlinput, 0,
685 key_usrreq,
686 raw_init, 0, 0, 0,
687 NULL,
688 }
689 };
690
691 struct domain keydomain =
692 { PF_KEY, "key", key_init, 0, 0,
693 keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] };
694
695 #endif
Cache object: d1e391429377dec3074c8f8ad3392955
|