]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netkey/keysock.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / sys / netkey / keysock.c
1 /*
2  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the project nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31
32 /* KAME @(#)$Id: keysock.c,v 1.2 1999/08/16 19:30:36 shin Exp $ */
33
34 /* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
35
36 #include <opt_ipsec.h>
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
56 #include <net/pfkeyv2.h>
57 #include <netkey/keydb.h>
58 #include <netkey/key.h>
59 #include <netkey/keysock.h>
60 #ifdef IPSEC_DEBUG
61 #include <netkey/key_debug.h>
62 #else
63 #define KEYDEBUG(lev,arg)
64 #endif
65
66 #include <machine/stdarg.h>
67
68 static MALLOC_DEFINE(M_SECA, "key mgmt",
69                      "security associations, key management");
70
71 struct sockaddr key_dst = { 2, PF_KEY, };
72 struct sockaddr key_src = { 2, PF_KEY, };
73 struct sockproto key_proto = { PF_KEY, PF_KEY_V2 };
74
75 static int key_sendup0 __P((struct rawcb *, struct mbuf *, int));
76
77 #define KMALLOC(p, t, n) \
78         ((p) = (t) malloc((unsigned long)(n), M_SECA, M_NOWAIT))
79 #define KFREE(p) \
80         free((caddr_t)(p), M_SECA);
81
82 /*
83  * key_abort()
84  * derived from net/rtsock.c:rts_abort()
85  */
86 static int
87 key_abort(struct socket *so)
88 {
89         int s, error;
90         s = splnet();
91         error = raw_usrreqs.pru_abort(so);
92         splx(s);
93         return error;
94 }
95
96 /*
97  * key_attach()
98  * derived from net/rtsock.c:rts_attach()
99  */
100 static int
101 key_attach(struct socket *so, int proto, struct proc *p)
102 {
103         struct keycb *kp;
104         int s, error;
105
106         if (sotorawcb(so) != 0)
107                 return EISCONN; /* XXX panic? */
108         MALLOC(kp, struct keycb *, sizeof *kp, M_PCB, M_WAITOK); /* XXX */
109         if (kp == 0)
110                 return ENOBUFS;
111         bzero(kp, sizeof *kp);
112
113         /*
114          * The splnet() is necessary to block protocols from sending
115          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
116          * this PCB is extant but incompletely initialized.
117          * Probably we should try to do more of this work beforehand and
118          * eliminate the spl.
119          */
120         s = splnet();
121         so->so_pcb = (caddr_t)kp;
122         error = raw_usrreqs.pru_attach(so, proto, p);
123         kp = (struct keycb *)sotorawcb(so);
124         if (error) {
125                 free(kp, M_PCB);
126                 so->so_pcb = (caddr_t) 0;
127                 splx(s);
128                 printf("key_usrreq: key_usrreq results %d\n", error);
129                 return error;
130         }
131
132         kp->kp_promisc = kp->kp_registered = 0;
133
134         if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
135                 key_cb.key_count++;
136         key_cb.any_count++;
137         kp->kp_raw.rcb_laddr = &key_src;
138         kp->kp_raw.rcb_faddr = &key_dst;
139         soisconnected(so);
140         so->so_options |= SO_USELOOPBACK;
141
142         splx(s);
143         return 0;
144 }
145
146 /*
147  * key_bind()
148  * derived from net/rtsock.c:rts_bind()
149  */
150 static int
151 key_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
152 {
153         int s, error;
154         s = splnet();
155         error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */
156         splx(s);
157         return error;
158 }
159
160 /*
161  * key_connect()
162  * derived from net/rtsock.c:rts_connect()
163  */
164 static int
165 key_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
166 {
167         int s, error;
168         s = splnet();
169         error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */
170         splx(s);
171         return error;
172 }
173
174 /*
175  * key_detach()
176  * derived from net/rtsock.c:rts_detach()
177  */
178 static int
179 key_detach(struct socket *so)
180 {
181         struct keycb *kp = (struct keycb *)sotorawcb(so);
182         int s, error;
183
184         s = splnet();
185         if (kp != 0) {
186                 if (kp->kp_raw.rcb_proto.sp_protocol
187                     == PF_KEY) /* XXX: AF_KEY */
188                         key_cb.key_count--;
189                 key_cb.any_count--;
190
191                 key_freereg(so);
192         }
193         error = raw_usrreqs.pru_detach(so);
194         splx(s);
195         return error;
196 }
197
198 /*
199  * key_disconnect()
200  * derived from net/rtsock.c:key_disconnect()
201  */
202 static int
203 key_disconnect(struct socket *so)
204 {
205         int s, error;
206         s = splnet();
207         error = raw_usrreqs.pru_disconnect(so);
208         splx(s);
209         return error;
210 }
211
212 /*
213  * key_peeraddr()
214  * derived from net/rtsock.c:rts_peeraddr()
215  */
216 static int
217 key_peeraddr(struct socket *so, struct sockaddr **nam)
218 {
219         int s, error;
220         s = splnet();
221         error = raw_usrreqs.pru_peeraddr(so, nam);
222         splx(s);
223         return error;
224 }
225
226 /*
227  * key_send()
228  * derived from net/rtsock.c:rts_send()
229  */
230 static int
231 key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
232          struct mbuf *control, struct proc *p)
233 {
234         int s, error;
235         s = splnet();
236         error = raw_usrreqs.pru_send(so, flags, m, nam, control, p);
237         splx(s);
238         return error;
239 }
240
241 /*
242  * key_shutdown()
243  * derived from net/rtsock.c:rts_shutdown()
244  */
245 static int
246 key_shutdown(struct socket *so)
247 {
248         int s, error;
249         s = splnet();
250         error = raw_usrreqs.pru_shutdown(so);
251         splx(s);
252         return error;
253 }
254
255 /*
256  * key_sockaddr()
257  * derived from net/rtsock.c:rts_sockaddr()
258  */
259 static int
260 key_sockaddr(struct socket *so, struct sockaddr **nam)
261 {
262         int s, error;
263         s = splnet();
264         error = raw_usrreqs.pru_sockaddr(so, nam);
265         splx(s);
266         return error;
267 }
268
269 struct pr_usrreqs key_usrreqs = {
270         key_abort, pru_accept_notsupp, key_attach, key_bind,
271         key_connect,
272         pru_connect2_notsupp, pru_control_notsupp, key_detach,
273         key_disconnect, pru_listen_notsupp, key_peeraddr,
274         pru_rcvd_notsupp,
275         pru_rcvoob_notsupp, key_send, pru_sense_null, key_shutdown,
276         key_sockaddr, sosend, soreceive, sopoll
277 };
278
279 /*
280  * key_output()
281  */
282 int
283 key_output(struct mbuf *m, struct socket *so)
284 {
285         struct sadb_msg *msg = NULL;
286         int len, error = 0;
287         int s;
288         int target;
289
290         if (m == 0)
291                 panic("key_output: NULL pointer was passed.\n");
292
293         if (m->m_len < sizeof(long)
294          && (m = m_pullup(m, 8)) == 0) {
295                 printf("key_output: can't pullup mbuf\n");
296                 error = ENOBUFS;
297                 goto end;
298         }
299
300         if ((m->m_flags & M_PKTHDR) == 0)
301                 panic("key_output: not M_PKTHDR ??");
302
303 #if defined(IPSEC_DEBUG)
304         KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
305 #endif /* defined(IPSEC_DEBUG) */
306
307         len = m->m_pkthdr.len;
308         if (len < sizeof(struct sadb_msg)
309          || len != PFKEY_UNUNIT64(mtod(m, struct sadb_msg *)->sadb_msg_len)) {
310                 printf("key_output: Invalid message length.\n");
311                 error = EINVAL;
312                 goto end;
313         }
314
315         /*
316          * allocate memory for sadb_msg, and copy to sadb_msg from mbuf
317          * XXX: To be processed directly without a copy.
318          */
319         KMALLOC(msg, struct sadb_msg *, len);
320         if (msg == 0) {
321                 printf("key_output: No more memory.\n");
322                 error = ENOBUFS;
323                 goto end;
324                 /* or do panic ? */
325         }
326         m_copydata(m, 0, len, (caddr_t)msg);
327
328         /*XXX giant lock*/
329         s = splnet();
330         if ((len = key_parse(&msg, so, &target)) == 0) {
331                 /* discard. i.e. no need to reply. */
332                 error = 0;
333                 splx(s);
334                 goto end;
335         }
336
337         /* send up message to the socket */
338         error = key_sendup(so, msg, len, target);
339         splx(s);
340         KFREE(msg);
341 end:
342         m_freem(m);
343         return (error);
344 }
345
346 /*
347  * send message to the socket.
348  */
349 static int
350 key_sendup0(rp, m, promisc)
351         struct rawcb *rp;
352         struct mbuf *m;
353         int promisc;
354 {
355         if (promisc) {
356                 struct sadb_msg *pmsg;
357
358                 M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT);
359                 if (m && m->m_len < sizeof(struct sadb_msg))
360                         m = m_pullup(m, sizeof(struct sadb_msg));
361                 if (!m) {
362                         printf("key_sendup0: cannot pullup\n");
363                         m_freem(m);
364                         return ENOBUFS;
365                 }
366                 m->m_pkthdr.len += sizeof(*pmsg);
367
368                 pmsg = mtod(m, struct sadb_msg *);
369                 bzero(pmsg, sizeof(*pmsg));
370                 pmsg->sadb_msg_version = PF_KEY_V2;
371                 pmsg->sadb_msg_type = SADB_X_PROMISC;
372                 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
373                 /* pid and seq? */
374         }
375
376         if (!sbappendaddr(&rp->rcb_socket->so_rcv,
377                         (struct sockaddr *)&key_src, m, NULL)) {
378                 printf("key_sendup0: sbappendaddr failed\n");
379                 m_freem(m);
380                 return ENOBUFS;
381         }
382         sorwakeup(rp->rcb_socket);
383         return 0;
384 }
385
386 int
387 key_sendup(so, msg, len, target)
388         struct socket *so;
389         struct sadb_msg *msg;
390         u_int len;
391         int target;     /*target of the resulting message*/
392 {
393         struct mbuf *m, *n, *mprev;
394         struct keycb *kp;
395         int sendup;
396         struct rawcb *rp;
397         int error;
398         int tlen;
399
400         /* sanity check */
401         if (so == 0 || msg == 0)
402                 panic("key_sendup: NULL pointer was passed.\n");
403
404         KEYDEBUG(KEYDEBUG_KEY_DUMP,
405                 printf("key_sendup: \n");
406                 kdebug_sadb(msg));
407
408         /*
409          * Get mbuf chain whenever possible (not clusters),
410          * to save socket buffer.  We'll be generating many SADB_ACQUIRE
411          * messages to listening key sockets.  If we simmply allocate clusters,
412          * sbappendaddr() will raise ENOBUFS due to too little sbspace().
413          * sbspace() computes # of actual data bytes AND mbuf region.
414          *
415          * TODO: SADB_ACQUIRE filters should be implemented.
416          */
417         tlen = len;
418         m = mprev = NULL;
419         while (tlen > 0) {
420                 if (tlen == len) {
421                         MGETHDR(n, M_DONTWAIT, MT_DATA);
422                         n->m_len = MHLEN;
423                 } else {
424                         MGET(n, M_DONTWAIT, MT_DATA);
425                         n->m_len = MLEN;
426                 }
427                 if (!n)
428                         return ENOBUFS;
429                 if (tlen > MCLBYTES) {  /*XXX better threshold? */
430                         MCLGET(n, M_DONTWAIT);
431                         if ((n->m_flags & M_EXT) == 0) {
432                                 m_free(n);
433                                 m_freem(m);
434                                 return ENOBUFS;
435                         }
436                         n->m_len = MCLBYTES;
437                 }
438
439                 if (tlen < n->m_len)
440                         n->m_len = tlen;
441                 n->m_next = NULL;
442                 if (m == NULL)
443                         m = mprev = n;
444                 else {
445                         mprev->m_next = n;
446                         mprev = n;
447                 }
448                 tlen -= n->m_len;
449                 n = NULL;
450         }
451         m->m_pkthdr.len = len;
452         m->m_pkthdr.rcvif = NULL;
453         m_copyback(m, 0, len, (caddr_t)msg);
454
455         LIST_FOREACH(rp, &rawcb_list, list)
456         {
457                 if (rp->rcb_proto.sp_family != PF_KEY)
458                         continue;
459                 if (rp->rcb_proto.sp_protocol
460                  && rp->rcb_proto.sp_protocol != PF_KEY_V2) {
461                         continue;
462                 }
463
464                 kp = (struct keycb *)rp;
465
466                 /*
467                  * If you are in promiscuous mode, and when you get broadcasted
468                  * reply, you'll get two PF_KEY messages.
469                  * (based on pf_key@inner.net message on 14 Oct 1998)
470                  */
471                 if (((struct keycb *)rp)->kp_promisc) {
472                         if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
473                                 (void)key_sendup0(rp, n, 1);
474                                 n = NULL;
475                         }
476                 }
477
478                 /* the exact target will be processed later */
479                 if (sotorawcb(so) == rp)
480                         continue;
481
482                 sendup = 0;
483                 switch (target) {
484                 case KEY_SENDUP_ONE:
485                         /* the statement has no effect */
486                         if (sotorawcb(so) == rp)
487                                 sendup++;
488                         break;
489                 case KEY_SENDUP_ALL:
490                         sendup++;
491                         break;
492                 case KEY_SENDUP_REGISTERED:
493                         if (kp->kp_registered)
494                                 sendup++;
495                         break;
496                 }
497
498                 if (!sendup)
499                         continue;
500
501                 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
502                         printf("key_sendup: m_copy fail\n");
503                         m_freem(m);
504                         return ENOBUFS;
505                 }
506
507                 if ((error = key_sendup0(rp, n, 0)) != 0) {
508                         m_freem(m);
509                         return error;
510                 }
511
512                 n = NULL;
513         }
514
515         error = key_sendup0(sotorawcb(so), m, 0);
516         m = NULL;
517         return error;
518 }
519
520 /* sysctl */
521 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
522
523 /*
524  * Definitions of protocols supported in the KEY domain.
525  */
526
527 extern struct domain keydomain;
528
529 struct protosw keysw[] = {
530 { SOCK_RAW,     &keydomain,     PF_KEY_V2,      PR_ATOMIC|PR_ADDR,
531   0,            key_output,     raw_ctlinput,   0,
532   0,
533   raw_init,     0,              0,              0,
534   &key_usrreqs
535 }
536 };
537
538 struct domain keydomain =
539     { PF_KEY, "key", key_init, 0, 0,
540       keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] };
541
542 DOMAIN_SET(key);