2 * SPDX-License-Identifier: BSD-3-Clause
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.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * a) Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
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.
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.
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.
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 $");
40 #include <netinet/sctp_os.h>
42 #if defined(__FreeBSD__) && !defined(__Userspace__)
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>
62 #include <netinet/icmp6.h>
63 #include <netinet/udp.h>
65 #if defined(__Userspace__)
68 #if defined(__Userspace__)
71 in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
76 memset(sin, 0, sizeof(*sin));
78 sin->sin_len = sizeof(struct sockaddr_in);
80 sin->sin_family = AF_INET;
81 sin->sin_port = sin6->sin6_port;
83 temp = sin6->sin6_addr.s6_addr16[7];
85 temp = temp | sin6->sin6_addr.s6_addr16[6];
86 sin->sin_addr.s_addr = temp;
88 sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
93 in6_sin6_2_sin_in_sock(struct sockaddr *nam)
95 struct sockaddr_in *sin_p;
96 struct sockaddr_in6 sin6;
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);
105 in6_sin_2_v4mapsin6(const struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
107 memset(sin6, 0, sizeof(struct sockaddr_in6));
108 sin6->sin6_family = AF_INET6;
110 sin6->sin6_len = sizeof(struct sockaddr_in6);
112 sin6->sin6_port = sin->sin_port;
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;
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;
128 #if !defined(__Userspace__)
130 #if defined(__APPLE__) || defined(__FreeBSD__)
131 sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
133 sctp6_input(struct mbuf **i_pak, int *offp, int proto)
140 struct sockaddr_in6 src, dst;
143 struct sctp_chunkhdr *ch;
146 #if defined(__FreeBSD__)
151 #if !(defined(__APPLE__) || defined(__FreeBSD__))
156 if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) {
157 SCTP_RELEASE_PKT(*i_pak);
158 return (IPPROTO_DONE);
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);
167 #ifdef SCTP_PACKET_LOGGING
168 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
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",
176 if_name(m->m_pkthdr.rcvif),
177 (int)m->m_pkthdr.csum_flags, CSUM_BITS);
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",
183 m->m_pkthdr.rcvif->if_name,
184 m->m_pkthdr.rcvif->if_unit,
185 m->m_pkthdr.csum_flags);
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",
191 m->m_pkthdr.rcvif->if_xname,
192 m->m_pkthdr.csum_flags);
194 #if defined(__FreeBSD__)
195 mflowid = m->m_pkthdr.flowid;
196 mflowtype = M_HASHTYPE_GET(m);
197 fibnum = M_GETFIB(m);
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);
206 SCTP_STAT_INCR(sctps_hdrops);
207 return (IPPROTO_DONE);
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;
217 src.sin6_len = sizeof(struct sockaddr_in6);
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 */
225 if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
229 memset(&dst, 0, sizeof(struct sockaddr_in6));
230 dst.sin6_family = AF_INET6;
232 dst.sin6_len = sizeof(struct sockaddr_in6);
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 */
240 if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
244 #if defined(__APPLE__)
245 #if defined(NFAITH) && 0 < NFAITH
246 if (faithprefix(&dst.sin6_addr)) {
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);
259 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
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);
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);
275 SCTP_STAT_INCR(sctps_recvswcrc);
278 sctp_common_input_processing(&m, iphlen, offset, length,
279 (struct sockaddr *)&src,
280 (struct sockaddr *)&dst,
284 #if defined(__FreeBSD__)
285 mflowtype, mflowid, fibnum,
292 return (IPPROTO_DONE);
295 #if defined(__APPLE__)
297 sctp6_input(struct mbuf **i_pak, int *offp)
299 return (sctp6_input_with_port(i_pak, offp, 0));
303 #if defined(__FreeBSD__)
305 sctp6_input(struct mbuf **i_pak, int *offp, int proto SCTP_UNUSED)
307 return (sctp6_input_with_port(i_pak, offp, 0));
312 sctp6_notify(struct sctp_inpcb *inp,
313 struct sctp_tcb *stcb,
314 struct sctp_nets *net,
319 #if defined(__APPLE__)
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);
339 SCTP_TCB_UNLOCK(stcb);
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);
351 atomic_subtract_int(&stcb->asoc.refcnt, 1);
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);
359 SCTP_TCB_UNLOCK(stcb);
362 case ICMP6_PACKET_TOO_BIG:
363 if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
364 SCTP_TCB_UNLOCK(stcb);
367 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
369 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
370 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1);
374 /* Update the path MTU. */
376 next_mtu -= sizeof(struct udphdr);
378 if (net->mtu > next_mtu) {
380 #if defined(__FreeBSD__)
382 sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu + sizeof(struct udphdr));
384 sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu);
388 /* Update the association MTU */
389 if (stcb->asoc.smallest_mtu > next_mtu) {
390 sctp_pathmtu_adjustment(stcb, next_mtu);
392 /* Finally, start the PMTU timer if it was running before. */
394 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
396 SCTP_TCB_UNLOCK(stcb);
399 SCTP_TCB_UNLOCK(stcb);
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)
408 sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
411 struct ip6ctlparam *ip6cp;
412 struct sctp_inpcb *inp;
413 struct sctp_tcb *stcb;
414 struct sctp_nets *net;
416 struct sockaddr_in6 src, dst;
419 if (pktdst->sa_family != AF_INET6 ||
420 pktdst->sa_len != sizeof(struct sockaddr_in6)) {
422 if (pktdst->sa_family != AF_INET6) {
427 if ((unsigned)cmd >= PRC_NCMDS) {
430 if (PRC_IS_REDIRECT(cmd)) {
432 } else if (inet6ctlerrmap[cmd] == 0) {
435 /* If the parameter is from icmp6, decode it. */
437 ip6cp = (struct ip6ctlparam *)d;
439 ip6cp = (struct ip6ctlparam *)NULL;
444 * XXX: We assume that when IPV6 is non NULL, M and OFF are
447 if (ip6cp->ip6c_m == NULL) {
451 /* Check if we can safely examine the ports and the
452 * verification tag of the SCTP common header.
454 if (ip6cp->ip6c_m->m_pkthdr.len <
455 (int32_t)(ip6cp->ip6c_off + offsetof(struct sctphdr, checksum))) {
459 /* Copy out the port numbers and the verification tag. */
460 memset(&sh, 0, sizeof(sh));
461 m_copydata(ip6cp->ip6c_m,
463 sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t),
465 memset(&src, 0, sizeof(struct sockaddr_in6));
466 src.sin6_family = AF_INET6;
468 src.sin6_len = sizeof(struct sockaddr_in6);
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) {
477 memset(&dst, 0, sizeof(struct sockaddr_in6));
478 dst.sin6_family = AF_INET6;
480 dst.sin6_len = sizeof(struct sockaddr_in6);
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) {
491 stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst,
492 (struct sockaddr *)&src,
493 &inp, &net, 1, SCTP_DEFAULT_VRFID);
494 if ((stcb != NULL) &&
497 /* Check the verification tag */
498 if (ntohl(sh.v_tag) != 0) {
500 * This must be the verification tag used for
501 * sending out packets. We don't consider
502 * packets reflecting the verification tag.
504 if (ntohl(sh.v_tag) != stcb->asoc.peer_vtag) {
505 SCTP_TCB_UNLOCK(stcb);
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)) {
515 * In this case we can check if we
516 * got an INIT chunk and if the
517 * initiate tag matches.
519 uint32_t initiate_tag;
522 m_copydata(ip6cp->ip6c_m,
524 sizeof(struct sctphdr),
526 (caddr_t)&chunk_type);
527 m_copydata(ip6cp->ip6c_m,
529 sizeof(struct sctphdr) +
530 sizeof(struct sctp_chunkhdr),
532 (caddr_t)&initiate_tag);
533 if ((chunk_type != SCTP_INITIATION) ||
534 (ntohl(initiate_tag) != stcb->asoc.my_vtag)) {
535 SCTP_TCB_UNLOCK(stcb);
539 SCTP_TCB_UNLOCK(stcb);
543 SCTP_TCB_UNLOCK(stcb);
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;
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);
565 SOCK_LOCK(upcall_socket);
566 sorele(upcall_socket);
570 if ((stcb == NULL) && (inp != NULL)) {
571 /* reduce inp's ref-count */
573 SCTP_INP_DECR_REF(inp);
574 SCTP_INP_WUNLOCK(inp);
577 SCTP_TCB_UNLOCK(stcb);
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
588 #if defined(__FreeBSD__) && !defined(__Userspace__)
590 sctp6_getcred(SYSCTL_HANDLER_ARGS)
593 struct sockaddr_in6 addrs[2];
594 struct sctp_inpcb *inp;
595 struct sctp_nets *net;
596 struct sctp_tcb *stcb;
600 vrf_id = SCTP_DEFAULT_VRFID;
602 #if defined(__FreeBSD__) && !defined(__Userspace__)
603 error = priv_check(req->td, PRIV_NETINET_GETCRED);
605 error = suser(req->p);
610 if (req->newlen != sizeof(addrs)) {
611 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
614 if (req->oldlen != sizeof(struct ucred)) {
615 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
618 error = SYSCTL_IN(req, addrs, sizeof(addrs));
622 stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[1]),
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 */
629 SCTP_INP_DECR_REF(inp);
632 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
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.
646 error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
648 SCTP_INP_WUNLOCK(inp);
651 cru2x(inp->sctp_socket->so_cred, &xuc);
652 SCTP_INP_WUNLOCK(inp);
653 error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
658 SYSCTL_PROC(_net_inet6_sctp6, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
660 sctp6_getcred, "S,ucred", "Get the ucred of a SCTP6 connection");
664 /* This is the same as the sctp_abort() could be made common */
665 #if defined(__Userspace__)
667 #elif defined(__FreeBSD__) || defined(_WIN32)
672 sctp6_abort(struct socket *so)
674 #if defined(__FreeBSD__) && !defined(__Userspace__)
675 struct epoch_tracker et;
677 struct sctp_inpcb *inp;
680 inp = (struct sctp_inpcb *)so->so_pcb;
682 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
683 #if (defined(__FreeBSD__) || defined(_WIN32)) && !defined(__Userspace__)
689 #if defined(__FreeBSD__) && !defined(__Userspace__)
693 flags = inp->sctp_flags;
694 #ifdef SCTP_LOG_CLOSING
695 sctp_log_closing(inp, NULL, 17);
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);
702 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
703 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
705 SCTP_SB_CLEAR(so->so_snd);
706 /* same for the rcv ones, they are only
707 * here for the accounting/select.
709 SCTP_SB_CLEAR(so->so_rcv);
710 #if defined(__APPLE__) && !defined(__Userspace__)
713 /* Now null out the reference, we are completely detached. */
718 flags = inp->sctp_flags;
719 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
720 goto sctp_must_try_again;
723 #if defined(__FreeBSD__) && !defined(__Userspace__)
731 #if defined(__Userspace__)
733 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
734 #elif defined(__FreeBSD__)
736 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
737 #elif defined(_WIN32)
739 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, PKTHREAD p SCTP_UNUSED)
742 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct proc *p SCTP_UNUSED)
746 struct sctp_inpcb *inp;
747 #if !defined(__Userspace__)
748 uint32_t vrf_id = SCTP_DEFAULT_VRFID;
751 inp = (struct sctp_inpcb *)so->so_pcb;
753 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
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));
762 error = sctp_inpcb_alloc(so, vrf_id);
765 inp = (struct sctp_inpcb *)so->so_pcb;
767 inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_V6; /* I'm v6! */
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 */
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.
778 inp->ip_inp.inp.inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
780 SCTP_INP_WUNLOCK(inp);
784 #if defined(__Userspace__)
786 sctp6_bind(struct socket *so, struct sockaddr *addr, void * p)
788 #elif defined(__FreeBSD__)
790 sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
792 #elif defined(__APPLE__)
794 sctp6_bind(struct socket *so, struct sockaddr *addr, struct proc *p)
796 #elif defined(_WIN32)
798 sctp6_bind(struct socket *so, struct sockaddr *addr, PKTHREAD p)
802 sctp6_bind(struct socket *so, struct mbuf *nam, struct proc *p)
804 struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
807 struct sctp_inpcb *inp;
811 inp = (struct sctp_inpcb *)so->so_pcb;
813 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
817 #if !(defined(_WIN32) && !defined(__Userspace__))
819 switch (addr->sa_family) {
823 if (addr->sa_len != sizeof(struct sockaddr_in)) {
824 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
833 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
834 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
841 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
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) {
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;
861 struct sockaddr_in6 *sin6_p;
863 sin6_p = (struct sockaddr_in6 *)addr;
865 if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
866 inp->ip_inp.inp.inp_vflag |= INP_IPV4;
869 if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
870 struct sockaddr_in sin;
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);
885 } else if (addr != NULL) {
886 struct sockaddr_in6 *sin6_p;
888 /* IPV6_V6ONLY socket */
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);
897 sin6_p = (struct sockaddr_in6 *)addr;
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);
907 error = sctp_inpcb_bind(so, addr, NULL, p);
910 inp->ip_inp.inp.inp_vflag = vflagsav;
915 #if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__)
916 #if !defined(__Userspace__)
921 sctp6_close(struct socket *so)
926 /* This could be made common with sctp_detach() since they are identical */
931 sctp6_detach(struct socket *so)
933 #if defined(__Userspace__)
937 return (sctp_detach(so));
943 #if !defined(__Userspace__)
947 sctp6_disconnect(struct socket *so)
949 return (sctp_disconnect(so));
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);
959 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
960 struct mbuf *control, struct proc *p);
964 #if !defined(_WIN32) && !defined(__Userspace__)
965 #if defined(__FreeBSD__)
967 sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
968 struct mbuf *control, struct thread *p)
970 #elif defined(__APPLE__)
972 sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
973 struct mbuf *control, struct proc *p)
977 sctp6_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam,
978 struct mbuf *control, struct proc *p)
980 struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
982 struct sctp_inpcb *inp;
985 struct sockaddr_in6 *sin6;
987 /* No SPL needed since sctp_output does this */
989 inp = (struct sctp_inpcb *)so->so_pcb;
992 SCTP_RELEASE_PKT(control);
996 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1000 * For the TCP model we may get a NULL addr, if we are a connected
1003 if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) &&
1005 goto connected_type;
1008 SCTP_RELEASE_PKT(m);
1010 SCTP_RELEASE_PKT(control);
1013 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EDESTADDRREQ);
1014 return (EDESTADDRREQ);
1017 sin6 = (struct sockaddr_in6 *)addr;
1018 if (SCTP_IPV6_V6ONLY(inp)) {
1020 * if IPV6_V6ONLY flag, we discard datagrams destined to a
1021 * v4 addr or v4-mapped addr
1023 if (addr->sa_family == AF_INET) {
1024 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1027 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1028 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1032 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1033 struct sockaddr_in sin;
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));
1041 /* now what about control */
1044 SCTP_PRINTF("huh? control set?\n");
1045 SCTP_RELEASE_PKT(inp->control);
1046 inp->control = NULL;
1048 inp->control = control;
1050 /* Place the data */
1052 SCTP_BUF_NEXT(inp->pkt_last) = m;
1055 inp->pkt_last = inp->pkt = m;
1058 #if (defined(__FreeBSD__) || defined(__APPLE__)) && !defined(__Userspace__)
1059 /* FreeBSD and MacOSX uses a flag passed */
1060 ((flags & PRUS_MORETOCOME) == 0)
1062 1 /* Open BSD does not have any "more to come"
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.
1073 #if defined(__FreeBSD__) && !defined(__Userspace__)
1074 struct epoch_tracker et;
1078 #if defined(__FreeBSD__) && !defined(__Userspace__)
1079 NET_EPOCH_ENTER(et);
1081 ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
1082 #if defined(__FreeBSD__) && !defined(__Userspace__)
1086 inp->control = NULL;
1094 #if defined(__Userspace__)
1096 sctp6_connect(struct socket *so, struct sockaddr *addr)
1099 #elif defined(__FreeBSD__)
1101 sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
1103 #elif defined(__APPLE__)
1105 sctp6_connect(struct socket *so, struct sockaddr *addr, struct proc *p)
1107 #elif defined(_WIN32)
1109 sctp6_connect(struct socket *so, struct sockaddr *addr, PKTHREAD p)
1113 sctp6_connect(struct socket *so, struct mbuf *nam, struct proc *p)
1115 struct sockaddr *addr = mtod(nam, struct sockaddr *);
1117 #if defined(__FreeBSD__) && !defined(__Userspace__)
1118 struct epoch_tracker et;
1122 struct sctp_inpcb *inp;
1123 struct sctp_tcb *stcb;
1125 struct sockaddr_in6 *sin6;
1126 union sctp_sockstore store;
1129 inp = (struct sctp_inpcb *)so->so_pcb;
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
1136 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1139 #if !(defined(_WIN32) && !defined(__Userspace__))
1140 switch (addr->sa_family) {
1144 if (addr->sa_len != sizeof(struct sockaddr_in)) {
1145 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1154 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
1155 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1162 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
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);
1176 SCTP_ASOC_CREATE_UNLOCK(inp);
1180 SCTP_INP_RLOCK(inp);
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);
1191 sin6 = (struct sockaddr_in6 *)addr;
1192 if (SCTP_IPV6_V6ONLY(inp)) {
1194 * if IPV6_V6ONLY flag, ignore connections destined to a v4
1195 * addr or v4-mapped addr
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);
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);
1210 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1211 /* convert v4-mapped into v4 addr */
1212 in6_sin6_2_sin(&store.sin, sin6);
1216 /* Now do we connect? */
1217 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1218 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1220 SCTP_TCB_LOCK(stcb);
1222 SCTP_INP_RUNLOCK(inp);
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);
1230 SCTP_INP_WLOCK(inp);
1231 SCTP_INP_DECR_REF(inp);
1232 SCTP_INP_WUNLOCK(inp);
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);
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);
1250 /* Gak! no memory */
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 */
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);
1263 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
1264 SCTP_TCB_UNLOCK(stcb);
1265 #if defined(__FreeBSD__) && !defined(__Userspace__)
1272 #if !defined(__Userspace__)
1273 sctp6_getaddr(struct socket *so, struct sockaddr **addr)
1275 struct sockaddr_in6 *sin6;
1277 sctp6_getaddr(struct socket *so, struct mbuf *nam)
1279 struct sockaddr_in6 *sin6 = mtod(nam, struct sockaddr_in6 *);
1281 struct sctp_inpcb *inp;
1283 struct sctp_ifa *sctp_ifa;
1285 #if defined(SCTP_KAME) && defined(SCTP_EMBEDDED_V6_SCOPE)
1290 * Do the malloc first in case it blocks.
1292 #if !defined(__Userspace__)
1293 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof(*sin6));
1297 SCTP_BUF_LEN(nam) = sizeof(*sin6);
1298 memset(sin6, 0, sizeof(*sin6));
1300 sin6->sin6_family = AF_INET6;
1301 #ifdef HAVE_SIN6_LEN
1302 sin6->sin6_len = sizeof(*sin6);
1305 inp = (struct sctp_inpcb *)so->so_pcb;
1307 #if !defined(__Userspace__)
1308 SCTP_FREE_SONAME(sin6);
1310 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
1311 return (ECONNRESET);
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;
1322 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1324 SCTP_INP_RUNLOCK(inp);
1325 #if !defined(__Userspace__)
1326 SCTP_FREE_SONAME(sin6);
1328 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1333 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1334 sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
1336 /* this will make coverity happy */
1339 if (sin_a6->sin6_family == AF_INET6) {
1344 if ((!fnd) || (sin_a6 == NULL)) {
1346 SCTP_INP_RUNLOCK(inp);
1347 #if !defined(__Userspace__)
1348 SCTP_FREE_SONAME(sin6);
1350 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
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);
1356 sin6->sin6_addr = sctp_ifa->address.sin6.sin6_addr;
1359 /* For the bound all case you get back 0 */
1360 memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
1363 /* Take the first IPv6 address in the list */
1364 struct sctp_laddr *laddr;
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;
1371 sin_a = &laddr->ifa->address.sin6;
1372 sin6->sin6_addr = sin_a->sin6_addr;
1378 #if !defined(__Userspace__)
1379 SCTP_FREE_SONAME(sin6);
1381 SCTP_INP_RUNLOCK(inp);
1382 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1386 SCTP_INP_RUNLOCK(inp);
1387 /* Scoping things for v6 */
1388 #ifdef SCTP_EMBEDDED_V6_SCOPE
1390 if ((error = sa6_recoverscope(sin6)) != 0) {
1391 SCTP_FREE_SONAME(sin6);
1395 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
1396 /* skip ifp check below */
1397 in6_recoverscope(sin6, &sin6->sin6_addr, NULL);
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;
1409 #if !defined(__Userspace__)
1410 sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
1412 struct sockaddr_in6 *sin6;
1414 sctp6_peeraddr(struct socket *so, struct mbuf *nam)
1416 struct sockaddr_in6 *sin6 = mtod(nam, struct sockaddr_in6 *);
1419 struct sockaddr_in6 *sin_a6;
1420 struct sctp_inpcb *inp;
1421 struct sctp_tcb *stcb;
1422 struct sctp_nets *net;
1427 /* Do the malloc first in case it blocks. */
1428 #if !defined(__Userspace__)
1429 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1433 SCTP_BUF_LEN(nam) = sizeof(*sin6);
1434 memset(sin6, 0, sizeof(*sin6));
1436 sin6->sin6_family = AF_INET6;
1437 #ifdef HAVE_SIN6_LEN
1438 sin6->sin6_len = sizeof(*sin6);
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);
1448 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOTCONN);
1451 SCTP_INP_RLOCK(inp);
1452 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1454 SCTP_TCB_LOCK(stcb);
1456 SCTP_INP_RUNLOCK(inp);
1458 #if !defined(__Userspace__)
1459 SCTP_FREE_SONAME(sin6);
1461 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
1462 return (ECONNRESET);
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) {
1469 sin6->sin6_port = stcb->rport;
1470 sin6->sin6_addr = sin_a6->sin6_addr;
1474 SCTP_TCB_UNLOCK(stcb);
1476 /* No IPv4 address */
1477 #if !defined(__Userspace__)
1478 SCTP_FREE_SONAME(sin6);
1480 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1483 #ifdef SCTP_EMBEDDED_V6_SCOPE
1485 if ((error = sa6_recoverscope(sin6)) != 0) {
1486 #if !defined(__Userspace__)
1487 SCTP_FREE_SONAME(sin6);
1489 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, error);
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;
1502 #if !defined(__Userspace__)
1504 sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
1506 #elif defined(__Userspace__)
1508 sctp6_in6getaddr(struct socket *so, struct mbuf *nam)
1511 struct sockaddr *addr = mtod(nam, struct sockaddr *);
1515 sctp6_in6getaddr(struct socket *so, struct mbuf *nam)
1518 struct sockaddr *addr = mtod(nam, struct sockaddr *);
1521 struct inpcb *inp = sotoinpcb(so);
1525 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1529 /* allow v6 addresses precedence */
1530 error = sctp6_getaddr(so, nam);
1533 #if !defined(__Userspace__)
1534 struct sockaddr_in6 *sin6;
1536 struct sockaddr_in6 sin6;
1539 /* try v4 next if v6 failed */
1540 error = sctp_ingetaddr(so, nam);
1544 #if !defined(__Userspace__)
1545 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1547 SCTP_FREE_SONAME(*nam);
1550 in6_sin_2_v4mapsin6((struct sockaddr_in *)*nam, sin6);
1551 SCTP_FREE_SONAME(*nam);
1552 *nam = (struct sockaddr *)sin6;
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));
1564 #if !defined(__Userspace__)
1566 sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
1568 #elif defined(__Userspace__)
1570 sctp6_getpeeraddr(struct socket *so, struct mbuf *nam)
1573 struct sockaddr *addr = mtod(nam, struct sockaddr *);
1578 sctp6_getpeeraddr(struct socket *so, struct mbuf *nam)
1581 struct sockaddr *addr = mtod(nam, struct sockaddr *);
1585 struct inpcb *inp = sotoinpcb(so);
1589 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1593 /* allow v6 addresses precedence */
1594 error = sctp6_peeraddr(so, nam);
1597 #if !defined(__Userspace__)
1598 struct sockaddr_in6 *sin6;
1600 struct sockaddr_in6 sin6;
1603 /* try v4 next if v6 failed */
1604 error = sctp_peeraddr(so, nam);
1608 #if !defined(__Userspace__)
1609 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1611 SCTP_FREE_SONAME(*nam);
1614 in6_sin_2_v4mapsin6((struct sockaddr_in *)*nam, sin6);
1615 SCTP_FREE_SONAME(*nam);
1616 *nam = (struct sockaddr *)sin6;
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));
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,
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__)
1675 pru_connect2_notsupp,
1696 #elif !defined(__Userspace__)
1698 sctp6_usrreq(so, req, m, nam, control, p)
1701 struct mbuf *m, *nam, *control;
1707 family = so->so_proto->pr_domain->dom_family;
1709 if (req == PRU_CONTROL) {
1712 error = in_control(so, (long)m, (caddr_t)nam,
1713 (struct ifnet *)control );
1717 error = in6_control(so, (long)m, (caddr_t)nam,
1718 (struct ifnet *)control, p);
1722 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
1723 error = EAFNOSUPPORT;
1729 error = sctp6_attach(so, family, p);
1732 error = sctp6_detach(so);
1736 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1739 error = sctp6_bind(so, nam, p);
1742 error = sctp_listen(so, p);
1746 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1749 error = sctp6_connect(so, nam, p);
1751 case PRU_DISCONNECT:
1752 error = sctp6_disconnect(so);
1756 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1759 error = sctp_accept(so, nam);
1762 error = sctp_shutdown(so);
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!
1771 error = sctp_usr_recvd(so, (int)((long)nam));
1775 /* Flags are ignored */
1776 error = sctp6_send(so, 0, m, nam, control, p);
1779 error = sctp6_abort(so);
1786 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
1787 error = EAFNOSUPPORT;
1790 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
1791 error = EAFNOSUPPORT;
1794 error = sctp6_getpeeraddr(so, nam);
1797 error = sctp6_in6getaddr(so, nam);