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