Merge branch 'vendor/GCC47'
[dragonfly.git] / sys / netproto / key / keysock.c
1 /*
2  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the project nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD: src/sys/netkey/keysock.c,v 1.1.2.4 2003/01/11 19:10:59 ume Exp $
30  * $KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $
31  */
32
33 #include "opt_ipsec.h"
34
35 /* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
36
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/sysctl.h>
42 #include <sys/mbuf.h>
43 #include <sys/malloc.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
46 #include <sys/domain.h>
47 #include <sys/protosw.h>
48 #include <sys/errno.h>
49
50 #include <sys/thread2.h>
51 #include <sys/msgport2.h>
52
53 #include <net/raw_cb.h>
54 #include <net/route.h>
55 #include <net/netmsg.h>
56 #include <netinet/in.h>
57
58 #include <net/pfkeyv2.h>
59 #include <net/netmsg2.h>
60
61 #include "keydb.h"
62 #include "key.h"
63 #include "keysock.h"
64 #include "key_debug.h"
65
66 #include <machine/stdarg.h>
67
68 struct sockaddr key_dst = { 2, PF_KEY, };
69 struct sockaddr key_src = { 2, PF_KEY, };
70
71 static int key_sendup0 (struct rawcb *, struct mbuf *, int);
72
73 struct pfkeystat pfkeystat;
74
75 /*
76  * key_output()
77  */
78 int
79 key_output(struct mbuf *m, struct socket *so, ...)
80 {
81         struct sadb_msg *msg;
82         int len, error = 0;
83
84         if (m == NULL)
85                 panic("key_output: NULL pointer was passed.");
86
87         pfkeystat.out_total++;
88         pfkeystat.out_bytes += m->m_pkthdr.len;
89
90         len = m->m_pkthdr.len;
91         if (len < sizeof(struct sadb_msg)) {
92                 pfkeystat.out_tooshort++;
93                 error = EINVAL;
94                 goto end;
95         }
96
97         if (m->m_len < sizeof(struct sadb_msg)) {
98                 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == NULL) {
99                         pfkeystat.out_nomem++;
100                         error = ENOBUFS;
101                         goto end;
102                 }
103         }
104
105         if ((m->m_flags & M_PKTHDR) == 0)
106                 panic("key_output: not M_PKTHDR ??");
107
108         KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
109
110         msg = mtod(m, struct sadb_msg *);
111         pfkeystat.out_msgtype[msg->sadb_msg_type]++;
112         if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
113                 pfkeystat.out_invlen++;
114                 error = EINVAL;
115                 goto end;
116         }
117
118         /*XXX giant lock*/
119         lwkt_gettoken(&key_token);
120         error = key_parse(m, so);
121         m = NULL;
122         lwkt_reltoken(&key_token);
123 end:
124         if (m)
125                 m_freem(m);
126         return error;
127 }
128
129 /*
130  * send message to the socket.
131  */
132 static int
133 key_sendup0(struct rawcb *rp, struct mbuf *m, int promisc)
134 {
135         int error;
136
137         if (promisc) {
138                 struct sadb_msg *pmsg;
139
140                 M_PREPEND(m, sizeof(struct sadb_msg), MB_DONTWAIT);
141                 if (m && m->m_len < sizeof(struct sadb_msg))
142                         m = m_pullup(m, sizeof(struct sadb_msg));
143                 if (!m) {
144                         pfkeystat.in_nomem++;
145                         m_freem(m);
146                         return ENOBUFS;
147                 }
148                 m->m_pkthdr.len += sizeof(*pmsg);
149
150                 pmsg = mtod(m, struct sadb_msg *);
151                 bzero(pmsg, sizeof(*pmsg));
152                 pmsg->sadb_msg_version = PF_KEY_V2;
153                 pmsg->sadb_msg_type = SADB_X_PROMISC;
154                 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
155                 /* pid and seq? */
156
157                 pfkeystat.in_msgtype[pmsg->sadb_msg_type]++;
158         }
159
160         lwkt_gettoken(&key_token);
161         if (!ssb_appendaddr(&rp->rcb_socket->so_rcv, &key_src, m, NULL)) {
162                 pfkeystat.in_nomem++;
163                 m_freem(m);
164                 error = ENOBUFS;
165         } else {
166                 error = 0;
167         }
168         lwkt_reltoken(&key_token);
169         sorwakeup(rp->rcb_socket);
170         return error;
171 }
172
173 /*
174  * XXX this interface should be obsoleted.
175  *
176  * Parameters:
177  *      target: target of the resulting message
178  */
179 int
180 key_sendup(struct socket *so, struct sadb_msg *msg, u_int len,
181            int target)
182 {
183         struct mbuf *m, *n, *mprev;
184         int tlen;
185
186         /* sanity check */
187         if (so == NULL || msg == NULL)
188                 panic("key_sendup: NULL pointer was passed.");
189
190         KEYDEBUG(KEYDEBUG_KEY_DUMP,
191                 kprintf("key_sendup: \n");
192                 kdebug_sadb(msg));
193
194         /*
195          * we increment statistics here, just in case we have ENOBUFS
196          * in this function.
197          */
198         pfkeystat.in_total++;
199         pfkeystat.in_bytes += len;
200         pfkeystat.in_msgtype[msg->sadb_msg_type]++;
201
202         /*
203          * Get mbuf chain whenever possible (not clusters),
204          * to save socket buffer.  We'll be generating many SADB_ACQUIRE
205          * messages to listening key sockets.  If we simply allocate clusters,
206          * ssb_appendaddr() will raise ENOBUFS due to too little ssb_space().
207          * ssb_space() computes # of actual data bytes AND mbuf region.
208          *
209          * TODO: SADB_ACQUIRE filters should be implemented.
210          */
211         tlen = len;
212         m = mprev = NULL;
213         while (tlen > 0) {
214                 if (tlen == len) {
215                         MGETHDR(n, MB_DONTWAIT, MT_DATA);
216                         n->m_len = MHLEN;
217                 } else {
218                         MGET(n, MB_DONTWAIT, MT_DATA);
219                         n->m_len = MLEN;
220                 }
221                 if (!n) {
222                         pfkeystat.in_nomem++;
223                         return ENOBUFS;
224                 }
225                 if (tlen >= MCLBYTES) { /*XXX better threshold? */
226                         MCLGET(n, MB_DONTWAIT);
227                         if ((n->m_flags & M_EXT) == 0) {
228                                 m_free(n);
229                                 m_freem(m);
230                                 pfkeystat.in_nomem++;
231                                 return ENOBUFS;
232                         }
233                         n->m_len = MCLBYTES;
234                 }
235
236                 if (tlen < n->m_len)
237                         n->m_len = tlen;
238                 n->m_next = NULL;
239                 if (m == NULL)
240                         m = mprev = n;
241                 else {
242                         mprev->m_next = n;
243                         mprev = n;
244                 }
245                 tlen -= n->m_len;
246                 n = NULL;
247         }
248         m->m_pkthdr.len = len;
249         m->m_pkthdr.rcvif = NULL;
250         m_copyback(m, 0, len, (caddr_t)msg);
251
252         /* avoid duplicated statistics */
253         pfkeystat.in_total--;
254         pfkeystat.in_bytes -= len;
255         pfkeystat.in_msgtype[msg->sadb_msg_type]--;
256
257         return key_sendup_mbuf(so, m, target);
258 }
259
260 /* so can be NULL if target != KEY_SENDUP_ONE */
261 int
262 key_sendup_mbuf(struct socket *so, struct mbuf *m, int target)
263 {
264         struct mbuf *n;
265         struct keycb *kp;
266         int sendup;
267         struct rawcb *rp;
268         int error = 0;
269
270         if (m == NULL)
271                 panic("key_sendup_mbuf: NULL pointer was passed.");
272         if (so == NULL && target == KEY_SENDUP_ONE)
273                 panic("key_sendup_mbuf: NULL pointer was passed.");
274
275         pfkeystat.in_total++;
276         pfkeystat.in_bytes += m->m_pkthdr.len;
277         if (m->m_len < sizeof(struct sadb_msg)) {
278 #if 1
279                 m = m_pullup(m, sizeof(struct sadb_msg));
280                 if (m == NULL) {
281                         pfkeystat.in_nomem++;
282                         return ENOBUFS;
283                 }
284 #else
285                 /* don't bother pulling it up just for stats */
286 #endif
287         }
288         if (m->m_len >= sizeof(struct sadb_msg)) {
289                 struct sadb_msg *msg;
290                 msg = mtod(m, struct sadb_msg *);
291                 pfkeystat.in_msgtype[msg->sadb_msg_type]++;
292         }
293
294         lwkt_gettoken(&key_token);
295
296         LIST_FOREACH(rp, &rawcb_list, list)
297         {
298                 if (rp->rcb_proto.sp_family != PF_KEY)
299                         continue;
300                 if (rp->rcb_proto.sp_protocol
301                  && rp->rcb_proto.sp_protocol != PF_KEY_V2) {
302                         continue;
303                 }
304
305                 kp = (struct keycb *)rp;
306
307                 /*
308                  * If you are in promiscuous mode, and when you get broadcasted
309                  * reply, you'll get two PF_KEY messages.
310                  * (based on pf_key@inner.net message on 14 Oct 1998)
311                  */
312                 if (((struct keycb *)rp)->kp_promisc) {
313                         if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
314                                 key_sendup0(rp, n, 1);
315                                 n = NULL;
316                         }
317                 }
318
319                 /* the exact target will be processed later */
320                 if (so && sotorawcb(so) == rp)
321                         continue;
322
323                 sendup = 0;
324                 switch (target) {
325                 case KEY_SENDUP_ONE:
326                         /* the statement has no effect */
327                         if (so && sotorawcb(so) == rp)
328                                 sendup++;
329                         break;
330                 case KEY_SENDUP_ALL:
331                         sendup++;
332                         break;
333                 case KEY_SENDUP_REGISTERED:
334                         if (kp->kp_registered)
335                                 sendup++;
336                         break;
337                 }
338                 pfkeystat.in_msgtarget[target]++;
339
340                 if (!sendup)
341                         continue;
342
343                 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
344                         m_freem(m);
345                         pfkeystat.in_nomem++;
346                         lwkt_reltoken(&key_token);
347                         return ENOBUFS;
348                 }
349
350                 if ((error = key_sendup0(rp, n, 0)) != 0) {
351                         lwkt_reltoken(&key_token);
352                         m_freem(m);
353                         return error;
354                 }
355
356                 n = NULL;
357         }
358         lwkt_reltoken(&key_token);
359
360         if (so) {
361                 error = key_sendup0(sotorawcb(so), m, 0);
362                 m = NULL;
363         } else {
364                 error = 0;
365                 m_freem(m);
366         }
367         return error;
368 }
369
370 /*
371  * key_abort()
372  * derived from net/rtsock.c:rts_abort()
373  */
374 static void
375 key_abort(netmsg_t msg)
376 {
377         lwkt_gettoken(&key_token);
378
379         raw_usrreqs.pru_abort(msg);
380         /* msg invalid now */
381
382         lwkt_reltoken(&key_token);
383 }
384
385 /*
386  * key_attach()
387  * derived from net/rtsock.c:rts_attach()
388  */
389 static void
390 key_attach(netmsg_t msg)
391 {
392         struct socket *so = msg->attach.base.nm_so;
393         int proto = msg->attach.nm_proto;
394         struct pru_attach_info *ai = msg->attach.nm_ai;
395         struct keycb *kp;
396         struct netmsg_pru_attach smsg;
397         int error;
398
399         if (sotorawcb(so) != NULL) {
400                 error = EISCONN;        /* XXX panic? */
401                 goto out;
402         }
403
404         /* XXX */
405         kp = kmalloc(sizeof *kp, M_PCB, M_WAITOK | M_ZERO);
406
407         /*
408          * The critical section is necessary to block protocols from sending
409          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
410          * this PCB is extant but incompletely initialized.
411          * Probably we should try to do more of this work beforehand and
412          * eliminate the critical section.
413          */
414         lwkt_gettoken(&key_token);
415         so->so_pcb = (caddr_t)kp;
416
417         netmsg_init(&smsg.base, so, &netisr_adone_rport, 0,
418                     raw_usrreqs.pru_attach);
419         smsg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE);
420         smsg.base.lmsg.ms_flags |= MSGF_SYNC;
421         smsg.nm_proto = proto;
422         smsg.nm_ai = ai;
423         raw_usrreqs.pru_attach((netmsg_t)&smsg);
424         error = smsg.base.lmsg.ms_error;
425
426         kp = (struct keycb *)sotorawcb(so);
427         if (error) {
428                 kfree(kp, M_PCB);
429                 so->so_pcb = (caddr_t) 0;
430                 lwkt_reltoken(&key_token);
431                 goto out;
432         }
433
434         kp->kp_promisc = kp->kp_registered = 0;
435
436         if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
437                 key_cb.key_count++;
438         key_cb.any_count++;
439         kp->kp_raw.rcb_laddr = &key_src;
440         kp->kp_raw.rcb_faddr = &key_dst;
441         soisconnected(so);
442         so->so_options |= SO_USELOOPBACK;
443
444         lwkt_reltoken(&key_token);
445         error = 0;
446 out:
447         lwkt_replymsg(&msg->attach.base.lmsg, error);
448 }
449
450 /*
451  * key_bind()
452  * derived from net/rtsock.c:rts_bind()
453  */
454 static void
455 key_bind(netmsg_t msg)
456 {
457         lwkt_gettoken(&key_token);
458
459         raw_usrreqs.pru_bind(msg); /* xxx just EINVAL */
460         /* msg invalid now */
461
462         lwkt_reltoken(&key_token);
463 }
464
465 /*
466  * key_connect()
467  * derived from net/rtsock.c:rts_connect()
468  */
469 static void
470 key_connect(netmsg_t msg)
471 {
472         lwkt_gettoken(&key_token);
473
474         raw_usrreqs.pru_connect(msg); /* XXX just EINVAL */
475         /* msg invalid now */
476
477         lwkt_reltoken(&key_token);
478 }
479
480 /*
481  * key_detach()
482  * derived from net/rtsock.c:rts_detach()
483  */
484 static void
485 key_detach(netmsg_t msg)
486 {
487         struct socket *so = msg->detach.base.nm_so;
488         struct keycb *kp = (struct keycb *)sotorawcb(so);
489
490         lwkt_gettoken(&key_token);
491
492         if (kp != NULL) {
493                 if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) {
494                         /* XXX: AF_KEY */
495                         key_cb.key_count--;
496                 }
497                 key_cb.any_count--;
498
499                 key_freereg(so);
500         }
501         raw_usrreqs.pru_detach(msg);
502         /* msg invalid now */
503
504         lwkt_reltoken(&key_token);
505 }
506
507 /*
508  * key_disconnect()
509  * derived from net/rtsock.c:key_disconnect()
510  */
511 static void
512 key_disconnect(netmsg_t msg)
513 {
514         lwkt_gettoken(&key_token);
515
516         raw_usrreqs.pru_disconnect(msg);
517         /* msg invalid now */
518
519         lwkt_reltoken(&key_token);
520 }
521
522 /*
523  * key_peeraddr()
524  * derived from net/rtsock.c:rts_peeraddr()
525  */
526 static void
527 key_peeraddr(netmsg_t msg)
528 {
529         lwkt_gettoken(&key_token);
530
531         raw_usrreqs.pru_peeraddr(msg);
532         /* msg invalid now */
533
534         lwkt_reltoken(&key_token);
535 }
536
537 /*
538  * key_send()
539  * derived from net/rtsock.c:rts_send()
540  */
541 static void
542 key_send(netmsg_t msg)
543 {
544         lwkt_gettoken(&key_token);
545
546         raw_usrreqs.pru_send(msg);
547         /* msg invalid now */
548
549         lwkt_reltoken(&key_token);
550 }
551
552 /*
553  * key_shutdown()
554  * derived from net/rtsock.c:rts_shutdown()
555  */
556 static void
557 key_shutdown(netmsg_t msg)
558 {
559         lwkt_gettoken(&key_token);
560
561         raw_usrreqs.pru_shutdown(msg);
562         /* msg invalid now */
563
564         lwkt_reltoken(&key_token);
565 }
566
567 /*
568  * key_sockaddr()
569  * derived from net/rtsock.c:rts_sockaddr()
570  */
571 static void
572 key_sockaddr(netmsg_t msg)
573 {
574         lwkt_gettoken(&key_token);
575
576         raw_usrreqs.pru_sockaddr(msg);
577         /* msg invalid now */
578
579         lwkt_reltoken(&key_token);
580 }
581
582 struct pr_usrreqs key_usrreqs = {
583         .pru_abort = key_abort,
584         .pru_accept = pr_generic_notsupp,
585         .pru_attach = key_attach,
586         .pru_bind = key_bind,
587         .pru_connect = key_connect,
588         .pru_connect2 = pr_generic_notsupp,
589         .pru_control = pr_generic_notsupp,
590         .pru_detach = key_detach,
591         .pru_disconnect = key_disconnect,
592         .pru_listen = pr_generic_notsupp,
593         .pru_peeraddr = key_peeraddr,
594         .pru_rcvd =  pr_generic_notsupp,
595         .pru_rcvoob = pr_generic_notsupp,
596         .pru_send = key_send,
597         .pru_sense = pru_sense_null,
598         .pru_shutdown = key_shutdown,
599         .pru_sockaddr = key_sockaddr,
600         .pru_sosend = sosend,
601         .pru_soreceive = soreceive
602 };
603
604 /* sysctl */
605 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
606
607 /*
608  * Definitions of protocols supported in the KEY domain.
609  */
610
611 extern struct domain keydomain;
612
613 struct protosw keysw[] = {
614     {
615         .pr_type = SOCK_RAW,
616         .pr_domain = &keydomain,
617         .pr_protocol = PF_KEY_V2,
618         .pr_flags = PR_ATOMIC|PR_ADDR,
619
620         .pr_input = NULL,
621         .pr_output = key_output,
622         .pr_ctlinput = raw_ctlinput,
623         .pr_ctloutput = NULL,
624
625         .pr_ctlport = cpu0_ctlport,
626         .pr_init = raw_init,
627         .pr_usrreqs = &key_usrreqs
628     }
629 };
630
631 struct domain keydomain = {
632         PF_KEY, "key", key_init, NULL, NULL,
633         keysw, &keysw[NELEM(keysw)],
634 };
635
636 DOMAIN_SET(key);