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.2/sys/netkey/keysock.c 154932 2006-01-27 21:50:11Z bz $");
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 key_output(struct mbuf *m, struct socket *so)
79 {
80 struct sadb_msg *msg;
81 int len, error = 0;
82 int s;
83
84 if (m == 0)
85 panic("key_output: NULL pointer was passed.");
86
87 pfkeystat.out_total++;
88 pfkeystat.out_bytes += m->m_pkthdr.len;
89
90 len = m->m_pkthdr.len;
91 if (len < sizeof(struct sadb_msg)) {
92 pfkeystat.out_tooshort++;
93 error = EINVAL;
94 goto end;
95 }
96
97 if (m->m_len < sizeof(struct sadb_msg)) {
98 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
99 pfkeystat.out_nomem++;
100 error = ENOBUFS;
101 goto end;
102 }
103 }
104
105 M_ASSERTPKTHDR(m);
106
107 KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
108
109 msg = mtod(m, struct sadb_msg *);
110 pfkeystat.out_msgtype[msg->sadb_msg_type]++;
111 if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
112 pfkeystat.out_invlen++;
113 error = EINVAL;
114 goto end;
115 }
116
117 /*XXX giant lock*/
118 s = splnet();
119 error = key_parse(m, so);
120 m = NULL;
121 splx(s);
122 end:
123 if (m)
124 m_freem(m);
125 return error;
126 }
127
128 /*
129 * send message to the socket.
130 */
131 static int
132 key_sendup0(rp, m, promisc)
133 struct rawcb *rp;
134 struct mbuf *m;
135 int promisc;
136 {
137 int error;
138
139 if (promisc) {
140 struct sadb_msg *pmsg;
141
142 M_PREPEND(m, sizeof(struct sadb_msg), M_DONTWAIT);
143 if (m && m->m_len < sizeof(struct sadb_msg))
144 m = m_pullup(m, sizeof(struct sadb_msg));
145 if (!m) {
146 pfkeystat.in_nomem++;
147 return ENOBUFS;
148 }
149 m->m_pkthdr.len += sizeof(*pmsg);
150
151 pmsg = mtod(m, struct sadb_msg *);
152 bzero(pmsg, sizeof(*pmsg));
153 pmsg->sadb_msg_version = PF_KEY_V2;
154 pmsg->sadb_msg_type = SADB_X_PROMISC;
155 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
156 /* pid and seq? */
157
158 pfkeystat.in_msgtype[pmsg->sadb_msg_type]++;
159 }
160
161 if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src,
162 m, NULL)) {
163 pfkeystat.in_nomem++;
164 m_freem(m);
165 error = ENOBUFS;
166 } else
167 error = 0;
168 sorwakeup(rp->rcb_socket);
169 return error;
170 }
171
172 /* so can be NULL if target != KEY_SENDUP_ONE */
173 int
174 key_sendup_mbuf(so, m, target)
175 struct socket *so;
176 struct mbuf *m;
177 int target;
178 {
179 struct mbuf *n;
180 struct keycb *kp;
181 int sendup;
182 struct rawcb *rp;
183 int error = 0;
184
185 if (m == NULL)
186 panic("key_sendup_mbuf: NULL pointer was passed.");
187 if (so == NULL && target == KEY_SENDUP_ONE)
188 panic("key_sendup_mbuf: NULL pointer was passed.");
189
190 pfkeystat.in_total++;
191 pfkeystat.in_bytes += m->m_pkthdr.len;
192 if (m->m_len < sizeof(struct sadb_msg)) {
193 m = m_pullup(m, sizeof(struct sadb_msg));
194 if (m == NULL) {
195 pfkeystat.in_nomem++;
196 return ENOBUFS;
197 }
198 }
199 if (m->m_len >= sizeof(struct sadb_msg)) {
200 struct sadb_msg *msg;
201 msg = mtod(m, struct sadb_msg *);
202 pfkeystat.in_msgtype[msg->sadb_msg_type]++;
203 }
204
205 LIST_FOREACH(rp, &rawcb_list, list) {
206 if (rp->rcb_proto.sp_family != PF_KEY)
207 continue;
208 if (rp->rcb_proto.sp_protocol &&
209 rp->rcb_proto.sp_protocol != PF_KEY_V2) {
210 continue;
211 }
212
213 kp = (struct keycb *)rp;
214
215 /*
216 * If you are in promiscuous mode, and when you get broadcasted
217 * reply, you'll get two PF_KEY messages.
218 * (based on pf_key@inner.net message on 14 Oct 1998)
219 */
220 if (((struct keycb *)rp)->kp_promisc) {
221 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
222 (void)key_sendup0(rp, n, 1);
223 n = NULL;
224 }
225 }
226
227 /* the exact target will be processed later */
228 if (so && sotorawcb(so) == rp)
229 continue;
230
231 sendup = 0;
232 switch (target) {
233 case KEY_SENDUP_ONE:
234 /* the statement has no effect */
235 if (so && sotorawcb(so) == rp)
236 sendup++;
237 break;
238 case KEY_SENDUP_ALL:
239 sendup++;
240 break;
241 case KEY_SENDUP_REGISTERED:
242 if (kp->kp_registered)
243 sendup++;
244 break;
245 }
246 pfkeystat.in_msgtarget[target]++;
247
248 if (!sendup)
249 continue;
250
251 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
252 m_freem(m);
253 pfkeystat.in_nomem++;
254 return ENOBUFS;
255 }
256
257 /*
258 * ignore error even if queue is full. PF_KEY does not
259 * guarantee the delivery of the message.
260 * this is important when target == KEY_SENDUP_ALL.
261 */
262 key_sendup0(rp, n, 0);
263
264 n = NULL;
265 }
266
267 if (so) {
268 error = key_sendup0(sotorawcb(so), m, 0);
269 m = NULL;
270 } else {
271 error = 0;
272 m_freem(m);
273 }
274 return error;
275 }
276
277 /*
278 * key_abort()
279 * derived from net/rtsock.c:rts_abort()
280 */
281 static int
282 key_abort(struct socket *so)
283 {
284 int s, error;
285 s = splnet();
286 error = raw_usrreqs.pru_abort(so);
287 splx(s);
288 return error;
289 }
290
291 /*
292 * key_attach()
293 * derived from net/rtsock.c:rts_attach()
294 */
295 static int
296 key_attach(struct socket *so, int proto, struct thread *p)
297 {
298 struct keycb *kp;
299 int s, error;
300
301 if (sotorawcb(so) != 0)
302 return EISCONN; /* XXX panic? */
303 kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK); /* XXX */
304 if (kp == 0)
305 return ENOBUFS;
306 bzero(kp, sizeof *kp);
307
308 /*
309 * The splnet() is necessary to block protocols from sending
310 * error notifications (like RTM_REDIRECT or RTM_LOSING) while
311 * this PCB is extant but incompletely initialized.
312 * Probably we should try to do more of this work beforehand and
313 * eliminate the spl.
314 */
315 s = splnet();
316 so->so_pcb = (caddr_t)kp;
317 error = raw_usrreqs.pru_attach(so, proto, p);
318 kp = (struct keycb *)sotorawcb(so);
319 if (error) {
320 free(kp, M_PCB);
321 so->so_pcb = (caddr_t) 0;
322 splx(s);
323 return error;
324 }
325
326 kp->kp_promisc = kp->kp_registered = 0;
327
328 if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
329 key_cb.key_count++;
330 key_cb.any_count++;
331 kp->kp_raw.rcb_laddr = &key_src;
332 kp->kp_raw.rcb_faddr = &key_dst;
333 soisconnected(so);
334 so->so_options |= SO_USELOOPBACK;
335
336 splx(s);
337 return 0;
338 }
339
340 /*
341 * key_bind()
342 * derived from net/rtsock.c:rts_bind()
343 */
344 static int
345 key_bind(struct socket *so, struct sockaddr *nam, struct thread *p)
346 {
347 int s, error;
348 s = splnet();
349 error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */
350 splx(s);
351 return error;
352 }
353
354 /*
355 * key_connect()
356 * derived from net/rtsock.c:rts_connect()
357 */
358 static int
359 key_connect(struct socket *so, struct sockaddr *nam, struct thread *p)
360 {
361 int s, error;
362 s = splnet();
363 error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */
364 splx(s);
365 return error;
366 }
367
368 /*
369 * key_detach()
370 * derived from net/rtsock.c:rts_detach()
371 */
372 static int
373 key_detach(struct socket *so)
374 {
375 struct keycb *kp = (struct keycb *)sotorawcb(so);
376 int s, error;
377
378 s = splnet();
379 if (kp != 0) {
380 if (kp->kp_raw.rcb_proto.sp_protocol
381 == PF_KEY) /* XXX: AF_KEY */
382 key_cb.key_count--;
383 key_cb.any_count--;
384
385 key_freereg(so);
386 }
387 error = raw_usrreqs.pru_detach(so);
388 splx(s);
389 return error;
390 }
391
392 /*
393 * key_disconnect()
394 * derived from net/rtsock.c:key_disconnect()
395 */
396 static int
397 key_disconnect(struct socket *so)
398 {
399 int s, error;
400 s = splnet();
401 error = raw_usrreqs.pru_disconnect(so);
402 splx(s);
403 return error;
404 }
405
406 /*
407 * key_peeraddr()
408 * derived from net/rtsock.c:rts_peeraddr()
409 */
410 static int
411 key_peeraddr(struct socket *so, struct sockaddr **nam)
412 {
413 int s, error;
414 s = splnet();
415 error = raw_usrreqs.pru_peeraddr(so, nam);
416 splx(s);
417 return error;
418 }
419
420 /*
421 * key_send()
422 * derived from net/rtsock.c:rts_send()
423 */
424 static int
425 key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
426 struct mbuf *control, struct thread *p)
427 {
428 int s, error;
429 s = splnet();
430 error = raw_usrreqs.pru_send(so, flags, m, nam, control, p);
431 splx(s);
432 return error;
433 }
434
435 /*
436 * key_shutdown()
437 * derived from net/rtsock.c:rts_shutdown()
438 */
439 static int
440 key_shutdown(struct socket *so)
441 {
442 int s, error;
443 s = splnet();
444 error = raw_usrreqs.pru_shutdown(so);
445 splx(s);
446 return error;
447 }
448
449 /*
450 * key_sockaddr()
451 * derived from net/rtsock.c:rts_sockaddr()
452 */
453 static int
454 key_sockaddr(struct socket *so, struct sockaddr **nam)
455 {
456 int s, error;
457 s = splnet();
458 error = raw_usrreqs.pru_sockaddr(so, nam);
459 splx(s);
460 return error;
461 }
462
463 struct pr_usrreqs key_usrreqs = {
464 .pru_abort = key_abort,
465 .pru_attach = key_attach,
466 .pru_bind = key_bind,
467 .pru_connect = key_connect,
468 .pru_detach = key_detach,
469 .pru_disconnect = key_disconnect,
470 .pru_peeraddr = key_peeraddr,
471 .pru_send = key_send,
472 .pru_shutdown = key_shutdown,
473 .pru_sockaddr = key_sockaddr,
474 };
475
476 /* sysctl */
477 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
478
479 /*
480 * Definitions of protocols supported in the KEY domain.
481 */
482
483 extern struct domain keydomain;
484
485 struct protosw keysw[] = {
486 {
487 .pr_type = SOCK_RAW,
488 .pr_domain = &keydomain,
489 .pr_protocol = PF_KEY_V2,
490 .pr_flags = PR_ATOMIC|PR_ADDR,
491 .pr_output = key_output,
492 .pr_ctlinput = raw_ctlinput,
493 .pr_init = raw_init,
494 .pr_usrreqs = &key_usrreqs
495 }
496 };
497
498 struct domain keydomain = {
499 .dom_family = PF_KEY,
500 .dom_name = "key",
501 .dom_init = key_init,
502 .dom_protosw = keysw,
503 .dom_protoswNPROTOSW = &keysw[sizeof(keysw)/sizeof(keysw[0])]
504 };
505
506 DOMAIN_SET(key);
Cache object: 3f23ee8c92cf3d9ad716b235df9a5faf
|