1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
5 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
6 * Copyright (c) 2008-2012, by Michael Tuexen. 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 are met:
10 *
11 * a) Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 *
14 * b) Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the distribution.
17 *
18 * c) Neither the name of Cisco Systems, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #if defined(__FreeBSD__) && !defined(__Userspace__)
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 361895 2020-06-07 14:39:20Z tuexen $");
38 #endif
39
40 #include <netinet/sctp_os.h>
41 #ifdef INET6
42 #if defined(__FreeBSD__) && !defined(__Userspace__)
43 #include <sys/proc.h>
44 #endif
45 #include <netinet/sctp_pcb.h>
46 #include <netinet/sctp_header.h>
47 #include <netinet/sctp_var.h>
48 #include <netinet6/sctp6_var.h>
49 #include <netinet/sctp_sysctl.h>
50 #include <netinet/sctp_output.h>
51 #include <netinet/sctp_uio.h>
52 #include <netinet/sctp_asconf.h>
53 #include <netinet/sctputil.h>
54 #include <netinet/sctp_indata.h>
55 #include <netinet/sctp_timer.h>
56 #include <netinet/sctp_auth.h>
57 #include <netinet/sctp_input.h>
58 #include <netinet/sctp_output.h>
59 #include <netinet/sctp_bsd_addr.h>
60 #include <netinet/sctp_crc32.h>
61 #if !defined(_WIN32)
62 #include <netinet/icmp6.h>
63 #include <netinet/udp.h>
64 #endif
65 #if defined(__Userspace__)
66 int ip6_v6only=0;
67 #endif
68 #if defined(__Userspace__)
69 #ifdef INET
70 void
in6_sin6_2_sin(struct sockaddr_in * sin,struct sockaddr_in6 * sin6)71 in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
72 {
73 #if defined(_WIN32)
74 uint32_t temp;
75 #endif
76 memset(sin, 0, sizeof(*sin));
77 #ifdef HAVE_SIN_LEN
78 sin->sin_len = sizeof(struct sockaddr_in);
79 #endif
80 sin->sin_family = AF_INET;
81 sin->sin_port = sin6->sin6_port;
82 #if defined(_WIN32)
83 temp = sin6->sin6_addr.s6_addr16[7];
84 temp = temp << 16;
85 temp = temp | sin6->sin6_addr.s6_addr16[6];
86 sin->sin_addr.s_addr = temp;
87 #else
88 sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
89 #endif
90 }
91
92 void
in6_sin6_2_sin_in_sock(struct sockaddr * nam)93 in6_sin6_2_sin_in_sock(struct sockaddr *nam)
94 {
95 struct sockaddr_in *sin_p;
96 struct sockaddr_in6 sin6;
97
98 /* save original sockaddr_in6 addr and convert it to sockaddr_in */
99 sin6 = *(struct sockaddr_in6 *)nam;
100 sin_p = (struct sockaddr_in *)nam;
101 in6_sin6_2_sin(sin_p, &sin6);
102 }
103
104 void
in6_sin_2_v4mapsin6(const struct sockaddr_in * sin,struct sockaddr_in6 * sin6)105 in6_sin_2_v4mapsin6(const struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
106 {
107 memset(sin6, 0, sizeof(struct sockaddr_in6));
108 sin6->sin6_family = AF_INET6;
109 #ifdef HAVE_SIN6_LEN
110 sin6->sin6_len = sizeof(struct sockaddr_in6);
111 #endif
112 sin6->sin6_port = sin->sin_port;
113 #if defined(_WIN32)
114 ((uint32_t *)&sin6->sin6_addr)[0] = 0;
115 ((uint32_t *)&sin6->sin6_addr)[1] = 0;
116 ((uint32_t *)&sin6->sin6_addr)[2] = htonl(0xffff);
117 ((uint32_t *)&sin6->sin6_addr)[3] = sin->sin_addr.s_addr;
118 #else
119 sin6->sin6_addr.s6_addr32[0] = 0;
120 sin6->sin6_addr.s6_addr32[1] = 0;
121 sin6->sin6_addr.s6_addr32[2] = htonl(0xffff);
122 sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
123 #endif
124 }
125 #endif
126 #endif
127
128 #if !defined(__Userspace__)
129 int
130 #if defined(__APPLE__) || defined(__FreeBSD__)
sctp6_input_with_port(struct mbuf ** i_pak,int * offp,uint16_t port)131 sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
132 #else
133 sctp6_input(struct mbuf **i_pak, int *offp, int proto)
134 #endif
135 {
136 struct mbuf *m;
137 int iphlen;
138 uint32_t vrf_id;
139 uint8_t ecn_bits;
140 struct sockaddr_in6 src, dst;
141 struct ip6_hdr *ip6;
142 struct sctphdr *sh;
143 struct sctp_chunkhdr *ch;
144 int length, offset;
145 uint8_t compute_crc;
146 #if defined(__FreeBSD__)
147 uint32_t mflowid;
148 uint8_t mflowtype;
149 uint16_t fibnum;
150 #endif
151 #if !(defined(__APPLE__) || defined(__FreeBSD__))
152 uint16_t port = 0;
153 #endif
154
155 iphlen = *offp;
156 if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) {
157 SCTP_RELEASE_PKT(*i_pak);
158 return (IPPROTO_DONE);
159 }
160 m = SCTP_HEADER_TO_CHAIN(*i_pak);
161 #ifdef SCTP_MBUF_LOGGING
162 /* Log in any input mbufs */
163 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
164 sctp_log_mbc(m, SCTP_MBUF_INPUT);
165 }
166 #endif
167 #ifdef SCTP_PACKET_LOGGING
168 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
169 sctp_packet_log(m);
170 }
171 #endif
172 #if defined(__FreeBSD__)
173 SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
174 "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%b.\n",
175 m->m_pkthdr.len,
176 if_name(m->m_pkthdr.rcvif),
177 (int)m->m_pkthdr.csum_flags, CSUM_BITS);
178 #endif
179 #if defined(__APPLE__)
180 SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
181 "sctp6_input(): Packet of length %d received on %s%d with csum_flags 0x%x.\n",
182 m->m_pkthdr.len,
183 m->m_pkthdr.rcvif->if_name,
184 m->m_pkthdr.rcvif->if_unit,
185 m->m_pkthdr.csum_flags);
186 #endif
187 #if defined(_WIN32) && !defined(__Userspace__)
188 SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
189 "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
190 m->m_pkthdr.len,
191 m->m_pkthdr.rcvif->if_xname,
192 m->m_pkthdr.csum_flags);
193 #endif
194 #if defined(__FreeBSD__)
195 mflowid = m->m_pkthdr.flowid;
196 mflowtype = M_HASHTYPE_GET(m);
197 fibnum = M_GETFIB(m);
198 #endif
199 SCTP_STAT_INCR(sctps_recvpackets);
200 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
201 /* Get IP, SCTP, and first chunk header together in the first mbuf. */
202 offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
203 if (m->m_len < offset) {
204 m = m_pullup(m, offset);
205 if (m == NULL) {
206 SCTP_STAT_INCR(sctps_hdrops);
207 return (IPPROTO_DONE);
208 }
209 }
210 ip6 = mtod(m, struct ip6_hdr *);
211 sh = (struct sctphdr *)(mtod(m, caddr_t) + iphlen);
212 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
213 offset -= sizeof(struct sctp_chunkhdr);
214 memset(&src, 0, sizeof(struct sockaddr_in6));
215 src.sin6_family = AF_INET6;
216 #ifdef HAVE_SIN6_LEN
217 src.sin6_len = sizeof(struct sockaddr_in6);
218 #endif
219 src.sin6_port = sh->src_port;
220 src.sin6_addr = ip6->ip6_src;
221 #if defined(__FreeBSD__)
222 #if defined(__APPLE__)
223 /* XXX: This code should also be used on Apple */
224 #endif
225 if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
226 goto out;
227 }
228 #endif
229 memset(&dst, 0, sizeof(struct sockaddr_in6));
230 dst.sin6_family = AF_INET6;
231 #ifdef HAVE_SIN6_LEN
232 dst.sin6_len = sizeof(struct sockaddr_in6);
233 #endif
234 dst.sin6_port = sh->dest_port;
235 dst.sin6_addr = ip6->ip6_dst;
236 #if defined(__FreeBSD__)
237 #if defined(__APPLE__)
238 /* XXX: This code should also be used on Apple */
239 #endif
240 if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
241 goto out;
242 }
243 #endif
244 #if defined(__APPLE__)
245 #if defined(NFAITH) && 0 < NFAITH
246 if (faithprefix(&dst.sin6_addr)) {
247 goto out;
248 }
249 #endif
250 #endif
251 length = ntohs(ip6->ip6_plen) + iphlen;
252 /* Validate mbuf chain length with IP payload length. */
253 if (SCTP_HEADER_LEN(m) != length) {
254 SCTPDBG(SCTP_DEBUG_INPUT1,
255 "sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
256 SCTP_STAT_INCR(sctps_hdrops);
257 goto out;
258 }
259 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
260 goto out;
261 }
262 ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
263 #if defined(__FreeBSD__)
264 if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
265 SCTP_STAT_INCR(sctps_recvhwcrc);
266 compute_crc = 0;
267 } else {
268 #else
269 if (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
270 (IN6_ARE_ADDR_EQUAL(&src.sin6_addr, &dst.sin6_addr))) {
271 SCTP_STAT_INCR(sctps_recvhwcrc);
272 compute_crc = 0;
273 } else {
274 #endif
275 SCTP_STAT_INCR(sctps_recvswcrc);
276 compute_crc = 1;
277 }
278 sctp_common_input_processing(&m, iphlen, offset, length,
279 (struct sockaddr *)&src,
280 (struct sockaddr *)&dst,
281 sh, ch,
282 compute_crc,
283 ecn_bits,
284 #if defined(__FreeBSD__)
285 mflowtype, mflowid, fibnum,
286 #endif
287 vrf_id, port);
288 out:
289 if (m) {
290 sctp_m_freem(m);
291 }
292 return (IPPROTO_DONE);
293 }
294
295 #if defined(__APPLE__)
296 int
297 sctp6_input(struct mbuf **i_pak, int *offp)
298 {
299 return (sctp6_input_with_port(i_pak, offp, 0));
300 }
301 #endif
302
303 #if defined(__FreeBSD__)
304 int
305 sctp6_input(struct mbuf **i_pak, int *offp, int proto SCTP_UNUSED)
306 {
307 return (sctp6_input_with_port(i_pak, offp, 0));
308 }
309 #endif
310
311 void
312 sctp6_notify(struct sctp_inpcb *inp,
313 struct sctp_tcb *stcb,
314 struct sctp_nets *net,
315 uint8_t icmp6_type,
316 uint8_t icmp6_code,
317 uint32_t next_mtu)
318 {
319 #if defined(__APPLE__)
320 struct socket *so;
321 #endif
322 int timer_stopped;
323
324 switch (icmp6_type) {
325 case ICMP6_DST_UNREACH:
326 if ((icmp6_code == ICMP6_DST_UNREACH_NOROUTE) ||
327 (icmp6_code == ICMP6_DST_UNREACH_ADMIN) ||
328 (icmp6_code == ICMP6_DST_UNREACH_BEYONDSCOPE) ||
329 (icmp6_code == ICMP6_DST_UNREACH_ADDR)) {
330 /* Mark the net unreachable. */
331 if (net->dest_state & SCTP_ADDR_REACHABLE) {
332 /* Ok that destination is not reachable */
333 net->dest_state &= ~SCTP_ADDR_REACHABLE;
334 net->dest_state &= ~SCTP_ADDR_PF;
335 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
336 stcb, 0, (void *)net, SCTP_SO_NOT_LOCKED);
337 }
338 }
339 SCTP_TCB_UNLOCK(stcb);
340 break;
341 case ICMP6_PARAM_PROB:
342 /* Treat it like an ABORT. */
343 if (icmp6_code == ICMP6_PARAMPROB_NEXTHEADER) {
344 sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
345 #if defined(__APPLE__)
346 so = SCTP_INP_SO(inp);
347 atomic_add_int(&stcb->asoc.refcnt, 1);
348 SCTP_TCB_UNLOCK(stcb);
349 SCTP_SOCKET_LOCK(so, 1);
350 SCTP_TCB_LOCK(stcb);
351 atomic_subtract_int(&stcb->asoc.refcnt, 1);
352 #endif
353 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
354 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
355 #if defined(__APPLE__)
356 SCTP_SOCKET_UNLOCK(so, 1);
357 #endif
358 } else {
359 SCTP_TCB_UNLOCK(stcb);
360 }
361 break;
362 case ICMP6_PACKET_TOO_BIG:
363 if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
364 SCTP_TCB_UNLOCK(stcb);
365 break;
366 }
367 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
368 timer_stopped = 1;
369 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
370 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1);
371 } else {
372 timer_stopped = 0;
373 }
374 /* Update the path MTU. */
375 if (net->port) {
376 next_mtu -= sizeof(struct udphdr);
377 }
378 if (net->mtu > next_mtu) {
379 net->mtu = next_mtu;
380 #if defined(__FreeBSD__)
381 if (net->port) {
382 sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu + sizeof(struct udphdr));
383 } else {
384 sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu);
385 }
386 #endif
387 }
388 /* Update the association MTU */
389 if (stcb->asoc.smallest_mtu > next_mtu) {
390 sctp_pathmtu_adjustment(stcb, next_mtu);
391 }
392 /* Finally, start the PMTU timer if it was running before. */
393 if (timer_stopped) {
394 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
395 }
396 SCTP_TCB_UNLOCK(stcb);
397 break;
398 default:
399 SCTP_TCB_UNLOCK(stcb);
400 break;
401 }
402 }
403
404 void
405 #if defined(__APPLE__) && !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) && !defined(APPLE_ELCAPITAN)
406 sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d, struct ifnet *ifp SCTP_UNUSED)
407 #else
408 sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
409 #endif
410 {
411 struct ip6ctlparam *ip6cp;
412 struct sctp_inpcb *inp;
413 struct sctp_tcb *stcb;
414 struct sctp_nets *net;
415 struct sctphdr sh;
416 struct sockaddr_in6 src, dst;
417
418 #ifdef HAVE_SA_LEN
419 if (pktdst->sa_family != AF_INET6 ||
420 pktdst->sa_len != sizeof(struct sockaddr_in6)) {
421 #else
422 if (pktdst->sa_family != AF_INET6) {
423 #endif
424 return;
425 }
426
427 if ((unsigned)cmd >= PRC_NCMDS) {
428 return;
429 }
430 if (PRC_IS_REDIRECT(cmd)) {
431 d = NULL;
432 } else if (inet6ctlerrmap[cmd] == 0) {
433 return;
434 }
435 /* If the parameter is from icmp6, decode it. */
436 if (d != NULL) {
437 ip6cp = (struct ip6ctlparam *)d;
438 } else {
439 ip6cp = (struct ip6ctlparam *)NULL;
440 }
441
442 if (ip6cp != NULL) {
443 /*
444 * XXX: We assume that when IPV6 is non NULL, M and OFF are
445 * valid.
446 */
447 if (ip6cp->ip6c_m == NULL) {
448 return;
449 }
450
451 /* Check if we can safely examine the ports and the
452 * verification tag of the SCTP common header.
453 */
454 if (ip6cp->ip6c_m->m_pkthdr.len <
455 (int32_t)(ip6cp->ip6c_off + offsetof(struct sctphdr, checksum))) {
456 return;
457 }
458
459 /* Copy out the port numbers and the verification tag. */
460 memset(&sh, 0, sizeof(sh));
461 m_copydata(ip6cp->ip6c_m,
462 ip6cp->ip6c_off,
463 sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t),
464 (caddr_t)&sh);
465 memset(&src, 0, sizeof(struct sockaddr_in6));
466 src.sin6_family = AF_INET6;
467 #ifdef HAVE_SIN6_LEN
468 src.sin6_len = sizeof(struct sockaddr_in6);
469 #endif
470 src.sin6_port = sh.src_port;
471 src.sin6_addr = ip6cp->ip6c_ip6->ip6_src;
472 #if defined(__FreeBSD__)
473 if (in6_setscope(&src.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) {
474 return;
475 }
476 #endif
477 memset(&dst, 0, sizeof(struct sockaddr_in6));
478 dst.sin6_family = AF_INET6;
479 #ifdef HAVE_SIN6_LEN
480 dst.sin6_len = sizeof(struct sockaddr_in6);
481 #endif
482 dst.sin6_port = sh.dest_port;
483 dst.sin6_addr = ip6cp->ip6c_ip6->ip6_dst;
484 #if defined(__FreeBSD__)
485 if (in6_setscope(&dst.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) {
486 return;
487 }
488 #endif
489 inp = NULL;
490 net = NULL;
491 stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst,
492 (struct sockaddr *)&src,
493 &inp, &net, 1, SCTP_DEFAULT_VRFID);
494 if ((stcb != NULL) &&
495 (net != NULL) &&
496 (inp != NULL)) {
497 /* Check the verification tag */
498 if (ntohl(sh.v_tag) != 0) {
499 /*
500 * This must be the verification tag used for
501 * sending out packets. We don't consider
502 * packets reflecting the verification tag.
503 */
504 if (ntohl(sh.v_tag) != stcb->asoc.peer_vtag) {
505 SCTP_TCB_UNLOCK(stcb);
506 return;
507 }
508 } else {
509 #if defined(__FreeBSD__)
510 if (ip6cp->ip6c_m->m_pkthdr.len >=
511 ip6cp->ip6c_off + sizeof(struct sctphdr) +
512 sizeof(struct sctp_chunkhdr) +
513 offsetof(struct sctp_init, a_rwnd)) {
514 /*
515 * In this case we can check if we
516 * got an INIT chunk and if the
517 * initiate tag matches.
518 */
519 uint32_t initiate_tag;
520 uint8_t chunk_type;
521
522 m_copydata(ip6cp->ip6c_m,
523 ip6cp->ip6c_off +
524 sizeof(struct sctphdr),
525 sizeof(uint8_t),
526 (caddr_t)&chunk_type);
527 m_copydata(ip6cp->ip6c_m,
528 ip6cp->ip6c_off +
529 sizeof(struct sctphdr) +
530 sizeof(struct sctp_chunkhdr),
531 sizeof(uint32_t),
532 (caddr_t)&initiate_tag);
533 if ((chunk_type != SCTP_INITIATION) ||
534 (ntohl(initiate_tag) != stcb->asoc.my_vtag)) {
535 SCTP_TCB_UNLOCK(stcb);
536 return;
537 }
538 } else {
539 SCTP_TCB_UNLOCK(stcb);
540 return;
541 }
542 #else
543 SCTP_TCB_UNLOCK(stcb);
544 return;
545 #endif
546 }
547 sctp6_notify(inp, stcb, net,
548 ip6cp->ip6c_icmp6->icmp6_type,
549 ip6cp->ip6c_icmp6->icmp6_code,
550 ntohl(ip6cp->ip6c_icmp6->icmp6_mtu));
551 #if defined(__Userspace__)
552 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) &&
553 (stcb->sctp_socket != NULL) {
554 struct socket *upcall_socket;
555
556 upcall_socket = stcb->sctp_socket;
557 SOCK_LOCK(upcall_socket);
558 soref(upcall_socket);
559 SOCK_UNLOCK(upcall_socket);
560 if ((upcall_socket->so_upcall != NULL) &&
561 (upcall_socket->so_error != 0)) {
562 (*upcall_socket->so_upcall)(upcall_socket, upcall_socket->so_upcallarg, M_NOWAIT);
563 }
564 ACCEPT_LOCK();
565 SOCK_LOCK(upcall_socket);
566 sorele(upcall_socket);
567 }
568 #endif
569 } else {
570 if ((stcb == NULL) && (inp != NULL)) {
571 /* reduce inp's ref-count */
572 SCTP_INP_WLOCK(inp);
573 SCTP_INP_DECR_REF(inp);
574 SCTP_INP_WUNLOCK(inp);
575 }
576 if (stcb) {
577 SCTP_TCB_UNLOCK(stcb);
578 }
579 }
580 }
581 }
582 #endif
583
584 /*
585 * this routine can probably be collasped into the one in sctp_userreq.c
586 * since they do the same thing and now we lookup with a sockaddr
587 */
588 #if defined(__FreeBSD__) && !defined(__Userspace__)
589 static int
590 sctp6_getcred(SYSCTL_HANDLER_ARGS)
591 {
592 struct xucred xuc;
593 struct sockaddr_in6 addrs[2];
594 struct sctp_inpcb *inp;
595 struct sctp_nets *net;
596 struct sctp_tcb *stcb;
597 int error;
598 uint32_t vrf_id;
599
600 vrf_id = SCTP_DEFAULT_VRFID;
601
602 #if defined(__FreeBSD__) && !defined(__Userspace__)
603 error = priv_check(req->td, PRIV_NETINET_GETCRED);
604 #else
605 error = suser(req->p);
606 #endif
607 if (error)
608 return (error);
609
610 if (req->newlen != sizeof(addrs)) {
611 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
612 return (EINVAL);
613 }
614 if (req->oldlen != sizeof(struct ucred)) {
615 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
616 return (EINVAL);
617 }
618 error = SYSCTL_IN(req, addrs, sizeof(addrs));
619 if (error)
620 return (error);
621
622 stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[1]),
623 sin6tosa(&addrs[0]),
624 &inp, &net, 1, vrf_id);
625 if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
626 if ((inp != NULL) && (stcb == NULL)) {
627 /* reduce ref-count */
628 SCTP_INP_WLOCK(inp);
629 SCTP_INP_DECR_REF(inp);
630 goto cred_can_cont;
631 }
632 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
633 error = ENOENT;
634 goto out;
635 }
636 SCTP_TCB_UNLOCK(stcb);
637 /* We use the write lock here, only
638 * since in the error leg we need it.
639 * If we used RLOCK, then we would have
640 * to wlock/decr/unlock/rlock. Which
641 * in theory could create a hole. Better
642 * to use higher wlock.
643 */
644 SCTP_INP_WLOCK(inp);
645 cred_can_cont:
646 error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
647 if (error) {
648 SCTP_INP_WUNLOCK(inp);
649 goto out;
650 }
651 cru2x(inp->sctp_socket->so_cred, &xuc);
652 SCTP_INP_WUNLOCK(inp);
653 error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
654 out:
655 return (error);
656 }
657
658 SYSCTL_PROC(_net_inet6_sctp6, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
659 0, 0,
660 sctp6_getcred, "S,ucred", "Get the ucred of a SCTP6 connection");
661
662 #endif
663
664 /* This is the same as the sctp_abort() could be made common */
665 #if defined(__Userspace__)
666 int
667 #elif defined(__FreeBSD__) || defined(_WIN32)
668 static void
669 #else
670 static int
671 #endif
672 sctp6_abort(struct socket *so)
673 {
674 #if defined(__FreeBSD__) && !defined(__Userspace__)
675 struct epoch_tracker et;
676 #endif
677 struct sctp_inpcb *inp;
678 uint32_t flags;
679
680 inp = (struct sctp_inpcb *)so->so_pcb;
681 if (inp == NULL) {
682 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
683 #if (defined(__FreeBSD__) || defined(_WIN32)) && !defined(__Userspace__)
684 return;
685 #else
686 return (EINVAL);
687 #endif
688 }
689 #if defined(__FreeBSD__) && !defined(__Userspace__)
690 NET_EPOCH_ENTER(et);
691 #endif
692 sctp_must_try_again:
693 flags = inp->sctp_flags;
694 #ifdef SCTP_LOG_CLOSING
695 sctp_log_closing(inp, NULL, 17);
696 #endif
697 if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
698 (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
699 #ifdef SCTP_LOG_CLOSING
700 sctp_log_closing(inp, NULL, 16);
701 #endif
702 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
703 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
704 SOCK_LOCK(so);
705 SCTP_SB_CLEAR(so->so_snd);
706 /* same for the rcv ones, they are only
707 * here for the accounting/select.
708 */
709 SCTP_SB_CLEAR(so->so_rcv);
710 #if defined(__APPLE__) && !defined(__Userspace__)
711 so->so_usecount--;
712 #else
713 /* Now null out the reference, we are completely detached. */
714 so->so_pcb = NULL;
715 #endif
716 SOCK_UNLOCK(so);
717 } else {
718 flags = inp->sctp_flags;
719 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
720 goto sctp_must_try_again;
721 }
722 }
723 #if defined(__FreeBSD__) && !defined(__Userspace__)
724 NET_EPOCH_EXIT(et);
725 return;
726 #else
727 return (0);
728 #endif
729 }
730
731 #if defined(__Userspace__)
732 int
733 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
734 #elif defined(__FreeBSD__)
735 static int
736 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
737 #elif defined(_WIN32)
738 static int
739 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, PKTHREAD p SCTP_UNUSED)
740 #else
741 static int
742 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct proc *p SCTP_UNUSED)
743 #endif
744 {
745 int error;
746 struct sctp_inpcb *inp;
747 #if !defined(__Userspace__)
748 uint32_t vrf_id = SCTP_DEFAULT_VRFID;
749 #endif
750
751 inp = (struct sctp_inpcb *)so->so_pcb;
752 if (inp != NULL) {
753 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
754 return (EINVAL);
755 }
756
757 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
758 error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
759 if (error)
760 return (error);
761 }
762 error = sctp_inpcb_alloc(so, vrf_id);
763 if (error)
764 return (error);
765 inp = (struct sctp_inpcb *)so->so_pcb;
766 SCTP_INP_WLOCK(inp);
767 inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_V6; /* I'm v6! */
768
769 inp->ip_inp.inp.inp_vflag |= INP_IPV6;
770 inp->ip_inp.inp.in6p_hops = -1; /* use kernel default */
771 inp->ip_inp.inp.in6p_cksum = -1; /* just to be sure */
772 #ifdef INET
773 /*
774 * XXX: ugly!! IPv4 TTL initialization is necessary for an IPv6
775 * socket as well, because the socket may be bound to an IPv6
776 * wildcard address, which may match an IPv4-mapped IPv6 address.
777 */
778 inp->ip_inp.inp.inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
779 #endif
780 SCTP_INP_WUNLOCK(inp);
781 return (0);
782 }
783
784 #if defined(__Userspace__)
785 int
786 sctp6_bind(struct socket *so, struct sockaddr *addr, void * p)
787 {
788 #elif defined(__FreeBSD__)
789 static int
790 sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
791 {
792 #elif defined(__APPLE__)
793 static int
794 sctp6_bind(struct socket *so, struct sockaddr *addr, struct proc *p)
795 {
796 #elif defined(_WIN32)
797 static int
798 sctp6_bind(struct socket *so, struct sockaddr *addr, PKTHREAD p)
799 {
800 #else
801 static int
802 sctp6_bind(struct socket *so, struct mbuf *nam, struct proc *p)
803 {
804 struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
805
806 #endif
807 struct sctp_inpcb *inp;
808 int error;
809 u_char vflagsav;
810
811 inp = (struct sctp_inpcb *)so->so_pcb;
812 if (inp == NULL) {
813 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
814 return (EINVAL);
815 }
816
817 #if !(defined(_WIN32) && !defined(__Userspace__))
818 if (addr) {
819 switch (addr->sa_family) {
820 #ifdef INET
821 case AF_INET:
822 #ifdef HAVE_SA_LEN
823 if (addr->sa_len != sizeof(struct sockaddr_in)) {
824 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
825 return (EINVAL);
826 }
827 #endif
828 break;
829 #endif
830 #ifdef INET6
831 case AF_INET6:
832 #ifdef HAVE_SA_LEN
833 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
834 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
835 return (EINVAL);
836 }
837 #endif
838 break;
839 #endif
840 default:
841 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
842 return (EINVAL);
843 }
844 }
845 #endif
846 vflagsav = inp->ip_inp.inp.inp_vflag;
847 inp->ip_inp.inp.inp_vflag &= ~INP_IPV4;
848 inp->ip_inp.inp.inp_vflag |= INP_IPV6;
849 if ((addr != NULL) && (SCTP_IPV6_V6ONLY(inp) == 0)) {
850 switch (addr->sa_family) {
851 #ifdef INET
852 case AF_INET:
853 /* binding v4 addr to v6 socket, so reset flags */
854 inp->ip_inp.inp.inp_vflag |= INP_IPV4;
855 inp->ip_inp.inp.inp_vflag &= ~INP_IPV6;
856 break;
857 #endif
858 #ifdef INET6
859 case AF_INET6:
860 {
861 struct sockaddr_in6 *sin6_p;
862
863 sin6_p = (struct sockaddr_in6 *)addr;
864
865 if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
866 inp->ip_inp.inp.inp_vflag |= INP_IPV4;
867 }
868 #ifdef INET
869 if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
870 struct sockaddr_in sin;
871
872 in6_sin6_2_sin(&sin, sin6_p);
873 inp->ip_inp.inp.inp_vflag |= INP_IPV4;
874 inp->ip_inp.inp.inp_vflag &= ~INP_IPV6;
875 error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p);
876 goto out;
877 }
878 #endif
879 break;
880 }
881 #endif
882 default:
883 break;
884 }
885 } else if (addr != NULL) {
886 struct sockaddr_in6 *sin6_p;
887
888 /* IPV6_V6ONLY socket */
889 #ifdef INET
890 if (addr->sa_family == AF_INET) {
891 /* can't bind v4 addr to v6 only socket! */
892 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
893 error = EINVAL;
894 goto out;
895 }
896 #endif
897 sin6_p = (struct sockaddr_in6 *)addr;
898
899 if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
900 /* can't bind v4-mapped addrs either! */
901 /* NOTE: we don't support SIIT */
902 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
903 error = EINVAL;
904 goto out;
905 }
906 }
907 error = sctp_inpcb_bind(so, addr, NULL, p);
908 out:
909 if (error != 0)
910 inp->ip_inp.inp.inp_vflag = vflagsav;
911 return (error);
912 }
913
914
915 #if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__)
916 #if !defined(__Userspace__)
917 static void
918 #else
919 void
920 #endif
921 sctp6_close(struct socket *so)
922 {
923 sctp_close(so);
924 }
925
926 /* This could be made common with sctp_detach() since they are identical */
927 #else
928
929 static
930 int
931 sctp6_detach(struct socket *so)
932 {
933 #if defined(__Userspace__)
934 sctp_close(so);
935 return (0);
936 #else
937 return (sctp_detach(so));
938 #endif
939 }
940
941 #endif
942
943 #if !defined(__Userspace__)
944 static
945 #endif
946 int
947 sctp6_disconnect(struct socket *so)
948 {
949 return (sctp_disconnect(so));
950 }
951
952
953 int
954 #if defined(__FreeBSD__) && !defined(__Userspace__)
955 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
956 struct mbuf *control, struct thread *p);
957
958 #else
959 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
960 struct mbuf *control, struct proc *p);
961
962 #endif
963
964 #if !defined(_WIN32) && !defined(__Userspace__)
965 #if defined(__FreeBSD__)
966 static int
967 sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
968 struct mbuf *control, struct thread *p)
969 {
970 #elif defined(__APPLE__)
971 static int
972 sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
973 struct mbuf *control, struct proc *p)
974 {
975 #else
976 static int
977 sctp6_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam,
978 struct mbuf *control, struct proc *p)
979 {
980 struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
981 #endif
982 struct sctp_inpcb *inp;
983
984 #ifdef INET
985 struct sockaddr_in6 *sin6;
986 #endif /* INET */
987 /* No SPL needed since sctp_output does this */
988
989 inp = (struct sctp_inpcb *)so->so_pcb;
990 if (inp == NULL) {
991 if (control) {
992 SCTP_RELEASE_PKT(control);
993 control = NULL;
994 }
995 SCTP_RELEASE_PKT(m);
996 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
997 return (EINVAL);
998 }
999 /*
1000 * For the TCP model we may get a NULL addr, if we are a connected
1001 * socket thats ok.
1002 */
1003 if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) &&
1004 (addr == NULL)) {
1005 goto connected_type;
1006 }
1007 if (addr == NULL) {
1008 SCTP_RELEASE_PKT(m);
1009 if (control) {
1010 SCTP_RELEASE_PKT(control);
1011 control = NULL;
1012 }
1013 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EDESTADDRREQ);
1014 return (EDESTADDRREQ);
1015 }
1016 #ifdef INET
1017 sin6 = (struct sockaddr_in6 *)addr;
1018 if (SCTP_IPV6_V6ONLY(inp)) {
1019 /*
1020 * if IPV6_V6ONLY flag, we discard datagrams destined to a
1021 * v4 addr or v4-mapped addr
1022 */
1023 if (addr->sa_family == AF_INET) {
1024 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1025 return (EINVAL);
1026 }
1027 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1028 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1029 return (EINVAL);
1030 }
1031 }
1032 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1033 struct sockaddr_in sin;
1034
1035 /* convert v4-mapped into v4 addr and send */
1036 in6_sin6_2_sin(&sin, sin6);
1037 return (sctp_sendm(so, flags, m, (struct sockaddr *)&sin, control, p));
1038 }
1039 #endif /* INET */
1040 connected_type:
1041 /* now what about control */
1042 if (control) {
1043 if (inp->control) {
1044 SCTP_PRINTF("huh? control set?\n");
1045 SCTP_RELEASE_PKT(inp->control);
1046 inp->control = NULL;
1047 }
1048 inp->control = control;
1049 }
1050 /* Place the data */
1051 if (inp->pkt) {
1052 SCTP_BUF_NEXT(inp->pkt_last) = m;
1053 inp->pkt_last = m;
1054 } else {
1055 inp->pkt_last = inp->pkt = m;
1056 }
1057 if (
1058 #if (defined(__FreeBSD__) || defined(__APPLE__)) && !defined(__Userspace__)
1059 /* FreeBSD and MacOSX uses a flag passed */
1060 ((flags & PRUS_MORETOCOME) == 0)
1061 #else
1062 1 /* Open BSD does not have any "more to come"
1063 * indication */
1064 #endif
1065 ) {
1066 /*
1067 * note with the current version this code will only be used
1068 * by OpenBSD, NetBSD and FreeBSD have methods for
1069 * re-defining sosend() to use sctp_sosend(). One can
1070 * optionaly switch back to this code (by changing back the
1071 * defininitions but this is not advisable.
1072 */
1073 #if defined(__FreeBSD__) && !defined(__Userspace__)
1074 struct epoch_tracker et;
1075 #endif
1076 int ret;
1077
1078 #if defined(__FreeBSD__) && !defined(__Userspace__)
1079 NET_EPOCH_ENTER(et);
1080 #endif
1081 ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
1082 #if defined(__FreeBSD__) && !defined(__Userspace__)
1083 NET_EPOCH_EXIT(et);
1084 #endif
1085 inp->pkt = NULL;
1086 inp->control = NULL;
1087 return (ret);
1088 } else {
1089 return (0);
1090 }
1091 }
1092 #endif
1093
1094 #if defined(__Userspace__)
1095 int
1096 sctp6_connect(struct socket *so, struct sockaddr *addr)
1097 {
1098 void *p = NULL;
1099 #elif defined(__FreeBSD__)
1100 static int
1101 sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
1102 {
1103 #elif defined(__APPLE__)
1104 static int
1105 sctp6_connect(struct socket *so, struct sockaddr *addr, struct proc *p)
1106 {
1107 #elif defined(_WIN32)
1108 static int
1109 sctp6_connect(struct socket *so, struct sockaddr *addr, PKTHREAD p)
1110 {
1111 #else
1112 static int
1113 sctp6_connect(struct socket *so, struct mbuf *nam, struct proc *p)
1114 {
1115 struct sockaddr *addr = mtod(nam, struct sockaddr *);
1116 #endif
1117 #if defined(__FreeBSD__) && !defined(__Userspace__)
1118 struct epoch_tracker et;
1119 #endif
1120 uint32_t vrf_id;
1121 int error = 0;
1122 struct sctp_inpcb *inp;
1123 struct sctp_tcb *stcb;
1124 #ifdef INET
1125 struct sockaddr_in6 *sin6;
1126 union sctp_sockstore store;
1127 #endif
1128
1129 inp = (struct sctp_inpcb *)so->so_pcb;
1130 if (inp == NULL) {
1131 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
1132 return (ECONNRESET); /* I made the same as TCP since we are
1133 * not setup? */
1134 }
1135 if (addr == NULL) {
1136 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1137 return (EINVAL);
1138 }
1139 #if !(defined(_WIN32) && !defined(__Userspace__))
1140 switch (addr->sa_family) {
1141 #ifdef INET
1142 case AF_INET:
1143 #ifdef HAVE_SA_LEN
1144 if (addr->sa_len != sizeof(struct sockaddr_in)) {
1145 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1146 return (EINVAL);
1147 }
1148 #endif
1149 break;
1150 #endif
1151 #ifdef INET6
1152 case AF_INET6:
1153 #ifdef HAVE_SA_LEN
1154 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
1155 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1156 return (EINVAL);
1157 }
1158 #endif
1159 break;
1160 #endif
1161 default:
1162 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1163 return (EINVAL);
1164 }
1165 #endif
1166
1167 vrf_id = inp->def_vrf_id;
1168 SCTP_ASOC_CREATE_LOCK(inp);
1169 SCTP_INP_RLOCK(inp);
1170 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
1171 SCTP_PCB_FLAGS_UNBOUND) {
1172 /* Bind a ephemeral port */
1173 SCTP_INP_RUNLOCK(inp);
1174 error = sctp6_bind(so, NULL, p);
1175 if (error) {
1176 SCTP_ASOC_CREATE_UNLOCK(inp);
1177
1178 return (error);
1179 }
1180 SCTP_INP_RLOCK(inp);
1181 }
1182 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
1183 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
1184 /* We are already connected AND the TCP model */
1185 SCTP_INP_RUNLOCK(inp);
1186 SCTP_ASOC_CREATE_UNLOCK(inp);
1187 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EADDRINUSE);
1188 return (EADDRINUSE);
1189 }
1190 #ifdef INET
1191 sin6 = (struct sockaddr_in6 *)addr;
1192 if (SCTP_IPV6_V6ONLY(inp)) {
1193 /*
1194 * if IPV6_V6ONLY flag, ignore connections destined to a v4
1195 * addr or v4-mapped addr
1196 */
1197 if (addr->sa_family == AF_INET) {
1198 SCTP_INP_RUNLOCK(inp);
1199 SCTP_ASOC_CREATE_UNLOCK(inp);
1200 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1201 return (EINVAL);
1202 }
1203 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1204 SCTP_INP_RUNLOCK(inp);
1205 SCTP_ASOC_CREATE_UNLOCK(inp);
1206 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1207 return (EINVAL);
1208 }
1209 }
1210 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1211 /* convert v4-mapped into v4 addr */
1212 in6_sin6_2_sin(&store.sin, sin6);
1213 addr = &store.sa;
1214 }
1215 #endif /* INET */
1216 /* Now do we connect? */
1217 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1218 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1219 if (stcb) {
1220 SCTP_TCB_LOCK(stcb);
1221 }
1222 SCTP_INP_RUNLOCK(inp);
1223 } else {
1224 SCTP_INP_RUNLOCK(inp);
1225 SCTP_INP_WLOCK(inp);
1226 SCTP_INP_INCR_REF(inp);
1227 SCTP_INP_WUNLOCK(inp);
1228 stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
1229 if (stcb == NULL) {
1230 SCTP_INP_WLOCK(inp);
1231 SCTP_INP_DECR_REF(inp);
1232 SCTP_INP_WUNLOCK(inp);
1233 }
1234 }
1235
1236 if (stcb != NULL) {
1237 /* Already have or am bring up an association */
1238 SCTP_ASOC_CREATE_UNLOCK(inp);
1239 SCTP_TCB_UNLOCK(stcb);
1240 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EALREADY);
1241 return (EALREADY);
1242 }
1243 /* We are GOOD to go */
1244 stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id,
1245 inp->sctp_ep.pre_open_stream_count,
1246 inp->sctp_ep.port, p,
1247 SCTP_INITIALIZE_AUTH_PARAMS);
1248 SCTP_ASOC_CREATE_UNLOCK(inp);
1249 if (stcb == NULL) {
1250 /* Gak! no memory */
1251 return (error);
1252 }
1253 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
1254 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
1255 /* Set the connected flag so we can queue data */
1256 soisconnecting(so);
1257 }
1258 SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
1259 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
1260 #if defined(__FreeBSD__) && !defined(__Userspace__)
1261 NET_EPOCH_ENTER(et);
1262 #endif
1263 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
1264 SCTP_TCB_UNLOCK(stcb);
1265 #if defined(__FreeBSD__) && !defined(__Userspace__)
1266 NET_EPOCH_EXIT(et);
1267 #endif
1268 return (error);
1269 }
1270
1271 static int
1272 #if !defined(__Userspace__)
1273 sctp6_getaddr(struct socket *so, struct sockaddr **addr)
1274 {
1275 struct sockaddr_in6 *sin6;
1276 #else
1277 sctp6_getaddr(struct socket *so, struct mbuf *nam)
1278 {
1279 struct sockaddr_in6 *sin6 = mtod(nam, struct sockaddr_in6 *);
1280 #endif
1281 struct sctp_inpcb *inp;
1282 uint32_t vrf_id;
1283 struct sctp_ifa *sctp_ifa;
1284
1285 #if defined(SCTP_KAME) && defined(SCTP_EMBEDDED_V6_SCOPE)
1286 int error;
1287 #endif
1288
1289 /*
1290 * Do the malloc first in case it blocks.
1291 */
1292 #if !defined(__Userspace__)
1293 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof(*sin6));
1294 if (sin6 == NULL)
1295 return (ENOMEM);
1296 #else
1297 SCTP_BUF_LEN(nam) = sizeof(*sin6);
1298 memset(sin6, 0, sizeof(*sin6));
1299 #endif
1300 sin6->sin6_family = AF_INET6;
1301 #ifdef HAVE_SIN6_LEN
1302 sin6->sin6_len = sizeof(*sin6);
1303 #endif
1304
1305 inp = (struct sctp_inpcb *)so->so_pcb;
1306 if (inp == NULL) {
1307 #if !defined(__Userspace__)
1308 SCTP_FREE_SONAME(sin6);
1309 #endif
1310 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
1311 return (ECONNRESET);
1312 }
1313 SCTP_INP_RLOCK(inp);
1314 sin6->sin6_port = inp->sctp_lport;
1315 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1316 /* For the bound all case you get back 0 */
1317 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1318 struct sctp_tcb *stcb;
1319 struct sockaddr_in6 *sin_a6;
1320 struct sctp_nets *net;
1321 int fnd;
1322 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1323 if (stcb == NULL) {
1324 SCTP_INP_RUNLOCK(inp);
1325 #if !defined(__Userspace__)
1326 SCTP_FREE_SONAME(sin6);
1327 #endif
1328 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1329 return (ENOENT);
1330 }
1331 fnd = 0;
1332 sin_a6 = NULL;
1333 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1334 sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
1335 if (sin_a6 == NULL)
1336 /* this will make coverity happy */
1337 continue;
1338
1339 if (sin_a6->sin6_family == AF_INET6) {
1340 fnd = 1;
1341 break;
1342 }
1343 }
1344 if ((!fnd) || (sin_a6 == NULL)) {
1345 /* punt */
1346 SCTP_INP_RUNLOCK(inp);
1347 #if !defined(__Userspace__)
1348 SCTP_FREE_SONAME(sin6);
1349 #endif
1350 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1351 return (ENOENT);
1352 }
1353 vrf_id = inp->def_vrf_id;
1354 sctp_ifa = sctp_source_address_selection(inp, stcb, (sctp_route_t *)&net->ro, net, 0, vrf_id);
1355 if (sctp_ifa) {
1356 sin6->sin6_addr = sctp_ifa->address.sin6.sin6_addr;
1357 }
1358 } else {
1359 /* For the bound all case you get back 0 */
1360 memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
1361 }
1362 } else {
1363 /* Take the first IPv6 address in the list */
1364 struct sctp_laddr *laddr;
1365 int fnd = 0;
1366
1367 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1368 if (laddr->ifa->address.sa.sa_family == AF_INET6) {
1369 struct sockaddr_in6 *sin_a;
1370
1371 sin_a = &laddr->ifa->address.sin6;
1372 sin6->sin6_addr = sin_a->sin6_addr;
1373 fnd = 1;
1374 break;
1375 }
1376 }
1377 if (!fnd) {
1378 #if !defined(__Userspace__)
1379 SCTP_FREE_SONAME(sin6);
1380 #endif
1381 SCTP_INP_RUNLOCK(inp);
1382 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1383 return (ENOENT);
1384 }
1385 }
1386 SCTP_INP_RUNLOCK(inp);
1387 /* Scoping things for v6 */
1388 #ifdef SCTP_EMBEDDED_V6_SCOPE
1389 #ifdef SCTP_KAME
1390 if ((error = sa6_recoverscope(sin6)) != 0) {
1391 SCTP_FREE_SONAME(sin6);
1392 return (error);
1393 }
1394 #else
1395 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
1396 /* skip ifp check below */
1397 in6_recoverscope(sin6, &sin6->sin6_addr, NULL);
1398 else
1399 sin6->sin6_scope_id = 0; /* XXX */
1400 #endif /* SCTP_KAME */
1401 #endif /* SCTP_EMBEDDED_V6_SCOPE */
1402 #if !defined(__Userspace__)
1403 (*addr) = (struct sockaddr *)sin6;
1404 #endif
1405 return (0);
1406 }
1407
1408 static int
1409 #if !defined(__Userspace__)
1410 sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
1411 {
1412 struct sockaddr_in6 *sin6;
1413 #else
1414 sctp6_peeraddr(struct socket *so, struct mbuf *nam)
1415 {
1416 struct sockaddr_in6 *sin6 = mtod(nam, struct sockaddr_in6 *);
1417 #endif
1418 int fnd;
1419 struct sockaddr_in6 *sin_a6;
1420 struct sctp_inpcb *inp;
1421 struct sctp_tcb *stcb;
1422 struct sctp_nets *net;
1423 #ifdef SCTP_KAME
1424 int error;
1425 #endif
1426
1427 /* Do the malloc first in case it blocks. */
1428 #if !defined(__Userspace__)
1429 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1430 if (sin6 == NULL)
1431 return (ENOMEM);
1432 #else
1433 SCTP_BUF_LEN(nam) = sizeof(*sin6);
1434 memset(sin6, 0, sizeof(*sin6));
1435 #endif
1436 sin6->sin6_family = AF_INET6;
1437 #ifdef HAVE_SIN6_LEN
1438 sin6->sin6_len = sizeof(*sin6);
1439 #endif
1440
1441 inp = (struct sctp_inpcb *)so->so_pcb;
1442 if ((inp == NULL) ||
1443 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
1444 /* UDP type and listeners will drop out here */
1445 #if !defined(__Userspace__)
1446 SCTP_FREE_SONAME(sin6);
1447 #endif
1448 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOTCONN);
1449 return (ENOTCONN);
1450 }
1451 SCTP_INP_RLOCK(inp);
1452 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1453 if (stcb) {
1454 SCTP_TCB_LOCK(stcb);
1455 }
1456 SCTP_INP_RUNLOCK(inp);
1457 if (stcb == NULL) {
1458 #if !defined(__Userspace__)
1459 SCTP_FREE_SONAME(sin6);
1460 #endif
1461 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
1462 return (ECONNRESET);
1463 }
1464 fnd = 0;
1465 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1466 sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
1467 if (sin_a6->sin6_family == AF_INET6) {
1468 fnd = 1;
1469 sin6->sin6_port = stcb->rport;
1470 sin6->sin6_addr = sin_a6->sin6_addr;
1471 break;
1472 }
1473 }
1474 SCTP_TCB_UNLOCK(stcb);
1475 if (!fnd) {
1476 /* No IPv4 address */
1477 #if !defined(__Userspace__)
1478 SCTP_FREE_SONAME(sin6);
1479 #endif
1480 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1481 return (ENOENT);
1482 }
1483 #ifdef SCTP_EMBEDDED_V6_SCOPE
1484 #ifdef SCTP_KAME
1485 if ((error = sa6_recoverscope(sin6)) != 0) {
1486 #if !defined(__Userspace__)
1487 SCTP_FREE_SONAME(sin6);
1488 #endif
1489 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, error);
1490 return (error);
1491 }
1492 #else
1493 in6_recoverscope(sin6, &sin6->sin6_addr, NULL);
1494 #endif /* SCTP_KAME */
1495 #endif /* SCTP_EMBEDDED_V6_SCOPE */
1496 #if !defined(__Userspace__)
1497 *addr = (struct sockaddr *)sin6;
1498 #endif
1499 return (0);
1500 }
1501
1502 #if !defined(__Userspace__)
1503 static int
1504 sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
1505 {
1506 #elif defined(__Userspace__)
1507 int
1508 sctp6_in6getaddr(struct socket *so, struct mbuf *nam)
1509 {
1510 #ifdef INET
1511 struct sockaddr *addr = mtod(nam, struct sockaddr *);
1512 #endif
1513 #else
1514 static int
1515 sctp6_in6getaddr(struct socket *so, struct mbuf *nam)
1516 {
1517 #ifdef INET
1518 struct sockaddr *addr = mtod(nam, struct sockaddr *);
1519 #endif
1520 #endif
1521 struct inpcb *inp = sotoinpcb(so);
1522 int error;
1523
1524 if (inp == NULL) {
1525 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1526 return (EINVAL);
1527 }
1528
1529 /* allow v6 addresses precedence */
1530 error = sctp6_getaddr(so, nam);
1531 #ifdef INET
1532 if (error) {
1533 #if !defined(__Userspace__)
1534 struct sockaddr_in6 *sin6;
1535 #else
1536 struct sockaddr_in6 sin6;
1537 #endif
1538
1539 /* try v4 next if v6 failed */
1540 error = sctp_ingetaddr(so, nam);
1541 if (error) {
1542 return (error);
1543 }
1544 #if !defined(__Userspace__)
1545 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1546 if (sin6 == NULL) {
1547 SCTP_FREE_SONAME(*nam);
1548 return (ENOMEM);
1549 }
1550 in6_sin_2_v4mapsin6((struct sockaddr_in *)*nam, sin6);
1551 SCTP_FREE_SONAME(*nam);
1552 *nam = (struct sockaddr *)sin6;
1553 #else
1554 in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
1555 SCTP_BUF_LEN(nam) = sizeof(struct sockaddr_in6);
1556 memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
1557 #endif
1558 }
1559 #endif
1560 return (error);
1561 }
1562
1563
1564 #if !defined(__Userspace__)
1565 static int
1566 sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
1567 {
1568 #elif defined(__Userspace__)
1569 int
1570 sctp6_getpeeraddr(struct socket *so, struct mbuf *nam)
1571 {
1572 #ifdef INET
1573 struct sockaddr *addr = mtod(nam, struct sockaddr *);
1574 #endif
1575 #else
1576 static
1577 int
1578 sctp6_getpeeraddr(struct socket *so, struct mbuf *nam)
1579 {
1580 #ifdef INET
1581 struct sockaddr *addr = mtod(nam, struct sockaddr *);
1582 #endif
1583
1584 #endif
1585 struct inpcb *inp = sotoinpcb(so);
1586 int error;
1587
1588 if (inp == NULL) {
1589 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1590 return (EINVAL);
1591 }
1592
1593 /* allow v6 addresses precedence */
1594 error = sctp6_peeraddr(so, nam);
1595 #ifdef INET
1596 if (error) {
1597 #if !defined(__Userspace__)
1598 struct sockaddr_in6 *sin6;
1599 #else
1600 struct sockaddr_in6 sin6;
1601 #endif
1602
1603 /* try v4 next if v6 failed */
1604 error = sctp_peeraddr(so, nam);
1605 if (error) {
1606 return (error);
1607 }
1608 #if !defined(__Userspace__)
1609 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1610 if (sin6 == NULL) {
1611 SCTP_FREE_SONAME(*nam);
1612 return (ENOMEM);
1613 }
1614 in6_sin_2_v4mapsin6((struct sockaddr_in *)*nam, sin6);
1615 SCTP_FREE_SONAME(*nam);
1616 *nam = (struct sockaddr *)sin6;
1617 #else
1618 in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
1619 SCTP_BUF_LEN(nam) = sizeof(struct sockaddr_in6);
1620 memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
1621 #endif
1622 }
1623 #endif
1624 return (error);
1625 }
1626
1627 #if !defined(__Userspace__)
1628 struct pr_usrreqs sctp6_usrreqs = {
1629 #if defined(__FreeBSD__)
1630 .pru_abort = sctp6_abort,
1631 .pru_accept = sctp_accept,
1632 .pru_attach = sctp6_attach,
1633 .pru_bind = sctp6_bind,
1634 .pru_connect = sctp6_connect,
1635 .pru_control = in6_control,
1636 .pru_close = sctp6_close,
1637 .pru_detach = sctp6_close,
1638 .pru_sopoll = sopoll_generic,
1639 .pru_flush = sctp_flush,
1640 .pru_disconnect = sctp6_disconnect,
1641 .pru_listen = sctp_listen,
1642 .pru_peeraddr = sctp6_getpeeraddr,
1643 .pru_send = sctp6_send,
1644 .pru_shutdown = sctp_shutdown,
1645 .pru_sockaddr = sctp6_in6getaddr,
1646 .pru_sosend = sctp_sosend,
1647 .pru_soreceive = sctp_soreceive
1648 #elif defined(__APPLE__) && !defined(__Userspace__)
1649 .pru_abort = sctp6_abort,
1650 .pru_accept = sctp_accept,
1651 .pru_attach = sctp6_attach,
1652 .pru_bind = sctp6_bind,
1653 .pru_connect = sctp6_connect,
1654 .pru_connect2 = pru_connect2_notsupp,
1655 .pru_control = in6_control,
1656 .pru_detach = sctp6_detach,
1657 .pru_disconnect = sctp6_disconnect,
1658 .pru_listen = sctp_listen,
1659 .pru_peeraddr = sctp6_getpeeraddr,
1660 .pru_rcvd = NULL,
1661 .pru_rcvoob = pru_rcvoob_notsupp,
1662 .pru_send = sctp6_send,
1663 .pru_sense = pru_sense_null,
1664 .pru_shutdown = sctp_shutdown,
1665 .pru_sockaddr = sctp6_in6getaddr,
1666 .pru_sosend = sctp_sosend,
1667 .pru_soreceive = sctp_soreceive,
1668 .pru_sopoll = sopoll
1669 #elif defined(_WIN32) && !defined(__Userspace__)
1670 sctp6_abort,
1671 sctp_accept,
1672 sctp6_attach,
1673 sctp6_bind,
1674 sctp6_connect,
1675 pru_connect2_notsupp,
1676 NULL,
1677 NULL,
1678 sctp6_disconnect,
1679 sctp_listen,
1680 sctp6_getpeeraddr,
1681 NULL,
1682 pru_rcvoob_notsupp,
1683 NULL,
1684 pru_sense_null,
1685 sctp_shutdown,
1686 sctp_flush,
1687 sctp6_in6getaddr,
1688 sctp_sosend,
1689 sctp_soreceive,
1690 sopoll_generic,
1691 NULL,
1692 sctp6_close
1693 #endif
1694 };
1695
1696 #elif !defined(__Userspace__)
1697 int
1698 sctp6_usrreq(so, req, m, nam, control, p)
1699 struct socket *so;
1700 int req;
1701 struct mbuf *m, *nam, *control;
1702 struct proc *p;
1703 {
1704 int error;
1705 int family;
1706
1707 family = so->so_proto->pr_domain->dom_family;
1708
1709 if (req == PRU_CONTROL) {
1710 switch (family) {
1711 case PF_INET:
1712 error = in_control(so, (long)m, (caddr_t)nam,
1713 (struct ifnet *)control );
1714 break;
1715 #ifdef INET6
1716 case PF_INET6:
1717 error = in6_control(so, (long)m, (caddr_t)nam,
1718 (struct ifnet *)control, p);
1719 break;
1720 #endif
1721 default:
1722 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
1723 error = EAFNOSUPPORT;
1724 }
1725 return (error);
1726 }
1727 switch (req) {
1728 case PRU_ATTACH:
1729 error = sctp6_attach(so, family, p);
1730 break;
1731 case PRU_DETACH:
1732 error = sctp6_detach(so);
1733 break;
1734 case PRU_BIND:
1735 if (nam == NULL) {
1736 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1737 return (EINVAL);
1738 }
1739 error = sctp6_bind(so, nam, p);
1740 break;
1741 case PRU_LISTEN:
1742 error = sctp_listen(so, p);
1743 break;
1744 case PRU_CONNECT:
1745 if (nam == NULL) {
1746 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1747 return (EINVAL);
1748 }
1749 error = sctp6_connect(so, nam, p);
1750 break;
1751 case PRU_DISCONNECT:
1752 error = sctp6_disconnect(so);
1753 break;
1754 case PRU_ACCEPT:
1755 if (nam == NULL) {
1756 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1757 return (EINVAL);
1758 }
1759 error = sctp_accept(so, nam);
1760 break;
1761 case PRU_SHUTDOWN:
1762 error = sctp_shutdown(so);
1763 break;
1764
1765 case PRU_RCVD:
1766 /*
1767 * For OpenBSD and NetBSD, this is real ugly. The (mbuf *)
1768 * nam that is passed (by soreceive()) is the int flags cast
1769 * as a (mbuf *) yuck!
1770 */
1771 error = sctp_usr_recvd(so, (int)((long)nam));
1772 break;
1773
1774 case PRU_SEND:
1775 /* Flags are ignored */
1776 error = sctp6_send(so, 0, m, nam, control, p);
1777 break;
1778 case PRU_ABORT:
1779 error = sctp6_abort(so);
1780 break;
1781
1782 case PRU_SENSE:
1783 error = 0;
1784 break;
1785 case PRU_RCVOOB:
1786 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
1787 error = EAFNOSUPPORT;
1788 break;
1789 case PRU_SENDOOB:
1790 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
1791 error = EAFNOSUPPORT;
1792 break;
1793 case PRU_PEERADDR:
1794 error = sctp6_getpeeraddr(so, nam);
1795 break;
1796 case PRU_SOCKADDR:
1797 error = sctp6_in6getaddr(so, nam);
1798 break;
1799 case PRU_SLOWTIMO:
1800 error = 0;
1801 break;
1802 default:
1803 error = 0;
1804 break;
1805 }
1806 return (error);
1807 }
1808 #endif
1809 #endif
1810