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