1 | /* $NetBSD: keysock.c,v 1.50 2016/06/10 13:27:16 ozaki-r Exp $ */ |
2 | /* $FreeBSD: src/sys/netipsec/keysock.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $ */ |
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 <sys/cdefs.h> |
35 | __KERNEL_RCSID(0, "$NetBSD: keysock.c,v 1.50 2016/06/10 13:27:16 ozaki-r Exp $" ); |
36 | |
37 | /* This code has derived from sys/net/rtsock.c on FreeBSD2.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/kmem.h> |
45 | #include <sys/mbuf.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 <netipsec/ipsec_osdep.h> |
62 | #include <netipsec/ipsec_private.h> |
63 | |
64 | struct key_cb { |
65 | int key_count; |
66 | int any_count; |
67 | }; |
68 | static struct key_cb key_cb; |
69 | |
70 | static struct sockaddr key_dst = { |
71 | .sa_len = 2, |
72 | .sa_family = PF_KEY, |
73 | }; |
74 | static struct sockaddr key_src = { |
75 | .sa_len = 2, |
76 | .sa_family = PF_KEY, |
77 | }; |
78 | |
79 | static const struct protosw keysw[]; |
80 | |
81 | static int key_sendup0(struct rawcb *, struct mbuf *, int, int); |
82 | |
83 | int key_registered_sb_max = (2048 * MHLEN); /* XXX arbitrary */ |
84 | |
85 | /* |
86 | * key_output() |
87 | */ |
88 | static int |
89 | key_output(struct mbuf *m, struct socket *so) |
90 | { |
91 | struct sadb_msg *msg; |
92 | int len, error = 0; |
93 | int s; |
94 | |
95 | if (m == 0) |
96 | panic("key_output: NULL pointer was passed" ); |
97 | |
98 | { |
99 | uint64_t *ps = PFKEY_STAT_GETREF(); |
100 | ps[PFKEY_STAT_OUT_TOTAL]++; |
101 | ps[PFKEY_STAT_OUT_BYTES] += m->m_pkthdr.len; |
102 | PFKEY_STAT_PUTREF(); |
103 | } |
104 | |
105 | len = m->m_pkthdr.len; |
106 | if (len < sizeof(struct sadb_msg)) { |
107 | PFKEY_STATINC(PFKEY_STAT_OUT_TOOSHORT); |
108 | error = EINVAL; |
109 | goto end; |
110 | } |
111 | |
112 | if (m->m_len < sizeof(struct sadb_msg)) { |
113 | if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) { |
114 | PFKEY_STATINC(PFKEY_STAT_OUT_NOMEM); |
115 | error = ENOBUFS; |
116 | goto end; |
117 | } |
118 | } |
119 | |
120 | if ((m->m_flags & M_PKTHDR) == 0) |
121 | panic("key_output: not M_PKTHDR ??" ); |
122 | |
123 | KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m)); |
124 | |
125 | msg = mtod(m, struct sadb_msg *); |
126 | PFKEY_STATINC(PFKEY_STAT_OUT_MSGTYPE + msg->sadb_msg_type); |
127 | if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) { |
128 | PFKEY_STATINC(PFKEY_STAT_OUT_INVLEN); |
129 | error = EINVAL; |
130 | goto end; |
131 | } |
132 | |
133 | /*XXX giant lock*/ |
134 | s = splsoftnet(); |
135 | error = key_parse(m, so); |
136 | m = NULL; |
137 | splx(s); |
138 | end: |
139 | if (m) |
140 | m_freem(m); |
141 | return error; |
142 | } |
143 | |
144 | /* |
145 | * send message to the socket. |
146 | */ |
147 | static int |
148 | key_sendup0( |
149 | struct rawcb *rp, |
150 | struct mbuf *m, |
151 | int promisc, |
152 | int sbprio |
153 | ) |
154 | { |
155 | int error; |
156 | int ok; |
157 | |
158 | if (promisc) { |
159 | struct sadb_msg *pmsg; |
160 | |
161 | M_PREPEND(m, sizeof(struct sadb_msg), M_DONTWAIT); |
162 | if (m && m->m_len < sizeof(struct sadb_msg)) |
163 | m = m_pullup(m, sizeof(struct sadb_msg)); |
164 | if (!m) { |
165 | PFKEY_STATINC(PFKEY_STAT_IN_NOMEM); |
166 | return ENOBUFS; |
167 | } |
168 | m->m_pkthdr.len += sizeof(*pmsg); |
169 | |
170 | pmsg = mtod(m, struct sadb_msg *); |
171 | memset(pmsg, 0, sizeof(*pmsg)); |
172 | pmsg->sadb_msg_version = PF_KEY_V2; |
173 | pmsg->sadb_msg_type = SADB_X_PROMISC; |
174 | pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); |
175 | /* pid and seq? */ |
176 | |
177 | PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE + pmsg->sadb_msg_type); |
178 | } |
179 | |
180 | if (sbprio == 0) |
181 | ok = sbappendaddr(&rp->rcb_socket->so_rcv, |
182 | (struct sockaddr *)&key_src, m, NULL); |
183 | else |
184 | ok = sbappendaddrchain(&rp->rcb_socket->so_rcv, |
185 | (struct sockaddr *)&key_src, m, sbprio); |
186 | |
187 | if (!ok) { |
188 | PFKEY_STATINC(PFKEY_STAT_IN_NOMEM); |
189 | m_freem(m); |
190 | error = ENOBUFS; |
191 | } else |
192 | error = 0; |
193 | sorwakeup(rp->rcb_socket); |
194 | return error; |
195 | } |
196 | |
197 | /* XXX this interface should be obsoleted. */ |
198 | int |
199 | key_sendup(struct socket *so, struct sadb_msg *msg, u_int len, |
200 | int target) /*target of the resulting message*/ |
201 | { |
202 | struct mbuf *m, *n, *mprev; |
203 | int tlen; |
204 | |
205 | /* sanity check */ |
206 | if (so == 0 || msg == 0) |
207 | panic("key_sendup: NULL pointer was passed" ); |
208 | |
209 | KEYDEBUG(KEYDEBUG_KEY_DUMP, |
210 | printf("key_sendup: \n" ); |
211 | kdebug_sadb(msg)); |
212 | |
213 | /* |
214 | * we increment statistics here, just in case we have ENOBUFS |
215 | * in this function. |
216 | */ |
217 | { |
218 | uint64_t *ps = PFKEY_STAT_GETREF(); |
219 | ps[PFKEY_STAT_IN_TOTAL]++; |
220 | ps[PFKEY_STAT_IN_BYTES] += len; |
221 | ps[PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type]++; |
222 | PFKEY_STAT_PUTREF(); |
223 | } |
224 | |
225 | /* |
226 | * Get mbuf chain whenever possible (not clusters), |
227 | * to save socket buffer. We'll be generating many SADB_ACQUIRE |
228 | * messages to listening key sockets. If we simply allocate clusters, |
229 | * sbappendaddr() will raise ENOBUFS due to too little sbspace(). |
230 | * sbspace() computes # of actual data bytes AND mbuf region. |
231 | * |
232 | * TODO: SADB_ACQUIRE filters should be implemented. |
233 | */ |
234 | tlen = len; |
235 | m = mprev = NULL; |
236 | while (tlen > 0) { |
237 | int mlen; |
238 | if (tlen == len) { |
239 | MGETHDR(n, M_DONTWAIT, MT_DATA); |
240 | mlen = MHLEN; |
241 | } else { |
242 | MGET(n, M_DONTWAIT, MT_DATA); |
243 | mlen = MLEN; |
244 | } |
245 | if (!n) { |
246 | PFKEY_STATINC(PFKEY_STAT_IN_NOMEM); |
247 | return ENOBUFS; |
248 | } |
249 | n->m_len = mlen; |
250 | if (tlen >= MCLBYTES) { /*XXX better threshold? */ |
251 | MCLGET(n, M_DONTWAIT); |
252 | if ((n->m_flags & M_EXT) == 0) { |
253 | m_free(n); |
254 | m_freem(m); |
255 | PFKEY_STATINC(PFKEY_STAT_IN_NOMEM); |
256 | return ENOBUFS; |
257 | } |
258 | n->m_len = MCLBYTES; |
259 | } |
260 | |
261 | if (tlen < n->m_len) |
262 | n->m_len = tlen; |
263 | n->m_next = NULL; |
264 | if (m == NULL) |
265 | m = mprev = n; |
266 | else { |
267 | mprev->m_next = n; |
268 | mprev = n; |
269 | } |
270 | tlen -= n->m_len; |
271 | n = NULL; |
272 | } |
273 | m->m_pkthdr.len = len; |
274 | m_reset_rcvif(m); |
275 | m_copyback(m, 0, len, msg); |
276 | |
277 | /* avoid duplicated statistics */ |
278 | { |
279 | uint64_t *ps = PFKEY_STAT_GETREF(); |
280 | ps[PFKEY_STAT_IN_TOTAL]--; |
281 | ps[PFKEY_STAT_IN_BYTES] -= len; |
282 | ps[PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type]--; |
283 | PFKEY_STAT_PUTREF(); |
284 | } |
285 | |
286 | return key_sendup_mbuf(so, m, target); |
287 | } |
288 | |
289 | /* so can be NULL if target != KEY_SENDUP_ONE */ |
290 | int |
291 | key_sendup_mbuf(struct socket *so, struct mbuf *m, |
292 | int target/*, sbprio */) |
293 | { |
294 | struct mbuf *n; |
295 | struct keycb *kp; |
296 | int sendup; |
297 | struct rawcb *rp; |
298 | int error = 0; |
299 | int sbprio = 0; /* XXX should be a parameter */ |
300 | |
301 | if (m == NULL) |
302 | panic("key_sendup_mbuf: NULL pointer was passed" ); |
303 | if (so == NULL && target == KEY_SENDUP_ONE) |
304 | panic("key_sendup_mbuf: NULL pointer was passed" ); |
305 | |
306 | /* |
307 | * RFC 2367 says ACQUIRE and other kernel-generated messages |
308 | * are special. We treat all KEY_SENDUP_REGISTERED messages |
309 | * as special, delivering them to all registered sockets |
310 | * even if the socket is at or above its so->so_rcv.sb_max limits. |
311 | * The only constraint is that the so_rcv data fall below |
312 | * key_registered_sb_max. |
313 | * Doing that check here avoids reworking every key_sendup_mbuf() |
314 | * in the short term. . The rework will be done after a technical |
315 | * conensus that this approach is appropriate. |
316 | */ |
317 | if (target == KEY_SENDUP_REGISTERED) { |
318 | sbprio = SB_PRIO_BESTEFFORT; |
319 | } |
320 | |
321 | { |
322 | uint64_t *ps = PFKEY_STAT_GETREF(); |
323 | ps[PFKEY_STAT_IN_TOTAL]++; |
324 | ps[PFKEY_STAT_IN_BYTES] += m->m_pkthdr.len; |
325 | PFKEY_STAT_PUTREF(); |
326 | } |
327 | if (m->m_len < sizeof(struct sadb_msg)) { |
328 | #if 1 |
329 | m = m_pullup(m, sizeof(struct sadb_msg)); |
330 | if (m == NULL) { |
331 | PFKEY_STATINC(PFKEY_STAT_IN_NOMEM); |
332 | return ENOBUFS; |
333 | } |
334 | #else |
335 | /* don't bother pulling it up just for stats */ |
336 | #endif |
337 | } |
338 | if (m->m_len >= sizeof(struct sadb_msg)) { |
339 | struct sadb_msg *msg; |
340 | msg = mtod(m, struct sadb_msg *); |
341 | PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type); |
342 | } |
343 | |
344 | LIST_FOREACH(rp, &rawcb_list, rcb_list) |
345 | { |
346 | struct socket * kso = rp->rcb_socket; |
347 | if (rp->rcb_proto.sp_family != PF_KEY) |
348 | continue; |
349 | if (rp->rcb_proto.sp_protocol |
350 | && rp->rcb_proto.sp_protocol != PF_KEY_V2) { |
351 | continue; |
352 | } |
353 | |
354 | kp = (struct keycb *)rp; |
355 | |
356 | /* |
357 | * If you are in promiscuous mode, and when you get broadcasted |
358 | * reply, you'll get two PF_KEY messages. |
359 | * (based on pf_key@inner.net message on 14 Oct 1998) |
360 | */ |
361 | if (((struct keycb *)rp)->kp_promisc) { |
362 | if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { |
363 | (void)key_sendup0(rp, n, 1, 0); |
364 | n = NULL; |
365 | } |
366 | } |
367 | |
368 | /* the exact target will be processed later */ |
369 | if (so && sotorawcb(so) == rp) |
370 | continue; |
371 | |
372 | sendup = 0; |
373 | switch (target) { |
374 | case KEY_SENDUP_ONE: |
375 | /* the statement has no effect */ |
376 | if (so && sotorawcb(so) == rp) |
377 | sendup++; |
378 | break; |
379 | case KEY_SENDUP_ALL: |
380 | sendup++; |
381 | break; |
382 | case KEY_SENDUP_REGISTERED: |
383 | if (kp->kp_registered) { |
384 | if (kso->so_rcv.sb_cc <= key_registered_sb_max) |
385 | sendup++; |
386 | else |
387 | printf("keysock: " |
388 | "registered sendup dropped, " |
389 | "sb_cc %ld max %d\n" , |
390 | kso->so_rcv.sb_cc, |
391 | key_registered_sb_max); |
392 | } |
393 | break; |
394 | } |
395 | PFKEY_STATINC(PFKEY_STAT_IN_MSGTARGET + target); |
396 | |
397 | if (!sendup) |
398 | continue; |
399 | |
400 | if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) { |
401 | m_freem(m); |
402 | PFKEY_STATINC(PFKEY_STAT_IN_NOMEM); |
403 | return ENOBUFS; |
404 | } |
405 | |
406 | if ((error = key_sendup0(rp, n, 0, 0)) != 0) { |
407 | m_freem(m); |
408 | return error; |
409 | } |
410 | |
411 | n = NULL; |
412 | } |
413 | |
414 | /* The 'later' time for processing the exact target has arrived */ |
415 | if (so) { |
416 | error = key_sendup0(sotorawcb(so), m, 0, sbprio); |
417 | m = NULL; |
418 | } else { |
419 | error = 0; |
420 | m_freem(m); |
421 | } |
422 | return error; |
423 | } |
424 | |
425 | static int |
426 | key_attach(struct socket *so, int proto) |
427 | { |
428 | struct keycb *kp; |
429 | int s, error; |
430 | |
431 | KASSERT(sotorawcb(so) == NULL); |
432 | kp = kmem_zalloc(sizeof(*kp), KM_SLEEP); |
433 | kp->kp_raw.rcb_len = sizeof(*kp); |
434 | so->so_pcb = kp; |
435 | |
436 | s = splsoftnet(); |
437 | error = raw_attach(so, proto); |
438 | if (error) { |
439 | PFKEY_STATINC(PFKEY_STAT_SOCKERR); |
440 | kmem_free(kp, sizeof(*kp)); |
441 | so->so_pcb = NULL; |
442 | goto out; |
443 | } |
444 | |
445 | kp->kp_promisc = kp->kp_registered = 0; |
446 | |
447 | if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ |
448 | key_cb.key_count++; |
449 | key_cb.any_count++; |
450 | kp->kp_raw.rcb_laddr = &key_src; |
451 | kp->kp_raw.rcb_faddr = &key_dst; |
452 | soisconnected(so); |
453 | so->so_options |= SO_USELOOPBACK; |
454 | out: |
455 | KASSERT(solocked(so)); |
456 | splx(s); |
457 | return error; |
458 | } |
459 | |
460 | static void |
461 | key_detach(struct socket *so) |
462 | { |
463 | struct keycb *kp = (struct keycb *)sotorawcb(so); |
464 | int s; |
465 | |
466 | KASSERT(solocked(so)); |
467 | KASSERT(kp != NULL); |
468 | |
469 | s = splsoftnet(); |
470 | if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ |
471 | key_cb.key_count--; |
472 | key_cb.any_count--; |
473 | key_freereg(so); |
474 | raw_detach(so); |
475 | splx(s); |
476 | } |
477 | |
478 | static int |
479 | key_accept(struct socket *so, struct sockaddr *nam) |
480 | { |
481 | KASSERT(solocked(so)); |
482 | |
483 | panic("key_accept" ); |
484 | |
485 | return EOPNOTSUPP; |
486 | } |
487 | |
488 | static int |
489 | key_bind(struct socket *so, struct sockaddr *nam, struct lwp *l) |
490 | { |
491 | KASSERT(solocked(so)); |
492 | |
493 | return EOPNOTSUPP; |
494 | } |
495 | |
496 | static int |
497 | key_listen(struct socket *so, struct lwp *l) |
498 | { |
499 | KASSERT(solocked(so)); |
500 | |
501 | return EOPNOTSUPP; |
502 | } |
503 | |
504 | static int |
505 | key_connect(struct socket *so, struct sockaddr *nam, struct lwp *l) |
506 | { |
507 | KASSERT(solocked(so)); |
508 | |
509 | return EOPNOTSUPP; |
510 | } |
511 | |
512 | static int |
513 | key_connect2(struct socket *so, struct socket *so2) |
514 | { |
515 | KASSERT(solocked(so)); |
516 | |
517 | return EOPNOTSUPP; |
518 | } |
519 | |
520 | static int |
521 | key_disconnect(struct socket *so) |
522 | { |
523 | struct rawcb *rp = sotorawcb(so); |
524 | int s; |
525 | |
526 | KASSERT(solocked(so)); |
527 | KASSERT(rp != NULL); |
528 | |
529 | s = splsoftnet(); |
530 | soisdisconnected(so); |
531 | raw_disconnect(rp); |
532 | splx(s); |
533 | |
534 | return 0; |
535 | } |
536 | |
537 | static int |
538 | key_shutdown(struct socket *so) |
539 | { |
540 | int s; |
541 | |
542 | KASSERT(solocked(so)); |
543 | |
544 | /* |
545 | * Mark the connection as being incapable of further input. |
546 | */ |
547 | s = splsoftnet(); |
548 | socantsendmore(so); |
549 | splx(s); |
550 | |
551 | return 0; |
552 | } |
553 | |
554 | static int |
555 | key_abort(struct socket *so) |
556 | { |
557 | KASSERT(solocked(so)); |
558 | |
559 | panic("key_abort" ); |
560 | |
561 | return EOPNOTSUPP; |
562 | } |
563 | |
564 | static int |
565 | key_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) |
566 | { |
567 | return EOPNOTSUPP; |
568 | } |
569 | |
570 | static int |
571 | key_stat(struct socket *so, struct stat *ub) |
572 | { |
573 | KASSERT(solocked(so)); |
574 | |
575 | return 0; |
576 | } |
577 | |
578 | static int |
579 | key_peeraddr(struct socket *so, struct sockaddr *nam) |
580 | { |
581 | struct rawcb *rp = sotorawcb(so); |
582 | |
583 | KASSERT(solocked(so)); |
584 | KASSERT(rp != NULL); |
585 | KASSERT(nam != NULL); |
586 | |
587 | if (rp->rcb_faddr == NULL) |
588 | return ENOTCONN; |
589 | |
590 | raw_setpeeraddr(rp, nam); |
591 | return 0; |
592 | } |
593 | |
594 | static int |
595 | key_sockaddr(struct socket *so, struct sockaddr *nam) |
596 | { |
597 | struct rawcb *rp = sotorawcb(so); |
598 | |
599 | KASSERT(solocked(so)); |
600 | KASSERT(rp != NULL); |
601 | KASSERT(nam != NULL); |
602 | |
603 | if (rp->rcb_faddr == NULL) |
604 | return ENOTCONN; |
605 | |
606 | raw_setsockaddr(rp, nam); |
607 | return 0; |
608 | } |
609 | |
610 | static int |
611 | key_rcvd(struct socket *so, int flags, struct lwp *l) |
612 | { |
613 | KASSERT(solocked(so)); |
614 | |
615 | return EOPNOTSUPP; |
616 | } |
617 | |
618 | static int |
619 | key_recvoob(struct socket *so, struct mbuf *m, int flags) |
620 | { |
621 | KASSERT(solocked(so)); |
622 | |
623 | return EOPNOTSUPP; |
624 | } |
625 | |
626 | static int |
627 | key_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, |
628 | struct mbuf *control, struct lwp *l) |
629 | { |
630 | int error = 0; |
631 | int s; |
632 | |
633 | KASSERT(solocked(so)); |
634 | KASSERT(so->so_proto == &keysw[0]); |
635 | |
636 | s = splsoftnet(); |
637 | error = raw_send(so, m, nam, control, l, &key_output); |
638 | splx(s); |
639 | |
640 | return error; |
641 | } |
642 | |
643 | static int |
644 | key_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) |
645 | { |
646 | KASSERT(solocked(so)); |
647 | |
648 | m_freem(m); |
649 | m_freem(control); |
650 | |
651 | return EOPNOTSUPP; |
652 | } |
653 | |
654 | static int |
655 | key_purgeif(struct socket *so, struct ifnet *ifa) |
656 | { |
657 | |
658 | panic("key_purgeif" ); |
659 | |
660 | return EOPNOTSUPP; |
661 | } |
662 | |
663 | /* |
664 | * Definitions of protocols supported in the KEY domain. |
665 | */ |
666 | |
667 | DOMAIN_DEFINE(keydomain); |
668 | |
669 | PR_WRAP_USRREQS(key) |
670 | #define key_attach key_attach_wrapper |
671 | #define key_detach key_detach_wrapper |
672 | #define key_accept key_accept_wrapper |
673 | #define key_bind key_bind_wrapper |
674 | #define key_listen key_listen_wrapper |
675 | #define key_connect key_connect_wrapper |
676 | #define key_connect2 key_connect2_wrapper |
677 | #define key_disconnect key_disconnect_wrapper |
678 | #define key_shutdown key_shutdown_wrapper |
679 | #define key_abort key_abort_wrapper |
680 | #define key_ioctl key_ioctl_wrapper |
681 | #define key_stat key_stat_wrapper |
682 | #define key_peeraddr key_peeraddr_wrapper |
683 | #define key_sockaddr key_sockaddr_wrapper |
684 | #define key_rcvd key_rcvd_wrapper |
685 | #define key_recvoob key_recvoob_wrapper |
686 | #define key_send key_send_wrapper |
687 | #define key_sendoob key_sendoob_wrapper |
688 | #define key_purgeif key_purgeif_wrapper |
689 | |
690 | static const struct pr_usrreqs key_usrreqs = { |
691 | .pr_attach = key_attach, |
692 | .pr_detach = key_detach, |
693 | .pr_accept = key_accept, |
694 | .pr_bind = key_bind, |
695 | .pr_listen = key_listen, |
696 | .pr_connect = key_connect, |
697 | .pr_connect2 = key_connect2, |
698 | .pr_disconnect = key_disconnect, |
699 | .pr_shutdown = key_shutdown, |
700 | .pr_abort = key_abort, |
701 | .pr_ioctl = key_ioctl, |
702 | .pr_stat = key_stat, |
703 | .pr_peeraddr = key_peeraddr, |
704 | .pr_sockaddr = key_sockaddr, |
705 | .pr_rcvd = key_rcvd, |
706 | .pr_recvoob = key_recvoob, |
707 | .pr_send = key_send, |
708 | .pr_sendoob = key_sendoob, |
709 | .pr_purgeif = key_purgeif, |
710 | }; |
711 | |
712 | static const struct protosw keysw[] = { |
713 | { |
714 | .pr_type = SOCK_RAW, |
715 | .pr_domain = &keydomain, |
716 | .pr_protocol = PF_KEY_V2, |
717 | .pr_flags = PR_ATOMIC|PR_ADDR, |
718 | .pr_ctlinput = raw_ctlinput, |
719 | .pr_usrreqs = &key_usrreqs, |
720 | .pr_init = raw_init, |
721 | } |
722 | }; |
723 | |
724 | struct domain keydomain = { |
725 | .dom_family = PF_KEY, |
726 | .dom_name = "key" , |
727 | .dom_init = key_init, |
728 | .dom_protosw = keysw, |
729 | .dom_protoswNPROTOSW = &keysw[__arraycount(keysw)], |
730 | }; |
731 | |