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