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