FreeBSD/Linux Kernel Cross Reference
sys/netkey/keysock.c
1 /* $KAME: keysock.c,v 1.32 2003/08/22 05:45:08 itojun Exp $ */
2
3 /*-
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD: releng/6.0/sys/netkey/keysock.c 139823 2005-01-07 01:45:51Z imp $");
34
35 #include "opt_ipsec.h"
36
37 /* This code has derived from sys/net/rtsock.c on FreeBSD 2.2.5 */
38
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/domain.h>
42 #include <sys/errno.h>
43 #include <sys/kernel.h>
44 #include <sys/lock.h>
45 #include <sys/malloc.h>
46 #include <sys/mbuf.h>
47 #include <sys/mutex.h>
48 #include <sys/protosw.h>
49 #include <sys/signalvar.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
52 #include <sys/sysctl.h>
53 #include <sys/systm.h>
54
55 #include <net/raw_cb.h>
56 #include <net/route.h>
57 #include <netinet/in.h>
58
59 #include <net/pfkeyv2.h>
60 #include <netkey/keydb.h>
61 #include <netkey/key.h>
62 #include <netkey/keysock.h>
63 #include <netkey/key_debug.h>
64
65 #include <machine/stdarg.h>
66
67 struct sockaddr key_dst = { 2, PF_KEY, };
68 struct sockaddr key_src = { 2, PF_KEY, };
69
70 static int key_sendup0(struct rawcb *, struct mbuf *, int);
71
72 struct pfkeystat pfkeystat;
73
74 /*
75 * key_output()
76 */
77 int
78 #if __STDC__
79 key_output(struct mbuf *m, ...)
80 #else
81 key_output(m, va_alist)
82 struct mbuf *m;
83 va_dcl
84 #endif
85 {
86 struct sadb_msg *msg;
87 int len, error = 0;
88 int s;
89 struct socket *so;
90 va_list ap;
91
92 va_start(ap, m);
93 so = va_arg(ap, struct socket *);
94 va_end(ap);
95
96 if (m == 0)
97 panic("key_output: NULL pointer was passed.");
98
99 pfkeystat.out_total++;
100 pfkeystat.out_bytes += m->m_pkthdr.len;
101
102 len = m->m_pkthdr.len;
103 if (len < sizeof(struct sadb_msg)) {
104 pfkeystat.out_tooshort++;
105 error = EINVAL;
106 goto end;
107 }
108
109 if (m->m_len < sizeof(struct sadb_msg)) {
110 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
111 pfkeystat.out_nomem++;
112 error = ENOBUFS;
113 goto end;
114 }
115 }
116
117 M_ASSERTPKTHDR(m);
118
119 KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
120
121 msg = mtod(m, struct sadb_msg *);
122 pfkeystat.out_msgtype[msg->sadb_msg_type]++;
123 if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
124 pfkeystat.out_invlen++;
125 error = EINVAL;
126 goto end;
127 }
128
129 /*XXX giant lock*/
130 s = splnet();
131 error = key_parse(m, so);
132 m = NULL;
133 splx(s);
134 end:
135 if (m)
136 m_freem(m);
137 return error;
138 }
139
140 /*
141 * send message to the socket.
142 */
143 static int
144 key_sendup0(rp, m, promisc)
145 struct rawcb *rp;
146 struct mbuf *m;
147 int promisc;
148 {
149 int error;
150
151 if (promisc) {
152 struct sadb_msg *pmsg;
153
154 M_PREPEND(m, sizeof(struct sadb_msg), M_DONTWAIT);
155 if (m && m->m_len < sizeof(struct sadb_msg))
156 m = m_pullup(m, sizeof(struct sadb_msg));
157 if (!m) {
158 pfkeystat.in_nomem++;
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 /* so can be NULL if target != KEY_SENDUP_ONE */
185 int
186 key_sendup_mbuf(so, m, target)
187 struct socket *so;
188 struct mbuf *m;
189 int target;
190 {
191 struct mbuf *n;
192 struct keycb *kp;
193 int sendup;
194 struct rawcb *rp;
195 int error = 0;
196
197 if (m == NULL)
198 panic("key_sendup_mbuf: NULL pointer was passed.");
199 if (so == NULL && target == KEY_SENDUP_ONE)
200 panic("key_sendup_mbuf: NULL pointer was passed.");
201
202 pfkeystat.in_total++;
203 pfkeystat.in_bytes += m->m_pkthdr.len;
204 if (m->m_len < sizeof(struct sadb_msg)) {
205 m = m_pullup(m, sizeof(struct sadb_msg));
206 if (m == NULL) {
207 pfkeystat.in_nomem++;
208 return ENOBUFS;
209 }
210 }
211 if (m->m_len >= sizeof(struct sadb_msg)) {
212 struct sadb_msg *msg;
213 msg = mtod(m, struct sadb_msg *);
214 pfkeystat.in_msgtype[msg->sadb_msg_type]++;
215 }
216
217 LIST_FOREACH(rp, &rawcb_list, list) {
218 if (rp->rcb_proto.sp_family != PF_KEY)
219 continue;
220 if (rp->rcb_proto.sp_protocol &&
221 rp->rcb_proto.sp_protocol != PF_KEY_V2) {
222 continue;
223 }
224
225 kp = (struct keycb *)rp;
226
227 /*
228 * If you are in promiscuous mode, and when you get broadcasted
229 * reply, you'll get two PF_KEY messages.
230 * (based on pf_key@inner.net message on 14 Oct 1998)
231 */
232 if (((struct keycb *)rp)->kp_promisc) {
233 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
234 (void)key_sendup0(rp, n, 1);
235 n = NULL;
236 }
237 }
238
239 /* the exact target will be processed later */
240 if (so && sotorawcb(so) == rp)
241 continue;
242
243 sendup = 0;
244 switch (target) {
245 case KEY_SENDUP_ONE:
246 /* the statement has no effect */
247 if (so && sotorawcb(so) == rp)
248 sendup++;
249 break;
250 case KEY_SENDUP_ALL:
251 sendup++;
252 break;
253 case KEY_SENDUP_REGISTERED:
254 if (kp->kp_registered)
255 sendup++;
256 break;
257 }
258 pfkeystat.in_msgtarget[target]++;
259
260 if (!sendup)
261 continue;
262
263 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
264 m_freem(m);
265 pfkeystat.in_nomem++;
266 return ENOBUFS;
267 }
268
269 /*
270 * ignore error even if queue is full. PF_KEY does not
271 * guarantee the delivery of the message.
272 * this is important when target == KEY_SENDUP_ALL.
273 */
274 key_sendup0(rp, n, 0);
275
276 n = NULL;
277 }
278
279 if (so) {
280 error = key_sendup0(sotorawcb(so), m, 0);
281 m = NULL;
282 } else {
283 error = 0;
284 m_freem(m);
285 }
286 return error;
287 }
288
289 /*
290 * key_abort()
291 * derived from net/rtsock.c:rts_abort()
292 */
293 static int
294 key_abort(struct socket *so)
295 {
296 int s, error;
297 s = splnet();
298 error = raw_usrreqs.pru_abort(so);
299 splx(s);
300 return error;
301 }
302
303 /*
304 * key_attach()
305 * derived from net/rtsock.c:rts_attach()
306 */
307 static int
308 key_attach(struct socket *so, int proto, struct thread *p)
309 {
310 struct keycb *kp;
311 int s, error;
312
313 if (sotorawcb(so) != 0)
314 return EISCONN; /* XXX panic? */
315 kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK); /* XXX */
316 if (kp == 0)
317 return ENOBUFS;
318 bzero(kp, sizeof *kp);
319
320 /*
321 * The splnet() is necessary to block protocols from sending
322 * error notifications (like RTM_REDIRECT or RTM_LOSING) while
323 * this PCB is extant but incompletely initialized.
324 * Probably we should try to do more of this work beforehand and
325 * eliminate the spl.
326 */
327 s = splnet();
328 so->so_pcb = (caddr_t)kp;
329 error = raw_usrreqs.pru_attach(so, proto, p);
330 kp = (struct keycb *)sotorawcb(so);
331 if (error) {
332 free(kp, M_PCB);
333 so->so_pcb = (caddr_t) 0;
334 splx(s);
335 return error;
336 }
337
338 kp->kp_promisc = kp->kp_registered = 0;
339
340 if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
341 key_cb.key_count++;
342 key_cb.any_count++;
343 kp->kp_raw.rcb_laddr = &key_src;
344 kp->kp_raw.rcb_faddr = &key_dst;
345 soisconnected(so);
346 so->so_options |= SO_USELOOPBACK;
347
348 splx(s);
349 return 0;
350 }
351
352 /*
353 * key_bind()
354 * derived from net/rtsock.c:rts_bind()
355 */
356 static int
357 key_bind(struct socket *so, struct sockaddr *nam, struct thread *p)
358 {
359 int s, error;
360 s = splnet();
361 error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */
362 splx(s);
363 return error;
364 }
365
366 /*
367 * key_connect()
368 * derived from net/rtsock.c:rts_connect()
369 */
370 static int
371 key_connect(struct socket *so, struct sockaddr *nam, struct thread *p)
372 {
373 int s, error;
374 s = splnet();
375 error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */
376 splx(s);
377 return error;
378 }
379
380 /*
381 * key_detach()
382 * derived from net/rtsock.c:rts_detach()
383 */
384 static int
385 key_detach(struct socket *so)
386 {
387 struct keycb *kp = (struct keycb *)sotorawcb(so);
388 int s, error;
389
390 s = splnet();
391 if (kp != 0) {
392 if (kp->kp_raw.rcb_proto.sp_protocol
393 == PF_KEY) /* XXX: AF_KEY */
394 key_cb.key_count--;
395 key_cb.any_count--;
396
397 key_freereg(so);
398 }
399 error = raw_usrreqs.pru_detach(so);
400 splx(s);
401 return error;
402 }
403
404 /*
405 * key_disconnect()
406 * derived from net/rtsock.c:key_disconnect()
407 */
408 static int
409 key_disconnect(struct socket *so)
410 {
411 int s, error;
412 s = splnet();
413 error = raw_usrreqs.pru_disconnect(so);
414 splx(s);
415 return error;
416 }
417
418 /*
419 * key_peeraddr()
420 * derived from net/rtsock.c:rts_peeraddr()
421 */
422 static int
423 key_peeraddr(struct socket *so, struct sockaddr **nam)
424 {
425 int s, error;
426 s = splnet();
427 error = raw_usrreqs.pru_peeraddr(so, nam);
428 splx(s);
429 return error;
430 }
431
432 /*
433 * key_send()
434 * derived from net/rtsock.c:rts_send()
435 */
436 static int
437 key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
438 struct mbuf *control, struct thread *p)
439 {
440 int s, error;
441 s = splnet();
442 error = raw_usrreqs.pru_send(so, flags, m, nam, control, p);
443 splx(s);
444 return error;
445 }
446
447 /*
448 * key_shutdown()
449 * derived from net/rtsock.c:rts_shutdown()
450 */
451 static int
452 key_shutdown(struct socket *so)
453 {
454 int s, error;
455 s = splnet();
456 error = raw_usrreqs.pru_shutdown(so);
457 splx(s);
458 return error;
459 }
460
461 /*
462 * key_sockaddr()
463 * derived from net/rtsock.c:rts_sockaddr()
464 */
465 static int
466 key_sockaddr(struct socket *so, struct sockaddr **nam)
467 {
468 int s, error;
469 s = splnet();
470 error = raw_usrreqs.pru_sockaddr(so, nam);
471 splx(s);
472 return error;
473 }
474
475 struct pr_usrreqs key_usrreqs = {
476 .pru_abort = key_abort,
477 .pru_attach = key_attach,
478 .pru_bind = key_bind,
479 .pru_connect = key_connect,
480 .pru_detach = key_detach,
481 .pru_disconnect = key_disconnect,
482 .pru_peeraddr = key_peeraddr,
483 .pru_send = key_send,
484 .pru_shutdown = key_shutdown,
485 .pru_sockaddr = key_sockaddr,
486 };
487
488 /* sysctl */
489 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
490
491 /*
492 * Definitions of protocols supported in the KEY domain.
493 */
494
495 extern struct domain keydomain;
496
497 struct protosw keysw[] = {
498 { SOCK_RAW, &keydomain, PF_KEY_V2, PR_ATOMIC|PR_ADDR,
499 0, (pr_output_t *)key_output, raw_ctlinput, 0,
500 0,
501 raw_init, 0, 0, 0,
502 &key_usrreqs
503 }
504 };
505
506 struct domain keydomain =
507 { PF_KEY, "key", key_init, 0, 0,
508 keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] };
509
510 DOMAIN_SET(key);
Cache object: b030122e0cb37ead52fffc227751f3b4
|