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