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