tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

sctp6_usrreq.c (46187B)


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