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