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