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