* Add __unused where necessary.
[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.9 2005/03/04 02:21:49 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/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 <netproto/ipsec/key.h>
57 #include <netproto/ipsec/keysock.h>
58 #include <netproto/ipsec/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 key_output(struct mbuf *m, struct socket *so, ...)
82 {
83         struct sadb_msg *msg;
84         int len, error = 0;
85         int s;
86
87         if (m == 0)
88                 panic("key_output: NULL pointer was passed.\n");
89
90         pfkeystat.out_total++;
91         pfkeystat.out_bytes += m->m_pkthdr.len;
92
93         len = m->m_pkthdr.len;
94         if (len < sizeof(struct sadb_msg)) {
95                 pfkeystat.out_tooshort++;
96                 error = EINVAL;
97                 goto end;
98         }
99
100         if (m->m_len < sizeof(struct sadb_msg)) {
101                 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
102                         pfkeystat.out_nomem++;
103                         error = ENOBUFS;
104                         goto end;
105                 }
106         }
107
108         if ((m->m_flags & M_PKTHDR) == 0)
109                 panic("key_output: not M_PKTHDR ??");
110
111         KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
112
113         msg = mtod(m, struct sadb_msg *);
114         pfkeystat.out_msgtype[msg->sadb_msg_type]++;
115         if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
116                 pfkeystat.out_invlen++;
117                 error = EINVAL;
118                 goto end;
119         }
120
121         /*XXX giant lock*/
122         s = splnet();
123         error = key_parse(m, so);
124         m = NULL;
125         splx(s);
126 end:
127         if (m)
128                 m_freem(m);
129         return error;
130 }
131
132 /*
133  * send message to the socket.
134  */
135 static int
136 key_sendup0(rp, m, promisc)
137         struct rawcb *rp;
138         struct mbuf *m;
139         int promisc;
140 {
141         int error;
142
143         if (promisc) {
144                 struct sadb_msg *pmsg;
145
146                 M_PREPEND(m, sizeof(struct sadb_msg), MB_DONTWAIT);
147                 if (m && m->m_len < sizeof(struct sadb_msg))
148                         m = m_pullup(m, sizeof(struct sadb_msg));
149                 if (!m) {
150                         pfkeystat.in_nomem++;
151                         m_freem(m);
152                         return ENOBUFS;
153                 }
154                 m->m_pkthdr.len += sizeof(*pmsg);
155
156                 pmsg = mtod(m, struct sadb_msg *);
157                 bzero(pmsg, sizeof(*pmsg));
158                 pmsg->sadb_msg_version = PF_KEY_V2;
159                 pmsg->sadb_msg_type = SADB_X_PROMISC;
160                 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
161                 /* pid and seq? */
162
163                 pfkeystat.in_msgtype[pmsg->sadb_msg_type]++;
164         }
165
166         if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src,
167             m, NULL)) {
168                 pfkeystat.in_nomem++;
169                 m_freem(m);
170                 error = ENOBUFS;
171         } else
172                 error = 0;
173         sorwakeup(rp->rcb_socket);
174         return error;
175 }
176
177 /* XXX this interface should be obsoleted. */
178 int
179 key_sendup(so, msg, len, target)
180         struct socket *so;
181         struct sadb_msg *msg;
182         u_int len;
183         int target;     /*target of the resulting message*/
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                 printf("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          * sbappendaddr() will raise ENOBUFS due to too little sbspace().
209          * sbspace() 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(so, m, target)
265         struct socket *so;
266         struct mbuf *m;
267         int target;
268 {
269         struct mbuf *n;
270         struct keycb *kp;
271         int sendup;
272         struct rawcb *rp;
273         int error = 0;
274
275         if (m == NULL)
276                 panic("key_sendup_mbuf: NULL pointer was passed.\n");
277         if (so == NULL && target == KEY_SENDUP_ONE)
278                 panic("key_sendup_mbuf: NULL pointer was passed.\n");
279
280         pfkeystat.in_total++;
281         pfkeystat.in_bytes += m->m_pkthdr.len;
282         if (m->m_len < sizeof(struct sadb_msg)) {
283 #if 1
284                 m = m_pullup(m, sizeof(struct sadb_msg));
285                 if (m == NULL) {
286                         pfkeystat.in_nomem++;
287                         return ENOBUFS;
288                 }
289 #else
290                 /* don't bother pulling it up just for stats */
291 #endif
292         }
293         if (m->m_len >= sizeof(struct sadb_msg)) {
294                 struct sadb_msg *msg;
295                 msg = mtod(m, struct sadb_msg *);
296                 pfkeystat.in_msgtype[msg->sadb_msg_type]++;
297         }
298
299         LIST_FOREACH(rp, &rawcb_list, list)
300         {
301                 if (rp->rcb_proto.sp_family != PF_KEY)
302                         continue;
303                 if (rp->rcb_proto.sp_protocol
304                  && rp->rcb_proto.sp_protocol != PF_KEY_V2) {
305                         continue;
306                 }
307
308                 kp = (struct keycb *)rp;
309
310                 /*
311                  * If you are in promiscuous mode, and when you get broadcasted
312                  * reply, you'll get two PF_KEY messages.
313                  * (based on pf_key@inner.net message on 14 Oct 1998)
314                  */
315                 if (((struct keycb *)rp)->kp_promisc) {
316                         if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
317                                 (void)key_sendup0(rp, n, 1);
318                                 n = NULL;
319                         }
320                 }
321
322                 /* the exact target will be processed later */
323                 if (so && sotorawcb(so) == rp)
324                         continue;
325
326                 sendup = 0;
327                 switch (target) {
328                 case KEY_SENDUP_ONE:
329                         /* the statement has no effect */
330                         if (so && sotorawcb(so) == rp)
331                                 sendup++;
332                         break;
333                 case KEY_SENDUP_ALL:
334                         sendup++;
335                         break;
336                 case KEY_SENDUP_REGISTERED:
337                         if (kp->kp_registered)
338                                 sendup++;
339                         break;
340                 }
341                 pfkeystat.in_msgtarget[target]++;
342
343                 if (!sendup)
344                         continue;
345
346                 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
347                         m_freem(m);
348                         pfkeystat.in_nomem++;
349                         return ENOBUFS;
350                 }
351
352                 if ((error = key_sendup0(rp, n, 0)) != 0) {
353                         m_freem(m);
354                         return error;
355                 }
356
357                 n = NULL;
358         }
359
360         if (so) {
361                 error = key_sendup0(sotorawcb(so), m, 0);
362                 m = NULL;
363         } else {
364                 error = 0;
365                 m_freem(m);
366         }
367         return error;
368 }
369
370 /*
371  * key_abort()
372  * derived from net/rtsock.c:rts_abort()
373  */
374 static int
375 key_abort(struct socket *so)
376 {
377         int s, error;
378         s = splnet();
379         error = raw_usrreqs.pru_abort(so);
380         splx(s);
381         return error;
382 }
383
384 /*
385  * key_attach()
386  * derived from net/rtsock.c:rts_attach()
387  */
388 static int
389 key_attach(struct socket *so, int proto, struct pru_attach_info *ai)
390 {
391         struct keycb *kp;
392         int s, error;
393
394         if (sotorawcb(so) != 0)
395                 return EISCONN; /* XXX panic? */
396         kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK|M_ZERO); /* XXX */
397         if (kp == 0)
398                 return ENOBUFS;
399
400         /*
401          * The splnet() is necessary to block protocols from sending
402          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
403          * this PCB is extant but incompletely initialized.
404          * Probably we should try to do more of this work beforehand and
405          * eliminate the spl.
406          */
407         s = splnet();
408         so->so_pcb = (caddr_t)kp;
409         error = raw_usrreqs.pru_attach(so, proto, ai);
410         kp = (struct keycb *)sotorawcb(so);
411         if (error) {
412                 free(kp, M_PCB);
413                 so->so_pcb = (caddr_t) 0;
414                 splx(s);
415                 return error;
416         }
417
418         kp->kp_promisc = kp->kp_registered = 0;
419
420         if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
421                 key_cb.key_count++;
422         key_cb.any_count++;
423         kp->kp_raw.rcb_laddr = &key_src;
424         kp->kp_raw.rcb_faddr = &key_dst;
425         soisconnected(so);
426         so->so_options |= SO_USELOOPBACK;
427
428         splx(s);
429         return 0;
430 }
431
432 /*
433  * key_bind()
434  * derived from net/rtsock.c:rts_bind()
435  */
436 static int
437 key_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
438 {
439         int s, error;
440         s = splnet();
441         error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */
442         splx(s);
443         return error;
444 }
445
446 /*
447  * key_connect()
448  * derived from net/rtsock.c:rts_connect()
449  */
450 static int
451 key_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
452 {
453         int s, error;
454         s = splnet();
455         error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */
456         splx(s);
457         return error;
458 }
459
460 /*
461  * key_detach()
462  * derived from net/rtsock.c:rts_detach()
463  */
464 static int
465 key_detach(struct socket *so)
466 {
467         struct keycb *kp = (struct keycb *)sotorawcb(so);
468         int s, error;
469
470         s = splnet();
471         if (kp != 0) {
472                 if (kp->kp_raw.rcb_proto.sp_protocol
473                     == PF_KEY) /* XXX: AF_KEY */
474                         key_cb.key_count--;
475                 key_cb.any_count--;
476
477                 key_freereg(so);
478         }
479         error = raw_usrreqs.pru_detach(so);
480         splx(s);
481         return error;
482 }
483
484 /*
485  * key_disconnect()
486  * derived from net/rtsock.c:key_disconnect()
487  */
488 static int
489 key_disconnect(struct socket *so)
490 {
491         int s, error;
492         s = splnet();
493         error = raw_usrreqs.pru_disconnect(so);
494         splx(s);
495         return error;
496 }
497
498 /*
499  * key_peeraddr()
500  * derived from net/rtsock.c:rts_peeraddr()
501  */
502 static int
503 key_peeraddr(struct socket *so, struct sockaddr **nam)
504 {
505         int s, error;
506         s = splnet();
507         error = raw_usrreqs.pru_peeraddr(so, nam);
508         splx(s);
509         return error;
510 }
511
512 /*
513  * key_send()
514  * derived from net/rtsock.c:rts_send()
515  */
516 static int
517 key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
518          struct mbuf *control, struct thread *td)
519 {
520         int s, error;
521         s = splnet();
522         error = raw_usrreqs.pru_send(so, flags, m, nam, control, td);
523         splx(s);
524         return error;
525 }
526
527 /*
528  * key_shutdown()
529  * derived from net/rtsock.c:rts_shutdown()
530  */
531 static int
532 key_shutdown(struct socket *so)
533 {
534         int s, error;
535         s = splnet();
536         error = raw_usrreqs.pru_shutdown(so);
537         splx(s);
538         return error;
539 }
540
541 /*
542  * key_sockaddr()
543  * derived from net/rtsock.c:rts_sockaddr()
544  */
545 static int
546 key_sockaddr(struct socket *so, struct sockaddr **nam)
547 {
548         int s, error;
549         s = splnet();
550         error = raw_usrreqs.pru_sockaddr(so, nam);
551         splx(s);
552         return error;
553 }
554
555 struct pr_usrreqs key_usrreqs = {
556         key_abort, pru_accept_notsupp, key_attach, key_bind,
557         key_connect,
558         pru_connect2_notsupp, pru_control_notsupp, key_detach,
559         key_disconnect, pru_listen_notsupp, key_peeraddr,
560         pru_rcvd_notsupp,
561         pru_rcvoob_notsupp, key_send, pru_sense_null, key_shutdown,
562         key_sockaddr, sosend, soreceive, sopoll
563 };
564
565 /* sysctl */
566 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
567
568 /*
569  * Definitions of protocols supported in the KEY domain.
570  */
571
572 extern struct domain keydomain;
573
574 struct protosw keysw[] = {
575 { SOCK_RAW,     &keydomain,     PF_KEY_V2,      PR_ATOMIC|PR_ADDR,
576   0,            key_output,     raw_ctlinput,   0,
577   cpu0_soport,
578   raw_init,     0,              0,              0,
579   &key_usrreqs
580 }
581 };
582
583 static void
584 key_init0(void)
585 {
586         bzero((caddr_t)&key_cb, sizeof(key_cb));
587         key_init();
588 }
589
590 struct domain keydomain = {
591         PF_KEY, "key", key_init0, NULL, NULL,
592         keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])],
593 };
594
595 DOMAIN_SET(key);