For kmalloc(), MALLOC() and contigmalloc(), use M_ZERO instead of
[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.19 2008/01/05 14:02:40 swildner 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         if (kp == 0)
388                 return ENOBUFS;
389
390         /*
391          * The critical section is necessary to block protocols from sending
392          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
393          * this PCB is extant but incompletely initialized.
394          * Probably we should try to do more of this work beforehand and
395          * eliminate the critical section.
396          */
397         crit_enter();
398         so->so_pcb = (caddr_t)kp;
399         error = raw_usrreqs.pru_attach(so, proto, ai);
400         kp = (struct keycb *)sotorawcb(so);
401         if (error) {
402                 kfree(kp, M_PCB);
403                 so->so_pcb = (caddr_t) 0;
404                 crit_exit();
405                 return error;
406         }
407
408         kp->kp_promisc = kp->kp_registered = 0;
409
410         if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
411                 key_cb.key_count++;
412         key_cb.any_count++;
413         kp->kp_raw.rcb_laddr = &key_src;
414         kp->kp_raw.rcb_faddr = &key_dst;
415         soisconnected(so);
416         so->so_options |= SO_USELOOPBACK;
417
418         crit_exit();
419         return 0;
420 }
421
422 /*
423  * key_bind()
424  * derived from net/rtsock.c:rts_bind()
425  */
426 static int
427 key_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
428 {
429         int error;
430
431         crit_enter();
432         error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */
433         crit_exit();
434         return error;
435 }
436
437 /*
438  * key_connect()
439  * derived from net/rtsock.c:rts_connect()
440  */
441 static int
442 key_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
443 {
444         int error;
445
446         crit_enter();
447         error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */
448         crit_exit();
449         return error;
450 }
451
452 /*
453  * key_detach()
454  * derived from net/rtsock.c:rts_detach()
455  */
456 static int
457 key_detach(struct socket *so)
458 {
459         struct keycb *kp = (struct keycb *)sotorawcb(so);
460         int error;
461
462         crit_enter();
463         if (kp != 0) {
464                 if (kp->kp_raw.rcb_proto.sp_protocol
465                     == PF_KEY) /* XXX: AF_KEY */
466                         key_cb.key_count--;
467                 key_cb.any_count--;
468
469                 key_freereg(so);
470         }
471         error = raw_usrreqs.pru_detach(so);
472         crit_exit();
473         return error;
474 }
475
476 /*
477  * key_disconnect()
478  * derived from net/rtsock.c:key_disconnect()
479  */
480 static int
481 key_disconnect(struct socket *so)
482 {
483         int error;
484
485         crit_enter();
486         error = raw_usrreqs.pru_disconnect(so);
487         crit_exit();
488         return error;
489 }
490
491 /*
492  * key_peeraddr()
493  * derived from net/rtsock.c:rts_peeraddr()
494  */
495 static int
496 key_peeraddr(struct socket *so, struct sockaddr **nam)
497 {
498         int error;
499
500         crit_enter();
501         error = raw_usrreqs.pru_peeraddr(so, nam);
502         crit_exit();
503         return error;
504 }
505
506 /*
507  * key_send()
508  * derived from net/rtsock.c:rts_send()
509  */
510 static int
511 key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
512          struct mbuf *control, struct thread *td)
513 {
514         int error;
515
516         crit_enter();
517         error = raw_usrreqs.pru_send(so, flags, m, nam, control, td);
518         crit_exit();
519         return error;
520 }
521
522 /*
523  * key_shutdown()
524  * derived from net/rtsock.c:rts_shutdown()
525  */
526 static int
527 key_shutdown(struct socket *so)
528 {
529         int error;
530
531         crit_enter();
532         error = raw_usrreqs.pru_shutdown(so);
533         crit_exit();
534         return error;
535 }
536
537 /*
538  * key_sockaddr()
539  * derived from net/rtsock.c:rts_sockaddr()
540  */
541 static int
542 key_sockaddr(struct socket *so, struct sockaddr **nam)
543 {
544         int error;
545
546         crit_enter();
547         error = raw_usrreqs.pru_sockaddr(so, nam);
548         crit_exit();
549         return error;
550 }
551
552 struct pr_usrreqs key_usrreqs = {
553         key_abort, pru_accept_notsupp, key_attach, key_bind,
554         key_connect,
555         pru_connect2_notsupp, pru_control_notsupp, key_detach,
556         key_disconnect, pru_listen_notsupp, key_peeraddr,
557         pru_rcvd_notsupp,
558         pru_rcvoob_notsupp, key_send, pru_sense_null, key_shutdown,
559         key_sockaddr, sosend, soreceive, sopoll
560 };
561
562 /* sysctl */
563 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
564
565 /*
566  * Definitions of protocols supported in the KEY domain.
567  */
568
569 extern struct domain keydomain;
570
571 struct protosw keysw[] = {
572 { SOCK_RAW,     &keydomain,     PF_KEY_V2,      PR_ATOMIC|PR_ADDR,
573   0,            key_output,     raw_ctlinput,   0,
574   cpu0_soport,
575   raw_init,     0,              0,              0,
576   &key_usrreqs
577 }
578 };
579
580 struct domain keydomain = {
581         PF_KEY, "key", key_init, NULL, NULL,
582         keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])],
583 };
584
585 DOMAIN_SET(key);