Home | History | Annotate | Download | only in netinet
      1 /*-
      2  * Copyright (c) 2001-2008, 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/netinet/sctp_usrreq.c 271221 2014-09-07 09:06:26Z tuexen $");
     36 #endif
     37 
     38 #include <netinet/sctp_os.h>
     39 #ifdef __FreeBSD__
     40 #include <sys/proc.h>
     41 #endif
     42 #include <netinet/sctp_pcb.h>
     43 #include <netinet/sctp_header.h>
     44 #include <netinet/sctp_var.h>
     45 #ifdef INET6
     46 #if defined(__Userspace_os_FreeBSD)
     47 #include <netinet6/sctp6_var.h>
     48 #endif
     49 #endif
     50 #include <netinet/sctp_sysctl.h>
     51 #include <netinet/sctp_output.h>
     52 #include <netinet/sctp_uio.h>
     53 #include <netinet/sctp_asconf.h>
     54 #include <netinet/sctputil.h>
     55 #include <netinet/sctp_indata.h>
     56 #include <netinet/sctp_timer.h>
     57 #include <netinet/sctp_auth.h>
     58 #include <netinet/sctp_bsd_addr.h>
     59 #if !defined(__Userspace__)
     60 #include <netinet/udp.h>
     61 #endif
     62 
     63 #if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
     64 #include <netinet/sctp_peeloff.h>
     65 #endif				/* HAVE_SCTP_PEELOFF_SOCKOPT */
     66 
     67 #if defined(__APPLE__)
     68 #define APPLE_FILE_NO 7
     69 #endif
     70 
     71 extern struct sctp_cc_functions sctp_cc_functions[];
     72 extern struct sctp_ss_functions sctp_ss_functions[];
     73 
     74 void
     75 #if defined(__Userspace__)
     76 sctp_init(uint16_t port,
     77           int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df),
     78           void (*debug_printf)(const char *format, ...))
     79 #elif defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) &&!defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION))
     80 sctp_init(struct protosw *pp SCTP_UNUSED, struct domain *dp SCTP_UNUSED)
     81 #else
     82 sctp_init(void)
     83 #endif
     84 {
     85 #if !defined(__Panda__) && !defined(__Userspace__)
     86 	u_long sb_max_adj;
     87 
     88 #endif
     89 #if defined(__Userspace__)
     90 #if defined(__Userspace_os_Windows)
     91 #if defined(INET) || defined(INET6)
     92 	WSADATA wsaData;
     93 
     94 	if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
     95 		SCTP_PRINTF("WSAStartup failed\n");
     96 		exit (-1);
     97 	}
     98 #endif
     99 	InitializeConditionVariable(&accept_cond);
    100 	InitializeCriticalSection(&accept_mtx);
    101 #else
    102 	pthread_cond_init(&accept_cond, NULL);
    103 	pthread_mutex_init(&accept_mtx, NULL);
    104 #endif
    105 #endif
    106 	/* Initialize and modify the sysctled variables */
    107 	sctp_init_sysctls();
    108 #if defined(__Userspace__)
    109 #if defined(__Userspace_os_Windows)
    110 	srand((unsigned int)time(NULL));
    111 #else
    112 	srandom(getpid()); /* so inp->sctp_ep.random_numbers are truly random... */
    113 #endif
    114 #endif
    115 #if defined(__Panda__)
    116 	sctp_sendspace = SB_MAX;
    117 	sctp_recvspace = SB_MAX;
    118 
    119 #elif defined(__Userspace__)
    120 	SCTP_BASE_SYSCTL(sctp_sendspace) = SB_MAX;
    121 	SCTP_BASE_SYSCTL(sctp_recvspace) = SB_RAW;
    122 	SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = port;
    123 #else
    124 #if !defined(__APPLE__)
    125 	if ((nmbclusters / 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
    126 		SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = (nmbclusters / 8);
    127 #endif
    128 	/*
    129 	 * Allow a user to take no more than 1/2 the number of clusters or
    130 	 * the SB_MAX whichever is smaller for the send window.
    131 	 */
    132 #if defined(__APPLE__)
    133 	sb_max_adj = (u_long)((u_quad_t) (sb_max) * MCLBYTES / (MSIZE + MCLBYTES));
    134 #else
    135 	sb_max_adj = (u_long)((u_quad_t) (SB_MAX) * MCLBYTES / (MSIZE + MCLBYTES));
    136 #endif
    137 #if defined(__APPLE__)
    138 	SCTP_BASE_SYSCTL(sctp_sendspace) = sb_max_adj;
    139 #else
    140 	SCTP_BASE_SYSCTL(sctp_sendspace) = min(sb_max_adj,
    141 	    (((uint32_t)nmbclusters / 2) * SCTP_DEFAULT_MAXSEGMENT));
    142 #endif
    143 	/*
    144 	 * Now for the recv window, should we take the same amount? or
    145 	 * should I do 1/2 the SB_MAX instead in the SB_MAX min above. For
    146 	 * now I will just copy.
    147 	 */
    148 	SCTP_BASE_SYSCTL(sctp_recvspace) = SCTP_BASE_SYSCTL(sctp_sendspace);
    149 #endif
    150 	SCTP_BASE_VAR(first_time) = 0;
    151 	SCTP_BASE_VAR(sctp_pcb_initialized) = 0;
    152 #if defined(__Userspace__)
    153 #if !defined(__Userspace_os_Windows)
    154 #if defined(INET) || defined(INET6)
    155 	SCTP_BASE_VAR(userspace_route) = -1;
    156 #endif
    157 #endif
    158 #ifdef INET
    159 	SCTP_BASE_VAR(userspace_rawsctp) = -1;
    160 	SCTP_BASE_VAR(userspace_udpsctp) = -1;
    161 #endif
    162 #ifdef INET6
    163 	SCTP_BASE_VAR(userspace_rawsctp6) = -1;
    164 	SCTP_BASE_VAR(userspace_udpsctp6) = -1;
    165 #endif
    166 	SCTP_BASE_VAR(timer_thread_should_exit) = 0;
    167 	SCTP_BASE_VAR(conn_output) = conn_output;
    168 	SCTP_BASE_VAR(debug_printf) = debug_printf;
    169 #endif
    170 	sctp_pcb_init();
    171 #if defined(__Userspace__)
    172 	sctp_start_timer();
    173 #endif
    174 #if defined(SCTP_PACKET_LOGGING)
    175 	SCTP_BASE_VAR(packet_log_writers) = 0;
    176 	SCTP_BASE_VAR(packet_log_end) = 0;
    177 	bzero(&SCTP_BASE_VAR(packet_log_buffer), SCTP_PACKET_LOG_SIZE);
    178 #endif
    179 #if defined(__APPLE__)
    180 	SCTP_BASE_VAR(sctp_main_timer_ticks) = 0;
    181 	sctp_start_main_timer();
    182 	timeout(sctp_delayed_startup, NULL, 1);
    183 #endif
    184 }
    185 
    186 void
    187 sctp_finish(void)
    188 {
    189 #if defined(__APPLE__)
    190 	untimeout(sctp_delayed_startup, NULL);
    191 	sctp_over_udp_stop();
    192 	sctp_address_monitor_stop();
    193 	sctp_stop_main_timer();
    194 #endif
    195 #if defined(__Userspace__)
    196 #if defined(INET) || defined(INET6)
    197 	recv_thread_destroy();
    198 #endif
    199 #if !defined(__Userspace_os_Windows)
    200 #if defined(INET) || defined(INET6)
    201 	if (SCTP_BASE_VAR(userspace_route) != -1) {
    202 		pthread_join(SCTP_BASE_VAR(recvthreadroute), NULL);
    203 	}
    204 #endif
    205 #endif
    206 #ifdef INET
    207 	if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
    208 #if defined(__Userspace_os_Windows)
    209 		WaitForSingleObject(SCTP_BASE_VAR(recvthreadraw), INFINITE);
    210 		CloseHandle(SCTP_BASE_VAR(recvthreadraw));
    211 #else
    212 		pthread_join(SCTP_BASE_VAR(recvthreadraw), NULL);
    213 #endif
    214 	}
    215 	if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
    216 #if defined(__Userspace_os_Windows)
    217 		WaitForSingleObject(SCTP_BASE_VAR(recvthreadudp), INFINITE);
    218 		CloseHandle(SCTP_BASE_VAR(recvthreadudp));
    219 #else
    220 		pthread_join(SCTP_BASE_VAR(recvthreadudp), NULL);
    221 #endif
    222 	}
    223 #endif
    224 #ifdef INET6
    225 	if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
    226 #if defined(__Userspace_os_Windows)
    227 		WaitForSingleObject(SCTP_BASE_VAR(recvthreadraw6), INFINITE);
    228 		CloseHandle(SCTP_BASE_VAR(recvthreadraw6));
    229 #else
    230 		pthread_join(SCTP_BASE_VAR(recvthreadraw6), NULL);
    231 #endif
    232 	}
    233 	if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
    234 #if defined(__Userspace_os_Windows)
    235 		WaitForSingleObject(SCTP_BASE_VAR(recvthreadudp6), INFINITE);
    236 		CloseHandle(SCTP_BASE_VAR(recvthreadudp6));
    237 #else
    238 		pthread_join(SCTP_BASE_VAR(recvthreadudp6), NULL);
    239 #endif
    240 	}
    241 #endif
    242 	SCTP_BASE_VAR(timer_thread_should_exit) = 1;
    243 #if defined(__Userspace_os_Windows)
    244 	WaitForSingleObject(SCTP_BASE_VAR(timer_thread), INFINITE);
    245 	CloseHandle(SCTP_BASE_VAR(timer_thread));
    246 #else
    247 	pthread_join(SCTP_BASE_VAR(timer_thread), NULL);
    248 #endif
    249 #endif
    250 	sctp_pcb_finish();
    251 #if defined(__Userspace__)
    252 #if defined(__Userspace_os_Windows)
    253 	DeleteConditionVariable(&accept_cond);
    254 	DeleteCriticalSection(&accept_mtx);
    255 #else
    256 	pthread_cond_destroy(&accept_cond);
    257 	pthread_mutex_destroy(&accept_mtx);
    258 #endif
    259 #endif
    260 #if defined(__Windows__)
    261 	sctp_finish_sysctls();
    262 #if defined(INET) || defined(INET6)
    263 	WSACleanup();
    264 #endif
    265 #endif
    266 }
    267 
    268 
    269 
    270 void
    271 sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz)
    272 {
    273 	struct sctp_tmit_chunk *chk;
    274 	uint16_t overhead;
    275 
    276 	/* Adjust that too */
    277 	stcb->asoc.smallest_mtu = nxtsz;
    278 	/* now off to subtract IP_DF flag if needed */
    279 	overhead = IP_HDR_SIZE;
    280 	if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
    281 		overhead += sctp_get_auth_chunk_len(stcb->asoc.peer_hmac_id);
    282 	}
    283 	TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
    284 		if ((chk->send_size + overhead) > nxtsz) {
    285 			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
    286 		}
    287 	}
    288 	TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
    289 		if ((chk->send_size + overhead) > nxtsz) {
    290 			/*
    291 			 * For this guy we also mark for immediate resend
    292 			 * since we sent to big of chunk
    293 			 */
    294 			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
    295 			if (chk->sent < SCTP_DATAGRAM_RESEND) {
    296 				sctp_flight_size_decrease(chk);
    297 				sctp_total_flight_decrease(stcb, chk);
    298 			}
    299 			if (chk->sent != SCTP_DATAGRAM_RESEND) {
    300 				sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
    301 			}
    302 			chk->sent = SCTP_DATAGRAM_RESEND;
    303 			chk->rec.data.doing_fast_retransmit = 0;
    304 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
    305 				sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
    306 					       chk->whoTo->flight_size,
    307 					       chk->book_size,
    308 					       (uintptr_t)chk->whoTo,
    309 					       chk->rec.data.TSN_seq);
    310 			}
    311 			/* Clear any time so NO RTT is being done */
    312 			chk->do_rtt = 0;
    313 		}
    314 	}
    315 }
    316 
    317 #ifdef INET
    318 #if !defined(__Userspace__)
    319 #if defined(__Panda__) || defined(__Windows__)
    320 void
    321 #else
    322 static void
    323 #endif
    324 sctp_notify_mbuf(struct sctp_inpcb *inp,
    325     struct sctp_tcb *stcb,
    326     struct sctp_nets *net,
    327     struct ip *ip,
    328     struct sctphdr *sh)
    329 {
    330 	struct icmp *icmph;
    331 	int totsz, tmr_stopped = 0;
    332 	uint16_t nxtsz;
    333 
    334 	/* protection */
    335 	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
    336 	    (ip == NULL) || (sh == NULL)) {
    337 		if (stcb != NULL) {
    338 			SCTP_TCB_UNLOCK(stcb);
    339 		}
    340 		return;
    341 	}
    342 	/* First job is to verify the vtag matches what I would send */
    343 	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
    344 		SCTP_TCB_UNLOCK(stcb);
    345 		return;
    346 	}
    347 	icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
    348 	    sizeof(struct ip)));
    349 	if (icmph->icmp_type != ICMP_UNREACH) {
    350 		/* We only care about unreachable */
    351 		SCTP_TCB_UNLOCK(stcb);
    352 		return;
    353 	}
    354 	if (icmph->icmp_code != ICMP_UNREACH_NEEDFRAG) {
    355 		/* not a unreachable message due to frag. */
    356 		SCTP_TCB_UNLOCK(stcb);
    357 		return;
    358 	}
    359 #if defined(__FreeBSD__) && __FreeBSD_version >= 1000000
    360 	totsz = ntohs(ip->ip_len);
    361 #else
    362 	totsz = ip->ip_len;
    363 #endif
    364 
    365 	nxtsz = ntohs(icmph->icmp_nextmtu);
    366 	if (nxtsz == 0) {
    367 		/*
    368 		 * old type router that does not tell us what the next size
    369 		 * mtu is. Rats we will have to guess (in a educated fashion
    370 		 * of course)
    371 		 */
    372 		nxtsz = sctp_get_prev_mtu(totsz);
    373 	}
    374 	/* Stop any PMTU timer */
    375 	if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
    376 		tmr_stopped = 1;
    377 		sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
    378 				SCTP_FROM_SCTP_USRREQ+SCTP_LOC_1);
    379 	}
    380 	/* Adjust destination size limit */
    381 	if (net->mtu > nxtsz) {
    382 		net->mtu = nxtsz;
    383 		if (net->port) {
    384 			net->mtu -= sizeof(struct udphdr);
    385 		}
    386 	}
    387 	/* now what about the ep? */
    388 	if (stcb->asoc.smallest_mtu > nxtsz) {
    389 		sctp_pathmtu_adjustment(stcb, nxtsz);
    390 	}
    391 	if (tmr_stopped)
    392 		sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
    393 
    394 	SCTP_TCB_UNLOCK(stcb);
    395 }
    396 
    397 void
    398 sctp_notify(struct sctp_inpcb *inp,
    399     struct ip *ip,
    400     struct sctphdr *sh,
    401     struct sockaddr *to,
    402     struct sctp_tcb *stcb,
    403     struct sctp_nets *net)
    404 {
    405 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    406 	struct socket *so;
    407 
    408 #endif
    409 	struct icmp *icmph;
    410 
    411 	/* protection */
    412 	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
    413 	    (sh == NULL) || (to == NULL)) {
    414 		if (stcb)
    415 			SCTP_TCB_UNLOCK(stcb);
    416 		return;
    417 	}
    418 	/* First job is to verify the vtag matches what I would send */
    419 	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
    420 		SCTP_TCB_UNLOCK(stcb);
    421 		return;
    422 	}
    423 
    424 	icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
    425 					       sizeof(struct ip)));
    426 	if (icmph->icmp_type != ICMP_UNREACH) {
    427 		/* We only care about unreachable */
    428 		SCTP_TCB_UNLOCK(stcb);
    429 		return;
    430 	}
    431 	if ((icmph->icmp_code == ICMP_UNREACH_NET) ||
    432 	    (icmph->icmp_code == ICMP_UNREACH_HOST) ||
    433 	    (icmph->icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
    434 	    (icmph->icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
    435 	    (icmph->icmp_code == ICMP_UNREACH_ISOLATED) ||
    436 	    (icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) ||
    437 	    (icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
    438 #if defined(__Panda__)
    439 	    (icmph->icmp_code == ICMP_UNREACH_ADMIN)) {
    440 #elif defined(__Userspace_os_NetBSD)
    441 	    (icmph->icmp_code == ICMP_UNREACH_ADMIN_PROHIBIT)) {
    442 #else
    443 	    (icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
    444 #endif
    445 
    446 		/*
    447 		 * Hmm reachablity problems we must examine closely. If its
    448 		 * not reachable, we may have lost a network. Or if there is
    449 		 * NO protocol at the other end named SCTP. well we consider
    450 		 * it a OOTB abort.
    451 		 */
    452 		if (net->dest_state & SCTP_ADDR_REACHABLE) {
    453 			/* Ok that destination is NOT reachable */
    454 			net->dest_state &= ~SCTP_ADDR_REACHABLE;
    455 			net->dest_state &= ~SCTP_ADDR_PF;
    456 			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
    457 					stcb, 0,
    458 					(void *)net, SCTP_SO_NOT_LOCKED);
    459 		}
    460 		SCTP_TCB_UNLOCK(stcb);
    461 	} else  if ((icmph->icmp_code == ICMP_UNREACH_PROTOCOL) ||
    462 		    (icmph->icmp_code == ICMP_UNREACH_PORT)) {
    463 		/*
    464 		 * Here the peer is either playing tricks on us,
    465 		 * including an address that belongs to someone who
    466 		 * does not support SCTP OR was a userland
    467 		 * implementation that shutdown and now is dead. In
    468 		 * either case treat it like a OOTB abort with no
    469 		 * TCB
    470 		 */
    471 		sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
    472 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    473 		so = SCTP_INP_SO(inp);
    474 		atomic_add_int(&stcb->asoc.refcnt, 1);
    475 		SCTP_TCB_UNLOCK(stcb);
    476 		SCTP_SOCKET_LOCK(so, 1);
    477 		SCTP_TCB_LOCK(stcb);
    478 		atomic_subtract_int(&stcb->asoc.refcnt, 1);
    479 #endif
    480 		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_2);
    481 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    482 		SCTP_SOCKET_UNLOCK(so, 1);
    483 		/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed.*/
    484 #endif
    485 		/* no need to unlock here, since the TCB is gone */
    486 	} else {
    487 		SCTP_TCB_UNLOCK(stcb);
    488 	}
    489 }
    490 #endif
    491 #endif
    492 
    493 #ifdef INET
    494 #if !defined(__Panda__) && !defined(__Userspace__)
    495 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
    496 void
    497 #else
    498 void *
    499 #endif
    500 sctp_ctlinput(cmd, sa, vip)
    501 	int cmd;
    502 	struct sockaddr *sa;
    503 	void *vip;
    504 {
    505 	struct ip *ip = vip;
    506 	struct sctphdr *sh;
    507 	uint32_t vrf_id;
    508 	/* FIX, for non-bsd is this right? */
    509 	vrf_id = SCTP_DEFAULT_VRFID;
    510 	if (sa->sa_family != AF_INET ||
    511 	    ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
    512 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
    513 		return;
    514 #else
    515 		return (NULL);
    516 #endif
    517 	}
    518 	if (PRC_IS_REDIRECT(cmd)) {
    519 		ip = 0;
    520 	} else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
    521 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
    522 		return;
    523 #else
    524 		return (NULL);
    525 #endif
    526 	}
    527 	if (ip) {
    528 		struct sctp_inpcb *inp = NULL;
    529 		struct sctp_tcb *stcb = NULL;
    530 		struct sctp_nets *net = NULL;
    531 		struct sockaddr_in to, from;
    532 
    533 		sh = (struct sctphdr *)((caddr_t)ip + (ip->ip_hl << 2));
    534 		bzero(&to, sizeof(to));
    535 		bzero(&from, sizeof(from));
    536 		from.sin_family = to.sin_family = AF_INET;
    537 #ifdef HAVE_SIN_LEN
    538 		from.sin_len = to.sin_len = sizeof(to);
    539 #endif
    540 		from.sin_port = sh->src_port;
    541 		from.sin_addr = ip->ip_src;
    542 		to.sin_port = sh->dest_port;
    543 		to.sin_addr = ip->ip_dst;
    544 
    545 		/*
    546 		 * 'to' holds the dest of the packet that failed to be sent.
    547 		 * 'from' holds our local endpoint address. Thus we reverse
    548 		 * the to and the from in the lookup.
    549 		 */
    550 		stcb = sctp_findassociation_addr_sa((struct sockaddr *)&to,
    551 		    (struct sockaddr *)&from,
    552 		    &inp, &net, 1, vrf_id);
    553 		if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
    554 			if (cmd != PRC_MSGSIZE) {
    555 				sctp_notify(inp, ip, sh,
    556 				    (struct sockaddr *)&to, stcb,
    557 				    net);
    558 			} else {
    559 				/* handle possible ICMP size messages */
    560 				sctp_notify_mbuf(inp, stcb, net, ip, sh);
    561 			}
    562 		} else {
    563 #if defined(__FreeBSD__) && __FreeBSD_version < 500000
    564 			/*
    565 			 * XXX must be fixed for 5.x and higher, leave for
    566 			 * 4.x
    567 			 */
    568 			if (PRC_IS_REDIRECT(cmd) && inp) {
    569 				in_rtchange((struct inpcb *)inp,
    570 				    inetctlerrmap[cmd]);
    571 			}
    572 #endif
    573 			if ((stcb == NULL) && (inp != NULL)) {
    574 				/* reduce ref-count */
    575 				SCTP_INP_WLOCK(inp);
    576 				SCTP_INP_DECR_REF(inp);
    577 				SCTP_INP_WUNLOCK(inp);
    578 			}
    579 			if (stcb) {
    580 				SCTP_TCB_UNLOCK(stcb);
    581 			}
    582 		}
    583 	}
    584 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
    585 	return;
    586 #else
    587 	return (NULL);
    588 #endif
    589 }
    590 #endif
    591 #endif
    592 
    593 #if defined(__FreeBSD__)
    594 static int
    595 sctp_getcred(SYSCTL_HANDLER_ARGS)
    596 {
    597 	struct xucred xuc;
    598 	struct sockaddr_in addrs[2];
    599 	struct sctp_inpcb *inp;
    600 	struct sctp_nets *net;
    601 	struct sctp_tcb *stcb;
    602 	int error;
    603 	uint32_t vrf_id;
    604 
    605 	/* FIX, for non-bsd is this right? */
    606 	vrf_id = SCTP_DEFAULT_VRFID;
    607 
    608 #if __FreeBSD_version > 602000
    609 	error = priv_check(req->td, PRIV_NETINET_GETCRED);
    610 
    611 #elif __FreeBSD_version >= 500000
    612 	error = suser(req->td);
    613 #else
    614 	error = suser(req->p);
    615 #endif
    616 	if (error)
    617 		return (error);
    618 
    619 	error = SYSCTL_IN(req, addrs, sizeof(addrs));
    620 	if (error)
    621 		return (error);
    622 
    623 	stcb = sctp_findassociation_addr_sa(sintosa(&addrs[1]),
    624 	    sintosa(&addrs[0]),
    625 	    &inp, &net, 1, vrf_id);
    626 	if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
    627 		if ((inp != NULL) && (stcb == NULL)) {
    628 			/* reduce ref-count */
    629 			SCTP_INP_WLOCK(inp);
    630 			SCTP_INP_DECR_REF(inp);
    631 			goto cred_can_cont;
    632 		}
    633 
    634 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
    635 		error = ENOENT;
    636 		goto out;
    637 	}
    638 	SCTP_TCB_UNLOCK(stcb);
    639 	/* We use the write lock here, only
    640 	 * since in the error leg we need it.
    641 	 * If we used RLOCK, then we would have
    642 	 * to wlock/decr/unlock/rlock. Which
    643 	 * in theory could create a hole. Better
    644 	 * to use higher wlock.
    645 	 */
    646 	SCTP_INP_WLOCK(inp);
    647  cred_can_cont:
    648 	error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
    649 	if (error) {
    650 		SCTP_INP_WUNLOCK(inp);
    651 		goto out;
    652 	}
    653 	cru2x(inp->sctp_socket->so_cred, &xuc);
    654 	SCTP_INP_WUNLOCK(inp);
    655 	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
    656 out:
    657 	return (error);
    658 }
    659 
    660 SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
    661     0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection");
    662 #endif				/* #if defined(__FreeBSD__) */
    663 
    664 
    665 #ifdef INET
    666 #if defined(__Panda__) || defined(__Windows__) || defined(__Userspace__)
    667 int
    668 #elif defined(__FreeBSD__) && __FreeBSD_version > 690000
    669 static void
    670 #else
    671 static int
    672 #endif
    673 sctp_abort(struct socket *so)
    674 {
    675 	struct sctp_inpcb *inp;
    676 	uint32_t flags;
    677 
    678 	inp = (struct sctp_inpcb *)so->so_pcb;
    679 	if (inp == NULL) {
    680 #if defined(__FreeBSD__) && __FreeBSD_version > 690000
    681 		return;
    682 #else
    683 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
    684 		return (EINVAL);
    685 #endif
    686 	}
    687 
    688  sctp_must_try_again:
    689 	flags = inp->sctp_flags;
    690 #ifdef SCTP_LOG_CLOSING
    691 	sctp_log_closing(inp, NULL, 17);
    692 #endif
    693 	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
    694 	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
    695 #ifdef SCTP_LOG_CLOSING
    696 		sctp_log_closing(inp, NULL, 16);
    697 #endif
    698 		sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
    699 				SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
    700 		SOCK_LOCK(so);
    701 		SCTP_SB_CLEAR(so->so_snd);
    702 		/* same for the rcv ones, they are only
    703 		 * here for the accounting/select.
    704 		 */
    705 		SCTP_SB_CLEAR(so->so_rcv);
    706 
    707 #if defined(__APPLE__)
    708 		so->so_usecount--;
    709 #else
    710 		/* Now null out the reference, we are completely detached. */
    711 		so->so_pcb = NULL;
    712 #endif
    713 		SOCK_UNLOCK(so);
    714 	} else {
    715 		flags = inp->sctp_flags;
    716 		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
    717 			goto sctp_must_try_again;
    718 		}
    719 	}
    720 #if defined(__FreeBSD__) && __FreeBSD_version > 690000
    721 	return;
    722 #else
    723 	return (0);
    724 #endif
    725 }
    726 
    727 #if defined(__Panda__) || defined(__Userspace__)
    728 int
    729 #else
    730 static int
    731 #endif
    732 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
    733 sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
    734 #elif defined(__Panda__) || defined(__Userspace__)
    735 sctp_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
    736 #elif defined(__Windows__)
    737 sctp_attach(struct socket *so, int proto SCTP_UNUSED, PKTHREAD p SCTP_UNUSED)
    738 #else
    739 sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct proc *p SCTP_UNUSED)
    740 #endif
    741 {
    742 	struct sctp_inpcb *inp;
    743 	struct inpcb *ip_inp;
    744 	int error;
    745 #if !defined(__Panda__) && !defined(__Userspace__)
    746 	uint32_t vrf_id = SCTP_DEFAULT_VRFID;
    747 #endif
    748 #ifdef IPSEC
    749 	uint32_t flags;
    750 #endif
    751 
    752 	inp = (struct sctp_inpcb *)so->so_pcb;
    753 	if (inp != 0) {
    754 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
    755 		return (EINVAL);
    756 	}
    757 	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
    758 		error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
    759 		if (error) {
    760 			return (error);
    761 		}
    762 	}
    763 	error = sctp_inpcb_alloc(so, vrf_id);
    764 	if (error) {
    765 		return (error);
    766 	}
    767 	inp = (struct sctp_inpcb *)so->so_pcb;
    768 	SCTP_INP_WLOCK(inp);
    769 	inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6;	/* I'm not v6! */
    770 	ip_inp = &inp->ip_inp.inp;
    771 	ip_inp->inp_vflag |= INP_IPV4;
    772 	ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
    773 #ifdef IPSEC
    774 #if !(defined(__APPLE__))
    775 	error = ipsec_init_policy(so, &ip_inp->inp_sp);
    776 #ifdef SCTP_LOG_CLOSING
    777 	sctp_log_closing(inp, NULL, 17);
    778 #endif
    779 	if (error != 0) {
    780 	try_again:
    781 		flags = inp->sctp_flags;
    782 		if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
    783 		    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
    784 #ifdef SCTP_LOG_CLOSING
    785 			sctp_log_closing(inp, NULL, 15);
    786 #endif
    787 			SCTP_INP_WUNLOCK(inp);
    788 			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
    789 					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
    790 		} else {
    791 			flags = inp->sctp_flags;
    792 			if ((flags &  SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
    793 				goto try_again;
    794 			} else {
    795 				SCTP_INP_WUNLOCK(inp);
    796 			}
    797 		}
    798 		return (error);
    799 	}
    800 #endif
    801 #endif				/* IPSEC */
    802 	SCTP_INP_WUNLOCK(inp);
    803 	return (0);
    804 }
    805 
    806 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
    807 static int
    808 sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
    809 {
    810 #elif defined(__FreeBSD__) || defined(__APPLE__)
    811 static int
    812 sctp_bind(struct socket *so, struct sockaddr *addr, struct proc *p) {
    813 #elif defined(__Panda__) || defined(__Userspace__)
    814 int
    815 sctp_bind(struct socket *so, struct sockaddr *addr) {
    816 	void *p = NULL;
    817 #elif defined(__Windows__)
    818 static int
    819 sctp_bind(struct socket *so, struct sockaddr *addr, PKTHREAD p) {
    820 #else
    821 static int
    822 sctp_bind(struct socket *so, struct mbuf *nam, struct proc *p)
    823 {
    824 	struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
    825 
    826 #endif
    827 	struct sctp_inpcb *inp;
    828 
    829 	inp = (struct sctp_inpcb *)so->so_pcb;
    830 	if (inp == NULL) {
    831 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
    832 		return (EINVAL);
    833 	}
    834 	if (addr != NULL) {
    835 #ifdef HAVE_SA_LEN
    836 		if ((addr->sa_family != AF_INET) ||
    837 		    (addr->sa_len != sizeof(struct sockaddr_in))) {
    838 #else
    839 		if (addr->sa_family != AF_INET) {
    840 #endif
    841 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
    842 			return (EINVAL);
    843 		}
    844 	}
    845 	return (sctp_inpcb_bind(so, addr, NULL, p));
    846 }
    847 
    848 #endif
    849 #if defined(__Userspace__)
    850 
    851 int
    852 sctpconn_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
    853 {
    854 	struct sctp_inpcb *inp;
    855 	struct inpcb *ip_inp;
    856 	int error;
    857 
    858 	inp = (struct sctp_inpcb *)so->so_pcb;
    859 	if (inp != NULL) {
    860 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
    861 		return (EINVAL);
    862 	}
    863 	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
    864 		error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
    865 		if (error) {
    866 			return (error);
    867 		}
    868 	}
    869 	error = sctp_inpcb_alloc(so, vrf_id);
    870 	if (error) {
    871 		return (error);
    872 	}
    873 	inp = (struct sctp_inpcb *)so->so_pcb;
    874 	SCTP_INP_WLOCK(inp);
    875 	inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6;
    876 	inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_CONN;
    877 	ip_inp = &inp->ip_inp.inp;
    878 	ip_inp->inp_vflag |= INP_CONN;
    879 	ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
    880 	SCTP_INP_WUNLOCK(inp);
    881 	return (0);
    882 }
    883 
    884 int
    885 sctpconn_bind(struct socket *so, struct sockaddr *addr)
    886 {
    887 	struct sctp_inpcb *inp;
    888 
    889 	inp = (struct sctp_inpcb *)so->so_pcb;
    890 	if (inp == NULL) {
    891 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
    892 		return (EINVAL);
    893 	}
    894 	if (addr != NULL) {
    895 #ifdef HAVE_SA_LEN
    896 		if ((addr->sa_family != AF_CONN) ||
    897 		    (addr->sa_len != sizeof(struct sockaddr_conn))) {
    898 #else
    899 		if (addr->sa_family != AF_CONN) {
    900 #endif
    901 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
    902 			return (EINVAL);
    903 		}
    904 	}
    905 	return (sctp_inpcb_bind(so, addr, NULL, NULL));
    906 }
    907 
    908 #endif
    909 #if (defined(__FreeBSD__) && __FreeBSD_version > 690000) || defined(__Windows__) || defined(__Userspace__)
    910 void
    911 sctp_close(struct socket *so)
    912 {
    913 	struct sctp_inpcb *inp;
    914 	uint32_t flags;
    915 
    916 	inp = (struct sctp_inpcb *)so->so_pcb;
    917 	if (inp == NULL)
    918 		return;
    919 
    920 	/* Inform all the lower layer assoc that we
    921 	 * are done.
    922 	 */
    923  sctp_must_try_again:
    924 	flags = inp->sctp_flags;
    925 #ifdef SCTP_LOG_CLOSING
    926 	sctp_log_closing(inp, NULL, 17);
    927 #endif
    928 	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
    929 	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
    930 #if defined(__Userspace__)
    931 		if (((so->so_options & SCTP_SO_LINGER) && (so->so_linger == 0)) ||
    932 		    (so->so_rcv.sb_cc > 0)) {
    933 #else
    934 		if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
    935 		    (so->so_rcv.sb_cc > 0)) {
    936 #endif
    937 #ifdef SCTP_LOG_CLOSING
    938 			sctp_log_closing(inp, NULL, 13);
    939 #endif
    940 			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
    941 					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
    942 		} else {
    943 #ifdef SCTP_LOG_CLOSING
    944 			sctp_log_closing(inp, NULL, 14);
    945 #endif
    946 			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
    947 					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
    948 		}
    949 		/* The socket is now detached, no matter what
    950 		 * the state of the SCTP association.
    951 		 */
    952 		SOCK_LOCK(so);
    953 		SCTP_SB_CLEAR(so->so_snd);
    954 		/* same for the rcv ones, they are only
    955 		 * here for the accounting/select.
    956 		 */
    957 		SCTP_SB_CLEAR(so->so_rcv);
    958 
    959 #if !defined(__APPLE__)
    960 		/* Now null out the reference, we are completely detached. */
    961 		so->so_pcb = NULL;
    962 #endif
    963 		SOCK_UNLOCK(so);
    964 	} else {
    965 		flags = inp->sctp_flags;
    966 		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
    967 			goto sctp_must_try_again;
    968 		}
    969 	}
    970 	return;
    971 }
    972 
    973 #else
    974 
    975 
    976 int
    977 sctp_detach(struct socket *so)
    978 {
    979 	struct sctp_inpcb *inp;
    980 	uint32_t flags;
    981 
    982 	inp = (struct sctp_inpcb *)so->so_pcb;
    983 	if (inp == NULL) {
    984 #if defined(__FreeBSD__) && __FreeBSD_version > 690000
    985 		return;
    986 #else
    987 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
    988 		return (EINVAL);
    989 #endif
    990 	}
    991  sctp_must_try_again:
    992 	flags = inp->sctp_flags;
    993 #ifdef SCTP_LOG_CLOSING
    994 	sctp_log_closing(inp, NULL, 17);
    995 #endif
    996 	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
    997 	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
    998 #if defined(__Userspace__)
    999 		if (((so->so_options & SCTP_SO_LINGER) && (so->so_linger == 0)) ||
   1000 		    (so->so_rcv.sb_cc > 0)) {
   1001 #else
   1002 		if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
   1003 		    (so->so_rcv.sb_cc > 0)) {
   1004 #endif
   1005 #ifdef SCTP_LOG_CLOSING
   1006 			sctp_log_closing(inp, NULL, 13);
   1007 #endif
   1008 			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
   1009 					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
   1010 		} else {
   1011 #ifdef SCTP_LOG_CLOSING
   1012 			sctp_log_closing(inp, NULL, 13);
   1013 #endif
   1014 			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
   1015 					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
   1016 		}
   1017 		/* The socket is now detached, no matter what
   1018 		 * the state of the SCTP association.
   1019 		 */
   1020 		SCTP_SB_CLEAR(so->so_snd);
   1021 		/* same for the rcv ones, they are only
   1022 		 * here for the accounting/select.
   1023 		 */
   1024 		SCTP_SB_CLEAR(so->so_rcv);
   1025 #if !defined(__APPLE__)
   1026 		/* Now disconnect */
   1027 		so->so_pcb = NULL;
   1028 #endif
   1029 	} else {
   1030 		flags = inp->sctp_flags;
   1031 		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
   1032 			goto sctp_must_try_again;
   1033 		}
   1034 	}
   1035 #if defined(__FreeBSD__) && __FreeBSD_version > 690000
   1036 	return;
   1037 #else
   1038 	return (0);
   1039 #endif
   1040 }
   1041 #endif
   1042 
   1043 #if defined(__Userspace__)
   1044 /* __Userspace__ is not calling sctp_sendm */
   1045 #endif
   1046 #if !(defined(__Panda__) || defined(__Windows__))
   1047 int
   1048 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
   1049 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
   1050     struct mbuf *control, struct thread *p);
   1051 
   1052 #else
   1053 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
   1054     struct mbuf *control, struct proc *p);
   1055 
   1056 #endif
   1057 
   1058 int
   1059 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
   1060 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
   1061     struct mbuf *control, struct thread *p)
   1062 {
   1063 #else
   1064 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
   1065     struct mbuf *control, struct proc *p)
   1066 {
   1067 #endif
   1068 	struct sctp_inpcb *inp;
   1069 	int error;
   1070 
   1071 	inp = (struct sctp_inpcb *)so->so_pcb;
   1072 	if (inp == NULL) {
   1073 		if (control) {
   1074 			sctp_m_freem(control);
   1075 			control = NULL;
   1076 		}
   1077 		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   1078 		sctp_m_freem(m);
   1079 		return (EINVAL);
   1080 	}
   1081 	/* Got to have an to address if we are NOT a connected socket */
   1082 	if ((addr == NULL) &&
   1083 	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) ||
   1084 	    (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))) {
   1085 		goto connected_type;
   1086 	} else if (addr == NULL) {
   1087 		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
   1088 		error = EDESTADDRREQ;
   1089 		sctp_m_freem(m);
   1090 		if (control) {
   1091 			sctp_m_freem(control);
   1092 			control = NULL;
   1093 		}
   1094 		return (error);
   1095 	}
   1096 #ifdef INET6
   1097 	if (addr->sa_family != AF_INET) {
   1098 		/* must be a v4 address! */
   1099 		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
   1100 		sctp_m_freem(m);
   1101 		if (control) {
   1102 			sctp_m_freem(control);
   1103 			control = NULL;
   1104 		}
   1105 		error = EDESTADDRREQ;
   1106 		return (error);
   1107 	}
   1108 #endif				/* INET6 */
   1109 connected_type:
   1110 	/* now what about control */
   1111 	if (control) {
   1112 		if (inp->control) {
   1113 			SCTP_PRINTF("huh? control set?\n");
   1114 			sctp_m_freem(inp->control);
   1115 			inp->control = NULL;
   1116 		}
   1117 		inp->control = control;
   1118 	}
   1119 	/* Place the data */
   1120 	if (inp->pkt) {
   1121 		SCTP_BUF_NEXT(inp->pkt_last) = m;
   1122 		inp->pkt_last = m;
   1123 	} else {
   1124 		inp->pkt_last = inp->pkt = m;
   1125 	}
   1126 	if (
   1127 #if defined(__FreeBSD__) || defined(__APPLE__)
   1128 	/* FreeBSD uses a flag passed */
   1129 	    ((flags & PRUS_MORETOCOME) == 0)
   1130 #else
   1131 	    1			/* Open BSD does not have any "more to come"
   1132 				 * indication */
   1133 #endif
   1134 	    ) {
   1135 		/*
   1136 		 * note with the current version this code will only be used
   1137 		 * by OpenBSD-- NetBSD, FreeBSD, and MacOS have methods for
   1138 		 * re-defining sosend to use the sctp_sosend. One can
   1139 		 * optionally switch back to this code (by changing back the
   1140 		 * definitions) but this is not advisable. This code is used
   1141 		 * by FreeBSD when sending a file with sendfile() though.
   1142 		 */
   1143 		int ret;
   1144 
   1145 		ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
   1146 		inp->pkt = NULL;
   1147 		inp->control = NULL;
   1148 		return (ret);
   1149 	} else {
   1150 		return (0);
   1151 	}
   1152 }
   1153 #endif
   1154 
   1155 int
   1156 sctp_disconnect(struct socket *so)
   1157 {
   1158 	struct sctp_inpcb *inp;
   1159 
   1160 	inp = (struct sctp_inpcb *)so->so_pcb;
   1161 	if (inp == NULL) {
   1162 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
   1163 		return (ENOTCONN);
   1164 	}
   1165 	SCTP_INP_RLOCK(inp);
   1166 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   1167 	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
   1168 		if (LIST_EMPTY(&inp->sctp_asoc_list)) {
   1169 			/* No connection */
   1170 			SCTP_INP_RUNLOCK(inp);
   1171 			return (0);
   1172 		} else {
   1173 			struct sctp_association *asoc;
   1174 			struct sctp_tcb *stcb;
   1175 
   1176 			stcb = LIST_FIRST(&inp->sctp_asoc_list);
   1177 			if (stcb == NULL) {
   1178 				SCTP_INP_RUNLOCK(inp);
   1179 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   1180 				return (EINVAL);
   1181 			}
   1182 			SCTP_TCB_LOCK(stcb);
   1183 			asoc = &stcb->asoc;
   1184 			if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
   1185 				/* We are about to be freed, out of here */
   1186 				SCTP_TCB_UNLOCK(stcb);
   1187 				SCTP_INP_RUNLOCK(inp);
   1188 				return (0);
   1189 			}
   1190 #if defined(__Userspace__)
   1191 			if (((so->so_options & SCTP_SO_LINGER) &&
   1192 			     (so->so_linger == 0)) ||
   1193 			    (so->so_rcv.sb_cc > 0)) {
   1194 #else
   1195 			if (((so->so_options & SO_LINGER) &&
   1196 			     (so->so_linger == 0)) ||
   1197 			    (so->so_rcv.sb_cc > 0)) {
   1198 #endif
   1199 				if (SCTP_GET_STATE(asoc) !=
   1200 				    SCTP_STATE_COOKIE_WAIT) {
   1201 					/* Left with Data unread */
   1202 					struct mbuf *err;
   1203 
   1204 					err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA);
   1205 					if (err) {
   1206 						/*
   1207 						 * Fill in the user
   1208 						 * initiated abort
   1209 						 */
   1210 						struct sctp_paramhdr *ph;
   1211 
   1212 						ph = mtod(err, struct sctp_paramhdr *);
   1213 						SCTP_BUF_LEN(err) = sizeof(struct sctp_paramhdr);
   1214 						ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
   1215 						ph->param_length = htons(SCTP_BUF_LEN(err));
   1216 					}
   1217 					sctp_send_abort_tcb(stcb, err, SCTP_SO_LOCKED);
   1218 					SCTP_STAT_INCR_COUNTER32(sctps_aborted);
   1219 				}
   1220 				SCTP_INP_RUNLOCK(inp);
   1221 				if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
   1222 				    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
   1223 					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
   1224 				}
   1225 				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_3);
   1226 				/* No unlock tcb assoc is gone */
   1227 				return (0);
   1228 			}
   1229 			if (TAILQ_EMPTY(&asoc->send_queue) &&
   1230 			    TAILQ_EMPTY(&asoc->sent_queue) &&
   1231 			    (asoc->stream_queue_cnt == 0)) {
   1232 				/* there is nothing queued to send, so done */
   1233 				if (asoc->locked_on_sending) {
   1234 					goto abort_anyway;
   1235 				}
   1236 				if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
   1237 				    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
   1238 					/* only send SHUTDOWN 1st time thru */
   1239 					struct sctp_nets *netp;
   1240 
   1241 					if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
   1242 					    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
   1243 						SCTP_STAT_DECR_GAUGE32(sctps_currestab);
   1244 					}
   1245 					SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
   1246 					SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
   1247 					sctp_stop_timers_for_shutdown(stcb);
   1248 					if (stcb->asoc.alternate) {
   1249 						netp = stcb->asoc.alternate;
   1250 					} else {
   1251 						netp = stcb->asoc.primary_destination;
   1252 					}
   1253 					sctp_send_shutdown(stcb,netp);
   1254 					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
   1255 							 stcb->sctp_ep, stcb, netp);
   1256 					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
   1257 							 stcb->sctp_ep, stcb, netp);
   1258 					sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
   1259 				}
   1260 			} else {
   1261 				/*
   1262 				 * we still got (or just got) data to send,
   1263 				 * so set SHUTDOWN_PENDING
   1264 				 */
   1265 				/*
   1266 				 * XXX sockets draft says that SCTP_EOF
   1267 				 * should be sent with no data. currently,
   1268 				 * we will allow user data to be sent first
   1269 				 * and move to SHUTDOWN-PENDING
   1270 				 */
   1271 				struct sctp_nets *netp;
   1272 				if (stcb->asoc.alternate) {
   1273 					netp = stcb->asoc.alternate;
   1274 				} else {
   1275 					netp = stcb->asoc.primary_destination;
   1276 				}
   1277 
   1278 				asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
   1279 				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
   1280 						 netp);
   1281 				if (asoc->locked_on_sending) {
   1282 					/* Locked to send out the data */
   1283 					struct sctp_stream_queue_pending *sp;
   1284 					sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
   1285 					if (sp == NULL) {
   1286 						SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
   1287 							    asoc->locked_on_sending->stream_no);
   1288 					} else {
   1289 						if ((sp->length == 0) && (sp->msg_is_complete == 0))
   1290 							asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
   1291 					}
   1292 				}
   1293 				if (TAILQ_EMPTY(&asoc->send_queue) &&
   1294 				    TAILQ_EMPTY(&asoc->sent_queue) &&
   1295 				    (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
   1296 					struct mbuf *op_err;
   1297 				abort_anyway:
   1298 					op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
   1299 					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ+SCTP_LOC_4;
   1300 					sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
   1301 					SCTP_STAT_INCR_COUNTER32(sctps_aborted);
   1302 					if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
   1303 					    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
   1304 						SCTP_STAT_DECR_GAUGE32(sctps_currestab);
   1305 					}
   1306 					SCTP_INP_RUNLOCK(inp);
   1307 					(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_5);
   1308 					return (0);
   1309 				} else {
   1310 					sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
   1311 				}
   1312 			}
   1313 			soisdisconnecting(so);
   1314 			SCTP_TCB_UNLOCK(stcb);
   1315 			SCTP_INP_RUNLOCK(inp);
   1316 			return (0);
   1317 		}
   1318 		/* not reached */
   1319 	} else {
   1320 		/* UDP model does not support this */
   1321 		SCTP_INP_RUNLOCK(inp);
   1322 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   1323 		return (EOPNOTSUPP);
   1324 	}
   1325 }
   1326 
   1327 #if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
   1328 int
   1329 sctp_flush(struct socket *so, int how)
   1330 {
   1331         /*
   1332 	 * We will just clear out the values and let
   1333 	 * subsequent close clear out the data, if any.
   1334 	 * Note if the user did a shutdown(SHUT_RD) they
   1335 	 * will not be able to read the data, the socket
   1336 	 * will block that from happening.
   1337 	 */
   1338 	struct sctp_inpcb *inp;
   1339 
   1340 	inp = (struct sctp_inpcb *)so->so_pcb;
   1341 	if (inp == NULL) {
   1342 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   1343 		return (EINVAL);
   1344 	}
   1345 	SCTP_INP_RLOCK(inp);
   1346 	/* For the 1 to many model this does nothing */
   1347 	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
   1348 		SCTP_INP_RUNLOCK(inp);
   1349 		return (0);
   1350 	}
   1351 	SCTP_INP_RUNLOCK(inp);
   1352         if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) {
   1353 		/* First make sure the sb will be happy, we don't
   1354 		 * use these except maybe the count
   1355 		 */
   1356 		SCTP_INP_WLOCK(inp);
   1357 		SCTP_INP_READ_LOCK(inp);
   1358 		inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ;
   1359 		SCTP_INP_READ_UNLOCK(inp);
   1360 		SCTP_INP_WUNLOCK(inp);
   1361 		so->so_rcv.sb_cc = 0;
   1362 		so->so_rcv.sb_mbcnt = 0;
   1363 		so->so_rcv.sb_mb = NULL;
   1364 	}
   1365         if ((how == PRU_FLUSH_WR) || (how == PRU_FLUSH_RDWR)) {
   1366 		/* First make sure the sb will be happy, we don't
   1367 		 * use these except maybe the count
   1368 		 */
   1369 		so->so_snd.sb_cc = 0;
   1370 		so->so_snd.sb_mbcnt = 0;
   1371 		so->so_snd.sb_mb = NULL;
   1372 
   1373 	}
   1374 	return (0);
   1375 }
   1376 #endif
   1377 
   1378 int
   1379 sctp_shutdown(struct socket *so)
   1380 {
   1381 	struct sctp_inpcb *inp;
   1382 
   1383 	inp = (struct sctp_inpcb *)so->so_pcb;
   1384 	if (inp == NULL) {
   1385 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   1386 		return (EINVAL);
   1387 	}
   1388 	SCTP_INP_RLOCK(inp);
   1389 	/* For UDP model this is a invalid call */
   1390 	if (!((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   1391 	      (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
   1392 		/* Restore the flags that the soshutdown took away. */
   1393 #if (defined(__FreeBSD__) && __FreeBSD_version >= 502115) || defined(__Windows__)
   1394 		SOCKBUF_LOCK(&so->so_rcv);
   1395 		so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
   1396 		SOCKBUF_UNLOCK(&so->so_rcv);
   1397 #else
   1398 		so->so_state &= ~SS_CANTRCVMORE;
   1399 #endif
   1400 		/* This proc will wakeup for read and do nothing (I hope) */
   1401 		SCTP_INP_RUNLOCK(inp);
   1402 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   1403 		return (EOPNOTSUPP);
   1404 	}
   1405 	/*
   1406 	 * Ok if we reach here its the TCP model and it is either a SHUT_WR
   1407 	 * or SHUT_RDWR. This means we put the shutdown flag against it.
   1408 	 */
   1409 	{
   1410 		struct sctp_tcb *stcb;
   1411 		struct sctp_association *asoc;
   1412 
   1413 		if ((so->so_state &
   1414 		     (SS_ISCONNECTED|SS_ISCONNECTING|SS_ISDISCONNECTING)) == 0) {
   1415 			SCTP_INP_RUNLOCK(inp);
   1416 			return (ENOTCONN);
   1417 		}
   1418 		socantsendmore(so);
   1419 
   1420 		stcb = LIST_FIRST(&inp->sctp_asoc_list);
   1421 		if (stcb == NULL) {
   1422 			/*
   1423 			 * Ok we hit the case that the shutdown call was
   1424 			 * made after an abort or something. Nothing to do
   1425 			 * now.
   1426 			 */
   1427 			SCTP_INP_RUNLOCK(inp);
   1428 			return (0);
   1429 		}
   1430 		SCTP_TCB_LOCK(stcb);
   1431 		asoc = &stcb->asoc;
   1432 		if (TAILQ_EMPTY(&asoc->send_queue) &&
   1433 		    TAILQ_EMPTY(&asoc->sent_queue) &&
   1434 		    (asoc->stream_queue_cnt == 0)) {
   1435 			if (asoc->locked_on_sending) {
   1436 				goto abort_anyway;
   1437 			}
   1438 			/* there is nothing queued to send, so I'm done... */
   1439 			if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
   1440 				/* only send SHUTDOWN the first time through */
   1441 				struct sctp_nets *netp;
   1442 
   1443 				if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
   1444 				    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
   1445 					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
   1446 				}
   1447 				SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
   1448 				SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
   1449 				sctp_stop_timers_for_shutdown(stcb);
   1450 				if (stcb->asoc.alternate) {
   1451 					netp = stcb->asoc.alternate;
   1452 				} else {
   1453 					netp = stcb->asoc.primary_destination;
   1454 				}
   1455 				sctp_send_shutdown(stcb, netp);
   1456 				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
   1457 						 stcb->sctp_ep, stcb, netp);
   1458 				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
   1459 						 stcb->sctp_ep, stcb, netp);
   1460 				sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
   1461 			}
   1462 		} else {
   1463 			/*
   1464 			 * we still got (or just got) data to send, so set
   1465 			 * SHUTDOWN_PENDING
   1466 			 */
   1467 			struct sctp_nets *netp;
   1468 			if (stcb->asoc.alternate) {
   1469 				netp = stcb->asoc.alternate;
   1470 			} else {
   1471 				netp = stcb->asoc.primary_destination;
   1472 			}
   1473 
   1474 			asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
   1475 			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
   1476 					 netp);
   1477 
   1478 			if (asoc->locked_on_sending) {
   1479 				/* Locked to send out the data */
   1480 				struct sctp_stream_queue_pending *sp;
   1481 				sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
   1482 				if (sp == NULL) {
   1483 					SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
   1484 						    asoc->locked_on_sending->stream_no);
   1485 				} else {
   1486 					if ((sp->length == 0)  && (sp-> msg_is_complete == 0)) {
   1487 						asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
   1488 					}
   1489 				}
   1490 			}
   1491 			if (TAILQ_EMPTY(&asoc->send_queue) &&
   1492 			    TAILQ_EMPTY(&asoc->sent_queue) &&
   1493 			    (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
   1494 				struct mbuf *op_err;
   1495 			abort_anyway:
   1496 				op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
   1497 				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ+SCTP_LOC_6;
   1498 				sctp_abort_an_association(stcb->sctp_ep, stcb,
   1499 							  op_err, SCTP_SO_LOCKED);
   1500 				goto skip_unlock;
   1501 			} else {
   1502 				sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
   1503 			}
   1504 		}
   1505 		SCTP_TCB_UNLOCK(stcb);
   1506 	}
   1507  skip_unlock:
   1508 	SCTP_INP_RUNLOCK(inp);
   1509 	return (0);
   1510 }
   1511 
   1512 /*
   1513  * copies a "user" presentable address and removes embedded scope, etc.
   1514  * returns 0 on success, 1 on error
   1515  */
   1516 static uint32_t
   1517 sctp_fill_user_address(struct sockaddr_storage *ss, struct sockaddr *sa)
   1518 {
   1519 #ifdef INET6
   1520 #if defined(SCTP_EMBEDDED_V6_SCOPE)
   1521 	struct sockaddr_in6 lsa6;
   1522 
   1523 	sa = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)sa,
   1524 	    &lsa6);
   1525 #endif
   1526 #endif
   1527 #ifdef HAVE_SA_LEN
   1528 	memcpy(ss, sa, sa->sa_len);
   1529 #else
   1530 	switch (sa->sa_family) {
   1531 #ifdef INET
   1532 	case AF_INET:
   1533 		memcpy(ss, sa, sizeof(struct sockaddr_in));
   1534 		break;
   1535 #endif
   1536 #ifdef INET6
   1537 	case AF_INET6:
   1538 		memcpy(ss, sa, sizeof(struct sockaddr_in6));
   1539 		break;
   1540 #endif
   1541 #if defined(__Userspace__)
   1542 	case AF_CONN:
   1543 		memcpy(ss, sa, sizeof(struct sockaddr_conn));
   1544 		break;
   1545 #endif
   1546 	default:
   1547 		/* TSNH */
   1548 		break;
   1549 	}
   1550 #endif
   1551 	return (0);
   1552 }
   1553 
   1554 
   1555 
   1556 /*
   1557  * NOTE: assumes addr lock is held
   1558  */
   1559 static size_t
   1560 sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
   1561 			   struct sctp_tcb *stcb,
   1562 			   size_t limit,
   1563 			   struct sockaddr_storage *sas,
   1564 			   uint32_t vrf_id)
   1565 {
   1566 	struct sctp_ifn *sctp_ifn;
   1567 	struct sctp_ifa *sctp_ifa;
   1568 	size_t actual;
   1569 	int loopback_scope;
   1570 #if defined(INET)
   1571 	int ipv4_local_scope, ipv4_addr_legal;
   1572 #endif
   1573 #if defined(INET6)
   1574 	int local_scope, site_scope, ipv6_addr_legal;
   1575 #endif
   1576 #if defined(__Userspace__)
   1577 	int conn_addr_legal;
   1578 #endif
   1579 	struct sctp_vrf *vrf;
   1580 
   1581 	actual = 0;
   1582 	if (limit <= 0)
   1583 		return (actual);
   1584 
   1585 	if (stcb) {
   1586 		/* Turn on all the appropriate scope */
   1587 		loopback_scope = stcb->asoc.scope.loopback_scope;
   1588 #if defined(INET)
   1589 		ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
   1590 		ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
   1591 #endif
   1592 #if defined(INET6)
   1593 		local_scope = stcb->asoc.scope.local_scope;
   1594 		site_scope = stcb->asoc.scope.site_scope;
   1595 		ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
   1596 #endif
   1597 #if defined(__Userspace__)
   1598 		conn_addr_legal = stcb->asoc.scope.conn_addr_legal;
   1599 #endif
   1600 	} else {
   1601 		/* Use generic values for endpoints. */
   1602 		loopback_scope = 1;
   1603 #if defined(INET)
   1604 		ipv4_local_scope = 1;
   1605 #endif
   1606 #if defined(INET6)
   1607 		local_scope = 1;
   1608 		site_scope = 1;
   1609 #endif
   1610 		if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   1611 #if defined(INET6)
   1612 			ipv6_addr_legal = 1;
   1613 #endif
   1614 #if defined(INET)
   1615 			if (SCTP_IPV6_V6ONLY(inp)) {
   1616 				ipv4_addr_legal = 0;
   1617 			} else {
   1618 				ipv4_addr_legal = 1;
   1619 			}
   1620 #endif
   1621 #if defined(__Userspace__)
   1622 			conn_addr_legal = 0;
   1623 #endif
   1624 		} else {
   1625 #if defined(INET6)
   1626 			ipv6_addr_legal = 0;
   1627 #endif
   1628 #if defined(__Userspace__)
   1629 			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
   1630 				conn_addr_legal = 1;
   1631 #if defined(INET)
   1632 				ipv4_addr_legal = 0;
   1633 #endif
   1634 			} else {
   1635 				conn_addr_legal = 0;
   1636 #if defined(INET)
   1637 				ipv4_addr_legal = 1;
   1638 #endif
   1639 			}
   1640 #else
   1641 #if defined(INET)
   1642 			ipv4_addr_legal = 1;
   1643 #endif
   1644 #endif
   1645 		}
   1646 	}
   1647 	vrf = sctp_find_vrf(vrf_id);
   1648 	if (vrf == NULL) {
   1649 		return (0);
   1650 	}
   1651 	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
   1652 		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
   1653 			if ((loopback_scope == 0) &&
   1654 			    SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
   1655 				/* Skip loopback if loopback_scope not set */
   1656 				continue;
   1657 			}
   1658 			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
   1659 				if (stcb) {
   1660 					/*
   1661 					 * For the BOUND-ALL case, the list
   1662 					 * associated with a TCB is Always
   1663 					 * considered a reverse list.. i.e.
   1664 					 * it lists addresses that are NOT
   1665 					 * part of the association. If this
   1666 					 * is one of those we must skip it.
   1667 					 */
   1668 					if (sctp_is_addr_restricted(stcb,
   1669 								    sctp_ifa)) {
   1670 						continue;
   1671 					}
   1672 				}
   1673 				switch (sctp_ifa->address.sa.sa_family) {
   1674 #ifdef INET
   1675 				case AF_INET:
   1676 					if (ipv4_addr_legal) {
   1677 						struct sockaddr_in *sin;
   1678 
   1679 						sin = &sctp_ifa->address.sin;
   1680 						if (sin->sin_addr.s_addr == 0) {
   1681 							/*
   1682 							 * we skip unspecifed
   1683 							 * addresses
   1684 							 */
   1685 							continue;
   1686 						}
   1687 #if defined(__FreeBSD__)
   1688 						if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
   1689 						                     &sin->sin_addr) != 0) {
   1690 							continue;
   1691 						}
   1692 #endif
   1693 						if ((ipv4_local_scope == 0) &&
   1694 						    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
   1695 							continue;
   1696 						}
   1697 #ifdef INET6
   1698 						if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
   1699 							in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas);
   1700 							((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
   1701 							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6));
   1702 							actual += sizeof(struct sockaddr_in6);
   1703 						} else {
   1704 #endif
   1705 							memcpy(sas, sin, sizeof(*sin));
   1706 							((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
   1707 							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin));
   1708 							actual += sizeof(*sin);
   1709 #ifdef INET6
   1710 						}
   1711 #endif
   1712 						if (actual >= limit) {
   1713 							return (actual);
   1714 						}
   1715 					} else {
   1716 						continue;
   1717 					}
   1718 					break;
   1719 #endif
   1720 #ifdef INET6
   1721 				case AF_INET6:
   1722 					if (ipv6_addr_legal) {
   1723 						struct sockaddr_in6 *sin6;
   1724 
   1725 #if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME)
   1726 						struct sockaddr_in6 lsa6;
   1727 #endif
   1728 						sin6 = &sctp_ifa->address.sin6;
   1729 						if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   1730 							/*
   1731 							 * we skip unspecifed
   1732 							 * addresses
   1733 							 */
   1734 							continue;
   1735 						}
   1736 #if defined(__FreeBSD__)
   1737 						if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
   1738 						                     &sin6->sin6_addr) != 0) {
   1739 							continue;
   1740 						}
   1741 #endif
   1742 						if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
   1743 							if (local_scope == 0)
   1744 								continue;
   1745 #if defined(SCTP_EMBEDDED_V6_SCOPE)
   1746 							if (sin6->sin6_scope_id == 0) {
   1747 #ifdef SCTP_KAME
   1748 								if (sa6_recoverscope(sin6) != 0)
   1749 									/*
   1750 									 * bad link
   1751 									 * local
   1752 									 * address
   1753 									 */
   1754 									continue;
   1755 #else
   1756 								lsa6 = *sin6;
   1757 								if (in6_recoverscope(&lsa6,
   1758 										     &lsa6.sin6_addr,
   1759 										     NULL))
   1760 									/*
   1761 									 * bad link
   1762 									 * local
   1763 									 * address
   1764 									 */
   1765 								continue;
   1766 								sin6 = &lsa6;
   1767 #endif				/* SCTP_KAME */
   1768 							}
   1769 #endif /* SCTP_EMBEDDED_V6_SCOPE */
   1770 						}
   1771 						if ((site_scope == 0) &&
   1772 						    (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
   1773 							continue;
   1774 						}
   1775 						memcpy(sas, sin6, sizeof(*sin6));
   1776 						((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
   1777 						sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6));
   1778 						actual += sizeof(*sin6);
   1779 						if (actual >= limit) {
   1780 							return (actual);
   1781 						}
   1782 					} else {
   1783 						continue;
   1784 					}
   1785 					break;
   1786 #endif
   1787 #if defined(__Userspace__)
   1788 				case AF_CONN:
   1789 					if (conn_addr_legal) {
   1790 						memcpy(sas, &sctp_ifa->address.sconn, sizeof(struct sockaddr_conn));
   1791 						((struct sockaddr_conn *)sas)->sconn_port = inp->sctp_lport;
   1792 						sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_conn));
   1793 						actual += sizeof(struct sockaddr_conn);
   1794 						if (actual >= limit) {
   1795 							return (actual);
   1796 						}
   1797 					} else {
   1798 						continue;
   1799 					}
   1800 #endif
   1801 				default:
   1802 					/* TSNH */
   1803 					break;
   1804 				}
   1805 			}
   1806 		}
   1807 	} else {
   1808 		struct sctp_laddr *laddr;
   1809 #ifndef HAVE_SA_LEN
   1810 		uint32_t sa_len = 0;
   1811 #endif
   1812 
   1813 		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
   1814 			if (stcb) {
   1815 				if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
   1816 					continue;
   1817 				}
   1818 			}
   1819 			if (sctp_fill_user_address(sas, &laddr->ifa->address.sa))
   1820 				continue;
   1821 			switch (laddr->ifa->address.sa.sa_family) {
   1822 #ifdef INET
   1823 			case AF_INET:
   1824 				((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
   1825 				break;
   1826 #endif
   1827 #ifdef INET6
   1828 			case AF_INET6:
   1829 				((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
   1830 				break;
   1831 #endif
   1832 #if defined(__Userspace__)
   1833 			case AF_CONN:
   1834 				((struct sockaddr_conn *)sas)->sconn_port = inp->sctp_lport;
   1835 				break;
   1836 #endif
   1837 			default:
   1838 				/* TSNH */
   1839 				break;
   1840 			}
   1841 #ifdef HAVE_SA_LEN
   1842 			sas = (struct sockaddr_storage *)((caddr_t)sas +
   1843 							  laddr->ifa->address.sa.sa_len);
   1844 			actual += laddr->ifa->address.sa.sa_len;
   1845 #else
   1846 			switch (laddr->ifa->address.sa.sa_family) {
   1847 #ifdef INET
   1848 			case AF_INET:
   1849 				sa_len = sizeof(struct sockaddr_in);
   1850 				break;
   1851 #endif
   1852 #ifdef INET6
   1853 			case AF_INET6:
   1854 				sa_len = sizeof(struct sockaddr_in6);
   1855 				break;
   1856 #endif
   1857 #if defined(__Userspace__)
   1858 			case AF_CONN:
   1859 				sa_len = sizeof(struct sockaddr_conn);
   1860 				break;
   1861 #endif
   1862 			default:
   1863 				/* TSNH */
   1864 				break;
   1865 			}
   1866 			sas = (struct sockaddr_storage *)((caddr_t)sas + sa_len);
   1867 			actual += sa_len;
   1868 #endif
   1869 			if (actual >= limit) {
   1870 				return (actual);
   1871 			}
   1872 		}
   1873 	}
   1874 	return (actual);
   1875 }
   1876 
   1877 static size_t
   1878 sctp_fill_up_addresses(struct sctp_inpcb *inp,
   1879                        struct sctp_tcb *stcb,
   1880                        size_t limit,
   1881                        struct sockaddr_storage *sas)
   1882 {
   1883 	size_t size = 0;
   1884 #ifdef SCTP_MVRF
   1885 	uint32_t id;
   1886 #endif
   1887 
   1888 	SCTP_IPI_ADDR_RLOCK();
   1889 #ifdef SCTP_MVRF
   1890 /*
   1891  * FIX ME: ?? this WILL report duplicate addresses if they appear
   1892  * in more than one VRF.
   1893  */
   1894 	/* fill up addresses for all VRFs on the endpoint */
   1895 	for (id = 0; (id < inp->num_vrfs) && (size < limit); id++) {
   1896 		size += sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
   1897 						   inp->m_vrf_ids[id]);
   1898 		sas = (struct sockaddr_storage *)((caddr_t)sas + size);
   1899 	}
   1900 #else
   1901 	/* fill up addresses for the endpoint's default vrf */
   1902 	size = sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
   1903 					  inp->def_vrf_id);
   1904 #endif
   1905 	SCTP_IPI_ADDR_RUNLOCK();
   1906 	return (size);
   1907 }
   1908 
   1909 /*
   1910  * NOTE: assumes addr lock is held
   1911  */
   1912 static int
   1913 sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
   1914 {
   1915 	int cnt = 0;
   1916 	struct sctp_vrf *vrf = NULL;
   1917 
   1918 	/*
   1919 	 * In both sub-set bound an bound_all cases we return the MAXIMUM
   1920 	 * number of addresses that you COULD get. In reality the sub-set
   1921 	 * bound may have an exclusion list for a given TCB OR in the
   1922 	 * bound-all case a TCB may NOT include the loopback or other
   1923 	 * addresses as well.
   1924 	 */
   1925 	vrf = sctp_find_vrf(vrf_id);
   1926 	if (vrf == NULL) {
   1927 		return (0);
   1928 	}
   1929 	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
   1930 		struct sctp_ifn *sctp_ifn;
   1931 		struct sctp_ifa *sctp_ifa;
   1932 
   1933 		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
   1934 			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
   1935 				/* Count them if they are the right type */
   1936 				switch (sctp_ifa->address.sa.sa_family) {
   1937 #ifdef INET
   1938 				case AF_INET:
   1939 					if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
   1940 						cnt += sizeof(struct sockaddr_in6);
   1941 					else
   1942 						cnt += sizeof(struct sockaddr_in);
   1943 					break;
   1944 #endif
   1945 #ifdef INET6
   1946 				case AF_INET6:
   1947 					cnt += sizeof(struct sockaddr_in6);
   1948 					break;
   1949 #endif
   1950 #if defined(__Userspace__)
   1951 				case AF_CONN:
   1952 					cnt += sizeof(struct sockaddr_conn);
   1953 					break;
   1954 #endif
   1955 				default:
   1956 					break;
   1957 				}
   1958 			}
   1959 		}
   1960 	} else {
   1961 		struct sctp_laddr *laddr;
   1962 
   1963 		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
   1964 			switch (laddr->ifa->address.sa.sa_family) {
   1965 #ifdef INET
   1966 			case AF_INET:
   1967 				if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
   1968 					cnt += sizeof(struct sockaddr_in6);
   1969 				else
   1970 					cnt += sizeof(struct sockaddr_in);
   1971 				break;
   1972 #endif
   1973 #ifdef INET6
   1974 			case AF_INET6:
   1975 				cnt += sizeof(struct sockaddr_in6);
   1976 				break;
   1977 #endif
   1978 #if defined(__Userspace__)
   1979 			case AF_CONN:
   1980 				cnt += sizeof(struct sockaddr_conn);
   1981 				break;
   1982 #endif
   1983 			default:
   1984 				break;
   1985 			}
   1986 		}
   1987 	}
   1988 	return (cnt);
   1989 }
   1990 
   1991 static int
   1992 sctp_count_max_addresses(struct sctp_inpcb *inp)
   1993 {
   1994 	int cnt = 0;
   1995 #ifdef SCTP_MVRF
   1996 	int id;
   1997 #endif
   1998 
   1999 	SCTP_IPI_ADDR_RLOCK();
   2000 #ifdef SCTP_MVRF
   2001 /*
   2002  * FIX ME: ?? this WILL count duplicate addresses if they appear
   2003  * in more than one VRF.
   2004  */
   2005 	/* count addresses for all VRFs on the endpoint */
   2006 	for (id = 0; id < inp->num_vrfs; id++) {
   2007 		cnt += sctp_count_max_addresses_vrf(inp, inp->m_vrf_ids[id]);
   2008 	}
   2009 #else
   2010 	/* count addresses for the endpoint's default VRF */
   2011 	cnt = sctp_count_max_addresses_vrf(inp, inp->def_vrf_id);
   2012 #endif
   2013 	SCTP_IPI_ADDR_RUNLOCK();
   2014 	return (cnt);
   2015 }
   2016 
   2017 static int
   2018 sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
   2019 		  size_t optsize, void *p, int delay)
   2020 {
   2021 	int error = 0;
   2022 	int creat_lock_on = 0;
   2023 	struct sctp_tcb *stcb = NULL;
   2024 	struct sockaddr *sa;
   2025 	int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
   2026 	uint32_t vrf_id;
   2027 	int bad_addresses = 0;
   2028 	sctp_assoc_t *a_id;
   2029 
   2030 	SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
   2031 
   2032 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
   2033 	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
   2034 		/* We are already connected AND the TCP model */
   2035 		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
   2036 		return (EADDRINUSE);
   2037 	}
   2038 
   2039 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
   2040 	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
   2041 		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2042 		return (EINVAL);
   2043 	}
   2044 
   2045 	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
   2046 		SCTP_INP_RLOCK(inp);
   2047 		stcb = LIST_FIRST(&inp->sctp_asoc_list);
   2048 		SCTP_INP_RUNLOCK(inp);
   2049 	}
   2050 	if (stcb) {
   2051 		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   2052 		return (EALREADY);
   2053 	}
   2054 	SCTP_INP_INCR_REF(inp);
   2055 	SCTP_ASOC_CREATE_LOCK(inp);
   2056 	creat_lock_on = 1;
   2057 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
   2058 	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
   2059 		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
   2060 		error = EFAULT;
   2061 		goto out_now;
   2062 	}
   2063 	totaddrp = (int *)optval;
   2064 	totaddr = *totaddrp;
   2065 	sa = (struct sockaddr *)(totaddrp + 1);
   2066 	stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (optsize - sizeof(int)), &bad_addresses);
   2067 	if ((stcb != NULL) || bad_addresses) {
   2068 		/* Already have or am bring up an association */
   2069 		SCTP_ASOC_CREATE_UNLOCK(inp);
   2070 		creat_lock_on = 0;
   2071 		if (stcb)
   2072 			SCTP_TCB_UNLOCK(stcb);
   2073 		if (bad_addresses == 0) {
   2074 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   2075 			error = EALREADY;
   2076 		}
   2077 		goto out_now;
   2078 	}
   2079 #ifdef INET6
   2080 	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
   2081 	    (num_v6 > 0)) {
   2082 		error = EINVAL;
   2083 		goto out_now;
   2084 	}
   2085 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
   2086 	    (num_v4 > 0)) {
   2087 		struct in6pcb *inp6;
   2088 
   2089 		inp6 = (struct in6pcb *)inp;
   2090 		if (SCTP_IPV6_V6ONLY(inp6)) {
   2091 			/*
   2092 			 * if IPV6_V6ONLY flag, ignore connections destined
   2093 			 * to a v4 addr or v4-mapped addr
   2094 			 */
   2095 			SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2096 			error = EINVAL;
   2097 			goto out_now;
   2098 		}
   2099 	}
   2100 #endif				/* INET6 */
   2101 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
   2102 	    SCTP_PCB_FLAGS_UNBOUND) {
   2103 		/* Bind a ephemeral port */
   2104 		error = sctp_inpcb_bind(so, NULL, NULL, p);
   2105 		if (error) {
   2106 			goto out_now;
   2107 		}
   2108 	}
   2109 
   2110 	/* FIX ME: do we want to pass in a vrf on the connect call? */
   2111 	vrf_id = inp->def_vrf_id;
   2112 
   2113 
   2114 	/* We are GOOD to go */
   2115 	stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id,
   2116 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
   2117 			       (struct thread *)p
   2118 #elif defined(__Windows__)
   2119 			       (PKTHREAD)p
   2120 #else
   2121 			       (struct proc *)p
   2122 #endif
   2123 		);
   2124 	if (stcb == NULL) {
   2125 		/* Gak! no memory */
   2126 		goto out_now;
   2127 	}
   2128 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
   2129 		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
   2130 		/* Set the connected flag so we can queue data */
   2131 		soisconnecting(so);
   2132 	}
   2133 	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
   2134 	/* move to second address */
   2135 	switch (sa->sa_family) {
   2136 #ifdef INET
   2137 	case AF_INET:
   2138 		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
   2139 		break;
   2140 #endif
   2141 #ifdef INET6
   2142 	case AF_INET6:
   2143 		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
   2144 		break;
   2145 #endif
   2146 	default:
   2147 		break;
   2148 	}
   2149 
   2150 	error = 0;
   2151 	sctp_connectx_helper_add(stcb, sa, (totaddr-1), &error);
   2152 	/* Fill in the return id */
   2153 	if (error) {
   2154 		(void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_6);
   2155 		goto out_now;
   2156 	}
   2157 	a_id = (sctp_assoc_t *)optval;
   2158 	*a_id = sctp_get_associd(stcb);
   2159 
   2160 	/* initialize authentication parameters for the assoc */
   2161 	sctp_initialize_auth_params(inp, stcb);
   2162 
   2163 	if (delay) {
   2164 		/* doing delayed connection */
   2165 		stcb->asoc.delayed_connection = 1;
   2166 		sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
   2167 	} else {
   2168 		(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
   2169 		sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
   2170 	}
   2171 	SCTP_TCB_UNLOCK(stcb);
   2172 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
   2173 		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
   2174 		/* Set the connected flag so we can queue data */
   2175 		soisconnecting(so);
   2176 	}
   2177  out_now:
   2178 	if (creat_lock_on) {
   2179 		SCTP_ASOC_CREATE_UNLOCK(inp);
   2180 	}
   2181 	SCTP_INP_DECR_REF(inp);
   2182 	return (error);
   2183 }
   2184 
   2185 #define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
   2186 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
   2187 	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
   2188 		SCTP_INP_RLOCK(inp); \
   2189 		stcb = LIST_FIRST(&inp->sctp_asoc_list); \
   2190 		if (stcb) { \
   2191 			SCTP_TCB_LOCK(stcb); \
   2192                 } \
   2193 		SCTP_INP_RUNLOCK(inp); \
   2194 	} else if (assoc_id > SCTP_ALL_ASSOC) { \
   2195 		stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
   2196 		if (stcb == NULL) { \
   2197 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
   2198 			error = ENOENT; \
   2199 			break; \
   2200 		} \
   2201 	} else { \
   2202 		stcb = NULL; \
   2203         } \
   2204   }
   2205 
   2206 
   2207 #define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
   2208 	if (size < sizeof(type)) { \
   2209 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
   2210 		error = EINVAL; \
   2211 		break; \
   2212 	} else { \
   2213 		destp = (type *)srcp; \
   2214 	} \
   2215       }
   2216 
   2217 #if defined(__Panda__) || defined(__Userspace__)
   2218 int
   2219 #else
   2220 static int
   2221 #endif
   2222 sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
   2223 	    void *p) {
   2224 	struct sctp_inpcb *inp = NULL;
   2225 	int error, val = 0;
   2226 	struct sctp_tcb *stcb = NULL;
   2227 
   2228 	if (optval == NULL) {
   2229 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2230 		return (EINVAL);
   2231 	}
   2232 
   2233 	inp = (struct sctp_inpcb *)so->so_pcb;
   2234 	if (inp == NULL) {
   2235 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2236 		return EINVAL;
   2237 	}
   2238 	error = 0;
   2239 
   2240 	switch (optname) {
   2241 	case SCTP_NODELAY:
   2242 	case SCTP_AUTOCLOSE:
   2243 	case SCTP_EXPLICIT_EOR:
   2244 	case SCTP_AUTO_ASCONF:
   2245 	case SCTP_DISABLE_FRAGMENTS:
   2246 	case SCTP_I_WANT_MAPPED_V4_ADDR:
   2247 	case SCTP_USE_EXT_RCVINFO:
   2248 		SCTP_INP_RLOCK(inp);
   2249 		switch (optname) {
   2250 		case SCTP_DISABLE_FRAGMENTS:
   2251 			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
   2252 			break;
   2253 		case SCTP_I_WANT_MAPPED_V4_ADDR:
   2254 			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
   2255 			break;
   2256 		case SCTP_AUTO_ASCONF:
   2257 			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
   2258 				/* only valid for bound all sockets */
   2259 				val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
   2260 			} else {
   2261 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2262 				error = EINVAL;
   2263 				goto flags_out;
   2264 			}
   2265 			break;
   2266 		case SCTP_EXPLICIT_EOR:
   2267 			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
   2268 			break;
   2269 		case SCTP_NODELAY:
   2270 			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
   2271 			break;
   2272 		case SCTP_USE_EXT_RCVINFO:
   2273 			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
   2274 			break;
   2275 		case SCTP_AUTOCLOSE:
   2276 			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
   2277 				val = TICKS_TO_SEC(inp->sctp_ep.auto_close_time);
   2278 			else
   2279 				val = 0;
   2280 			break;
   2281 
   2282 		default:
   2283 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
   2284 			error = ENOPROTOOPT;
   2285 		} /* end switch (sopt->sopt_name) */
   2286 		if (*optsize < sizeof(val)) {
   2287 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2288 			error = EINVAL;
   2289 		}
   2290 	flags_out:
   2291 		SCTP_INP_RUNLOCK(inp);
   2292 		if (error == 0) {
   2293 			/* return the option value */
   2294 			*(int *)optval = val;
   2295 			*optsize = sizeof(val);
   2296 		}
   2297 		break;
   2298         case SCTP_GET_PACKET_LOG:
   2299 	{
   2300 #ifdef  SCTP_PACKET_LOGGING
   2301 		uint8_t *target;
   2302 		int ret;
   2303 
   2304 		SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize);
   2305 		ret = sctp_copy_out_packet_log(target , (int)*optsize);
   2306 		*optsize = ret;
   2307 #else
   2308 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   2309 		error = EOPNOTSUPP;
   2310 #endif
   2311 		break;
   2312 	}
   2313 	case SCTP_REUSE_PORT:
   2314 	{
   2315 		uint32_t *value;
   2316 
   2317 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
   2318 			/* Can't do this for a 1-m socket */
   2319 			error = EINVAL;
   2320 			break;
   2321 		}
   2322 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2323 		*value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
   2324 		*optsize = sizeof(uint32_t);
   2325 		break;
   2326 	}
   2327 	case SCTP_PARTIAL_DELIVERY_POINT:
   2328 	{
   2329 		uint32_t *value;
   2330 
   2331 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2332 		*value = inp->partial_delivery_point;
   2333 		*optsize = sizeof(uint32_t);
   2334 		break;
   2335 	}
   2336 	case SCTP_FRAGMENT_INTERLEAVE:
   2337 	{
   2338 		uint32_t *value;
   2339 
   2340 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2341 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) {
   2342 			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) {
   2343 				*value = SCTP_FRAG_LEVEL_2;
   2344 			} else {
   2345 				*value = SCTP_FRAG_LEVEL_1;
   2346 			}
   2347 		} else {
   2348 			*value = SCTP_FRAG_LEVEL_0;
   2349 		}
   2350 		*optsize = sizeof(uint32_t);
   2351 		break;
   2352 	}
   2353 	case SCTP_CMT_ON_OFF:
   2354 	{
   2355 		struct sctp_assoc_value *av;
   2356 
   2357 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2358 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2359 		if (stcb) {
   2360 			av->assoc_value = stcb->asoc.sctp_cmt_on_off;
   2361 			SCTP_TCB_UNLOCK(stcb);
   2362 		} else {
   2363 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2364 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2365 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   2366 				SCTP_INP_RLOCK(inp);
   2367 				av->assoc_value = inp->sctp_cmt_on_off;
   2368 				SCTP_INP_RUNLOCK(inp);
   2369 			} else {
   2370 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2371 				error = EINVAL;
   2372 			}
   2373 		}
   2374 		if (error == 0) {
   2375 			*optsize = sizeof(struct sctp_assoc_value);
   2376 		}
   2377 		break;
   2378 	}
   2379 	case SCTP_PLUGGABLE_CC:
   2380 	{
   2381 		struct sctp_assoc_value *av;
   2382 
   2383 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2384 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2385 		if (stcb) {
   2386 			av->assoc_value = stcb->asoc.congestion_control_module;
   2387 			SCTP_TCB_UNLOCK(stcb);
   2388 		} else {
   2389 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2390 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2391 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   2392 				SCTP_INP_RLOCK(inp);
   2393 				av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
   2394 				SCTP_INP_RUNLOCK(inp);
   2395 			} else {
   2396 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2397 				error = EINVAL;
   2398 			}
   2399 		}
   2400 		if (error == 0) {
   2401 			*optsize = sizeof(struct sctp_assoc_value);
   2402 		}
   2403 		break;
   2404 	}
   2405 	case SCTP_CC_OPTION:
   2406 	{
   2407 		struct sctp_cc_option *cc_opt;
   2408 
   2409 		SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
   2410 		SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
   2411 		if (stcb == NULL) {
   2412 			error = EINVAL;
   2413 		} else {
   2414 			if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
   2415 				error = ENOTSUP;
   2416 			} else {
   2417 				error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 0, cc_opt);
   2418 				*optsize = sizeof(struct sctp_cc_option);
   2419 			}
   2420 			SCTP_TCB_UNLOCK(stcb);
   2421 		}
   2422 		break;
   2423 	}
   2424 	case SCTP_PLUGGABLE_SS:
   2425 	{
   2426 		struct sctp_assoc_value *av;
   2427 
   2428 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2429 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2430 		if (stcb) {
   2431 			av->assoc_value = stcb->asoc.stream_scheduling_module;
   2432 			SCTP_TCB_UNLOCK(stcb);
   2433 		} else {
   2434 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2435 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2436 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   2437 				SCTP_INP_RLOCK(inp);
   2438 				av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
   2439 				SCTP_INP_RUNLOCK(inp);
   2440 			} else {
   2441 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2442 				error = EINVAL;
   2443 			}
   2444 		}
   2445 		if (error == 0) {
   2446 			*optsize = sizeof(struct sctp_assoc_value);
   2447 		}
   2448 		break;
   2449 	}
   2450 	case SCTP_SS_VALUE:
   2451 	{
   2452 		struct sctp_stream_value *av;
   2453 
   2454 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
   2455 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2456 		if (stcb) {
   2457 			if (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
   2458 			                                              &av->stream_value) < 0) {
   2459 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2460 				error = EINVAL;
   2461 			} else {
   2462 				*optsize = sizeof(struct sctp_stream_value);
   2463 			}
   2464 			SCTP_TCB_UNLOCK(stcb);
   2465 		} else {
   2466 			/* Can't get stream value without association */
   2467 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2468 			error = EINVAL;
   2469 		}
   2470 		break;
   2471 	}
   2472 	case SCTP_GET_ADDR_LEN:
   2473 	{
   2474 		struct sctp_assoc_value *av;
   2475 
   2476 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2477 		error = EINVAL;
   2478 #ifdef INET
   2479 		if (av->assoc_value == AF_INET) {
   2480 			av->assoc_value = sizeof(struct sockaddr_in);
   2481 			error = 0;
   2482 		}
   2483 #endif
   2484 #ifdef INET6
   2485 		if (av->assoc_value == AF_INET6) {
   2486 			av->assoc_value = sizeof(struct sockaddr_in6);
   2487 			error = 0;
   2488 		}
   2489 #endif
   2490 #if defined(__Userspace__)
   2491 		if (av->assoc_value == AF_CONN) {
   2492 			av->assoc_value = sizeof(struct sockaddr_conn);
   2493 			error = 0;
   2494 		}
   2495 #endif
   2496 		if (error) {
   2497 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   2498 		} else {
   2499 			*optsize = sizeof(struct sctp_assoc_value);
   2500 		}
   2501 		break;
   2502 	}
   2503 	case SCTP_GET_ASSOC_NUMBER:
   2504 	{
   2505 		uint32_t *value, cnt;
   2506 
   2507 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2508 		cnt = 0;
   2509 		SCTP_INP_RLOCK(inp);
   2510 		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   2511 			cnt++;
   2512 		}
   2513 		SCTP_INP_RUNLOCK(inp);
   2514 		*value = cnt;
   2515 		*optsize = sizeof(uint32_t);
   2516 		break;
   2517 	}
   2518 	case SCTP_GET_ASSOC_ID_LIST:
   2519 	{
   2520 		struct sctp_assoc_ids *ids;
   2521 		unsigned int at, limit;
   2522 
   2523 		SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
   2524 		at = 0;
   2525 		limit = (*optsize-sizeof(uint32_t))/ sizeof(sctp_assoc_t);
   2526 		SCTP_INP_RLOCK(inp);
   2527 		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   2528 			if (at < limit) {
   2529 				ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
   2530 			} else {
   2531 				error = EINVAL;
   2532 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   2533 				break;
   2534 			}
   2535 		}
   2536 		SCTP_INP_RUNLOCK(inp);
   2537 		if (error == 0) {
   2538 			ids->gaids_number_of_ids = at;
   2539 			*optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
   2540 		}
   2541 		break;
   2542 	}
   2543 	case SCTP_CONTEXT:
   2544 	{
   2545 		struct sctp_assoc_value *av;
   2546 
   2547 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2548 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2549 
   2550 		if (stcb) {
   2551 			av->assoc_value = stcb->asoc.context;
   2552 			SCTP_TCB_UNLOCK(stcb);
   2553 		} else {
   2554 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2555 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2556 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   2557 				SCTP_INP_RLOCK(inp);
   2558 				av->assoc_value = inp->sctp_context;
   2559 				SCTP_INP_RUNLOCK(inp);
   2560 			} else {
   2561 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2562 				error = EINVAL;
   2563 			}
   2564 		}
   2565 		if (error == 0) {
   2566 			*optsize = sizeof(struct sctp_assoc_value);
   2567 		}
   2568 		break;
   2569 	}
   2570 	case SCTP_VRF_ID:
   2571 	{
   2572 		uint32_t *default_vrfid;
   2573 
   2574 		SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
   2575 		*default_vrfid = inp->def_vrf_id;
   2576 		*optsize = sizeof(uint32_t);
   2577 		break;
   2578 	}
   2579 	case SCTP_GET_ASOC_VRF:
   2580 	{
   2581 		struct sctp_assoc_value *id;
   2582 
   2583 		SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
   2584 		SCTP_FIND_STCB(inp, stcb, id->assoc_id);
   2585 		if (stcb == NULL) {
   2586 			error = EINVAL;
   2587 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   2588 		} else {
   2589 			id->assoc_value = stcb->asoc.vrf_id;
   2590 			*optsize = sizeof(struct sctp_assoc_value);
   2591 		}
   2592 		break;
   2593 	}
   2594 	case SCTP_GET_VRF_IDS:
   2595 	{
   2596 #ifdef SCTP_MVRF
   2597 		int siz_needed;
   2598 		uint32_t *vrf_ids;
   2599 
   2600 		SCTP_CHECK_AND_CAST(vrf_ids, optval, uint32_t, *optsize);
   2601 		siz_needed = inp->num_vrfs * sizeof(uint32_t);
   2602 		if (*optsize < siz_needed) {
   2603 			error = EINVAL;
   2604 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   2605 		} else {
   2606 			memcpy(vrf_ids, inp->m_vrf_ids, siz_needed);
   2607 			*optsize = siz_needed;
   2608 		}
   2609 #else
   2610 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   2611 		error = EOPNOTSUPP;
   2612 #endif
   2613 		break;
   2614 	}
   2615 	case SCTP_GET_NONCE_VALUES:
   2616 	{
   2617 		struct sctp_get_nonce_values *gnv;
   2618 
   2619 		SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
   2620 		SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
   2621 
   2622 		if (stcb) {
   2623 			gnv->gn_peers_tag = stcb->asoc.peer_vtag;
   2624 			gnv->gn_local_tag = stcb->asoc.my_vtag;
   2625 			SCTP_TCB_UNLOCK(stcb);
   2626 			*optsize = sizeof(struct sctp_get_nonce_values);
   2627 		} else {
   2628 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
   2629 			error = ENOTCONN;
   2630 		}
   2631 		break;
   2632 	}
   2633 	case SCTP_DELAYED_SACK:
   2634 	{
   2635 		struct sctp_sack_info *sack;
   2636 
   2637 		SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, *optsize);
   2638 		SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
   2639 		if (stcb) {
   2640 			sack->sack_delay = stcb->asoc.delayed_ack;
   2641 			sack->sack_freq = stcb->asoc.sack_freq;
   2642 			SCTP_TCB_UNLOCK(stcb);
   2643 		} else {
   2644 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2645 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2646 			    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC)) {
   2647 				SCTP_INP_RLOCK(inp);
   2648 				sack->sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
   2649 				sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
   2650 				SCTP_INP_RUNLOCK(inp);
   2651 			} else {
   2652 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2653 				error = EINVAL;
   2654 			}
   2655 		}
   2656 		if (error == 0) {
   2657 			*optsize = sizeof(struct sctp_sack_info);
   2658 		}
   2659 		break;
   2660 	}
   2661 	case SCTP_GET_SNDBUF_USE:
   2662 	{
   2663 		struct sctp_sockstat *ss;
   2664 
   2665 		SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
   2666 		SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
   2667 
   2668 		if (stcb) {
   2669 			ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
   2670 			ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
   2671 						 stcb->asoc.size_on_all_streams);
   2672 			SCTP_TCB_UNLOCK(stcb);
   2673 			*optsize = sizeof(struct sctp_sockstat);
   2674 		} else {
   2675 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
   2676 			error = ENOTCONN;
   2677 		}
   2678 		break;
   2679 	}
   2680 	case SCTP_MAX_BURST:
   2681 	{
   2682 #if defined(__FreeBSD__) && __FreeBSD_version < 900000
   2683 		uint8_t *value;
   2684 
   2685 		SCTP_CHECK_AND_CAST(value, optval, uint8_t, *optsize);
   2686 
   2687 		SCTP_INP_RLOCK(inp);
   2688 		if (inp->sctp_ep.max_burst < 256) {
   2689 			*value = inp->sctp_ep.max_burst;
   2690 		} else {
   2691 			*value = 255;
   2692 		}
   2693 		SCTP_INP_RUNLOCK(inp);
   2694 		*optsize = sizeof(uint8_t);
   2695 #else
   2696 		struct sctp_assoc_value *av;
   2697 
   2698 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2699 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2700 
   2701 		if (stcb) {
   2702 			av->assoc_value = stcb->asoc.max_burst;
   2703 			SCTP_TCB_UNLOCK(stcb);
   2704 		} else {
   2705 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2706 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2707 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   2708 				SCTP_INP_RLOCK(inp);
   2709 				av->assoc_value = inp->sctp_ep.max_burst;
   2710 				SCTP_INP_RUNLOCK(inp);
   2711 			} else {
   2712 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2713 				error = EINVAL;
   2714 			}
   2715 		}
   2716 		if (error == 0) {
   2717 			*optsize = sizeof(struct sctp_assoc_value);
   2718 		}
   2719 #endif
   2720 		break;
   2721 	}
   2722 	case SCTP_MAXSEG:
   2723 	{
   2724 		struct sctp_assoc_value *av;
   2725 		int ovh;
   2726 
   2727 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2728 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2729 
   2730 		if (stcb) {
   2731 			av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
   2732 			SCTP_TCB_UNLOCK(stcb);
   2733 		} else {
   2734 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2735 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2736 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   2737 				SCTP_INP_RLOCK(inp);
   2738 				if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   2739 					ovh = SCTP_MED_OVERHEAD;
   2740 				} else {
   2741 					ovh = SCTP_MED_V4_OVERHEAD;
   2742 				}
   2743 				if (inp->sctp_frag_point >= SCTP_DEFAULT_MAXSEGMENT)
   2744 					av->assoc_value = 0;
   2745 				else
   2746 					av->assoc_value = inp->sctp_frag_point - ovh;
   2747 				SCTP_INP_RUNLOCK(inp);
   2748 			} else {
   2749 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2750 				error = EINVAL;
   2751 			}
   2752 		}
   2753 		if (error == 0) {
   2754 			*optsize = sizeof(struct sctp_assoc_value);
   2755 		}
   2756 		break;
   2757 	}
   2758 	case SCTP_GET_STAT_LOG:
   2759 		error = sctp_fill_stat_log(optval, optsize);
   2760 		break;
   2761 	case SCTP_EVENTS:
   2762 	{
   2763 		struct sctp_event_subscribe *events;
   2764 
   2765 		SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
   2766 		memset(events, 0, sizeof(struct sctp_event_subscribe));
   2767 		SCTP_INP_RLOCK(inp);
   2768 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
   2769 			events->sctp_data_io_event = 1;
   2770 
   2771 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT))
   2772 			events->sctp_association_event = 1;
   2773 
   2774 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT))
   2775 			events->sctp_address_event = 1;
   2776 
   2777 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
   2778 			events->sctp_send_failure_event = 1;
   2779 
   2780 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR))
   2781 			events->sctp_peer_error_event = 1;
   2782 
   2783 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
   2784 			events->sctp_shutdown_event = 1;
   2785 
   2786 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT))
   2787 			events->sctp_partial_delivery_event = 1;
   2788 
   2789 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT))
   2790 			events->sctp_adaptation_layer_event = 1;
   2791 
   2792 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT))
   2793 			events->sctp_authentication_event = 1;
   2794 
   2795 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT))
   2796 			events->sctp_sender_dry_event = 1;
   2797 
   2798 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
   2799 			events->sctp_stream_reset_event = 1;
   2800 		SCTP_INP_RUNLOCK(inp);
   2801 		*optsize = sizeof(struct sctp_event_subscribe);
   2802 		break;
   2803 	}
   2804 	case SCTP_ADAPTATION_LAYER:
   2805 	{
   2806 		uint32_t *value;
   2807 
   2808 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2809 
   2810 		SCTP_INP_RLOCK(inp);
   2811 		*value = inp->sctp_ep.adaptation_layer_indicator;
   2812 		SCTP_INP_RUNLOCK(inp);
   2813 		*optsize = sizeof(uint32_t);
   2814 		break;
   2815 	}
   2816 	case SCTP_SET_INITIAL_DBG_SEQ:
   2817 	{
   2818 		uint32_t *value;
   2819 
   2820 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2821 		SCTP_INP_RLOCK(inp);
   2822 		*value = inp->sctp_ep.initial_sequence_debug;
   2823 		SCTP_INP_RUNLOCK(inp);
   2824 		*optsize = sizeof(uint32_t);
   2825 		break;
   2826 	}
   2827 	case SCTP_GET_LOCAL_ADDR_SIZE:
   2828 	{
   2829 		uint32_t *value;
   2830 
   2831 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2832 		SCTP_INP_RLOCK(inp);
   2833 		*value = sctp_count_max_addresses(inp);
   2834 		SCTP_INP_RUNLOCK(inp);
   2835 		*optsize = sizeof(uint32_t);
   2836 		break;
   2837 	}
   2838 	case SCTP_GET_REMOTE_ADDR_SIZE:
   2839 	{
   2840 		uint32_t *value;
   2841 		size_t size;
   2842 		struct sctp_nets *net;
   2843 
   2844 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2845 		/* FIXME MT: change to sctp_assoc_value? */
   2846 		SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
   2847 
   2848 		if (stcb) {
   2849 			size = 0;
   2850 			/* Count the sizes */
   2851 			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   2852 				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
   2853 					size += sizeof(struct sockaddr_in6);
   2854 				} else {
   2855 					switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
   2856 #ifdef INET
   2857 					case AF_INET:
   2858 						size += sizeof(struct sockaddr_in);
   2859 						break;
   2860 #endif
   2861 #ifdef INET6
   2862 					case AF_INET6:
   2863 						size += sizeof(struct sockaddr_in6);
   2864 						break;
   2865 #endif
   2866 #if defined(__Userspace__)
   2867 					case AF_CONN:
   2868 						size += sizeof(struct sockaddr_conn);
   2869 						break;
   2870 #endif
   2871 					default:
   2872 						break;
   2873 					}
   2874 				}
   2875 			}
   2876 			SCTP_TCB_UNLOCK(stcb);
   2877 			*value = (uint32_t) size;
   2878 			*optsize = sizeof(uint32_t);
   2879 		} else {
   2880 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
   2881 			error = ENOTCONN;
   2882 		}
   2883 		break;
   2884 	}
   2885 	case SCTP_GET_PEER_ADDRESSES:
   2886 		/*
   2887 		 * Get the address information, an array is passed in to
   2888 		 * fill up we pack it.
   2889 		 */
   2890 	{
   2891 		size_t cpsz, left;
   2892 		struct sockaddr_storage *sas;
   2893 		struct sctp_nets *net;
   2894 		struct sctp_getaddresses *saddr;
   2895 
   2896 		SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
   2897 		SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
   2898 
   2899 		if (stcb) {
   2900 			left = (*optsize) - sizeof(struct sctp_getaddresses);
   2901 			*optsize = sizeof(struct sctp_getaddresses);
   2902 			sas = (struct sockaddr_storage *)&saddr->addr[0];
   2903 
   2904 			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   2905 				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
   2906 					cpsz = sizeof(struct sockaddr_in6);
   2907 				} else {
   2908 					switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
   2909 #ifdef INET
   2910 					case AF_INET:
   2911 						cpsz = sizeof(struct sockaddr_in);
   2912 						break;
   2913 #endif
   2914 #ifdef INET6
   2915 					case AF_INET6:
   2916 						cpsz = sizeof(struct sockaddr_in6);
   2917 						break;
   2918 #endif
   2919 #if defined(__Userspace__)
   2920 					case AF_CONN:
   2921 						cpsz = sizeof(struct sockaddr_conn);
   2922 						break;
   2923 #endif
   2924 					default:
   2925 						cpsz = 0;
   2926 						break;
   2927 					}
   2928 				}
   2929 				if (cpsz == 0) {
   2930 					break;
   2931 				}
   2932 				if (left < cpsz) {
   2933 					/* not enough room. */
   2934 					break;
   2935 				}
   2936 #if defined(INET) && defined(INET6)
   2937 				if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
   2938 				    (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
   2939 					/* Must map the address */
   2940 					in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr,
   2941 							    (struct sockaddr_in6 *)sas);
   2942 				} else {
   2943 #endif
   2944 					memcpy(sas, &net->ro._l_addr, cpsz);
   2945 #if defined(INET) && defined(INET6)
   2946 				}
   2947 #endif
   2948 				((struct sockaddr_in *)sas)->sin_port = stcb->rport;
   2949 
   2950 				sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz);
   2951 				left -= cpsz;
   2952 				*optsize += cpsz;
   2953 			}
   2954 			SCTP_TCB_UNLOCK(stcb);
   2955 		} else {
   2956 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   2957 			error = ENOENT;
   2958 		}
   2959 		break;
   2960 	}
   2961 	case SCTP_GET_LOCAL_ADDRESSES:
   2962 	{
   2963 		size_t limit, actual;
   2964 		struct sockaddr_storage *sas;
   2965 		struct sctp_getaddresses *saddr;
   2966 
   2967 		SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
   2968 		SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
   2969 
   2970 		sas = (struct sockaddr_storage *)&saddr->addr[0];
   2971 		limit = *optsize - sizeof(sctp_assoc_t);
   2972 		actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
   2973 		if (stcb) {
   2974 			SCTP_TCB_UNLOCK(stcb);
   2975 		}
   2976 		*optsize = sizeof(struct sockaddr_storage) + actual;
   2977 		break;
   2978 	}
   2979 	case SCTP_PEER_ADDR_PARAMS:
   2980 	{
   2981 		struct sctp_paddrparams *paddrp;
   2982 		struct sctp_nets *net;
   2983 
   2984 		SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
   2985 		SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
   2986 
   2987 		net = NULL;
   2988 		if (stcb) {
   2989 			net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
   2990 		} else {
   2991 			/* We increment here since sctp_findassociation_ep_addr() wil
   2992 			 * do a decrement if it finds the stcb as long as the locked
   2993 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   2994 			 */
   2995 			SCTP_INP_INCR_REF(inp);
   2996 			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddrp->spp_address, &net, NULL, NULL);
   2997 			if (stcb == NULL) {
   2998 				SCTP_INP_DECR_REF(inp);
   2999 			}
   3000 		}
   3001 		if (stcb && (net == NULL)) {
   3002 			struct sockaddr *sa;
   3003 
   3004 			sa = (struct sockaddr *)&paddrp->spp_address;
   3005 #ifdef INET
   3006 			if (sa->sa_family == AF_INET) {
   3007 				struct sockaddr_in *sin;
   3008 
   3009 				sin = (struct sockaddr_in *)sa;
   3010 				if (sin->sin_addr.s_addr) {
   3011 					error = EINVAL;
   3012 					SCTP_TCB_UNLOCK(stcb);
   3013 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3014 					break;
   3015 				}
   3016 			} else
   3017 #endif
   3018 #ifdef INET6
   3019 			if (sa->sa_family == AF_INET6) {
   3020 				struct sockaddr_in6 *sin6;
   3021 
   3022 				sin6 = (struct sockaddr_in6 *)sa;
   3023 				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   3024 					error = EINVAL;
   3025 					SCTP_TCB_UNLOCK(stcb);
   3026 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3027 					break;
   3028 				}
   3029 			} else
   3030 #endif
   3031 #if defined(__Userspace__)
   3032 			if (sa->sa_family == AF_CONN) {
   3033 				struct sockaddr_conn *sconn;
   3034 
   3035 				sconn = (struct sockaddr_conn *)sa;
   3036 				if (sconn->sconn_addr != NULL) {
   3037 					error = EINVAL;
   3038 					SCTP_TCB_UNLOCK(stcb);
   3039 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3040 					break;
   3041 				}
   3042 			} else
   3043 #endif
   3044 			{
   3045 				error = EAFNOSUPPORT;
   3046 				SCTP_TCB_UNLOCK(stcb);
   3047 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3048 				break;
   3049 			}
   3050 		}
   3051 
   3052 		if (stcb) {
   3053 			/* Applies to the specific association */
   3054 			paddrp->spp_flags = 0;
   3055 			if (net) {
   3056 				int ovh;
   3057 				if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   3058 					ovh = SCTP_MED_OVERHEAD;
   3059 				} else {
   3060 					ovh = SCTP_MED_V4_OVERHEAD;
   3061 				}
   3062 
   3063 				paddrp->spp_hbinterval = net->heart_beat_delay;
   3064 				paddrp->spp_pathmaxrxt = net->failure_threshold;
   3065 				paddrp->spp_pathmtu = net->mtu - ovh;
   3066 				/* get flags for HB */
   3067 				if (net->dest_state & SCTP_ADDR_NOHB) {
   3068 					paddrp->spp_flags |= SPP_HB_DISABLE;
   3069 				} else {
   3070 					paddrp->spp_flags |= SPP_HB_ENABLE;
   3071 				}
   3072 				/* get flags for PMTU */
   3073 				if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
   3074 					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
   3075 				} else {
   3076 					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
   3077 				}
   3078 				if (net->dscp & 0x01) {
   3079 					paddrp->spp_dscp = net->dscp & 0xfc;
   3080 					paddrp->spp_flags |= SPP_DSCP;
   3081 				}
   3082 #ifdef INET6
   3083 				if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
   3084 				    (net->flowlabel & 0x80000000)) {
   3085 					paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
   3086 					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
   3087 				}
   3088 #endif
   3089 			} else {
   3090 				/*
   3091 				 * No destination so return default
   3092 				 * value
   3093 				 */
   3094 				paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
   3095 				paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc);
   3096 				if (stcb->asoc.default_dscp & 0x01) {
   3097 					paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
   3098 					paddrp->spp_flags |= SPP_DSCP;
   3099 				}
   3100 #ifdef INET6
   3101 				if (stcb->asoc.default_flowlabel & 0x80000000) {
   3102 					paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
   3103 					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
   3104 				}
   3105 #endif
   3106 				/* default settings should be these */
   3107 				if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
   3108 					paddrp->spp_flags |= SPP_HB_DISABLE;
   3109 				} else {
   3110 					paddrp->spp_flags |= SPP_HB_ENABLE;
   3111 				}
   3112 				if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
   3113 					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
   3114 				} else {
   3115 					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
   3116 				}
   3117 				paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
   3118 			}
   3119 			paddrp->spp_assoc_id = sctp_get_associd(stcb);
   3120 			SCTP_TCB_UNLOCK(stcb);
   3121 		} else {
   3122 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3123 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3124 			    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
   3125 				/* Use endpoint defaults */
   3126 				SCTP_INP_RLOCK(inp);
   3127 				paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
   3128 				paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
   3129 				paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
   3130 				/* get inp's default */
   3131 				if (inp->sctp_ep.default_dscp & 0x01) {
   3132 					paddrp->spp_dscp = inp->sctp_ep.default_dscp & 0xfc;
   3133 					paddrp->spp_flags |= SPP_DSCP;
   3134 				}
   3135 #ifdef INET6
   3136 				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
   3137 				    (inp->sctp_ep.default_flowlabel & 0x80000000)) {
   3138 					paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
   3139 					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
   3140 				}
   3141 #endif
   3142 				/* can't return this */
   3143 				paddrp->spp_pathmtu = 0;
   3144 
   3145 				if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
   3146 					paddrp->spp_flags |= SPP_HB_ENABLE;
   3147 				} else {
   3148 					paddrp->spp_flags |= SPP_HB_DISABLE;
   3149 				}
   3150 				if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
   3151 					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
   3152 				} else {
   3153 					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
   3154 				}
   3155 				SCTP_INP_RUNLOCK(inp);
   3156 			} else {
   3157 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3158 				error = EINVAL;
   3159 			}
   3160 		}
   3161 		if (error == 0) {
   3162 			*optsize = sizeof(struct sctp_paddrparams);
   3163 		}
   3164 		break;
   3165 	}
   3166 	case SCTP_GET_PEER_ADDR_INFO:
   3167 	{
   3168 		struct sctp_paddrinfo *paddri;
   3169 		struct sctp_nets *net;
   3170 
   3171 		SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
   3172 		SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
   3173 
   3174 		net = NULL;
   3175 		if (stcb) {
   3176 			net = sctp_findnet(stcb, (struct sockaddr *)&paddri->spinfo_address);
   3177 		} else {
   3178 			/* We increment here since sctp_findassociation_ep_addr() wil
   3179 			 * do a decrement if it finds the stcb as long as the locked
   3180 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   3181 			 */
   3182 			SCTP_INP_INCR_REF(inp);
   3183 			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddri->spinfo_address, &net, NULL, NULL);
   3184 			if (stcb == NULL) {
   3185 				SCTP_INP_DECR_REF(inp);
   3186 			}
   3187 		}
   3188 
   3189 		if ((stcb) && (net)) {
   3190 			if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
   3191 				/* It's unconfirmed */
   3192 				paddri->spinfo_state = SCTP_UNCONFIRMED;
   3193 			} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
   3194 				/* It's active */
   3195 				paddri->spinfo_state = SCTP_ACTIVE;
   3196 			} else {
   3197 				/* It's inactive */
   3198 				paddri->spinfo_state = SCTP_INACTIVE;
   3199 			}
   3200 			paddri->spinfo_cwnd = net->cwnd;
   3201 			paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
   3202 			paddri->spinfo_rto = net->RTO;
   3203 			paddri->spinfo_assoc_id = sctp_get_associd(stcb);
   3204 			paddri->spinfo_mtu = net->mtu;
   3205 			SCTP_TCB_UNLOCK(stcb);
   3206 			*optsize = sizeof(struct sctp_paddrinfo);
   3207 		} else {
   3208 			if (stcb) {
   3209 				SCTP_TCB_UNLOCK(stcb);
   3210 			}
   3211 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   3212 			error = ENOENT;
   3213 		}
   3214 		break;
   3215 	}
   3216 	case SCTP_PCB_STATUS:
   3217 	{
   3218 		struct sctp_pcbinfo *spcb;
   3219 
   3220 		SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
   3221 		sctp_fill_pcbinfo(spcb);
   3222 		*optsize = sizeof(struct sctp_pcbinfo);
   3223 		break;
   3224 	}
   3225 	case SCTP_STATUS:
   3226 	{
   3227 		struct sctp_nets *net;
   3228 		struct sctp_status *sstat;
   3229 
   3230 		SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
   3231 		SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
   3232 
   3233 		if (stcb == NULL) {
   3234 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3235 			error = EINVAL;
   3236 			break;
   3237 		}
   3238 		/*
   3239 		 * I think passing the state is fine since
   3240 		 * sctp_constants.h will be available to the user
   3241 		 * land.
   3242 		 */
   3243 		sstat->sstat_state = stcb->asoc.state;
   3244 		sstat->sstat_assoc_id = sctp_get_associd(stcb);
   3245 		sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
   3246 		sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
   3247 		/*
   3248 		 * We can't include chunks that have been passed to
   3249 		 * the socket layer. Only things in queue.
   3250 		 */
   3251 		sstat->sstat_penddata = (stcb->asoc.cnt_on_reasm_queue +
   3252 					 stcb->asoc.cnt_on_all_streams);
   3253 
   3254 
   3255 		sstat->sstat_instrms = stcb->asoc.streamincnt;
   3256 		sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
   3257 		sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
   3258 #ifdef HAVE_SA_LEN
   3259 		memcpy(&sstat->sstat_primary.spinfo_address,
   3260 		       &stcb->asoc.primary_destination->ro._l_addr,
   3261 		       ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
   3262 #else
   3263 		if (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET) {
   3264 			memcpy(&sstat->sstat_primary.spinfo_address,
   3265 			       &stcb->asoc.primary_destination->ro._l_addr,
   3266 			       sizeof(struct sockaddr_in));
   3267 		} else {
   3268 			memcpy(&sstat->sstat_primary.spinfo_address,
   3269 			       &stcb->asoc.primary_destination->ro._l_addr,
   3270 			       sizeof(struct sockaddr_in6));
   3271 		}
   3272 #endif
   3273 		net = stcb->asoc.primary_destination;
   3274 		((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
   3275 		/*
   3276 		 * Again the user can get info from sctp_constants.h
   3277 		 * for what the state of the network is.
   3278 		 */
   3279 		if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
   3280 			/* It's unconfirmed */
   3281 			sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
   3282 		} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
   3283 			/* It's active */
   3284 			sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
   3285 		} else {
   3286 			/* It's inactive */
   3287 			sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
   3288 		}
   3289 		sstat->sstat_primary.spinfo_cwnd = net->cwnd;
   3290 		sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
   3291 		sstat->sstat_primary.spinfo_rto = net->RTO;
   3292 		sstat->sstat_primary.spinfo_mtu = net->mtu;
   3293 		sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
   3294 		SCTP_TCB_UNLOCK(stcb);
   3295 		*optsize = sizeof(struct sctp_status);
   3296 		break;
   3297 	}
   3298 	case SCTP_RTOINFO:
   3299 	{
   3300 		struct sctp_rtoinfo *srto;
   3301 
   3302 		SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
   3303 		SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
   3304 
   3305 		if (stcb) {
   3306 			srto->srto_initial = stcb->asoc.initial_rto;
   3307 			srto->srto_max = stcb->asoc.maxrto;
   3308 			srto->srto_min = stcb->asoc.minrto;
   3309 			SCTP_TCB_UNLOCK(stcb);
   3310 		} else {
   3311 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3312 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3313 			    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
   3314 				SCTP_INP_RLOCK(inp);
   3315 				srto->srto_initial = inp->sctp_ep.initial_rto;
   3316 				srto->srto_max = inp->sctp_ep.sctp_maxrto;
   3317 				srto->srto_min = inp->sctp_ep.sctp_minrto;
   3318 				SCTP_INP_RUNLOCK(inp);
   3319 			} else {
   3320 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3321 				error = EINVAL;
   3322 			}
   3323 		}
   3324 		if (error == 0) {
   3325 			*optsize = sizeof(struct sctp_rtoinfo);
   3326 		}
   3327 		break;
   3328 	}
   3329 	case SCTP_TIMEOUTS:
   3330 	{
   3331 		struct sctp_timeouts *stimo;
   3332 
   3333 		SCTP_CHECK_AND_CAST(stimo, optval, struct sctp_timeouts, *optsize);
   3334 		SCTP_FIND_STCB(inp, stcb, stimo->stimo_assoc_id);
   3335 
   3336 		if (stcb) {
   3337 			stimo->stimo_init= stcb->asoc.timoinit;
   3338 			stimo->stimo_data= stcb->asoc.timodata;
   3339 			stimo->stimo_sack= stcb->asoc.timosack;
   3340 			stimo->stimo_shutdown= stcb->asoc.timoshutdown;
   3341 			stimo->stimo_heartbeat= stcb->asoc.timoheartbeat;
   3342 			stimo->stimo_cookie= stcb->asoc.timocookie;
   3343 			stimo->stimo_shutdownack= stcb->asoc.timoshutdownack;
   3344 			SCTP_TCB_UNLOCK(stcb);
   3345 			*optsize = sizeof(struct sctp_timeouts);
   3346 		} else {
   3347 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3348 			error = EINVAL;
   3349 		}
   3350 		break;
   3351 	}
   3352 	case SCTP_ASSOCINFO:
   3353 	{
   3354 		struct sctp_assocparams *sasoc;
   3355 
   3356 		SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
   3357 		SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
   3358 
   3359 		if (stcb) {
   3360 			sasoc->sasoc_cookie_life = TICKS_TO_MSEC(stcb->asoc.cookie_life);
   3361 			sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
   3362 			sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
   3363 			sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
   3364 			sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
   3365 			SCTP_TCB_UNLOCK(stcb);
   3366 		} else {
   3367 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3368 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3369 			    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
   3370 				SCTP_INP_RLOCK(inp);
   3371 				sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
   3372 				sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
   3373 				sasoc->sasoc_number_peer_destinations = 0;
   3374 				sasoc->sasoc_peer_rwnd = 0;
   3375 				sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
   3376 				SCTP_INP_RUNLOCK(inp);
   3377 			} else {
   3378 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3379 				error = EINVAL;
   3380 			}
   3381 		}
   3382 		if (error == 0) {
   3383 			*optsize = sizeof(struct sctp_assocparams);
   3384 		}
   3385 		break;
   3386 	}
   3387 	case SCTP_DEFAULT_SEND_PARAM:
   3388 	{
   3389 		struct sctp_sndrcvinfo *s_info;
   3390 
   3391 		SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
   3392 		SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
   3393 
   3394 		if (stcb) {
   3395 			memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
   3396 			SCTP_TCB_UNLOCK(stcb);
   3397 		} else {
   3398 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3399 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3400 			    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC)) {
   3401 				SCTP_INP_RLOCK(inp);
   3402 				memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
   3403 				SCTP_INP_RUNLOCK(inp);
   3404 			} else {
   3405 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3406 				error = EINVAL;
   3407 			}
   3408 		}
   3409 		if (error == 0) {
   3410 			*optsize = sizeof(struct sctp_sndrcvinfo);
   3411 		}
   3412 		break;
   3413 	}
   3414 	case SCTP_INITMSG:
   3415 	{
   3416 		struct sctp_initmsg *sinit;
   3417 
   3418 		SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
   3419 		SCTP_INP_RLOCK(inp);
   3420 		sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
   3421 		sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
   3422 		sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
   3423 		sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
   3424 		SCTP_INP_RUNLOCK(inp);
   3425 		*optsize = sizeof(struct sctp_initmsg);
   3426 		break;
   3427 	}
   3428 	case SCTP_PRIMARY_ADDR:
   3429 		/* we allow a "get" operation on this */
   3430 	{
   3431 		struct sctp_setprim *ssp;
   3432 
   3433 		SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
   3434 		SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
   3435 
   3436 		if (stcb) {
   3437 			/* simply copy out the sockaddr_storage... */
   3438 			size_t len;
   3439 
   3440 			len = *optsize;
   3441 #ifdef HAVE_SA_LEN
   3442 			if (len > stcb->asoc.primary_destination->ro._l_addr.sa.sa_len)
   3443 				len = stcb->asoc.primary_destination->ro._l_addr.sa.sa_len;
   3444 #else
   3445 			if (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET &&
   3446 			    len > sizeof(struct sockaddr_in))
   3447 				len = sizeof(struct sockaddr_in);
   3448 			else if (
   3449 			    stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET6 &&
   3450 			    len > sizeof(struct sockaddr_in6))
   3451 				len = sizeof(struct sockaddr_in6);
   3452 #endif
   3453 
   3454 			memcpy(&ssp->ssp_addr,
   3455 			       &stcb->asoc.primary_destination->ro._l_addr,
   3456 			       len);
   3457 			SCTP_TCB_UNLOCK(stcb);
   3458 			*optsize = sizeof(struct sctp_setprim);
   3459 		} else {
   3460 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3461 			error = EINVAL;
   3462 		}
   3463 		break;
   3464 	}
   3465 	case SCTP_HMAC_IDENT:
   3466 	{
   3467 		struct sctp_hmacalgo *shmac;
   3468 		sctp_hmaclist_t *hmaclist;
   3469 		uint32_t size;
   3470 		int i;
   3471 
   3472 		SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
   3473 
   3474 		SCTP_INP_RLOCK(inp);
   3475 		hmaclist = inp->sctp_ep.local_hmacs;
   3476 		if (hmaclist == NULL) {
   3477 			/* no HMACs to return */
   3478 			*optsize = sizeof(*shmac);
   3479 			SCTP_INP_RUNLOCK(inp);
   3480 			break;
   3481 		}
   3482 		/* is there room for all of the hmac ids? */
   3483 		size = sizeof(*shmac) + (hmaclist->num_algo *
   3484 					 sizeof(shmac->shmac_idents[0]));
   3485 		if ((size_t)(*optsize) < size) {
   3486 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3487 			error = EINVAL;
   3488 			SCTP_INP_RUNLOCK(inp);
   3489 			break;
   3490 		}
   3491 		/* copy in the list */
   3492 		shmac->shmac_number_of_idents = hmaclist->num_algo;
   3493 		for (i = 0; i < hmaclist->num_algo; i++) {
   3494 			shmac->shmac_idents[i] = hmaclist->hmac[i];
   3495 		}
   3496 		SCTP_INP_RUNLOCK(inp);
   3497 		*optsize = size;
   3498 		break;
   3499 	}
   3500 	case SCTP_AUTH_ACTIVE_KEY:
   3501 	{
   3502 		struct sctp_authkeyid *scact;
   3503 
   3504 		SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
   3505 		SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
   3506 
   3507 		if (stcb) {
   3508 			/* get the active key on the assoc */
   3509 			scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
   3510 			SCTP_TCB_UNLOCK(stcb);
   3511 		} else {
   3512 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3513 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3514 			    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC)) {
   3515 				/* get the endpoint active key */
   3516 				SCTP_INP_RLOCK(inp);
   3517 				scact->scact_keynumber = inp->sctp_ep.default_keyid;
   3518 				SCTP_INP_RUNLOCK(inp);
   3519 			} else {
   3520 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3521 				error = EINVAL;
   3522 			}
   3523 		}
   3524 		if (error == 0) {
   3525 			*optsize = sizeof(struct sctp_authkeyid);
   3526 		}
   3527 		break;
   3528 	}
   3529 	case SCTP_LOCAL_AUTH_CHUNKS:
   3530 	{
   3531 		struct sctp_authchunks *sac;
   3532 		sctp_auth_chklist_t *chklist = NULL;
   3533 		size_t size = 0;
   3534 
   3535 		SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
   3536 		SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
   3537 
   3538 		if (stcb) {
   3539 			/* get off the assoc */
   3540 			chklist = stcb->asoc.local_auth_chunks;
   3541 			/* is there enough space? */
   3542 			size = sctp_auth_get_chklist_size(chklist);
   3543 			if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
   3544 				error = EINVAL;
   3545 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3546 			} else {
   3547 				/* copy in the chunks */
   3548 				(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
   3549 				sac->gauth_number_of_chunks = (uint32_t)size;
   3550 				*optsize = sizeof(struct sctp_authchunks) + size;
   3551 			}
   3552 			SCTP_TCB_UNLOCK(stcb);
   3553 		} else {
   3554 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3555 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3556 			    (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC)) {
   3557 				/* get off the endpoint */
   3558 				SCTP_INP_RLOCK(inp);
   3559 				chklist = inp->sctp_ep.local_auth_chunks;
   3560 				/* is there enough space? */
   3561 				size = sctp_auth_get_chklist_size(chklist);
   3562 				if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
   3563 					error = EINVAL;
   3564 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3565 				} else {
   3566 					/* copy in the chunks */
   3567 					(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
   3568 					sac->gauth_number_of_chunks = (uint32_t)size;
   3569 					*optsize = sizeof(struct sctp_authchunks) + size;
   3570 				}
   3571 				SCTP_INP_RUNLOCK(inp);
   3572 			} else {
   3573 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3574 				error = EINVAL;
   3575 			}
   3576 		}
   3577 		break;
   3578 	}
   3579 	case SCTP_PEER_AUTH_CHUNKS:
   3580 	{
   3581 		struct sctp_authchunks *sac;
   3582 		sctp_auth_chklist_t *chklist = NULL;
   3583 		size_t size = 0;
   3584 
   3585 		SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
   3586 		SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
   3587 
   3588 		if (stcb) {
   3589 			/* get off the assoc */
   3590 			chklist = stcb->asoc.peer_auth_chunks;
   3591 			/* is there enough space? */
   3592 			size = sctp_auth_get_chklist_size(chklist);
   3593 			if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
   3594 				error = EINVAL;
   3595 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3596 			} else {
   3597 				/* copy in the chunks */
   3598 				(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
   3599 				sac->gauth_number_of_chunks = (uint32_t)size;
   3600 				*optsize = sizeof(struct sctp_authchunks) + size;
   3601 			}
   3602 			SCTP_TCB_UNLOCK(stcb);
   3603 		} else {
   3604 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   3605 			error = ENOENT;
   3606 		}
   3607 		break;
   3608 	}
   3609 #if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
   3610 	case SCTP_PEELOFF:
   3611 	{
   3612 		struct sctp_peeloff_opt *peeloff;
   3613 
   3614 		SCTP_CHECK_AND_CAST(peeloff, optval, struct sctp_peeloff_opt, *optsize);
   3615 		/* do the peeloff */
   3616 		error = sctp_peeloff_option(p, peeloff);
   3617 		if (error == 0) {
   3618 			*optsize = sizeof(struct sctp_peeloff_opt);
   3619 		}
   3620 	}
   3621 	break;
   3622 #endif /* HAVE_SCTP_PEELOFF_SOCKOPT */
   3623 	case SCTP_EVENT:
   3624 	{
   3625 		struct sctp_event *event;
   3626 		uint32_t event_type;
   3627 
   3628 		SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
   3629 		SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
   3630 
   3631 		switch (event->se_type) {
   3632 		case SCTP_ASSOC_CHANGE:
   3633 			event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
   3634 			break;
   3635 		case SCTP_PEER_ADDR_CHANGE:
   3636 			event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
   3637 			break;
   3638 		case SCTP_REMOTE_ERROR:
   3639 			event_type = SCTP_PCB_FLAGS_RECVPEERERR;
   3640 			break;
   3641 		case SCTP_SEND_FAILED:
   3642 			event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
   3643 			break;
   3644 		case SCTP_SHUTDOWN_EVENT:
   3645 			event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
   3646 			break;
   3647 		case SCTP_ADAPTATION_INDICATION:
   3648 			event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
   3649 			break;
   3650 		case SCTP_PARTIAL_DELIVERY_EVENT:
   3651 			event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
   3652 			break;
   3653 		case SCTP_AUTHENTICATION_EVENT:
   3654 			event_type = SCTP_PCB_FLAGS_AUTHEVNT;
   3655 			break;
   3656 		case SCTP_STREAM_RESET_EVENT:
   3657 			event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
   3658 			break;
   3659 		case SCTP_SENDER_DRY_EVENT:
   3660 			event_type = SCTP_PCB_FLAGS_DRYEVNT;
   3661 			break;
   3662 		case SCTP_NOTIFICATIONS_STOPPED_EVENT:
   3663 			event_type = 0;
   3664 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
   3665 			error = ENOTSUP;
   3666 			break;
   3667 		case SCTP_ASSOC_RESET_EVENT:
   3668 			event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
   3669 			break;
   3670 		case SCTP_STREAM_CHANGE_EVENT:
   3671 			event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
   3672 			break;
   3673 		case SCTP_SEND_FAILED_EVENT:
   3674 			event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
   3675 			break;
   3676 		default:
   3677 			event_type = 0;
   3678 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3679 			error = EINVAL;
   3680 			break;
   3681 		}
   3682 		if (event_type > 0) {
   3683 			if (stcb) {
   3684 				event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
   3685 				SCTP_TCB_UNLOCK(stcb);
   3686 			} else {
   3687 				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3688 				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3689 				    (event->se_assoc_id == SCTP_FUTURE_ASSOC)) {
   3690 					SCTP_INP_RLOCK(inp);
   3691 					event->se_on = sctp_is_feature_on(inp, event_type);
   3692 					SCTP_INP_RUNLOCK(inp);
   3693 				} else {
   3694 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3695 					error = EINVAL;
   3696 				}
   3697 			}
   3698 		}
   3699 		if (error == 0) {
   3700 			*optsize = sizeof(struct sctp_event);
   3701 		}
   3702 		break;
   3703 	}
   3704 	case SCTP_RECVRCVINFO:
   3705 	{
   3706 		int onoff;
   3707 
   3708 		if (*optsize < sizeof(int)) {
   3709 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3710 			error = EINVAL;
   3711 		} else {
   3712 			SCTP_INP_RLOCK(inp);
   3713 			onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
   3714 			SCTP_INP_RUNLOCK(inp);
   3715 		}
   3716 		if (error == 0) {
   3717 			/* return the option value */
   3718 			*(int *)optval = onoff;
   3719 			*optsize = sizeof(int);
   3720 		}
   3721 		break;
   3722 	}
   3723 	case SCTP_RECVNXTINFO:
   3724 	{
   3725 		int onoff;
   3726 
   3727 		if (*optsize < sizeof(int)) {
   3728 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3729 			error = EINVAL;
   3730 		} else {
   3731 			SCTP_INP_RLOCK(inp);
   3732 			onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
   3733 			SCTP_INP_RUNLOCK(inp);
   3734 		}
   3735 		if (error == 0) {
   3736 			/* return the option value */
   3737 			*(int *)optval = onoff;
   3738 			*optsize = sizeof(int);
   3739 		}
   3740 		break;
   3741 	}
   3742 	case SCTP_DEFAULT_SNDINFO:
   3743 	{
   3744 		struct sctp_sndinfo *info;
   3745 
   3746 		SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
   3747 		SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
   3748 
   3749 		if (stcb) {
   3750 			info->snd_sid = stcb->asoc.def_send.sinfo_stream;
   3751 			info->snd_flags = stcb->asoc.def_send.sinfo_flags;
   3752 			info->snd_flags &= 0xfff0;
   3753 			info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
   3754 			info->snd_context = stcb->asoc.def_send.sinfo_context;
   3755 			SCTP_TCB_UNLOCK(stcb);
   3756 		} else {
   3757 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3758 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3759 			    (info->snd_assoc_id == SCTP_FUTURE_ASSOC)) {
   3760 				SCTP_INP_RLOCK(inp);
   3761 				info->snd_sid = inp->def_send.sinfo_stream;
   3762 				info->snd_flags = inp->def_send.sinfo_flags;
   3763 				info->snd_flags &= 0xfff0;
   3764 				info->snd_ppid = inp->def_send.sinfo_ppid;
   3765 				info->snd_context = inp->def_send.sinfo_context;
   3766 				SCTP_INP_RUNLOCK(inp);
   3767 			} else {
   3768 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3769 				error = EINVAL;
   3770 			}
   3771 		}
   3772 		if (error == 0) {
   3773 			*optsize = sizeof(struct sctp_sndinfo);
   3774 		}
   3775 		break;
   3776 	}
   3777 	case SCTP_DEFAULT_PRINFO:
   3778 	{
   3779 		struct sctp_default_prinfo *info;
   3780 
   3781 		SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
   3782 		SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
   3783 
   3784 		if (stcb) {
   3785 			info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
   3786 			info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
   3787 			SCTP_TCB_UNLOCK(stcb);
   3788 		} else {
   3789 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3790 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3791 			    (info->pr_assoc_id == SCTP_FUTURE_ASSOC)) {
   3792 				SCTP_INP_RLOCK(inp);
   3793 				info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
   3794 				info->pr_value = inp->def_send.sinfo_timetolive;
   3795 				SCTP_INP_RUNLOCK(inp);
   3796 			} else {
   3797 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3798 				error = EINVAL;
   3799 			}
   3800 		}
   3801 		if (error == 0) {
   3802 			*optsize = sizeof(struct sctp_default_prinfo);
   3803 		}
   3804 		break;
   3805 	}
   3806 	case SCTP_PEER_ADDR_THLDS:
   3807 	{
   3808 		struct sctp_paddrthlds *thlds;
   3809 		struct sctp_nets *net;
   3810 
   3811 		SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
   3812 		SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
   3813 
   3814 		net = NULL;
   3815 		if (stcb) {
   3816 			net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
   3817 		} else {
   3818 			/* We increment here since sctp_findassociation_ep_addr() wil
   3819 			 * do a decrement if it finds the stcb as long as the locked
   3820 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   3821 			 */
   3822 			SCTP_INP_INCR_REF(inp);
   3823 			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&thlds->spt_address, &net, NULL, NULL);
   3824 			if (stcb == NULL) {
   3825 				SCTP_INP_DECR_REF(inp);
   3826 			}
   3827 		}
   3828 		if (stcb && (net == NULL)) {
   3829 			struct sockaddr *sa;
   3830 
   3831 			sa = (struct sockaddr *)&thlds->spt_address;
   3832 #ifdef INET
   3833 			if (sa->sa_family == AF_INET) {
   3834 				struct sockaddr_in *sin;
   3835 
   3836 				sin = (struct sockaddr_in *)sa;
   3837 				if (sin->sin_addr.s_addr) {
   3838 					error = EINVAL;
   3839 					SCTP_TCB_UNLOCK(stcb);
   3840 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3841 					break;
   3842 				}
   3843 			} else
   3844 #endif
   3845 #ifdef INET6
   3846 			if (sa->sa_family == AF_INET6) {
   3847 				struct sockaddr_in6 *sin6;
   3848 
   3849 				sin6 = (struct sockaddr_in6 *)sa;
   3850 				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   3851 					error = EINVAL;
   3852 					SCTP_TCB_UNLOCK(stcb);
   3853 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3854 					break;
   3855 				}
   3856 			} else
   3857 #endif
   3858 #if defined(__Userspace__)
   3859 			if (sa->sa_family == AF_CONN) {
   3860 				struct sockaddr_conn *sconn;
   3861 
   3862 				sconn = (struct sockaddr_conn *)sa;
   3863 				if (sconn->sconn_addr != NULL) {
   3864 					error = EINVAL;
   3865 					SCTP_TCB_UNLOCK(stcb);
   3866 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3867 					break;
   3868 				}
   3869 			} else
   3870 #endif
   3871 			{
   3872 				error = EAFNOSUPPORT;
   3873 				SCTP_TCB_UNLOCK(stcb);
   3874 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3875 				break;
   3876 			}
   3877 		}
   3878 
   3879 		if (stcb) {
   3880 			if (net) {
   3881 				thlds->spt_pathmaxrxt = net->failure_threshold;
   3882 				thlds->spt_pathpfthld = net->pf_threshold;
   3883 			} else {
   3884 				thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
   3885 				thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
   3886 			}
   3887 			thlds->spt_assoc_id = sctp_get_associd(stcb);
   3888 			SCTP_TCB_UNLOCK(stcb);
   3889 		} else {
   3890 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3891 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3892 			    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
   3893 				/* Use endpoint defaults */
   3894 				SCTP_INP_RLOCK(inp);
   3895 				thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
   3896 				thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
   3897 				SCTP_INP_RUNLOCK(inp);
   3898 			} else {
   3899 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3900 				error = EINVAL;
   3901 			}
   3902 		}
   3903 		if (error == 0) {
   3904 			*optsize = sizeof(struct sctp_paddrthlds);
   3905 		}
   3906 		break;
   3907 	}
   3908 	case SCTP_REMOTE_UDP_ENCAPS_PORT:
   3909 	{
   3910 		struct sctp_udpencaps *encaps;
   3911 		struct sctp_nets *net;
   3912 
   3913 		SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
   3914 		SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
   3915 
   3916 		if (stcb) {
   3917 			net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
   3918 		} else {
   3919 			/* We increment here since sctp_findassociation_ep_addr() wil
   3920 			 * do a decrement if it finds the stcb as long as the locked
   3921 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   3922 			 */
   3923 			net = NULL;
   3924 			SCTP_INP_INCR_REF(inp);
   3925 			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
   3926 			if (stcb == NULL) {
   3927 				SCTP_INP_DECR_REF(inp);
   3928 			}
   3929 		}
   3930 		if (stcb && (net == NULL)) {
   3931 			struct sockaddr *sa;
   3932 
   3933 			sa = (struct sockaddr *)&encaps->sue_address;
   3934 #ifdef INET
   3935 			if (sa->sa_family == AF_INET) {
   3936 				struct sockaddr_in *sin;
   3937 
   3938 				sin = (struct sockaddr_in *)sa;
   3939 				if (sin->sin_addr.s_addr) {
   3940 					error = EINVAL;
   3941 					SCTP_TCB_UNLOCK(stcb);
   3942 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3943 					break;
   3944 				}
   3945 			} else
   3946 #endif
   3947 #ifdef INET6
   3948 			if (sa->sa_family == AF_INET6) {
   3949 				struct sockaddr_in6 *sin6;
   3950 
   3951 				sin6 = (struct sockaddr_in6 *)sa;
   3952 				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   3953 					error = EINVAL;
   3954 					SCTP_TCB_UNLOCK(stcb);
   3955 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3956 					break;
   3957 				}
   3958 			} else
   3959 #endif
   3960 #if defined(__Userspace__)
   3961 			if (sa->sa_family == AF_CONN) {
   3962 				struct sockaddr_conn *sconn;
   3963 
   3964 				sconn = (struct sockaddr_conn *)sa;
   3965 				if (sconn->sconn_addr != NULL) {
   3966 					error = EINVAL;
   3967 					SCTP_TCB_UNLOCK(stcb);
   3968 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3969 					break;
   3970 				}
   3971 			} else
   3972 #endif
   3973 			{
   3974 				error = EAFNOSUPPORT;
   3975 				SCTP_TCB_UNLOCK(stcb);
   3976 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3977 				break;
   3978 			}
   3979 		}
   3980 
   3981 		if (stcb) {
   3982 			if (net) {
   3983 				encaps->sue_port = net->port;
   3984 			} else {
   3985 				encaps->sue_port = stcb->asoc.port;
   3986 			}
   3987 			SCTP_TCB_UNLOCK(stcb);
   3988 		} else {
   3989 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3990 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3991 			    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
   3992 				SCTP_INP_RLOCK(inp);
   3993 				encaps->sue_port = inp->sctp_ep.port;
   3994 				SCTP_INP_RUNLOCK(inp);
   3995 			} else {
   3996 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3997 				error = EINVAL;
   3998 			}
   3999 		}
   4000 		if (error == 0) {
   4001 			*optsize = sizeof(struct sctp_udpencaps);
   4002 		}
   4003 		break;
   4004 	}
   4005 	case SCTP_ECN_SUPPORTED:
   4006 	{
   4007 		struct sctp_assoc_value *av;
   4008 
   4009 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   4010 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4011 
   4012 		if (stcb) {
   4013 			av->assoc_value = stcb->asoc.ecn_supported;
   4014 			SCTP_TCB_UNLOCK(stcb);
   4015 		} else {
   4016 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4017 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4018 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   4019 				SCTP_INP_RLOCK(inp);
   4020 				av->assoc_value = inp->ecn_supported;
   4021 				SCTP_INP_RUNLOCK(inp);
   4022 			} else {
   4023 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4024 				error = EINVAL;
   4025 			}
   4026 		}
   4027 		if (error == 0) {
   4028 			*optsize = sizeof(struct sctp_assoc_value);
   4029 		}
   4030 		break;
   4031 	}
   4032 	case SCTP_PR_SUPPORTED:
   4033 	{
   4034 		struct sctp_assoc_value *av;
   4035 
   4036 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   4037 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4038 
   4039 		if (stcb) {
   4040 			av->assoc_value = stcb->asoc.prsctp_supported;
   4041 			SCTP_TCB_UNLOCK(stcb);
   4042 		} else {
   4043 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4044 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4045 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   4046 				SCTP_INP_RLOCK(inp);
   4047 				av->assoc_value = inp->prsctp_supported;
   4048 				SCTP_INP_RUNLOCK(inp);
   4049 			} else {
   4050 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4051 				error = EINVAL;
   4052 			}
   4053 		}
   4054 		if (error == 0) {
   4055 			*optsize = sizeof(struct sctp_assoc_value);
   4056 		}
   4057 		break;
   4058 	}
   4059 	case SCTP_AUTH_SUPPORTED:
   4060 	{
   4061 		struct sctp_assoc_value *av;
   4062 
   4063 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   4064 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4065 
   4066 		if (stcb) {
   4067 			av->assoc_value = stcb->asoc.auth_supported;
   4068 			SCTP_TCB_UNLOCK(stcb);
   4069 		} else {
   4070 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4071 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4072 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   4073 				SCTP_INP_RLOCK(inp);
   4074 				av->assoc_value = inp->auth_supported;
   4075 				SCTP_INP_RUNLOCK(inp);
   4076 			} else {
   4077 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4078 				error = EINVAL;
   4079 			}
   4080 		}
   4081 		if (error == 0) {
   4082 			*optsize = sizeof(struct sctp_assoc_value);
   4083 		}
   4084 		break;
   4085 	}
   4086 	case SCTP_ASCONF_SUPPORTED:
   4087 	{
   4088 		struct sctp_assoc_value *av;
   4089 
   4090 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   4091 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4092 
   4093 		if (stcb) {
   4094 			av->assoc_value = stcb->asoc.asconf_supported;
   4095 			SCTP_TCB_UNLOCK(stcb);
   4096 		} else {
   4097 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4098 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4099 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   4100 				SCTP_INP_RLOCK(inp);
   4101 				av->assoc_value = inp->asconf_supported;
   4102 				SCTP_INP_RUNLOCK(inp);
   4103 			} else {
   4104 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4105 				error = EINVAL;
   4106 			}
   4107 		}
   4108 		if (error == 0) {
   4109 			*optsize = sizeof(struct sctp_assoc_value);
   4110 		}
   4111 		break;
   4112 	}
   4113 	case SCTP_RECONFIG_SUPPORTED:
   4114 	{
   4115 		struct sctp_assoc_value *av;
   4116 
   4117 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   4118 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4119 
   4120 		if (stcb) {
   4121 			av->assoc_value = stcb->asoc.reconfig_supported;
   4122 			SCTP_TCB_UNLOCK(stcb);
   4123 		} else {
   4124 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4125 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4126 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   4127 				SCTP_INP_RLOCK(inp);
   4128 				av->assoc_value = inp->reconfig_supported;
   4129 				SCTP_INP_RUNLOCK(inp);
   4130 			} else {
   4131 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4132 				error = EINVAL;
   4133 			}
   4134 		}
   4135 		if (error == 0) {
   4136 			*optsize = sizeof(struct sctp_assoc_value);
   4137 		}
   4138 		break;
   4139 	}
   4140 	case SCTP_NRSACK_SUPPORTED:
   4141 	{
   4142 		struct sctp_assoc_value *av;
   4143 
   4144 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   4145 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4146 
   4147 		if (stcb) {
   4148 			av->assoc_value = stcb->asoc.nrsack_supported;
   4149 			SCTP_TCB_UNLOCK(stcb);
   4150 		} else {
   4151 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4152 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4153 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   4154 				SCTP_INP_RLOCK(inp);
   4155 				av->assoc_value = inp->nrsack_supported;
   4156 				SCTP_INP_RUNLOCK(inp);
   4157 			} else {
   4158 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4159 				error = EINVAL;
   4160 			}
   4161 		}
   4162 		if (error == 0) {
   4163 			*optsize = sizeof(struct sctp_assoc_value);
   4164 		}
   4165 		break;
   4166 	}
   4167 	case SCTP_PKTDROP_SUPPORTED:
   4168 	{
   4169 		struct sctp_assoc_value *av;
   4170 
   4171 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   4172 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4173 
   4174 		if (stcb) {
   4175 			av->assoc_value = stcb->asoc.pktdrop_supported;
   4176 			SCTP_TCB_UNLOCK(stcb);
   4177 		} else {
   4178 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4179 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4180 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   4181 				SCTP_INP_RLOCK(inp);
   4182 				av->assoc_value = inp->pktdrop_supported;
   4183 				SCTP_INP_RUNLOCK(inp);
   4184 			} else {
   4185 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4186 				error = EINVAL;
   4187 			}
   4188 		}
   4189 		if (error == 0) {
   4190 			*optsize = sizeof(struct sctp_assoc_value);
   4191 		}
   4192 		break;
   4193 	}
   4194 	case SCTP_ENABLE_STREAM_RESET:
   4195 	{
   4196 		struct sctp_assoc_value *av;
   4197 
   4198 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   4199 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4200 
   4201 		if (stcb) {
   4202 			av->assoc_value = (uint32_t)stcb->asoc.local_strreset_support;
   4203 			SCTP_TCB_UNLOCK(stcb);
   4204 		} else {
   4205 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4206 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4207 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   4208 				SCTP_INP_RLOCK(inp);
   4209 				av->assoc_value = (uint32_t)inp->local_strreset_support;
   4210 				SCTP_INP_RUNLOCK(inp);
   4211 			} else {
   4212 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4213 				error = EINVAL;
   4214 			}
   4215 		}
   4216 		if (error == 0) {
   4217 			*optsize = sizeof(struct sctp_assoc_value);
   4218 		}
   4219 		break;
   4220 	}
   4221 	case SCTP_PR_STREAM_STATUS:
   4222 	{
   4223 		struct sctp_prstatus *sprstat;
   4224 		uint16_t sid;
   4225 		uint16_t policy;
   4226 
   4227 		SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
   4228 		SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
   4229 
   4230 		sid = sprstat->sprstat_sid;
   4231 		policy = sprstat->sprstat_policy;
   4232 #if defined(SCTP_DETAILED_STR_STATS)
   4233 		if ((stcb != NULL) &&
   4234 		    (policy != SCTP_PR_SCTP_NONE) &&
   4235 		    (sid < stcb->asoc.streamoutcnt) &&
   4236 		    ((policy == SCTP_PR_SCTP_ALL) ||
   4237 		     (PR_SCTP_VALID_POLICY(policy)))) {
   4238 #else
   4239 		if ((stcb != NULL) &&
   4240 		    (policy != SCTP_PR_SCTP_NONE) &&
   4241 		    (sid < stcb->asoc.streamoutcnt) &&
   4242 		    (policy == SCTP_PR_SCTP_ALL)) {
   4243 #endif
   4244 			if (policy == SCTP_PR_SCTP_ALL) {
   4245 				sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
   4246 				sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
   4247 			} else {
   4248 				sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[policy];
   4249 				sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[policy];
   4250 			}
   4251 			SCTP_TCB_UNLOCK(stcb);
   4252 			*optsize = sizeof(struct sctp_prstatus);
   4253 		} else {
   4254 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4255 			error = EINVAL;
   4256 		}
   4257 		break;
   4258 	}
   4259 	case SCTP_PR_ASSOC_STATUS:
   4260 	{
   4261 		struct sctp_prstatus *sprstat;
   4262 		uint16_t policy;
   4263 
   4264 		SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
   4265 		SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
   4266 
   4267 		policy = sprstat->sprstat_policy;
   4268 		if ((stcb != NULL) &&
   4269 		    (policy != SCTP_PR_SCTP_NONE) &&
   4270 		    ((policy == SCTP_PR_SCTP_ALL) ||
   4271 		     (PR_SCTP_VALID_POLICY(policy)))) {
   4272 			if (policy == SCTP_PR_SCTP_ALL) {
   4273 				sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[0];
   4274 				sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[0];
   4275 			} else {
   4276 				sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[policy];
   4277 				sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[policy];
   4278 			}
   4279 			SCTP_TCB_UNLOCK(stcb);
   4280 			*optsize = sizeof(struct sctp_prstatus);
   4281 		} else {
   4282 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4283 			error = EINVAL;
   4284 		}
   4285 		break;
   4286 	}
   4287 	default:
   4288 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
   4289 		error = ENOPROTOOPT;
   4290 		break;
   4291 	} /* end switch (sopt->sopt_name) */
   4292 	if (error) {
   4293 		*optsize = 0;
   4294 	}
   4295 	return (error);
   4296 }
   4297 
   4298 #if defined(__Panda__) || defined(__Userspace__)
   4299 int
   4300 #else
   4301 static int
   4302 #endif
   4303 sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
   4304 	    void *p)
   4305 {
   4306 	int error, set_opt;
   4307 	uint32_t *mopt;
   4308 	struct sctp_tcb *stcb = NULL;
   4309 	struct sctp_inpcb *inp = NULL;
   4310 	uint32_t vrf_id;
   4311 
   4312 	if (optval == NULL) {
   4313 		SCTP_PRINTF("optval is NULL\n");
   4314 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4315 		return (EINVAL);
   4316 	}
   4317 	inp = (struct sctp_inpcb *)so->so_pcb;
   4318 	if (inp == NULL) {
   4319 		SCTP_PRINTF("inp is NULL?\n");
   4320 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4321 		return (EINVAL);
   4322 	}
   4323 	vrf_id = inp->def_vrf_id;
   4324 
   4325 	error = 0;
   4326 	switch (optname) {
   4327 	case SCTP_NODELAY:
   4328 	case SCTP_AUTOCLOSE:
   4329 	case SCTP_AUTO_ASCONF:
   4330 	case SCTP_EXPLICIT_EOR:
   4331 	case SCTP_DISABLE_FRAGMENTS:
   4332 	case SCTP_USE_EXT_RCVINFO:
   4333 	case SCTP_I_WANT_MAPPED_V4_ADDR:
   4334 		/* copy in the option value */
   4335 		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
   4336 		set_opt = 0;
   4337 		if (error)
   4338 			break;
   4339 		switch (optname) {
   4340 		case SCTP_DISABLE_FRAGMENTS:
   4341 			set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
   4342 			break;
   4343 		case SCTP_AUTO_ASCONF:
   4344 			/*
   4345 			 * NOTE: we don't really support this flag
   4346 			 */
   4347 			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
   4348 				/* only valid for bound all sockets */
   4349 				if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
   4350 				    (*mopt != 0)) {
   4351 					/* forbidden by admin */
   4352 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
   4353 					return (EPERM);
   4354 				}
   4355 				set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
   4356 			} else {
   4357 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4358 				return (EINVAL);
   4359 			}
   4360 			break;
   4361 		case SCTP_EXPLICIT_EOR:
   4362 			set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
   4363 			break;
   4364 		case SCTP_USE_EXT_RCVINFO:
   4365 			set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
   4366 			break;
   4367 		case SCTP_I_WANT_MAPPED_V4_ADDR:
   4368 			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   4369 				set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
   4370 			} else {
   4371 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4372 				return (EINVAL);
   4373 			}
   4374 			break;
   4375 		case SCTP_NODELAY:
   4376 			set_opt = SCTP_PCB_FLAGS_NODELAY;
   4377 			break;
   4378 		case SCTP_AUTOCLOSE:
   4379 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4380 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
   4381 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4382 				return (EINVAL);
   4383 			}
   4384 			set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
   4385 			/*
   4386 			 * The value is in ticks. Note this does not effect
   4387 			 * old associations, only new ones.
   4388 			 */
   4389 			inp->sctp_ep.auto_close_time = SEC_TO_TICKS(*mopt);
   4390 			break;
   4391 		}
   4392 		SCTP_INP_WLOCK(inp);
   4393 		if (*mopt != 0) {
   4394 			sctp_feature_on(inp, set_opt);
   4395 		} else {
   4396 			sctp_feature_off(inp, set_opt);
   4397 		}
   4398 		SCTP_INP_WUNLOCK(inp);
   4399 		break;
   4400 	case SCTP_REUSE_PORT:
   4401 	{
   4402 		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
   4403 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND)  == 0) {
   4404 			/* Can't set it after we are bound */
   4405 			error = EINVAL;
   4406 			break;
   4407 		}
   4408 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
   4409 			/* Can't do this for a 1-m socket */
   4410 			error = EINVAL;
   4411 			break;
   4412 		}
   4413 		if (optval)
   4414 			sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
   4415 		else
   4416 			sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
   4417 		break;
   4418 	}
   4419 	case SCTP_PARTIAL_DELIVERY_POINT:
   4420 	{
   4421 		uint32_t *value;
   4422 
   4423 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
   4424 		if (*value > SCTP_SB_LIMIT_RCV(so)) {
   4425 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4426 			error = EINVAL;
   4427 			break;
   4428 		}
   4429 		inp->partial_delivery_point = *value;
   4430 		break;
   4431 	}
   4432 	case SCTP_FRAGMENT_INTERLEAVE:
   4433 		/* not yet until we re-write sctp_recvmsg() */
   4434 	{
   4435 		uint32_t *level;
   4436 
   4437 		SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
   4438 		if (*level == SCTP_FRAG_LEVEL_2) {
   4439 			sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
   4440 			sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
   4441 		} else if (*level == SCTP_FRAG_LEVEL_1) {
   4442 			sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
   4443 			sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
   4444 		} else if (*level == SCTP_FRAG_LEVEL_0) {
   4445 			sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
   4446 			sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
   4447 
   4448 		} else {
   4449 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4450 			error = EINVAL;
   4451 		}
   4452 		break;
   4453 	}
   4454 	case SCTP_CMT_ON_OFF:
   4455 		if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
   4456 			struct sctp_assoc_value *av;
   4457 
   4458 			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   4459 			if (av->assoc_value > SCTP_CMT_MAX) {
   4460 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4461 				error = EINVAL;
   4462 				break;
   4463 			}
   4464 			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4465 			if (stcb) {
   4466 				stcb->asoc.sctp_cmt_on_off = av->assoc_value;
   4467 				SCTP_TCB_UNLOCK(stcb);
   4468 			} else {
   4469 				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4470 				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4471 				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
   4472 				    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4473 					SCTP_INP_WLOCK(inp);
   4474 					inp->sctp_cmt_on_off = av->assoc_value;
   4475 					SCTP_INP_WUNLOCK(inp);
   4476 				}
   4477 				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
   4478 				    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4479 					SCTP_INP_RLOCK(inp);
   4480 					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4481 						SCTP_TCB_LOCK(stcb);
   4482 						stcb->asoc.sctp_cmt_on_off = av->assoc_value;
   4483 						SCTP_TCB_UNLOCK(stcb);
   4484 					}
   4485 					SCTP_INP_RUNLOCK(inp);
   4486 				}
   4487 			}
   4488 		} else {
   4489 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
   4490 			error = ENOPROTOOPT;
   4491 		}
   4492 		break;
   4493 	case SCTP_PLUGGABLE_CC:
   4494 	{
   4495 		struct sctp_assoc_value *av;
   4496 		struct sctp_nets *net;
   4497 
   4498 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   4499 		if ((av->assoc_value != SCTP_CC_RFC2581) &&
   4500 		    (av->assoc_value != SCTP_CC_HSTCP) &&
   4501 		    (av->assoc_value != SCTP_CC_HTCP) &&
   4502 		    (av->assoc_value != SCTP_CC_RTCC)) {
   4503 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4504 			error = EINVAL;
   4505 			break;
   4506 		}
   4507 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4508 		if (stcb) {
   4509 			stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
   4510 			stcb->asoc.congestion_control_module = av->assoc_value;
   4511 			if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
   4512 				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   4513 					stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
   4514 				}
   4515 			}
   4516 			SCTP_TCB_UNLOCK(stcb);
   4517 		} else {
   4518 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4519 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4520 			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
   4521 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4522 				SCTP_INP_WLOCK(inp);
   4523 				inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
   4524 				SCTP_INP_WUNLOCK(inp);
   4525 			}
   4526 			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
   4527 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4528 				SCTP_INP_RLOCK(inp);
   4529 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4530 					SCTP_TCB_LOCK(stcb);
   4531 					stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
   4532 					stcb->asoc.congestion_control_module = av->assoc_value;
   4533 					if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
   4534 						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   4535 							stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
   4536 						}
   4537 					}
   4538 					SCTP_TCB_UNLOCK(stcb);
   4539 				}
   4540 				SCTP_INP_RUNLOCK(inp);
   4541 			}
   4542 		}
   4543 		break;
   4544 	}
   4545 	case SCTP_CC_OPTION:
   4546 	{
   4547 		struct sctp_cc_option *cc_opt;
   4548 
   4549 		SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
   4550 		SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
   4551 		if (stcb == NULL) {
   4552 			if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
   4553 				SCTP_INP_RLOCK(inp);
   4554 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4555 					SCTP_TCB_LOCK(stcb);
   4556 					if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
   4557 						(*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1, cc_opt);
   4558 					}
   4559 					SCTP_TCB_UNLOCK(stcb);
   4560 				}
   4561 				SCTP_INP_RUNLOCK(inp);
   4562 			} else {
   4563 				error = EINVAL;
   4564 			}
   4565 		} else {
   4566 			if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
   4567 				error = ENOTSUP;
   4568 			} else {
   4569 				error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1,
   4570 											   cc_opt);
   4571 			}
   4572 			SCTP_TCB_UNLOCK(stcb);
   4573 		}
   4574 		break;
   4575 	}
   4576 	case SCTP_PLUGGABLE_SS:
   4577 	{
   4578 		struct sctp_assoc_value *av;
   4579 
   4580 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   4581 		if ((av->assoc_value != SCTP_SS_DEFAULT) &&
   4582 		    (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
   4583 		    (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
   4584 		    (av->assoc_value != SCTP_SS_PRIORITY) &&
   4585 		    (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
   4586 		    (av->assoc_value != SCTP_SS_FIRST_COME)) {
   4587 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4588 			error = EINVAL;
   4589 			break;
   4590 		}
   4591 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4592 		if (stcb) {
   4593 			stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
   4594 			stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
   4595 			stcb->asoc.stream_scheduling_module = av->assoc_value;
   4596 			stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
   4597 			SCTP_TCB_UNLOCK(stcb);
   4598 		} else {
   4599 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4600 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4601 			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
   4602 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4603 				SCTP_INP_WLOCK(inp);
   4604 				inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
   4605 				SCTP_INP_WUNLOCK(inp);
   4606 			}
   4607 			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
   4608 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4609 				SCTP_INP_RLOCK(inp);
   4610 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4611 					SCTP_TCB_LOCK(stcb);
   4612 					stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
   4613 					stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
   4614 					stcb->asoc.stream_scheduling_module = av->assoc_value;
   4615 					stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
   4616 					SCTP_TCB_UNLOCK(stcb);
   4617 				}
   4618 				SCTP_INP_RUNLOCK(inp);
   4619 			}
   4620 		}
   4621 		break;
   4622 	}
   4623 	case SCTP_SS_VALUE:
   4624 	{
   4625 		struct sctp_stream_value *av;
   4626 
   4627 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
   4628 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4629 		if (stcb) {
   4630 			if (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
   4631 			                                              av->stream_value) < 0) {
   4632 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4633 				error = EINVAL;
   4634 			}
   4635 			SCTP_TCB_UNLOCK(stcb);
   4636 		} else {
   4637 			if (av->assoc_id == SCTP_CURRENT_ASSOC) {
   4638 				SCTP_INP_RLOCK(inp);
   4639 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4640 					SCTP_TCB_LOCK(stcb);
   4641 					stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
   4642 					                                          &stcb->asoc,
   4643 					                                          &stcb->asoc.strmout[av->stream_id],
   4644 					                                          av->stream_value);
   4645 					SCTP_TCB_UNLOCK(stcb);
   4646 				}
   4647 				SCTP_INP_RUNLOCK(inp);
   4648 
   4649 			} else {
   4650 				/* Can't set stream value without association */
   4651 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4652 				error = EINVAL;
   4653 			}
   4654 		}
   4655 		break;
   4656 	}
   4657 	case SCTP_CLR_STAT_LOG:
   4658 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   4659 		error = EOPNOTSUPP;
   4660 		break;
   4661 	case SCTP_CONTEXT:
   4662 	{
   4663 		struct sctp_assoc_value *av;
   4664 
   4665 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   4666 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4667 
   4668 		if (stcb) {
   4669 			stcb->asoc.context = av->assoc_value;
   4670 			SCTP_TCB_UNLOCK(stcb);
   4671 		} else {
   4672 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4673 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4674 			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
   4675 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4676 				SCTP_INP_WLOCK(inp);
   4677 				inp->sctp_context = av->assoc_value;
   4678 				SCTP_INP_WUNLOCK(inp);
   4679 			}
   4680 			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
   4681 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4682 				SCTP_INP_RLOCK(inp);
   4683 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4684 					SCTP_TCB_LOCK(stcb);
   4685 					stcb->asoc.context = av->assoc_value;
   4686 					SCTP_TCB_UNLOCK(stcb);
   4687 				}
   4688 				SCTP_INP_RUNLOCK(inp);
   4689 			}
   4690 		}
   4691 		break;
   4692 	}
   4693 	case SCTP_VRF_ID:
   4694 	{
   4695 		uint32_t *default_vrfid;
   4696 #ifdef SCTP_MVRF
   4697 		int i;
   4698 #endif
   4699 		SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
   4700 		if (*default_vrfid > SCTP_MAX_VRF_ID) {
   4701 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4702 			error = EINVAL;
   4703 			break;
   4704 		}
   4705 #ifdef SCTP_MVRF
   4706 		for (i = 0; i < inp->num_vrfs; i++) {
   4707 			/* The VRF must be in the VRF list */
   4708 			if (*default_vrfid == inp->m_vrf_ids[i]) {
   4709 				SCTP_INP_WLOCK(inp);
   4710 				inp->def_vrf_id = *default_vrfid;
   4711 				SCTP_INP_WUNLOCK(inp);
   4712 				goto sctp_done;
   4713 			}
   4714 		}
   4715 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4716 		error = EINVAL;
   4717 #else
   4718 		inp->def_vrf_id = *default_vrfid;
   4719 #endif
   4720 #ifdef SCTP_MVRF
   4721 	sctp_done:
   4722 #endif
   4723 		break;
   4724 	}
   4725 	case SCTP_DEL_VRF_ID:
   4726 	{
   4727 #ifdef SCTP_MVRF
   4728 		uint32_t *del_vrfid;
   4729 		int i, fnd = 0;
   4730 
   4731 		SCTP_CHECK_AND_CAST(del_vrfid, optval, uint32_t, optsize);
   4732 		if (*del_vrfid > SCTP_MAX_VRF_ID) {
   4733 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4734 			error = EINVAL;
   4735 			break;
   4736 		}
   4737 		if (inp->num_vrfs == 1) {
   4738 			/* Can't delete last one */
   4739 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4740 			error = EINVAL;
   4741 			break;
   4742 		}
   4743 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
   4744 			/* Can't add more once you are bound */
   4745 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4746 			error = EINVAL;
   4747 			break;
   4748 		}
   4749 		SCTP_INP_WLOCK(inp);
   4750 		for (i = 0; i < inp->num_vrfs; i++) {
   4751 			if (*del_vrfid == inp->m_vrf_ids[i]) {
   4752 				fnd = 1;
   4753 				break;
   4754 			}
   4755 		}
   4756 		if (!fnd) {
   4757 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4758 			error = EINVAL;
   4759 			break;
   4760 		}
   4761 		if (i != (inp->num_vrfs - 1)) {
   4762 			/* Take bottom one and move to this slot */
   4763 			inp->m_vrf_ids[i] = inp->m_vrf_ids[(inp->num_vrfs-1)];
   4764 		}
   4765 		if (*del_vrfid == inp->def_vrf_id) {
   4766 			/* Take the first one as the new default */
   4767 			inp->def_vrf_id = inp->m_vrf_ids[0];
   4768 		}
   4769 		/* Drop the number by one killing last one */
   4770 		inp->num_vrfs--;
   4771 #else
   4772 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   4773 		error = EOPNOTSUPP;
   4774 #endif
   4775 		break;
   4776 	}
   4777 	case SCTP_ADD_VRF_ID:
   4778 	{
   4779 #ifdef SCTP_MVRF
   4780 		uint32_t *add_vrfid;
   4781 		int i;
   4782 
   4783 		SCTP_CHECK_AND_CAST(add_vrfid, optval, uint32_t, optsize);
   4784 		if (*add_vrfid > SCTP_MAX_VRF_ID) {
   4785 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4786 			error = EINVAL;
   4787 			break;
   4788 		}
   4789 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
   4790 			/* Can't add more once you are bound */
   4791 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4792 			error = EINVAL;
   4793 			break;
   4794 		}
   4795 		SCTP_INP_WLOCK(inp);
   4796 		/* Verify its not already here */
   4797 		for (i = 0; i < inp->num_vrfs; i++) {
   4798 			if (*add_vrfid == inp->m_vrf_ids[i]) {
   4799 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   4800 				error = EALREADY;
   4801 				SCTP_INP_WUNLOCK(inp);
   4802 				break;
   4803 			}
   4804 		}
   4805 		if ((inp->num_vrfs + 1) > inp->vrf_size) {
   4806 			/* need to grow array */
   4807 			uint32_t *tarray;
   4808 			SCTP_MALLOC(tarray, uint32_t *,
   4809 				    (sizeof(uint32_t) * (inp->vrf_size + SCTP_DEFAULT_VRF_SIZE)),
   4810 				    SCTP_M_MVRF);
   4811 			if (tarray == NULL) {
   4812 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
   4813 				error = ENOMEM;
   4814 				SCTP_INP_WUNLOCK(inp);
   4815 				break;
   4816 			}
   4817 			memcpy(tarray, inp->m_vrf_ids, (sizeof(uint32_t) * inp->vrf_size));
   4818 			SCTP_FREE(inp->m_vrf_ids, SCTP_M_MVRF);
   4819 			inp->m_vrf_ids = tarray;
   4820 			inp->vrf_size += SCTP_DEFAULT_VRF_SIZE;
   4821 		}
   4822 		inp->m_vrf_ids[inp->num_vrfs] = *add_vrfid;
   4823 		inp->num_vrfs++;
   4824 		SCTP_INP_WUNLOCK(inp);
   4825 #else
   4826 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   4827 		error = EOPNOTSUPP;
   4828 #endif
   4829 		break;
   4830 	}
   4831 	case SCTP_DELAYED_SACK:
   4832 	{
   4833 		struct sctp_sack_info *sack;
   4834 
   4835 		SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
   4836 		SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
   4837 		if (sack->sack_delay) {
   4838 			if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
   4839 				sack->sack_delay = SCTP_MAX_SACK_DELAY;
   4840 			if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
   4841 				sack->sack_delay = TICKS_TO_MSEC(1);
   4842 			}
   4843 		}
   4844 		if (stcb) {
   4845 			if (sack->sack_delay) {
   4846 				stcb->asoc.delayed_ack = sack->sack_delay;
   4847 			}
   4848 			if (sack->sack_freq) {
   4849 				stcb->asoc.sack_freq = sack->sack_freq;
   4850 			}
   4851 			SCTP_TCB_UNLOCK(stcb);
   4852 		} else {
   4853 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4854 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4855 			    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
   4856 			    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
   4857 				SCTP_INP_WLOCK(inp);
   4858 				if (sack->sack_delay) {
   4859 					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
   4860 				}
   4861 				if (sack->sack_freq) {
   4862 					inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
   4863 				}
   4864 				SCTP_INP_WUNLOCK(inp);
   4865 			}
   4866 			if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
   4867 			    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
   4868 				SCTP_INP_RLOCK(inp);
   4869 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4870 					SCTP_TCB_LOCK(stcb);
   4871 					if (sack->sack_delay) {
   4872 						stcb->asoc.delayed_ack = sack->sack_delay;
   4873 					}
   4874 					if (sack->sack_freq) {
   4875 						stcb->asoc.sack_freq = sack->sack_freq;
   4876 					}
   4877 					SCTP_TCB_UNLOCK(stcb);
   4878 				}
   4879 				SCTP_INP_RUNLOCK(inp);
   4880 			}
   4881 		}
   4882 		break;
   4883 	}
   4884 	case SCTP_AUTH_CHUNK:
   4885 	{
   4886 		struct sctp_authchunk *sauth;
   4887 
   4888 		SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
   4889 
   4890 		SCTP_INP_WLOCK(inp);
   4891 		if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
   4892 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4893 			error = EINVAL;
   4894 		}
   4895 		SCTP_INP_WUNLOCK(inp);
   4896 		break;
   4897 	}
   4898 	case SCTP_AUTH_KEY:
   4899 	{
   4900 		struct sctp_authkey *sca;
   4901 		struct sctp_keyhead *shared_keys;
   4902 		sctp_sharedkey_t *shared_key;
   4903 		sctp_key_t *key = NULL;
   4904 		size_t size;
   4905 
   4906 		SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
   4907 		if (sca->sca_keylength == 0) {
   4908 			size = optsize - sizeof(struct sctp_authkey);
   4909 		} else {
   4910 		        if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
   4911 				size = sca->sca_keylength;
   4912 			} else {
   4913 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4914 				error = EINVAL;
   4915 				break;
   4916 			}
   4917 		}
   4918 		SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
   4919 
   4920 		if (stcb) {
   4921 			shared_keys = &stcb->asoc.shared_keys;
   4922 			/* clear the cached keys for this key id */
   4923 			sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
   4924 			/*
   4925 			 * create the new shared key and
   4926 			 * insert/replace it
   4927 			 */
   4928 			if (size > 0) {
   4929 				key = sctp_set_key(sca->sca_key, (uint32_t) size);
   4930 				if (key == NULL) {
   4931 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
   4932 					error = ENOMEM;
   4933 					SCTP_TCB_UNLOCK(stcb);
   4934 					break;
   4935 				}
   4936 			}
   4937 			shared_key = sctp_alloc_sharedkey();
   4938 			if (shared_key == NULL) {
   4939 				sctp_free_key(key);
   4940 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
   4941 				error = ENOMEM;
   4942 				SCTP_TCB_UNLOCK(stcb);
   4943 				break;
   4944 			}
   4945 			shared_key->key = key;
   4946 			shared_key->keyid = sca->sca_keynumber;
   4947 			error = sctp_insert_sharedkey(shared_keys, shared_key);
   4948 			SCTP_TCB_UNLOCK(stcb);
   4949 		} else {
   4950 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4951 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4952 			    (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
   4953 			    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
   4954 				SCTP_INP_WLOCK(inp);
   4955 				shared_keys = &inp->sctp_ep.shared_keys;
   4956 				/*
   4957 				 * clear the cached keys on all assocs for
   4958 				 * this key id
   4959 				 */
   4960 				sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
   4961 				/*
   4962 				 * create the new shared key and
   4963 				 * insert/replace it
   4964 				 */
   4965 				if (size > 0) {
   4966 					key = sctp_set_key(sca->sca_key, (uint32_t) size);
   4967 					if (key == NULL) {
   4968 						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
   4969 						error = ENOMEM;
   4970 						SCTP_INP_WUNLOCK(inp);
   4971 						break;
   4972 					}
   4973 				}
   4974 				shared_key = sctp_alloc_sharedkey();
   4975 				if (shared_key == NULL) {
   4976 					sctp_free_key(key);
   4977 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
   4978 					error = ENOMEM;
   4979 					SCTP_INP_WUNLOCK(inp);
   4980 					break;
   4981 				}
   4982 				shared_key->key = key;
   4983 				shared_key->keyid = sca->sca_keynumber;
   4984 				error = sctp_insert_sharedkey(shared_keys, shared_key);
   4985 				SCTP_INP_WUNLOCK(inp);
   4986 			}
   4987 			if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
   4988 			    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
   4989 				SCTP_INP_RLOCK(inp);
   4990 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4991 					SCTP_TCB_LOCK(stcb);
   4992 					shared_keys = &stcb->asoc.shared_keys;
   4993 					/* clear the cached keys for this key id */
   4994 					sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
   4995 					/*
   4996 					 * create the new shared key and
   4997 					 * insert/replace it
   4998 					 */
   4999 					if (size > 0) {
   5000 						key = sctp_set_key(sca->sca_key, (uint32_t) size);
   5001 						if (key == NULL) {
   5002 							SCTP_TCB_UNLOCK(stcb);
   5003 							continue;
   5004 						}
   5005 					}
   5006 					shared_key = sctp_alloc_sharedkey();
   5007 					if (shared_key == NULL) {
   5008 						sctp_free_key(key);
   5009 						SCTP_TCB_UNLOCK(stcb);
   5010 						continue;
   5011 					}
   5012 					shared_key->key = key;
   5013 					shared_key->keyid = sca->sca_keynumber;
   5014 					error = sctp_insert_sharedkey(shared_keys, shared_key);
   5015 					SCTP_TCB_UNLOCK(stcb);
   5016 				}
   5017 				SCTP_INP_RUNLOCK(inp);
   5018 			}
   5019 		}
   5020 		break;
   5021 	}
   5022 	case SCTP_HMAC_IDENT:
   5023 	{
   5024 		struct sctp_hmacalgo *shmac;
   5025 		sctp_hmaclist_t *hmaclist;
   5026 		uint16_t hmacid;
   5027 		uint32_t i;
   5028 
   5029 		SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
   5030 		if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) {
   5031 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5032 			error = EINVAL;
   5033 			break;
   5034 		}
   5035 
   5036 		hmaclist = sctp_alloc_hmaclist(shmac->shmac_number_of_idents);
   5037 		if (hmaclist == NULL) {
   5038 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
   5039 			error = ENOMEM;
   5040 			break;
   5041 		}
   5042 		for (i = 0; i < shmac->shmac_number_of_idents; i++) {
   5043 			hmacid = shmac->shmac_idents[i];
   5044 			if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
   5045 				/* invalid HMACs were found */;
   5046 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5047 				error = EINVAL;
   5048 				sctp_free_hmaclist(hmaclist);
   5049 				goto sctp_set_hmac_done;
   5050 			}
   5051 		}
   5052 		for (i = 0; i < hmaclist->num_algo; i++) {
   5053 			if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
   5054 				/* already in list */
   5055 				break;
   5056 			}
   5057 		}
   5058 		if (i == hmaclist->num_algo) {
   5059 			/* not found in list */
   5060 			sctp_free_hmaclist(hmaclist);
   5061 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5062 			error = EINVAL;
   5063 			break;
   5064 		}
   5065 		/* set it on the endpoint */
   5066 		SCTP_INP_WLOCK(inp);
   5067 		if (inp->sctp_ep.local_hmacs)
   5068 			sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
   5069 		inp->sctp_ep.local_hmacs = hmaclist;
   5070 		SCTP_INP_WUNLOCK(inp);
   5071 	sctp_set_hmac_done:
   5072 		break;
   5073 	}
   5074 	case SCTP_AUTH_ACTIVE_KEY:
   5075 	{
   5076 		struct sctp_authkeyid *scact;
   5077 
   5078 		SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
   5079 		SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
   5080 
   5081 		/* set the active key on the right place */
   5082 		if (stcb) {
   5083 			/* set the active key on the assoc */
   5084 			if (sctp_auth_setactivekey(stcb,
   5085 						   scact->scact_keynumber)) {
   5086 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
   5087 						    SCTP_FROM_SCTP_USRREQ,
   5088 						    EINVAL);
   5089 				error = EINVAL;
   5090 			}
   5091 			SCTP_TCB_UNLOCK(stcb);
   5092 		} else {
   5093 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5094 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   5095 			    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
   5096 			    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
   5097 				SCTP_INP_WLOCK(inp);
   5098 				if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
   5099 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5100 					error = EINVAL;
   5101 				}
   5102 				SCTP_INP_WUNLOCK(inp);
   5103 			}
   5104 			if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
   5105 			    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
   5106 				SCTP_INP_RLOCK(inp);
   5107 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   5108 					SCTP_TCB_LOCK(stcb);
   5109 					sctp_auth_setactivekey(stcb, scact->scact_keynumber);
   5110 					SCTP_TCB_UNLOCK(stcb);
   5111 				}
   5112 				SCTP_INP_RUNLOCK(inp);
   5113 			}
   5114 		}
   5115 		break;
   5116 	}
   5117 	case SCTP_AUTH_DELETE_KEY:
   5118 	{
   5119 		struct sctp_authkeyid *scdel;
   5120 
   5121 		SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
   5122 		SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
   5123 
   5124 		/* delete the key from the right place */
   5125 		if (stcb) {
   5126 			if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
   5127 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5128 				error = EINVAL;
   5129 			}
   5130 			SCTP_TCB_UNLOCK(stcb);
   5131 		} else {
   5132 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5133 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   5134 			    (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
   5135 			    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
   5136 				SCTP_INP_WLOCK(inp);
   5137 				if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
   5138 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5139 					error = EINVAL;
   5140 				}
   5141 				SCTP_INP_WUNLOCK(inp);
   5142 			}
   5143 			if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
   5144 			    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
   5145 				SCTP_INP_RLOCK(inp);
   5146 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   5147 					SCTP_TCB_LOCK(stcb);
   5148 					sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
   5149 					SCTP_TCB_UNLOCK(stcb);
   5150 				}
   5151 				SCTP_INP_RUNLOCK(inp);
   5152 			}
   5153 		}
   5154 		break;
   5155 	}
   5156 	case SCTP_AUTH_DEACTIVATE_KEY:
   5157 	{
   5158 		struct sctp_authkeyid *keyid;
   5159 
   5160 		SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
   5161 		SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
   5162 
   5163 		/* deactivate the key from the right place */
   5164 		if (stcb) {
   5165 			if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
   5166 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5167 				error = EINVAL;
   5168 			}
   5169 			SCTP_TCB_UNLOCK(stcb);
   5170 		} else {
   5171 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5172 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   5173 			    (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
   5174 			    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
   5175 				SCTP_INP_WLOCK(inp);
   5176 				if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
   5177 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5178 					error = EINVAL;
   5179 				}
   5180 				SCTP_INP_WUNLOCK(inp);
   5181 			}
   5182 			if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
   5183 			    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
   5184 				SCTP_INP_RLOCK(inp);
   5185 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   5186 					SCTP_TCB_LOCK(stcb);
   5187 					sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
   5188 					SCTP_TCB_UNLOCK(stcb);
   5189 				}
   5190 				SCTP_INP_RUNLOCK(inp);
   5191 			}
   5192 		}
   5193 		break;
   5194 	}
   5195 	case SCTP_ENABLE_STREAM_RESET:
   5196 	{
   5197 		struct sctp_assoc_value *av;
   5198 
   5199 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   5200 		if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
   5201 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5202 			error = EINVAL;
   5203 			break;
   5204 		}
   5205 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   5206 		if (stcb) {
   5207 			stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
   5208 			SCTP_TCB_UNLOCK(stcb);
   5209 		} else {
   5210 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5211 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   5212 			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
   5213 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   5214 				SCTP_INP_WLOCK(inp);
   5215 				inp->local_strreset_support = (uint8_t)av->assoc_value;
   5216 				SCTP_INP_WUNLOCK(inp);
   5217 			}
   5218 			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
   5219 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   5220 				SCTP_INP_RLOCK(inp);
   5221 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   5222 					SCTP_TCB_LOCK(stcb);
   5223 					stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
   5224 					SCTP_TCB_UNLOCK(stcb);
   5225 				}
   5226 				SCTP_INP_RUNLOCK(inp);
   5227 			}
   5228 
   5229 		}
   5230 		break;
   5231 	}
   5232 	case SCTP_RESET_STREAMS:
   5233 	{
   5234 		struct sctp_reset_streams *strrst;
   5235 		int i, send_out = 0;
   5236 		int send_in = 0;
   5237 
   5238 		SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
   5239 		SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
   5240 		if (stcb == NULL) {
   5241 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   5242 			error = ENOENT;
   5243 			break;
   5244 		}
   5245 		if (stcb->asoc.reconfig_supported == 0) {
   5246 			/*
   5247 			 * Peer does not support the chunk type.
   5248 			 */
   5249 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   5250 			error = EOPNOTSUPP;
   5251 			SCTP_TCB_UNLOCK(stcb);
   5252 			break;
   5253 		}
   5254 		if (stcb->asoc.stream_reset_outstanding) {
   5255 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   5256 			error = EALREADY;
   5257 			SCTP_TCB_UNLOCK(stcb);
   5258 			break;
   5259 		}
   5260 		if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
   5261 			send_in = 1;
   5262 		}
   5263 		if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
   5264 			send_out = 1;
   5265 		}
   5266 		if ((send_in == 0) && (send_out == 0)) {
   5267 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5268 			error = EINVAL;
   5269 			SCTP_TCB_UNLOCK(stcb);
   5270 			break;
   5271 		}
   5272 		for (i = 0; i < strrst->srs_number_streams; i++) {
   5273 			if ((send_in) &&
   5274 			    (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
   5275 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5276 				error = EINVAL;
   5277 				break;
   5278 			}
   5279 			if ((send_out) &&
   5280 			    (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
   5281 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5282 				error = EINVAL;
   5283 				break;
   5284 			}
   5285 		}
   5286 		if (error) {
   5287 			SCTP_TCB_UNLOCK(stcb);
   5288 			break;
   5289 		}
   5290 		error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
   5291 						strrst->srs_stream_list,
   5292 						send_out, send_in, 0, 0, 0, 0, 0);
   5293 
   5294 		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
   5295 		SCTP_TCB_UNLOCK(stcb);
   5296 		break;
   5297 	}
   5298 	case SCTP_ADD_STREAMS:
   5299 	{
   5300 		struct sctp_add_streams *stradd;
   5301 		uint8_t addstream = 0;
   5302 		uint16_t add_o_strmcnt = 0;
   5303 		uint16_t add_i_strmcnt = 0;
   5304 
   5305 		SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
   5306 		SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
   5307 		if (stcb == NULL) {
   5308 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   5309 			error = ENOENT;
   5310 			break;
   5311 		}
   5312 		if (stcb->asoc.reconfig_supported == 0) {
   5313 			/*
   5314 			 * Peer does not support the chunk type.
   5315 			 */
   5316 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   5317 			error = EOPNOTSUPP;
   5318 			SCTP_TCB_UNLOCK(stcb);
   5319 			break;
   5320 		}
   5321 		if (stcb->asoc.stream_reset_outstanding) {
   5322 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   5323 			error = EALREADY;
   5324 			SCTP_TCB_UNLOCK(stcb);
   5325 			break;
   5326 		}
   5327 		if ((stradd->sas_outstrms == 0) &&
   5328 		    (stradd->sas_instrms == 0)) {
   5329 			error = EINVAL;
   5330 			goto skip_stuff;
   5331 		}
   5332 		if (stradd->sas_outstrms) {
   5333 			addstream = 1;
   5334 			/* We allocate here */
   5335 			add_o_strmcnt = stradd->sas_outstrms;
   5336 			if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
   5337 				/* You can't have more than 64k */
   5338 				error = EINVAL;
   5339 				goto skip_stuff;
   5340 			}
   5341 		}
   5342 		if (stradd->sas_instrms) {
   5343 			int cnt;
   5344 
   5345 			addstream |= 2;
   5346 			/* We allocate inside sctp_send_str_reset_req() */
   5347 			add_i_strmcnt = stradd->sas_instrms;
   5348 			cnt = add_i_strmcnt;
   5349 			cnt += stcb->asoc.streamincnt;
   5350 			if (cnt > 0x0000ffff) {
   5351 				/* You can't have more than 64k */
   5352 				error = EINVAL;
   5353 				goto skip_stuff;
   5354 			}
   5355 			if (cnt > (int)stcb->asoc.max_inbound_streams) {
   5356 				/* More than you are allowed */
   5357 				error = EINVAL;
   5358 				goto skip_stuff;
   5359 			}
   5360 		}
   5361 		error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
   5362 		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
   5363 	skip_stuff:
   5364 		SCTP_TCB_UNLOCK(stcb);
   5365 		break;
   5366 	}
   5367 	case SCTP_RESET_ASSOC:
   5368 	{
   5369 		uint32_t *value;
   5370 
   5371 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
   5372 		SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
   5373 		if (stcb == NULL) {
   5374 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   5375 			error = ENOENT;
   5376 			break;
   5377 		}
   5378 		if (stcb->asoc.reconfig_supported == 0) {
   5379 			/*
   5380 			 * Peer does not support the chunk type.
   5381 			 */
   5382 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   5383 			error = EOPNOTSUPP;
   5384 			SCTP_TCB_UNLOCK(stcb);
   5385 			break;
   5386 		}
   5387 		if (stcb->asoc.stream_reset_outstanding) {
   5388 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   5389 			error = EALREADY;
   5390 			SCTP_TCB_UNLOCK(stcb);
   5391 			break;
   5392 		}
   5393 		error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0);
   5394 		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
   5395 		SCTP_TCB_UNLOCK(stcb);
   5396 		break;
   5397 	}
   5398 	case SCTP_CONNECT_X:
   5399 		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
   5400 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5401 			error = EINVAL;
   5402 			break;
   5403 		}
   5404 		error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
   5405 		break;
   5406 	case SCTP_CONNECT_X_DELAYED:
   5407 		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
   5408 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5409 			error = EINVAL;
   5410 			break;
   5411 		}
   5412 		error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
   5413 		break;
   5414 	case SCTP_CONNECT_X_COMPLETE:
   5415 	{
   5416 		struct sockaddr *sa;
   5417 		struct sctp_nets *net;
   5418 
   5419 		/* FIXME MT: check correct? */
   5420 		SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
   5421 
   5422 		/* find tcb */
   5423 		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
   5424 			SCTP_INP_RLOCK(inp);
   5425 			stcb = LIST_FIRST(&inp->sctp_asoc_list);
   5426 			if (stcb) {
   5427 				SCTP_TCB_LOCK(stcb);
   5428 				net = sctp_findnet(stcb, sa);
   5429 			}
   5430 			SCTP_INP_RUNLOCK(inp);
   5431 		} else {
   5432 			/* We increment here since sctp_findassociation_ep_addr() wil
   5433 			 * do a decrement if it finds the stcb as long as the locked
   5434 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   5435 			 */
   5436 			SCTP_INP_INCR_REF(inp);
   5437 			stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
   5438 			if (stcb == NULL) {
   5439 				SCTP_INP_DECR_REF(inp);
   5440 			}
   5441 		}
   5442 
   5443 		if (stcb == NULL) {
   5444 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   5445 			error = ENOENT;
   5446 			break;
   5447 		}
   5448 		if (stcb->asoc.delayed_connection == 1) {
   5449 			stcb->asoc.delayed_connection = 0;
   5450 			(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
   5451 			sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
   5452 					stcb->asoc.primary_destination,
   5453 					SCTP_FROM_SCTP_USRREQ+SCTP_LOC_9);
   5454 			sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
   5455 		} else {
   5456 			/*
   5457 			 * already expired or did not use delayed
   5458 			 * connectx
   5459 			 */
   5460 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   5461 			error = EALREADY;
   5462 		}
   5463 		SCTP_TCB_UNLOCK(stcb);
   5464 		break;
   5465 	}
   5466 	case SCTP_MAX_BURST:
   5467 	{
   5468 #if defined(__FreeBSD__) && __FreeBSD_version < 900000
   5469 		uint8_t *burst;
   5470 
   5471 		SCTP_CHECK_AND_CAST(burst, optval, uint8_t, optsize);
   5472 
   5473 		SCTP_INP_WLOCK(inp);
   5474 		inp->sctp_ep.max_burst = *burst;
   5475 		SCTP_INP_WUNLOCK(inp);
   5476 #else
   5477 		struct sctp_assoc_value *av;
   5478 
   5479 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   5480 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   5481 
   5482 		if (stcb) {
   5483 			stcb->asoc.max_burst = av->assoc_value;
   5484 			SCTP_TCB_UNLOCK(stcb);
   5485 		} else {
   5486 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5487 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   5488 			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
   5489 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   5490 				SCTP_INP_WLOCK(inp);
   5491 				inp->sctp_ep.max_burst = av->assoc_value;
   5492 				SCTP_INP_WUNLOCK(inp);
   5493 			}
   5494 			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
   5495 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   5496 				SCTP_INP_RLOCK(inp);
   5497 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   5498 					SCTP_TCB_LOCK(stcb);
   5499 					stcb->asoc.max_burst = av->assoc_value;
   5500 					SCTP_TCB_UNLOCK(stcb);
   5501 				}
   5502 				SCTP_INP_RUNLOCK(inp);
   5503 			}
   5504 		}
   5505 #endif
   5506 		break;
   5507 	}
   5508 	case SCTP_MAXSEG:
   5509 	{
   5510 		struct sctp_assoc_value *av;
   5511 		int ovh;
   5512 
   5513 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   5514 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   5515 
   5516 		if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   5517 			ovh = SCTP_MED_OVERHEAD;
   5518 		} else {
   5519 			ovh = SCTP_MED_V4_OVERHEAD;
   5520 		}
   5521 		if (stcb) {
   5522 			if (av->assoc_value) {
   5523 				stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
   5524 			} else {
   5525 				stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
   5526 			}
   5527 			SCTP_TCB_UNLOCK(stcb);
   5528 		} else {
   5529 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5530 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   5531 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   5532 				SCTP_INP_WLOCK(inp);
   5533 				/* FIXME MT: I think this is not in tune with the API ID */
   5534 				if (av->assoc_value) {
   5535 					inp->sctp_frag_point = (av->assoc_value + ovh);
   5536 				} else {
   5537 					inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
   5538 				}
   5539 				SCTP_INP_WUNLOCK(inp);
   5540 			} else {
   5541 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5542 				error = EINVAL;
   5543 			}
   5544 		}
   5545 		break;
   5546 	}
   5547 	case SCTP_EVENTS:
   5548 	{
   5549 		struct sctp_event_subscribe *events;
   5550 
   5551 		SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
   5552 
   5553 		SCTP_INP_WLOCK(inp);
   5554 		if (events->sctp_data_io_event) {
   5555 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
   5556 		} else {
   5557 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
   5558 		}
   5559 
   5560 		if (events->sctp_association_event) {
   5561 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
   5562 		} else {
   5563 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
   5564 		}
   5565 
   5566 		if (events->sctp_address_event) {
   5567 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
   5568 		} else {
   5569 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
   5570 		}
   5571 
   5572 		if (events->sctp_send_failure_event) {
   5573 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
   5574 		} else {
   5575 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
   5576 		}
   5577 
   5578 		if (events->sctp_peer_error_event) {
   5579 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
   5580 		} else {
   5581 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
   5582 		}
   5583 
   5584 		if (events->sctp_shutdown_event) {
   5585 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
   5586 		} else {
   5587 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
   5588 		}
   5589 
   5590 		if (events->sctp_partial_delivery_event) {
   5591 			sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
   5592 		} else {
   5593 			sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
   5594 		}
   5595 
   5596 		if (events->sctp_adaptation_layer_event) {
   5597 			sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
   5598 		} else {
   5599 			sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
   5600 		}
   5601 
   5602 		if (events->sctp_authentication_event) {
   5603 			sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
   5604 		} else {
   5605 			sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
   5606 		}
   5607 
   5608 		if (events->sctp_sender_dry_event) {
   5609 			sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
   5610 		} else {
   5611 			sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
   5612 		}
   5613 
   5614 		if (events->sctp_stream_reset_event) {
   5615 			sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
   5616 		} else {
   5617 			sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
   5618 		}
   5619 		SCTP_INP_WUNLOCK(inp);
   5620 
   5621 		SCTP_INP_RLOCK(inp);
   5622 		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   5623 			SCTP_TCB_LOCK(stcb);
   5624 			if (events->sctp_association_event) {
   5625 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
   5626 			} else {
   5627 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
   5628 			}
   5629 			if (events->sctp_address_event) {
   5630 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
   5631 			} else {
   5632 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
   5633 			}
   5634 			if (events->sctp_send_failure_event) {
   5635 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
   5636 			} else {
   5637 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
   5638 			}
   5639 			if (events->sctp_peer_error_event) {
   5640 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
   5641 			} else {
   5642 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
   5643 			}
   5644 			if (events->sctp_shutdown_event) {
   5645 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
   5646 			} else {
   5647 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
   5648 			}
   5649 			if (events->sctp_partial_delivery_event) {
   5650 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
   5651 			} else {
   5652 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
   5653 			}
   5654 			if (events->sctp_adaptation_layer_event) {
   5655 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
   5656 			} else {
   5657 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
   5658 			}
   5659 			if (events->sctp_authentication_event) {
   5660 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
   5661 			} else {
   5662 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
   5663 			}
   5664 			if (events->sctp_sender_dry_event) {
   5665 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
   5666 			} else {
   5667 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
   5668 			}
   5669 			if (events->sctp_stream_reset_event) {
   5670 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
   5671 			} else {
   5672 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
   5673 			}
   5674 			SCTP_TCB_UNLOCK(stcb);
   5675 		}
   5676 		/* Send up the sender dry event only for 1-to-1 style sockets. */
   5677 		if (events->sctp_sender_dry_event) {
   5678 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5679 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
   5680 				stcb = LIST_FIRST(&inp->sctp_asoc_list);
   5681 				if (stcb) {
   5682 					SCTP_TCB_LOCK(stcb);
   5683 					if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
   5684 					    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
   5685 					    (stcb->asoc.stream_queue_cnt == 0)) {
   5686 						sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb,  0, NULL, SCTP_SO_LOCKED);
   5687 					}
   5688 					SCTP_TCB_UNLOCK(stcb);
   5689 				}
   5690 			}
   5691 		}
   5692 		SCTP_INP_RUNLOCK(inp);
   5693 		break;
   5694 	}
   5695 	case SCTP_ADAPTATION_LAYER:
   5696 	{
   5697 		struct sctp_setadaptation *adap_bits;
   5698 
   5699 		SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
   5700 		SCTP_INP_WLOCK(inp);
   5701 		inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
   5702 		inp->sctp_ep.adaptation_layer_indicator_provided = 1;
   5703 		SCTP_INP_WUNLOCK(inp);
   5704 		break;
   5705 	}
   5706 #ifdef SCTP_DEBUG
   5707 	case SCTP_SET_INITIAL_DBG_SEQ:
   5708 	{
   5709 		uint32_t *vvv;
   5710 
   5711 		SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
   5712 		SCTP_INP_WLOCK(inp);
   5713 		inp->sctp_ep.initial_sequence_debug = *vvv;
   5714 		SCTP_INP_WUNLOCK(inp);
   5715 		break;
   5716 	}
   5717 #endif
   5718 	case SCTP_DEFAULT_SEND_PARAM:
   5719 	{
   5720 		struct sctp_sndrcvinfo *s_info;
   5721 
   5722 		SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
   5723 		SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
   5724 
   5725 		if (stcb) {
   5726 			if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
   5727 				memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
   5728 			} else {
   5729 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5730 				error = EINVAL;
   5731 			}
   5732 			SCTP_TCB_UNLOCK(stcb);
   5733 		} else {
   5734 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5735 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   5736 			    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
   5737 			    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
   5738 				SCTP_INP_WLOCK(inp);
   5739 				memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
   5740 				SCTP_INP_WUNLOCK(inp);
   5741 			}
   5742 			if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
   5743 			    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
   5744 				SCTP_INP_RLOCK(inp);
   5745 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   5746 					SCTP_TCB_LOCK(stcb);
   5747 					if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
   5748 						memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
   5749 					}
   5750 					SCTP_TCB_UNLOCK(stcb);
   5751 				}
   5752 				SCTP_INP_RUNLOCK(inp);
   5753 			}
   5754 		}
   5755 		break;
   5756 	}
   5757 	case SCTP_PEER_ADDR_PARAMS:
   5758 	{
   5759 		struct sctp_paddrparams *paddrp;
   5760 		struct sctp_nets *net;
   5761 
   5762 		SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
   5763 		SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
   5764 		net = NULL;
   5765 		if (stcb) {
   5766 			net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
   5767 		} else {
   5768 			/* We increment here since sctp_findassociation_ep_addr() wil
   5769 			 * do a decrement if it finds the stcb as long as the locked
   5770 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   5771 			 */
   5772 			SCTP_INP_INCR_REF(inp);
   5773 			stcb = sctp_findassociation_ep_addr(&inp,
   5774 							    (struct sockaddr *)&paddrp->spp_address,
   5775 							    &net, NULL, NULL);
   5776 			if (stcb == NULL) {
   5777 				SCTP_INP_DECR_REF(inp);
   5778 			}
   5779 		}
   5780 		if (stcb && (net == NULL)) {
   5781 			struct sockaddr *sa;
   5782 
   5783 			sa = (struct sockaddr *)&paddrp->spp_address;
   5784 #ifdef INET
   5785 			if (sa->sa_family == AF_INET) {
   5786 
   5787 				struct sockaddr_in *sin;
   5788 				sin = (struct sockaddr_in *)sa;
   5789 				if (sin->sin_addr.s_addr) {
   5790 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5791 					SCTP_TCB_UNLOCK(stcb);
   5792 					error = EINVAL;
   5793 					break;
   5794 				}
   5795 			} else
   5796 #endif
   5797 #ifdef INET6
   5798 			if (sa->sa_family == AF_INET6) {
   5799 				struct sockaddr_in6 *sin6;
   5800 
   5801 				sin6 = (struct sockaddr_in6 *)sa;
   5802 				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   5803 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5804 					SCTP_TCB_UNLOCK(stcb);
   5805 					error = EINVAL;
   5806 					break;
   5807 				}
   5808 			} else
   5809 #endif
   5810 #if defined(__Userspace__)
   5811 			if (sa->sa_family == AF_CONN) {
   5812 				struct sockaddr_conn *sconn;
   5813 
   5814 				sconn = (struct sockaddr_conn *)sa;
   5815 				if (sconn->sconn_addr != NULL) {
   5816 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5817 					SCTP_TCB_UNLOCK(stcb);
   5818 					error = EINVAL;
   5819 					break;
   5820 				}
   5821 			} else
   5822 #endif
   5823 			{
   5824 				error = EAFNOSUPPORT;
   5825 				SCTP_TCB_UNLOCK(stcb);
   5826 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   5827 				break;
   5828 			}
   5829 		}
   5830 		/* sanity checks */
   5831 		if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
   5832 			if (stcb)
   5833 				SCTP_TCB_UNLOCK(stcb);
   5834 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5835 			return (EINVAL);
   5836 		}
   5837 
   5838 		if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
   5839 			if (stcb)
   5840 				SCTP_TCB_UNLOCK(stcb);
   5841 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5842 			return (EINVAL);
   5843 		}
   5844 
   5845 		if (stcb) {
   5846 			/************************TCB SPECIFIC SET ******************/
   5847 			/*
   5848 			 * do we change the timer for HB, we run
   5849 			 * only one?
   5850 			 */
   5851 			int ovh = 0;
   5852 
   5853 			if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   5854 				ovh = SCTP_MED_OVERHEAD;
   5855 			} else {
   5856 				ovh = SCTP_MED_V4_OVERHEAD;
   5857 			}
   5858 
   5859 			/* network sets ? */
   5860 			if (net) {
   5861 				/************************NET SPECIFIC SET ******************/
   5862 				if (paddrp->spp_flags & SPP_HB_DISABLE) {
   5863 					if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
   5864 					    !(net->dest_state & SCTP_ADDR_NOHB)) {
   5865 						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
   5866 								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
   5867 					}
   5868 					net->dest_state |= SCTP_ADDR_NOHB;
   5869 				}
   5870 				if (paddrp->spp_flags & SPP_HB_ENABLE) {
   5871 					if (paddrp->spp_hbinterval) {
   5872 						net->heart_beat_delay = paddrp->spp_hbinterval;
   5873 					} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
   5874 						net->heart_beat_delay = 0;
   5875 					}
   5876 					sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
   5877 					                SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
   5878 					sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
   5879 					net->dest_state &= ~SCTP_ADDR_NOHB;
   5880 				}
   5881 				if (paddrp->spp_flags & SPP_HB_DEMAND) {
   5882 					/* on demand HB */
   5883 					sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
   5884 					sctp_chunk_output(inp, stcb,  SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
   5885 					sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
   5886 				}
   5887 				if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
   5888 					if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
   5889 						sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
   5890 								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
   5891 					}
   5892 					net->dest_state |= SCTP_ADDR_NO_PMTUD;
   5893 					net->mtu = paddrp->spp_pathmtu + ovh;
   5894 					if (net->mtu < stcb->asoc.smallest_mtu) {
   5895 						sctp_pathmtu_adjustment(stcb, net->mtu);
   5896 					}
   5897 				}
   5898 				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
   5899 					if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
   5900 						sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
   5901 					}
   5902 					net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
   5903 				}
   5904 				if (paddrp->spp_pathmaxrxt) {
   5905 					if (net->dest_state & SCTP_ADDR_PF) {
   5906 						if (net->error_count > paddrp->spp_pathmaxrxt) {
   5907 							net->dest_state &= ~SCTP_ADDR_PF;
   5908 						}
   5909 					} else {
   5910 						if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
   5911 						    (net->error_count > net->pf_threshold)) {
   5912 							net->dest_state |= SCTP_ADDR_PF;
   5913 							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
   5914 							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
   5915 							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
   5916 						}
   5917 					}
   5918 					if (net->dest_state & SCTP_ADDR_REACHABLE) {
   5919 						if (net->error_count > paddrp->spp_pathmaxrxt) {
   5920 							net->dest_state &= ~SCTP_ADDR_REACHABLE;
   5921 							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
   5922 						}
   5923 					} else {
   5924 						if (net->error_count <= paddrp->spp_pathmaxrxt) {
   5925 							net->dest_state |= SCTP_ADDR_REACHABLE;
   5926 							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
   5927 						}
   5928 					}
   5929 					net->failure_threshold = paddrp->spp_pathmaxrxt;
   5930 				}
   5931 				if (paddrp->spp_flags & SPP_DSCP) {
   5932 					net->dscp = paddrp->spp_dscp & 0xfc;
   5933 					net->dscp |= 0x01;
   5934 				}
   5935 #ifdef INET6
   5936 				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
   5937 					if (net->ro._l_addr.sa.sa_family == AF_INET6) {
   5938 						net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
   5939 						net->flowlabel |= 0x80000000;
   5940 					}
   5941 				}
   5942 #endif
   5943 			} else {
   5944 				/************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
   5945 				if (paddrp->spp_pathmaxrxt) {
   5946 					stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
   5947 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   5948 						if (net->dest_state & SCTP_ADDR_PF) {
   5949 							if (net->error_count > paddrp->spp_pathmaxrxt) {
   5950 								net->dest_state &= ~SCTP_ADDR_PF;
   5951 							}
   5952 						} else {
   5953 							if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
   5954 							    (net->error_count > net->pf_threshold)) {
   5955 								net->dest_state |= SCTP_ADDR_PF;
   5956 								sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
   5957 								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
   5958 								sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
   5959 							}
   5960 						}
   5961 						if (net->dest_state & SCTP_ADDR_REACHABLE) {
   5962 							if (net->error_count > paddrp->spp_pathmaxrxt) {
   5963 								net->dest_state &= ~SCTP_ADDR_REACHABLE;
   5964 								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
   5965 							}
   5966 						} else {
   5967 							if (net->error_count <= paddrp->spp_pathmaxrxt) {
   5968 								net->dest_state |= SCTP_ADDR_REACHABLE;
   5969 								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
   5970 							}
   5971 						}
   5972 						net->failure_threshold = paddrp->spp_pathmaxrxt;
   5973 					}
   5974 				}
   5975 
   5976 				if (paddrp->spp_flags & SPP_HB_ENABLE) {
   5977 					if (paddrp->spp_hbinterval) {
   5978 						stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
   5979 					} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
   5980 						stcb->asoc.heart_beat_delay = 0;
   5981 					}
   5982 					/* Turn back on the timer */
   5983 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   5984 						if (paddrp->spp_hbinterval) {
   5985 							net->heart_beat_delay = paddrp->spp_hbinterval;
   5986 						} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
   5987 							net->heart_beat_delay = 0;
   5988 						}
   5989 						if (net->dest_state & SCTP_ADDR_NOHB) {
   5990 							net->dest_state &= ~SCTP_ADDR_NOHB;
   5991 						}
   5992 						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
   5993 								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
   5994 						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
   5995 					}
   5996 					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
   5997 				}
   5998 				if (paddrp->spp_flags & SPP_HB_DISABLE) {
   5999 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   6000 						if (!(net->dest_state & SCTP_ADDR_NOHB)) {
   6001 							net->dest_state |= SCTP_ADDR_NOHB;
   6002 							if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
   6003 								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
   6004 							}
   6005 						}
   6006 					}
   6007 					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
   6008 				}
   6009 				if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
   6010 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   6011 						if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
   6012 							sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
   6013 									SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
   6014 						}
   6015 						net->dest_state |= SCTP_ADDR_NO_PMTUD;
   6016 						net->mtu = paddrp->spp_pathmtu + ovh;
   6017 						if (net->mtu < stcb->asoc.smallest_mtu) {
   6018 							sctp_pathmtu_adjustment(stcb, net->mtu);
   6019 						}
   6020 					}
   6021 					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
   6022 				}
   6023 				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
   6024 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   6025 						if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
   6026 							sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
   6027 						}
   6028 						net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
   6029 					}
   6030 					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
   6031 				}
   6032 				if (paddrp->spp_flags & SPP_DSCP) {
   6033 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   6034 						net->dscp = paddrp->spp_dscp & 0xfc;
   6035 						net->dscp |= 0x01;
   6036 					}
   6037 					stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
   6038 					stcb->asoc.default_dscp |= 0x01;
   6039 				}
   6040 #ifdef INET6
   6041 				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
   6042 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   6043 						if (net->ro._l_addr.sa.sa_family == AF_INET6) {
   6044 							net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
   6045 							net->flowlabel |= 0x80000000;
   6046 						}
   6047 					}
   6048 					stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
   6049 					stcb->asoc.default_flowlabel |= 0x80000000;
   6050 				}
   6051 #endif
   6052 			}
   6053 			SCTP_TCB_UNLOCK(stcb);
   6054 		} else {
   6055 			/************************NO TCB, SET TO default stuff ******************/
   6056 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   6057 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   6058 			    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
   6059 				SCTP_INP_WLOCK(inp);
   6060 				/*
   6061 				 * For the TOS/FLOWLABEL stuff you set it
   6062 				 * with the options on the socket
   6063 				 */
   6064 				if (paddrp->spp_pathmaxrxt) {
   6065 					inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
   6066 				}
   6067 
   6068 				if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
   6069 					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
   6070 				else if (paddrp->spp_hbinterval) {
   6071 					if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
   6072 						paddrp->spp_hbinterval= SCTP_MAX_HB_INTERVAL;
   6073 					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
   6074 				}
   6075 
   6076 				if (paddrp->spp_flags & SPP_HB_ENABLE) {
   6077 					if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
   6078 						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
   6079 					} else if (paddrp->spp_hbinterval) {
   6080 						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
   6081 					}
   6082 					sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
   6083 				} else if (paddrp->spp_flags & SPP_HB_DISABLE) {
   6084 					sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
   6085 				}
   6086 				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
   6087 					sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
   6088 				} else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
   6089 					sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
   6090 				}
   6091 				if (paddrp->spp_flags & SPP_DSCP) {
   6092 					inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
   6093 					inp->sctp_ep.default_dscp |= 0x01;
   6094 				}
   6095 #ifdef INET6
   6096 				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
   6097 					if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   6098 						inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
   6099 						inp->sctp_ep.default_flowlabel |= 0x80000000;
   6100 					}
   6101 				}
   6102 #endif
   6103 				SCTP_INP_WUNLOCK(inp);
   6104 			} else {
   6105 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6106 				error = EINVAL;
   6107 			}
   6108 		}
   6109 		break;
   6110 	}
   6111 	case SCTP_RTOINFO:
   6112 	{
   6113 		struct sctp_rtoinfo *srto;
   6114 		uint32_t new_init, new_min, new_max;
   6115 
   6116 		SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
   6117 		SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
   6118 
   6119 		if (stcb) {
   6120 			if (srto->srto_initial)
   6121 				new_init = srto->srto_initial;
   6122 			else
   6123 				new_init = stcb->asoc.initial_rto;
   6124 			if (srto->srto_max)
   6125 				new_max = srto->srto_max;
   6126 			else
   6127 				new_max = stcb->asoc.maxrto;
   6128 			if (srto->srto_min)
   6129 				new_min = srto->srto_min;
   6130 			else
   6131 				new_min = stcb->asoc.minrto;
   6132 			if ((new_min <= new_init) && (new_init <= new_max)) {
   6133 				stcb->asoc.initial_rto = new_init;
   6134 				stcb->asoc.maxrto = new_max;
   6135 				stcb->asoc.minrto = new_min;
   6136 			} else {
   6137 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6138 				error = EINVAL;
   6139 			}
   6140 			SCTP_TCB_UNLOCK(stcb);
   6141 		} else {
   6142 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   6143 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   6144 			    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
   6145 				SCTP_INP_WLOCK(inp);
   6146 				if (srto->srto_initial)
   6147 					new_init = srto->srto_initial;
   6148 				else
   6149 					new_init = inp->sctp_ep.initial_rto;
   6150 				if (srto->srto_max)
   6151 					new_max = srto->srto_max;
   6152 				else
   6153 					new_max = inp->sctp_ep.sctp_maxrto;
   6154 				if (srto->srto_min)
   6155 					new_min = srto->srto_min;
   6156 				else
   6157 					new_min = inp->sctp_ep.sctp_minrto;
   6158 				if ((new_min <= new_init) && (new_init <= new_max)) {
   6159 					inp->sctp_ep.initial_rto = new_init;
   6160 					inp->sctp_ep.sctp_maxrto = new_max;
   6161 					inp->sctp_ep.sctp_minrto = new_min;
   6162 				} else {
   6163 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6164 					error = EINVAL;
   6165 				}
   6166 				SCTP_INP_WUNLOCK(inp);
   6167 			} else {
   6168 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6169 				error = EINVAL;
   6170 			}
   6171 		}
   6172 		break;
   6173 	}
   6174 	case SCTP_ASSOCINFO:
   6175 	{
   6176 		struct sctp_assocparams *sasoc;
   6177 
   6178 		SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
   6179 		SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
   6180 		if (sasoc->sasoc_cookie_life) {
   6181 			/* boundary check the cookie life */
   6182 			if (sasoc->sasoc_cookie_life < 1000)
   6183 				sasoc->sasoc_cookie_life = 1000;
   6184 			if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
   6185 				sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
   6186 			}
   6187 		}
   6188 		if (stcb) {
   6189 			if (sasoc->sasoc_asocmaxrxt)
   6190 				stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
   6191 			if (sasoc->sasoc_cookie_life) {
   6192 				stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
   6193 			}
   6194 			SCTP_TCB_UNLOCK(stcb);
   6195 		} else {
   6196 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   6197 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   6198 			    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
   6199 				SCTP_INP_WLOCK(inp);
   6200 				if (sasoc->sasoc_asocmaxrxt)
   6201 					inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
   6202 				if (sasoc->sasoc_cookie_life) {
   6203 					inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
   6204 				}
   6205 				SCTP_INP_WUNLOCK(inp);
   6206 			} else {
   6207 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6208 				error = EINVAL;
   6209 			}
   6210 		}
   6211 		break;
   6212 	}
   6213 	case SCTP_INITMSG:
   6214 	{
   6215 		struct sctp_initmsg *sinit;
   6216 
   6217 		SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
   6218 		SCTP_INP_WLOCK(inp);
   6219 		if (sinit->sinit_num_ostreams)
   6220 			inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
   6221 
   6222 		if (sinit->sinit_max_instreams)
   6223 			inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
   6224 
   6225 		if (sinit->sinit_max_attempts)
   6226 			inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
   6227 
   6228 		if (sinit->sinit_max_init_timeo)
   6229 			inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
   6230 		SCTP_INP_WUNLOCK(inp);
   6231 		break;
   6232 	}
   6233 	case SCTP_PRIMARY_ADDR:
   6234 	{
   6235 		struct sctp_setprim *spa;
   6236 		struct sctp_nets *net;
   6237 
   6238 		SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
   6239 		SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
   6240 
   6241 		net = NULL;
   6242 		if (stcb) {
   6243 			net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
   6244 		} else {
   6245 			/* We increment here since sctp_findassociation_ep_addr() wil
   6246 			 * do a decrement if it finds the stcb as long as the locked
   6247 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   6248 			 */
   6249 			SCTP_INP_INCR_REF(inp);
   6250 			stcb = sctp_findassociation_ep_addr(&inp,
   6251 							    (struct sockaddr *)&spa->ssp_addr,
   6252 							    &net, NULL, NULL);
   6253 			if (stcb == NULL) {
   6254 				SCTP_INP_DECR_REF(inp);
   6255 			}
   6256 		}
   6257 
   6258 		if ((stcb) && (net)) {
   6259 			if ((net != stcb->asoc.primary_destination) &&
   6260 			    (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
   6261 				/* Ok we need to set it */
   6262 				if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
   6263 					if ((stcb->asoc.alternate) &&
   6264 					    (!(net->dest_state & SCTP_ADDR_PF)) &&
   6265 					    (net->dest_state & SCTP_ADDR_REACHABLE)) {
   6266 						sctp_free_remote_addr(stcb->asoc.alternate);
   6267 						stcb->asoc.alternate = NULL;
   6268 					}
   6269 				}
   6270 			}
   6271 		} else {
   6272 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6273 			error = EINVAL;
   6274 		}
   6275 		if (stcb) {
   6276 			SCTP_TCB_UNLOCK(stcb);
   6277 		}
   6278 		break;
   6279 	}
   6280 	case SCTP_SET_DYNAMIC_PRIMARY:
   6281 	{
   6282 		union sctp_sockstore *ss;
   6283 #ifdef SCTP_MVRF
   6284 		int i, fnd = 0;
   6285 #endif
   6286 #if !defined(__Windows__) && !defined(__Userspace__)
   6287 #if defined(__APPLE__)
   6288 		struct proc *proc;
   6289 #endif
   6290 #ifdef __FreeBSD__
   6291 #if __FreeBSD_version > 602000
   6292 		error = priv_check(curthread,
   6293 				   PRIV_NETINET_RESERVEDPORT);
   6294 #elif __FreeBSD_version >= 500000
   6295 		error = suser((struct thread *)p);
   6296 #else
   6297 		error = suser(p);
   6298 #endif
   6299 #elif defined(__APPLE__)
   6300 		proc = (struct proc *)p;
   6301 		if (p) {
   6302 			error = suser(proc->p_ucred, &proc->p_acflag);
   6303 		} else {
   6304 			break;
   6305 		}
   6306 #else
   6307 		error = suser(p, 0);
   6308 #endif
   6309 #endif
   6310 		if (error)
   6311 			break;
   6312 
   6313 		SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
   6314 		/* SUPER USER CHECK? */
   6315 #ifdef SCTP_MVRF
   6316 		for (i = 0; i < inp->num_vrfs; i++) {
   6317 			if (vrf_id == inp->m_vrf_ids[i]) {
   6318 				fnd = 1;
   6319 				break;
   6320 			}
   6321 		}
   6322 		if (!fnd) {
   6323 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6324 			error = EINVAL;
   6325 			break;
   6326 		}
   6327 #endif
   6328 		error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
   6329 		break;
   6330 	}
   6331 	case SCTP_SET_PEER_PRIMARY_ADDR:
   6332 	{
   6333 		struct sctp_setpeerprim *sspp;
   6334 
   6335 		SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
   6336 		SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
   6337 		if (stcb != NULL) {
   6338 			struct sctp_ifa *ifa;
   6339 			ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
   6340 						    stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
   6341 			if (ifa == NULL) {
   6342 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6343 				error = EINVAL;
   6344 				goto out_of_it;
   6345 			}
   6346 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
   6347 				/* Must validate the ifa found is in our ep */
   6348 				struct sctp_laddr *laddr;
   6349 				int found = 0;
   6350 				LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
   6351 					if (laddr->ifa == NULL) {
   6352 						SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
   6353 							__FUNCTION__);
   6354 						continue;
   6355 					}
   6356 					if (laddr->ifa == ifa) {
   6357 						found = 1;
   6358 						break;
   6359 					}
   6360 				}
   6361 				if (!found) {
   6362 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6363 					error = EINVAL;
   6364 					goto out_of_it;
   6365 				}
   6366 #if defined(__FreeBSD__)
   6367 			} else {
   6368 				switch (sspp->sspp_addr.ss_family) {
   6369 #ifdef INET
   6370 				case AF_INET:
   6371 				{
   6372 					struct sockaddr_in *sin;
   6373 
   6374 					sin = (struct sockaddr_in *)&sspp->sspp_addr;
   6375 					if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
   6376 					                     &sin->sin_addr) != 0) {
   6377 						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6378 						error = EINVAL;
   6379 						goto out_of_it;
   6380 					}
   6381 					break;
   6382 				}
   6383 #endif
   6384 #ifdef INET6
   6385 				case AF_INET6:
   6386 				{
   6387 					struct sockaddr_in6 *sin6;
   6388 
   6389 					sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
   6390 					if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
   6391 					                     &sin6->sin6_addr) != 0) {
   6392 						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6393 						error = EINVAL;
   6394 						goto out_of_it;
   6395 					}
   6396 					break;
   6397 				}
   6398 #endif
   6399 				default:
   6400 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6401 					error = EINVAL;
   6402 					goto out_of_it;
   6403 				}
   6404 #endif
   6405 			}
   6406 			if (sctp_set_primary_ip_address_sa(stcb,
   6407 							   (struct sockaddr *)&sspp->sspp_addr) != 0) {
   6408 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6409 				error = EINVAL;
   6410 			}
   6411 		out_of_it:
   6412 			SCTP_TCB_UNLOCK(stcb);
   6413 		} else {
   6414 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6415 			error = EINVAL;
   6416 		}
   6417 		break;
   6418 	}
   6419 	case SCTP_BINDX_ADD_ADDR:
   6420 	{
   6421 		struct sctp_getaddresses *addrs;
   6422 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
   6423 		struct thread *td;
   6424 
   6425 		td = (struct thread *)p;
   6426 #endif
   6427 		SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
   6428 				    optsize);
   6429 #ifdef INET
   6430 		if (addrs->addr->sa_family == AF_INET) {
   6431 			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
   6432 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6433 				error = EINVAL;
   6434 				break;
   6435 			}
   6436 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   6437 			if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
   6438 				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6439 				break;
   6440 			}
   6441 #endif
   6442 		} else
   6443 #endif
   6444 #ifdef INET6
   6445 		if (addrs->addr->sa_family == AF_INET6) {
   6446 			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
   6447 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6448 				error = EINVAL;
   6449 				break;
   6450 			}
   6451 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   6452 			if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
   6453 											   (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
   6454 			  SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6455 			  break;
   6456 			}
   6457 #endif
   6458 		} else
   6459 #endif
   6460 		{
   6461 		       error = EAFNOSUPPORT;
   6462 		       break;
   6463 		}
   6464 		sctp_bindx_add_address(so, inp, addrs->addr,
   6465 				       addrs->sget_assoc_id, vrf_id,
   6466 				       &error, p);
   6467 		break;
   6468 	}
   6469 	case SCTP_BINDX_REM_ADDR:
   6470 	{
   6471 		struct sctp_getaddresses *addrs;
   6472 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
   6473 		struct thread *td;
   6474 		td = (struct thread *)p;
   6475 
   6476 #endif
   6477 		SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
   6478 #ifdef INET
   6479 		if (addrs->addr->sa_family == AF_INET) {
   6480 			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
   6481 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6482 				error = EINVAL;
   6483 				break;
   6484 			}
   6485 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   6486 		if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
   6487 				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6488 				break;
   6489 			}
   6490 #endif
   6491 		} else
   6492 #endif
   6493 #ifdef INET6
   6494 		if (addrs->addr->sa_family == AF_INET6) {
   6495 			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
   6496 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6497 				error = EINVAL;
   6498 				break;
   6499 			}
   6500 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   6501 			if (td != NULL &&
   6502 			    (error = prison_local_ip6(td->td_ucred,
   6503 			                              &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
   6504 			                              (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
   6505 				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6506 				break;
   6507 			}
   6508 #endif
   6509 		} else
   6510 #endif
   6511 		{
   6512 			error = EAFNOSUPPORT;
   6513 			break;
   6514 		}
   6515 		sctp_bindx_delete_address(inp, addrs->addr,
   6516 					  addrs->sget_assoc_id, vrf_id,
   6517 					  &error);
   6518 		break;
   6519 	}
   6520 #ifdef __APPLE__
   6521 	case SCTP_LISTEN_FIX:
   6522 		/* only applies to one-to-many sockets */
   6523 		if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
   6524 			/* make sure the ACCEPTCONN flag is OFF */
   6525 			so->so_options &= ~SO_ACCEPTCONN;
   6526 		} else {
   6527 			/* otherwise, not allowed */
   6528 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6529 			error = EINVAL;
   6530 		}
   6531 		break;
   6532 #endif				/* __APPLE__ */
   6533 	case SCTP_EVENT:
   6534 	{
   6535 		struct sctp_event *event;
   6536 		uint32_t event_type;
   6537 
   6538 		SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
   6539 		SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
   6540 		switch (event->se_type) {
   6541 		case SCTP_ASSOC_CHANGE:
   6542 			event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
   6543 			break;
   6544 		case SCTP_PEER_ADDR_CHANGE:
   6545 			event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
   6546 			break;
   6547 		case SCTP_REMOTE_ERROR:
   6548 			event_type = SCTP_PCB_FLAGS_RECVPEERERR;
   6549 			break;
   6550 		case SCTP_SEND_FAILED:
   6551 			event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
   6552 			break;
   6553 		case SCTP_SHUTDOWN_EVENT:
   6554 			event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
   6555 			break;
   6556 		case SCTP_ADAPTATION_INDICATION:
   6557 			event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
   6558 			break;
   6559 		case SCTP_PARTIAL_DELIVERY_EVENT:
   6560 			event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
   6561 			break;
   6562 		case SCTP_AUTHENTICATION_EVENT:
   6563 			event_type = SCTP_PCB_FLAGS_AUTHEVNT;
   6564 			break;
   6565 		case SCTP_STREAM_RESET_EVENT:
   6566 			event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
   6567 			break;
   6568 		case SCTP_SENDER_DRY_EVENT:
   6569 			event_type = SCTP_PCB_FLAGS_DRYEVNT;
   6570 			break;
   6571 		case SCTP_NOTIFICATIONS_STOPPED_EVENT:
   6572 			event_type = 0;
   6573 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
   6574 			error = ENOTSUP;
   6575 			break;
   6576 		case SCTP_ASSOC_RESET_EVENT:
   6577 			event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
   6578 			break;
   6579 		case SCTP_STREAM_CHANGE_EVENT:
   6580 			event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
   6581 			break;
   6582 		case SCTP_SEND_FAILED_EVENT:
   6583 			event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
   6584 			break;
   6585 		default:
   6586 			event_type = 0;
   6587 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6588 			error = EINVAL;
   6589 			break;
   6590 		}
   6591 		if (event_type > 0) {
   6592 			if (stcb) {
   6593 				if (event->se_on) {
   6594 					sctp_stcb_feature_on(inp, stcb, event_type);
   6595 					if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
   6596 						if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
   6597 						    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
   6598 						    (stcb->asoc.stream_queue_cnt == 0)) {
   6599 							sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb,  0, NULL, SCTP_SO_LOCKED);
   6600 						}
   6601 					}
   6602 				} else {
   6603 					sctp_stcb_feature_off(inp, stcb, event_type);
   6604 				}
   6605 				SCTP_TCB_UNLOCK(stcb);
   6606 			} else {
   6607 				/*
   6608 				 * We don't want to send up a storm of events,
   6609 				 * so return an error for sender dry events
   6610 				 */
   6611 				if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
   6612 				    ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
   6613 				    ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
   6614 				    ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
   6615 				     (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
   6616 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
   6617 					error = ENOTSUP;
   6618 					break;
   6619 				}
   6620 				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   6621 				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   6622 				    (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
   6623 				    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
   6624 					SCTP_INP_WLOCK(inp);
   6625 					if (event->se_on) {
   6626 						sctp_feature_on(inp, event_type);
   6627 					} else {
   6628 						sctp_feature_off(inp, event_type);
   6629 					}
   6630 					SCTP_INP_WUNLOCK(inp);
   6631 				}
   6632 				if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
   6633 				    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
   6634 					SCTP_INP_RLOCK(inp);
   6635 					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   6636 						SCTP_TCB_LOCK(stcb);
   6637 						if (event->se_on) {
   6638 							sctp_stcb_feature_on(inp, stcb, event_type);
   6639 						} else {
   6640 							sctp_stcb_feature_off(inp, stcb, event_type);
   6641 						}
   6642 						SCTP_TCB_UNLOCK(stcb);
   6643 					}
   6644 					SCTP_INP_RUNLOCK(inp);
   6645 				}
   6646 			}
   6647 		}
   6648 		break;
   6649 	}
   6650 	case SCTP_RECVRCVINFO:
   6651 	{
   6652 		int *onoff;
   6653 
   6654 		SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
   6655 		SCTP_INP_WLOCK(inp);
   6656 		if (*onoff != 0) {
   6657 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
   6658 		} else {
   6659 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
   6660 		}
   6661 		SCTP_INP_WUNLOCK(inp);
   6662 		break;
   6663 	}
   6664 	case SCTP_RECVNXTINFO:
   6665 	{
   6666 		int *onoff;
   6667 
   6668 		SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
   6669 		SCTP_INP_WLOCK(inp);
   6670 		if (*onoff != 0) {
   6671 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
   6672 		} else {
   6673 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
   6674 		}
   6675 		SCTP_INP_WUNLOCK(inp);
   6676 		break;
   6677 	}
   6678 	case SCTP_DEFAULT_SNDINFO:
   6679 	{
   6680 		struct sctp_sndinfo *info;
   6681 		uint16_t policy;
   6682 
   6683 		SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
   6684 		SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
   6685 
   6686 		if (stcb) {
   6687 			if (info->snd_sid < stcb->asoc.streamoutcnt) {
   6688 				stcb->asoc.def_send.sinfo_stream = info->snd_sid;
   6689 				policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
   6690 				stcb->asoc.def_send.sinfo_flags = info->snd_flags;
   6691 				stcb->asoc.def_send.sinfo_flags |= policy;
   6692 				stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
   6693 				stcb->asoc.def_send.sinfo_context = info->snd_context;
   6694 			} else {
   6695 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6696 				error = EINVAL;
   6697 			}
   6698 			SCTP_TCB_UNLOCK(stcb);
   6699 		} else {
   6700 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   6701 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   6702 			    (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
   6703 			    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
   6704 				SCTP_INP_WLOCK(inp);
   6705 				inp->def_send.sinfo_stream = info->snd_sid;
   6706 				policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
   6707 				inp->def_send.sinfo_flags = info->snd_flags;
   6708 				inp->def_send.sinfo_flags |= policy;
   6709 				inp->def_send.sinfo_ppid = info->snd_ppid;
   6710 				inp->def_send.sinfo_context = info->snd_context;
   6711 				SCTP_INP_WUNLOCK(inp);
   6712 			}
   6713 			if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
   6714 			    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
   6715 				SCTP_INP_RLOCK(inp);
   6716 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   6717 					SCTP_TCB_LOCK(stcb);
   6718 					if (info->snd_sid < stcb->asoc.streamoutcnt) {
   6719 						stcb->asoc.def_send.sinfo_stream = info->snd_sid;
   6720 						policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
   6721 						stcb->asoc.def_send.sinfo_flags = info->snd_flags;
   6722 						stcb->asoc.def_send.sinfo_flags |= policy;
   6723 						stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
   6724 						stcb->asoc.def_send.sinfo_context = info->snd_context;
   6725 					}
   6726 					SCTP_TCB_UNLOCK(stcb);
   6727 				}
   6728 				SCTP_INP_RUNLOCK(inp);
   6729 			}
   6730 		}
   6731 		break;
   6732 	}
   6733 	case SCTP_DEFAULT_PRINFO:
   6734 	{
   6735 		struct sctp_default_prinfo *info;
   6736 
   6737 		SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
   6738 		SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
   6739 
   6740 		if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
   6741 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6742 			error = EINVAL;
   6743 			break;
   6744 		}
   6745 		if (stcb) {
   6746 			stcb->asoc.def_send.sinfo_flags &= 0xfff0;
   6747 			stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
   6748 			stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
   6749 			SCTP_TCB_UNLOCK(stcb);
   6750 		} else {
   6751 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   6752 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   6753 			    (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
   6754 			    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
   6755 				SCTP_INP_WLOCK(inp);
   6756 				inp->def_send.sinfo_flags &= 0xfff0;
   6757 				inp->def_send.sinfo_flags |= info->pr_policy;
   6758 				inp->def_send.sinfo_timetolive = info->pr_value;
   6759 				SCTP_INP_WUNLOCK(inp);
   6760 			}
   6761 			if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
   6762 			    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
   6763 				SCTP_INP_RLOCK(inp);
   6764 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   6765 					SCTP_TCB_LOCK(stcb);
   6766 					stcb->asoc.def_send.sinfo_flags &= 0xfff0;
   6767 					stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
   6768 					stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
   6769 					SCTP_TCB_UNLOCK(stcb);
   6770 				}
   6771 				SCTP_INP_RUNLOCK(inp);
   6772 			}
   6773 		}
   6774 		break;
   6775 	}
   6776 	case SCTP_PEER_ADDR_THLDS:
   6777 		/* Applies to the specific association */
   6778 	{
   6779 		struct sctp_paddrthlds *thlds;
   6780 		struct sctp_nets *net;
   6781 
   6782 		SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
   6783 		SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
   6784 		net = NULL;
   6785 		if (stcb) {
   6786 			net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
   6787 		} else {
   6788 			/* We increment here since sctp_findassociation_ep_addr() wil
   6789 			 * do a decrement if it finds the stcb as long as the locked
   6790 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   6791 			 */
   6792 			SCTP_INP_INCR_REF(inp);
   6793 			stcb = sctp_findassociation_ep_addr(&inp,
   6794 							    (struct sockaddr *)&thlds->spt_address,
   6795 							    &net, NULL, NULL);
   6796 			if (stcb == NULL) {
   6797 				SCTP_INP_DECR_REF(inp);
   6798 			}
   6799 		}
   6800 		if (stcb && (net == NULL)) {
   6801 			struct sockaddr *sa;
   6802 
   6803 			sa = (struct sockaddr *)&thlds->spt_address;
   6804 #ifdef INET
   6805 			if (sa->sa_family == AF_INET) {
   6806 
   6807 				struct sockaddr_in *sin;
   6808 				sin = (struct sockaddr_in *)sa;
   6809 				if (sin->sin_addr.s_addr) {
   6810 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6811 					SCTP_TCB_UNLOCK(stcb);
   6812 					error = EINVAL;
   6813 					break;
   6814 				}
   6815 			} else
   6816 #endif
   6817 #ifdef INET6
   6818 			if (sa->sa_family == AF_INET6) {
   6819 				struct sockaddr_in6 *sin6;
   6820 
   6821 				sin6 = (struct sockaddr_in6 *)sa;
   6822 				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   6823 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6824 					SCTP_TCB_UNLOCK(stcb);
   6825 					error = EINVAL;
   6826 					break;
   6827 				}
   6828 			} else
   6829 #endif
   6830 #if defined(__Userspace__)
   6831 			if (sa->sa_family == AF_CONN) {
   6832 				struct sockaddr_conn *sconn;
   6833 
   6834 				sconn = (struct sockaddr_conn *)sa;
   6835 				if (sconn->sconn_addr != NULL) {
   6836 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6837 					SCTP_TCB_UNLOCK(stcb);
   6838 					error = EINVAL;
   6839 					break;
   6840 				}
   6841 			} else
   6842 #endif
   6843 			{
   6844 				error = EAFNOSUPPORT;
   6845 				SCTP_TCB_UNLOCK(stcb);
   6846 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6847 				break;
   6848 			}
   6849 		}
   6850 		if (stcb) {
   6851 			if (net) {
   6852 				if (net->dest_state & SCTP_ADDR_PF) {
   6853 					if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
   6854 					    (net->failure_threshold <= thlds->spt_pathpfthld)) {
   6855 						net->dest_state &= ~SCTP_ADDR_PF;
   6856 					}
   6857 				} else {
   6858 					if ((net->failure_threshold > thlds->spt_pathpfthld) &&
   6859 					    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
   6860 						net->dest_state |= SCTP_ADDR_PF;
   6861 						sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
   6862 						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
   6863 						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
   6864 					}
   6865 				}
   6866 				if (net->dest_state & SCTP_ADDR_REACHABLE) {
   6867 					if (net->failure_threshold > thlds->spt_pathmaxrxt) {
   6868 						net->dest_state &= ~SCTP_ADDR_REACHABLE;
   6869 						sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
   6870 					}
   6871 				} else {
   6872 					if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
   6873 						net->dest_state |= SCTP_ADDR_REACHABLE;
   6874 						sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
   6875 					}
   6876 				}
   6877 				net->failure_threshold = thlds->spt_pathmaxrxt;
   6878 				net->pf_threshold = thlds->spt_pathpfthld;
   6879 			} else {
   6880 				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   6881 					if (net->dest_state & SCTP_ADDR_PF) {
   6882 						if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
   6883 						    (net->failure_threshold <= thlds->spt_pathpfthld)) {
   6884 							net->dest_state &= ~SCTP_ADDR_PF;
   6885 						}
   6886 					} else {
   6887 						if ((net->failure_threshold > thlds->spt_pathpfthld) &&
   6888 						    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
   6889 							net->dest_state |= SCTP_ADDR_PF;
   6890 							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
   6891 							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
   6892 							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
   6893 						}
   6894 					}
   6895 					if (net->dest_state & SCTP_ADDR_REACHABLE) {
   6896 						if (net->failure_threshold > thlds->spt_pathmaxrxt) {
   6897 							net->dest_state &= ~SCTP_ADDR_REACHABLE;
   6898 							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
   6899 						}
   6900 					} else {
   6901 						if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
   6902 							net->dest_state |= SCTP_ADDR_REACHABLE;
   6903 							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
   6904 						}
   6905 					}
   6906 					net->failure_threshold = thlds->spt_pathmaxrxt;
   6907 					net->pf_threshold = thlds->spt_pathpfthld;
   6908 				}
   6909 				stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
   6910 				stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
   6911 			}
   6912 		} else {
   6913 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   6914 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   6915 			    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
   6916 				SCTP_INP_WLOCK(inp);
   6917 				inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
   6918 				inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
   6919 				SCTP_INP_WUNLOCK(inp);
   6920 			} else {
   6921 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6922 				error = EINVAL;
   6923 			}
   6924 		}
   6925 		break;
   6926 	}
   6927 	case SCTP_REMOTE_UDP_ENCAPS_PORT:
   6928 	{
   6929 		struct sctp_udpencaps *encaps;
   6930 		struct sctp_nets *net;
   6931 
   6932 		SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
   6933 		SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
   6934 		if (stcb) {
   6935 			net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
   6936 		} else {
   6937 			/* We increment here since sctp_findassociation_ep_addr() wil
   6938 			 * do a decrement if it finds the stcb as long as the locked
   6939 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   6940 			 */
   6941 			net = NULL;
   6942 			SCTP_INP_INCR_REF(inp);
   6943 			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
   6944 			if (stcb == NULL) {
   6945 				SCTP_INP_DECR_REF(inp);
   6946 			}
   6947 		}
   6948 		if (stcb && (net == NULL)) {
   6949 			struct sockaddr *sa;
   6950 
   6951 			sa = (struct sockaddr *)&encaps->sue_address;
   6952 #ifdef INET
   6953 			if (sa->sa_family == AF_INET) {
   6954 
   6955 				struct sockaddr_in *sin;
   6956 				sin = (struct sockaddr_in *)sa;
   6957 				if (sin->sin_addr.s_addr) {
   6958 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6959 					SCTP_TCB_UNLOCK(stcb);
   6960 					error = EINVAL;
   6961 					break;
   6962 				}
   6963 			} else
   6964 #endif
   6965 #ifdef INET6
   6966 			if (sa->sa_family == AF_INET6) {
   6967 				struct sockaddr_in6 *sin6;
   6968 
   6969 				sin6 = (struct sockaddr_in6 *)sa;
   6970 				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   6971 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6972 					SCTP_TCB_UNLOCK(stcb);
   6973 					error = EINVAL;
   6974 					break;
   6975 				}
   6976 			} else
   6977 #endif
   6978 #if defined(__Userspace__)
   6979 			if (sa->sa_family == AF_CONN) {
   6980 				struct sockaddr_conn *sconn;
   6981 
   6982 				sconn = (struct sockaddr_conn *)sa;
   6983 				if (sconn->sconn_addr != NULL) {
   6984 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6985 					SCTP_TCB_UNLOCK(stcb);
   6986 					error = EINVAL;
   6987 					break;
   6988 				}
   6989 			} else
   6990 #endif
   6991 			{
   6992 					error = EAFNOSUPPORT;
   6993 					SCTP_TCB_UNLOCK(stcb);
   6994 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6995 					break;
   6996 				}
   6997 		}
   6998 
   6999 		if (stcb) {
   7000 			if (net) {
   7001 				net->port = encaps->sue_port;
   7002 			} else {
   7003 				stcb->asoc.port = encaps->sue_port;
   7004 			}
   7005 			SCTP_TCB_UNLOCK(stcb);
   7006 		} else {
   7007 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   7008 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   7009 			    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
   7010 				SCTP_INP_WLOCK(inp);
   7011 				inp->sctp_ep.port = encaps->sue_port;
   7012 				SCTP_INP_WUNLOCK(inp);
   7013 			} else {
   7014 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7015 				error = EINVAL;
   7016 			}
   7017 		}
   7018 		break;
   7019 	}
   7020 	case SCTP_ECN_SUPPORTED:
   7021 	{
   7022 		struct sctp_assoc_value *av;
   7023 
   7024 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   7025 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   7026 
   7027 		if (stcb) {
   7028 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7029 			error = EINVAL;
   7030 			SCTP_TCB_UNLOCK(stcb);
   7031 		} else {
   7032 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   7033 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   7034 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   7035 				SCTP_INP_WLOCK(inp);
   7036 				if (av->assoc_value == 0) {
   7037 					inp->ecn_supported = 0;
   7038 				} else {
   7039 					inp->ecn_supported = 1;
   7040 				}
   7041 				SCTP_INP_WUNLOCK(inp);
   7042 			} else {
   7043 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7044 				error = EINVAL;
   7045 			}
   7046 		}
   7047 		break;
   7048 	}
   7049 	case SCTP_PR_SUPPORTED:
   7050 	{
   7051 		struct sctp_assoc_value *av;
   7052 
   7053 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   7054 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   7055 
   7056 		if (stcb) {
   7057 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7058 			error = EINVAL;
   7059 			SCTP_TCB_UNLOCK(stcb);
   7060 		} else {
   7061 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   7062 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   7063 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   7064 				SCTP_INP_WLOCK(inp);
   7065 				if (av->assoc_value == 0) {
   7066 					inp->prsctp_supported = 0;
   7067 				} else {
   7068 					inp->prsctp_supported = 1;
   7069 				}
   7070 				SCTP_INP_WUNLOCK(inp);
   7071 			} else {
   7072 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7073 				error = EINVAL;
   7074 			}
   7075 		}
   7076 		break;
   7077 	}
   7078 	case SCTP_AUTH_SUPPORTED:
   7079 	{
   7080 		struct sctp_assoc_value *av;
   7081 
   7082 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   7083 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   7084 
   7085 		if (stcb) {
   7086 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7087 			error = EINVAL;
   7088 			SCTP_TCB_UNLOCK(stcb);
   7089 		} else {
   7090 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   7091 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   7092 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   7093 				if ((av->assoc_value == 0) &&
   7094 				    (inp->asconf_supported == 1)) {
   7095 				    	/* AUTH is required for ASCONF */
   7096 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7097 					error = EINVAL;
   7098 				} else {
   7099 					SCTP_INP_WLOCK(inp);
   7100 					if (av->assoc_value == 0) {
   7101 						inp->auth_supported = 0;
   7102 					} else {
   7103 						inp->auth_supported = 1;
   7104 					}
   7105 					SCTP_INP_WUNLOCK(inp);
   7106 				}
   7107 			} else {
   7108 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7109 				error = EINVAL;
   7110 			}
   7111 		}
   7112 		break;
   7113 	}
   7114 	case SCTP_ASCONF_SUPPORTED:
   7115 	{
   7116 		struct sctp_assoc_value *av;
   7117 
   7118 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   7119 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   7120 
   7121 		if (stcb) {
   7122 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7123 			error = EINVAL;
   7124 			SCTP_TCB_UNLOCK(stcb);
   7125 		} else {
   7126 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   7127 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   7128 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   7129 				if ((av->assoc_value != 0) &&
   7130 				    (inp->auth_supported == 0)) {
   7131 				    	/* AUTH is required for ASCONF */
   7132 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7133 					error = EINVAL;
   7134 				} else {
   7135 					SCTP_INP_WLOCK(inp);
   7136 					if (av->assoc_value == 0) {
   7137 						inp->asconf_supported = 0;
   7138 						sctp_auth_delete_chunk(SCTP_ASCONF,
   7139 						                       inp->sctp_ep.local_auth_chunks);
   7140 						sctp_auth_delete_chunk(SCTP_ASCONF_ACK,
   7141 						                       inp->sctp_ep.local_auth_chunks);
   7142 					} else {
   7143 						inp->asconf_supported = 1;
   7144 						sctp_auth_add_chunk(SCTP_ASCONF,
   7145 						                    inp->sctp_ep.local_auth_chunks);
   7146 						sctp_auth_add_chunk(SCTP_ASCONF_ACK,
   7147 						                    inp->sctp_ep.local_auth_chunks);
   7148 					}
   7149 					SCTP_INP_WUNLOCK(inp);
   7150 				}
   7151 			} else {
   7152 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7153 				error = EINVAL;
   7154 			}
   7155 		}
   7156 		break;
   7157 	}
   7158 	case SCTP_RECONFIG_SUPPORTED:
   7159 	{
   7160 		struct sctp_assoc_value *av;
   7161 
   7162 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   7163 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   7164 
   7165 		if (stcb) {
   7166 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7167 			error = EINVAL;
   7168 			SCTP_TCB_UNLOCK(stcb);
   7169 		} else {
   7170 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   7171 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   7172 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   7173 				SCTP_INP_WLOCK(inp);
   7174 				if (av->assoc_value == 0) {
   7175 					inp->reconfig_supported = 0;
   7176 				} else {
   7177 					inp->reconfig_supported = 1;
   7178 				}
   7179 				SCTP_INP_WUNLOCK(inp);
   7180 			} else {
   7181 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7182 				error = EINVAL;
   7183 			}
   7184 		}
   7185 		break;
   7186 	}
   7187 	case SCTP_NRSACK_SUPPORTED:
   7188 	{
   7189 		struct sctp_assoc_value *av;
   7190 
   7191 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   7192 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   7193 
   7194 		if (stcb) {
   7195 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7196 			error = EINVAL;
   7197 			SCTP_TCB_UNLOCK(stcb);
   7198 		} else {
   7199 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   7200 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   7201 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   7202 				SCTP_INP_WLOCK(inp);
   7203 				if (av->assoc_value == 0) {
   7204 					inp->nrsack_supported = 0;
   7205 				} else {
   7206 					inp->nrsack_supported = 1;
   7207 				}
   7208 				SCTP_INP_WUNLOCK(inp);
   7209 			} else {
   7210 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7211 				error = EINVAL;
   7212 			}
   7213 		}
   7214 		break;
   7215 	}
   7216 	case SCTP_PKTDROP_SUPPORTED:
   7217 	{
   7218 		struct sctp_assoc_value *av;
   7219 
   7220 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   7221 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   7222 
   7223 		if (stcb) {
   7224 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7225 			error = EINVAL;
   7226 			SCTP_TCB_UNLOCK(stcb);
   7227 		} else {
   7228 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   7229 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   7230 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   7231 				SCTP_INP_WLOCK(inp);
   7232 				if (av->assoc_value == 0) {
   7233 					inp->pktdrop_supported = 0;
   7234 				} else {
   7235 					inp->pktdrop_supported = 1;
   7236 				}
   7237 				SCTP_INP_WUNLOCK(inp);
   7238 			} else {
   7239 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7240 				error = EINVAL;
   7241 			}
   7242 		}
   7243 		break;
   7244 	}
   7245 	default:
   7246 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
   7247 		error = ENOPROTOOPT;
   7248 		break;
   7249 	} /* end switch (opt) */
   7250 	return (error);
   7251 }
   7252 
   7253 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   7254 int
   7255 sctp_ctloutput(struct socket *so, struct sockopt *sopt)
   7256 {
   7257 	void *optval = NULL;
   7258 	size_t optsize = 0;
   7259 	void *p;
   7260 	int error = 0;
   7261 
   7262 	if (sopt->sopt_level != IPPROTO_SCTP) {
   7263 		/* wrong proto level... send back up to IP */
   7264 #ifdef INET6
   7265 		if (INP_CHECK_SOCKAF(so, AF_INET6))
   7266 			error = ip6_ctloutput(so, sopt);
   7267 #endif				/* INET6 */
   7268 #if defined(INET) && defined(INET6)
   7269 		else
   7270 #endif
   7271 #ifdef INET
   7272 			error = ip_ctloutput(so, sopt);
   7273 #endif
   7274 		return (error);
   7275 	}
   7276 	optsize = sopt->sopt_valsize;
   7277 	if (optsize) {
   7278 		SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
   7279 		if (optval == NULL) {
   7280 			SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
   7281 			return (ENOBUFS);
   7282 		}
   7283 		error = sooptcopyin(sopt, optval, optsize, optsize);
   7284 		if (error) {
   7285 			SCTP_FREE(optval, SCTP_M_SOCKOPT);
   7286 			goto out;
   7287 		}
   7288 	}
   7289 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__Windows__)
   7290 	p = (void *)sopt->sopt_td;
   7291 #else
   7292 	p = (void *)sopt->sopt_p;
   7293 #endif
   7294 	if (sopt->sopt_dir == SOPT_SET) {
   7295 		error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
   7296 	} else if (sopt->sopt_dir == SOPT_GET) {
   7297 		error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
   7298 	} else {
   7299 		SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7300 		error = EINVAL;
   7301 	}
   7302 	if ((error == 0) && (optval != NULL)) {
   7303 		error = sooptcopyout(sopt, optval, optsize);
   7304 		SCTP_FREE(optval, SCTP_M_SOCKOPT);
   7305 	} else if (optval != NULL) {
   7306 		SCTP_FREE(optval, SCTP_M_SOCKOPT);
   7307 	}
   7308 out:
   7309 	return (error);
   7310 }
   7311 #endif
   7312 
   7313 #ifdef INET
   7314 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
   7315 static int
   7316 sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
   7317 {
   7318 #else
   7319 #if defined(__FreeBSD__) || defined(__APPLE__)
   7320 static int
   7321 sctp_connect(struct socket *so, struct sockaddr *addr, struct proc *p)
   7322 {
   7323 #elif defined(__Panda__) || defined(__Userspace__)
   7324 int
   7325 sctp_connect(struct socket *so, struct sockaddr *addr)
   7326 {
   7327 	void *p = NULL;
   7328 #elif defined(__Windows__)
   7329 static int
   7330 sctp_connect(struct socket *so, struct sockaddr *addr, PKTHREAD p)
   7331 {
   7332 #else
   7333 static int
   7334 sctp_connect(struct socket *so, struct mbuf *nam, struct proc *p)
   7335 {
   7336 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
   7337 
   7338 #endif
   7339 #endif
   7340 #ifdef SCTP_MVRF
   7341 	int i, fnd = 0;
   7342 #endif
   7343 	int error = 0;
   7344 	int create_lock_on = 0;
   7345 	uint32_t vrf_id;
   7346 	struct sctp_inpcb *inp;
   7347 	struct sctp_tcb *stcb = NULL;
   7348 
   7349 	inp = (struct sctp_inpcb *)so->so_pcb;
   7350 	if (inp == NULL) {
   7351 		/* I made the same as TCP since we are not setup? */
   7352 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7353 		return (ECONNRESET);
   7354 	}
   7355 	if (addr == NULL) {
   7356 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7357 		return EINVAL;
   7358 	}
   7359 
   7360 #if defined(__Userspace__)
   7361         /* TODO __Userspace__ falls into this code for IPv6 stuff at the moment... */
   7362 #endif
   7363 #if !defined(__Windows__) && !defined(__Userspace_os_Linux) && !defined(__Userspace_os_Windows)
   7364 	switch (addr->sa_family) {
   7365 #ifdef INET6
   7366 	case AF_INET6:
   7367 	{
   7368 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   7369 		struct sockaddr_in6 *sin6p;
   7370 
   7371 #endif
   7372 		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
   7373 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7374 			return (EINVAL);
   7375 		}
   7376 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   7377 		sin6p = (struct sockaddr_in6 *)addr;
   7378 		if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
   7379 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   7380 			return (error);
   7381 		}
   7382 #endif
   7383 		break;
   7384 	}
   7385 #endif
   7386 #ifdef INET
   7387 	case AF_INET:
   7388 	{
   7389 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   7390 		struct sockaddr_in *sinp;
   7391 
   7392 #endif
   7393 #if !defined(__Userspace_os_Windows)
   7394 		if (addr->sa_len != sizeof(struct sockaddr_in)) {
   7395 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7396 			return (EINVAL);
   7397 		}
   7398 #endif
   7399 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   7400 		sinp = (struct sockaddr_in *)addr;
   7401 		if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
   7402 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   7403 			return (error);
   7404 		}
   7405 #endif
   7406 		break;
   7407 	}
   7408 #endif
   7409 	default:
   7410 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
   7411 		return (EAFNOSUPPORT);
   7412 	}
   7413 #endif
   7414 	SCTP_INP_INCR_REF(inp);
   7415 	SCTP_ASOC_CREATE_LOCK(inp);
   7416 	create_lock_on = 1;
   7417 
   7418 
   7419 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
   7420 	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
   7421 		/* Should I really unlock ? */
   7422 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
   7423 	        error = EFAULT;
   7424 		goto out_now;
   7425 	}
   7426 #ifdef INET6
   7427 	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
   7428 	    (addr->sa_family == AF_INET6)) {
   7429 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7430 		error = EINVAL;
   7431 		goto out_now;
   7432 	}
   7433 #endif
   7434 #if defined(__Userspace__)
   7435 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) &&
   7436 	    (addr->sa_family != AF_CONN)) {
   7437 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7438 		error = EINVAL;
   7439 		goto out_now;
   7440 	}
   7441 #endif
   7442 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
   7443 	    SCTP_PCB_FLAGS_UNBOUND) {
   7444 		/* Bind a ephemeral port */
   7445 		error = sctp_inpcb_bind(so, NULL, NULL, p);
   7446 		if (error) {
   7447 			goto out_now;
   7448 		}
   7449 	}
   7450 	/* Now do we connect? */
   7451 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
   7452 	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
   7453 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7454 		error = EINVAL;
   7455 		goto out_now;
   7456 	}
   7457 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
   7458 	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
   7459 		/* We are already connected AND the TCP model */
   7460 		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
   7461 		error = EADDRINUSE;
   7462 		goto out_now;
   7463 	}
   7464 	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
   7465 		SCTP_INP_RLOCK(inp);
   7466 		stcb = LIST_FIRST(&inp->sctp_asoc_list);
   7467 		SCTP_INP_RUNLOCK(inp);
   7468 	} else {
   7469 		/* We increment here since sctp_findassociation_ep_addr() will
   7470 		 * do a decrement if it finds the stcb as long as the locked
   7471 		 * tcb (last argument) is NOT a TCB.. aka NULL.
   7472 		 */
   7473 		SCTP_INP_INCR_REF(inp);
   7474 		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
   7475 		if (stcb == NULL) {
   7476 			SCTP_INP_DECR_REF(inp);
   7477 		} else {
   7478 			SCTP_TCB_UNLOCK(stcb);
   7479 		}
   7480 	}
   7481 	if (stcb != NULL) {
   7482 		/* Already have or am bring up an association */
   7483 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   7484 		error = EALREADY;
   7485 		goto out_now;
   7486 	}
   7487 
   7488 	vrf_id = inp->def_vrf_id;
   7489 #ifdef SCTP_MVRF
   7490 	for (i = 0; i < inp->num_vrfs; i++) {
   7491 		if (vrf_id == inp->m_vrf_ids[i]) {
   7492 			fnd = 1;
   7493 			break;
   7494 		}
   7495 	}
   7496 	if (!fnd) {
   7497 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7498 		error = EINVAL;
   7499 		goto out_now;
   7500 	}
   7501 #endif
   7502 	/* We are GOOD to go */
   7503 	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
   7504 	if (stcb == NULL) {
   7505 		/* Gak! no memory */
   7506 		goto out_now;
   7507 	}
   7508 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
   7509 		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
   7510 		/* Set the connected flag so we can queue data */
   7511 		soisconnecting(so);
   7512 	}
   7513 	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
   7514 	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
   7515 
   7516 	/* initialize authentication parameters for the assoc */
   7517 	sctp_initialize_auth_params(inp, stcb);
   7518 
   7519 	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
   7520 	SCTP_TCB_UNLOCK(stcb);
   7521  out_now:
   7522 	if (create_lock_on) {
   7523 		SCTP_ASOC_CREATE_UNLOCK(inp);
   7524 	}
   7525 
   7526 	SCTP_INP_DECR_REF(inp);
   7527 	return (error);
   7528 }
   7529 #endif
   7530 
   7531 #if defined(__Userspace__)
   7532 int
   7533 sctpconn_connect(struct socket *so, struct sockaddr *addr)
   7534 {
   7535 #ifdef SCTP_MVRF
   7536 	int i, fnd = 0;
   7537 #endif
   7538 	void *p = NULL;
   7539 	int error = 0;
   7540 	int create_lock_on = 0;
   7541 	uint32_t vrf_id;
   7542 	struct sctp_inpcb *inp;
   7543 	struct sctp_tcb *stcb = NULL;
   7544 
   7545 	inp = (struct sctp_inpcb *)so->so_pcb;
   7546 	if (inp == NULL) {
   7547 		/* I made the same as TCP since we are not setup? */
   7548 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7549 		return (ECONNRESET);
   7550 	}
   7551 	if (addr == NULL) {
   7552 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7553 		return EINVAL;
   7554 	}
   7555 	switch (addr->sa_family) {
   7556 #ifdef INET
   7557 	case AF_INET:
   7558 #ifdef HAVE_SA_LEN
   7559 		if (addr->sa_len != sizeof(struct sockaddr_in)) {
   7560 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7561 			return (EINVAL);
   7562 		}
   7563 #endif
   7564 		break;
   7565 #endif
   7566 #ifdef INET6
   7567 	case AF_INET6:
   7568 #ifdef HAVE_SA_LEN
   7569 		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
   7570 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7571 			return (EINVAL);
   7572 		}
   7573 #endif
   7574 		break;
   7575 #endif
   7576 	case AF_CONN:
   7577 #ifdef HAVE_SA_LEN
   7578 		if (addr->sa_len != sizeof(struct sockaddr_conn)) {
   7579 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7580 			return (EINVAL);
   7581 		}
   7582 #endif
   7583 		break;
   7584 	default:
   7585 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
   7586 		return (EAFNOSUPPORT);
   7587 	}
   7588 	SCTP_INP_INCR_REF(inp);
   7589 	SCTP_ASOC_CREATE_LOCK(inp);
   7590 	create_lock_on = 1;
   7591 
   7592 
   7593 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
   7594 	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
   7595 		/* Should I really unlock ? */
   7596 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
   7597 	        error = EFAULT;
   7598 		goto out_now;
   7599 	}
   7600 #ifdef INET6
   7601 	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
   7602 	    (addr->sa_family == AF_INET6)) {
   7603 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7604 		error = EINVAL;
   7605 		goto out_now;
   7606 	}
   7607 #endif
   7608 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == SCTP_PCB_FLAGS_UNBOUND) {
   7609 		/* Bind a ephemeral port */
   7610 		error = sctp_inpcb_bind(so, NULL, NULL, p);
   7611 		if (error) {
   7612 			goto out_now;
   7613 		}
   7614 	}
   7615 	/* Now do we connect? */
   7616 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
   7617 	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
   7618 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7619 		error = EINVAL;
   7620 		goto out_now;
   7621 	}
   7622 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
   7623 	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
   7624 		/* We are already connected AND the TCP model */
   7625 		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
   7626 		error = EADDRINUSE;
   7627 		goto out_now;
   7628 	}
   7629 	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
   7630 		SCTP_INP_RLOCK(inp);
   7631 		stcb = LIST_FIRST(&inp->sctp_asoc_list);
   7632 		SCTP_INP_RUNLOCK(inp);
   7633 	} else {
   7634 		/* We increment here since sctp_findassociation_ep_addr() will
   7635 		 * do a decrement if it finds the stcb as long as the locked
   7636 		 * tcb (last argument) is NOT a TCB.. aka NULL.
   7637 		 */
   7638 		SCTP_INP_INCR_REF(inp);
   7639 		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
   7640 		if (stcb == NULL) {
   7641 			SCTP_INP_DECR_REF(inp);
   7642 		} else {
   7643 			SCTP_TCB_UNLOCK(stcb);
   7644 		}
   7645 	}
   7646 	if (stcb != NULL) {
   7647 		/* Already have or am bring up an association */
   7648 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   7649 		error = EALREADY;
   7650 		goto out_now;
   7651 	}
   7652 
   7653 	vrf_id = inp->def_vrf_id;
   7654 #ifdef SCTP_MVRF
   7655 	for (i = 0; i < inp->num_vrfs; i++) {
   7656 		if (vrf_id == inp->m_vrf_ids[i]) {
   7657 			fnd = 1;
   7658 			break;
   7659 		}
   7660 	}
   7661 	if (!fnd) {
   7662 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7663 		error = EINVAL;
   7664 		goto out_now;
   7665 	}
   7666 #endif
   7667 	/* We are GOOD to go */
   7668 	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
   7669 	if (stcb == NULL) {
   7670 		/* Gak! no memory */
   7671 		goto out_now;
   7672 	}
   7673 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
   7674 		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
   7675 		/* Set the connected flag so we can queue data */
   7676 		soisconnecting(so);
   7677 	}
   7678 	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
   7679 	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
   7680 
   7681 	/* initialize authentication parameters for the assoc */
   7682 	sctp_initialize_auth_params(inp, stcb);
   7683 
   7684 	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
   7685 	SCTP_TCB_UNLOCK(stcb);
   7686  out_now:
   7687 	if (create_lock_on) {
   7688 		SCTP_ASOC_CREATE_UNLOCK(inp);
   7689 	}
   7690 
   7691 	SCTP_INP_DECR_REF(inp);
   7692 	return (error);
   7693 }
   7694 #endif
   7695 int
   7696 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
   7697 #if __FreeBSD_version >= 700000
   7698 sctp_listen(struct socket *so, int backlog, struct thread *p)
   7699 #else
   7700 sctp_listen(struct socket *so, struct thread *p)
   7701 #endif
   7702 #elif defined(__Windows__)
   7703 sctp_listen(struct socket *so, int backlog, PKTHREAD p)
   7704 #elif defined(__Userspace__)
   7705 sctp_listen(struct socket *so, int backlog, struct proc *p)
   7706 #else
   7707 sctp_listen(struct socket *so, struct proc *p)
   7708 #endif
   7709 {
   7710 	/*
   7711 	 * Note this module depends on the protocol processing being called
   7712 	 * AFTER any socket level flags and backlog are applied to the
   7713 	 * socket. The traditional way that the socket flags are applied is
   7714 	 * AFTER protocol processing. We have made a change to the
   7715 	 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
   7716 	 * place if the socket API for SCTP is to work properly.
   7717 	 */
   7718 
   7719 	int error = 0;
   7720 	struct sctp_inpcb *inp;
   7721 
   7722 	inp = (struct sctp_inpcb *)so->so_pcb;
   7723 	if (inp == NULL) {
   7724 		/* I made the same as TCP since we are not setup? */
   7725 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7726 		return (ECONNRESET);
   7727 	}
   7728 	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
   7729 		/* See if we have a listener */
   7730 		struct sctp_inpcb *tinp;
   7731 		union sctp_sockstore store;
   7732 
   7733 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
   7734 			/* not bound all */
   7735 			struct sctp_laddr *laddr;
   7736 
   7737 			LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
   7738 				memcpy(&store, &laddr->ifa->address, sizeof(store));
   7739 				switch (store.sa.sa_family) {
   7740 #ifdef INET
   7741 				case AF_INET:
   7742 					store.sin.sin_port = inp->sctp_lport;
   7743 					break;
   7744 #endif
   7745 #ifdef INET6
   7746 				case AF_INET6:
   7747 					store.sin6.sin6_port = inp->sctp_lport;
   7748 					break;
   7749 #endif
   7750 #if defined(__Userspace__)
   7751 				case AF_CONN:
   7752 					store.sconn.sconn_port = inp->sctp_lport;
   7753 					break;
   7754 #endif
   7755 				default:
   7756 					break;
   7757 				}
   7758 				tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
   7759 				if (tinp && (tinp != inp) &&
   7760 				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
   7761 				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
   7762 				    (tinp->sctp_socket->so_qlimit)) {
   7763 					/* we have a listener already and its not this inp. */
   7764 					SCTP_INP_DECR_REF(tinp);
   7765 					return (EADDRINUSE);
   7766 				} else if (tinp) {
   7767 					SCTP_INP_DECR_REF(tinp);
   7768 				}
   7769 			}
   7770 		} else {
   7771 			/* Setup a local addr bound all */
   7772 			memset(&store, 0, sizeof(store));
   7773 #ifdef INET6
   7774 			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   7775 				store.sa.sa_family = AF_INET6;
   7776 #ifdef HAVE_SA_LEN
   7777 				store.sa.sa_len = sizeof(struct sockaddr_in6);
   7778 #endif
   7779 			}
   7780 #endif
   7781 #if defined(__Userspace__)
   7782 			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
   7783 				store.sa.sa_family = AF_CONN;
   7784 #ifdef HAVE_SA_LEN
   7785 				store.sa.sa_len = sizeof(struct sockaddr_conn);
   7786 #endif
   7787 			}
   7788 #endif
   7789 #ifdef INET
   7790 #if defined(__Userspace__)
   7791 			if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
   7792 			    ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) == 0)) {
   7793 #else
   7794 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
   7795 #endif
   7796 				store.sa.sa_family = AF_INET;
   7797 #ifdef HAVE_SA_LEN
   7798 				store.sa.sa_len = sizeof(struct sockaddr_in);
   7799 #endif
   7800 			}
   7801 #endif
   7802 			switch (store.sa.sa_family) {
   7803 #ifdef INET
   7804 			case AF_INET:
   7805 				store.sin.sin_port = inp->sctp_lport;
   7806 				break;
   7807 #endif
   7808 #ifdef INET6
   7809 			case AF_INET6:
   7810 				store.sin6.sin6_port = inp->sctp_lport;
   7811 				break;
   7812 #endif
   7813 #if defined(__Userspace__)
   7814 			case AF_CONN:
   7815 				store.sconn.sconn_port = inp->sctp_lport;
   7816 				break;
   7817 #endif
   7818 			default:
   7819 				break;
   7820 			}
   7821 			tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
   7822 			if (tinp && (tinp != inp) &&
   7823 			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
   7824 			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
   7825 			    (tinp->sctp_socket->so_qlimit)) {
   7826 				/* we have a listener already and its not this inp. */
   7827 				SCTP_INP_DECR_REF(tinp);
   7828 				return (EADDRINUSE);
   7829 			} else if (tinp) {
   7830 				SCTP_INP_DECR_REF(inp);
   7831 			}
   7832 		}
   7833 	}
   7834 	SCTP_INP_RLOCK(inp);
   7835 #ifdef SCTP_LOCK_LOGGING
   7836 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
   7837 		sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
   7838 	}
   7839 #endif
   7840 	SOCK_LOCK(so);
   7841 #if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Userspace__)
   7842 	error = solisten_proto_check(so);
   7843 	if (error) {
   7844 		SOCK_UNLOCK(so);
   7845 		SCTP_INP_RUNLOCK(inp);
   7846 		return (error);
   7847 	}
   7848 #endif
   7849 	if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
   7850 	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
   7851 		/* The unlucky case
   7852 		 * - We are in the tcp pool with this guy.
   7853 		 * - Someone else is in the main inp slot.
   7854 		 * - We must move this guy (the listener) to the main slot
   7855 		 * - We must then move the guy that was listener to the TCP Pool.
   7856 		 */
   7857 		if (sctp_swap_inpcb_for_listen(inp)) {
   7858 			goto in_use;
   7859 		}
   7860 	}
   7861 
   7862 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
   7863 	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
   7864 		/* We are already connected AND the TCP model */
   7865 	in_use:
   7866 		SCTP_INP_RUNLOCK(inp);
   7867 		SOCK_UNLOCK(so);
   7868 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
   7869 		return (EADDRINUSE);
   7870 	}
   7871 	SCTP_INP_RUNLOCK(inp);
   7872 	if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
   7873 		/* We must do a bind. */
   7874 		SOCK_UNLOCK(so);
   7875 		if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
   7876 			/* bind error, probably perm */
   7877 			return (error);
   7878 		}
   7879 		SOCK_LOCK(so);
   7880 	}
   7881 #if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__) || defined(__Userspace__)
   7882 #if __FreeBSD_version >= 700000 || defined(__Windows__) || defined(__Userspace__)
   7883 	/* It appears for 7.0 and on, we must always call this. */
   7884 	solisten_proto(so, backlog);
   7885 #else
   7886 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) == 0) {
   7887 		solisten_proto(so);
   7888 	}
   7889 #endif
   7890 #endif
   7891 	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
   7892 		/* remove the ACCEPTCONN flag for one-to-many sockets */
   7893 #if defined(__Userspace__)
   7894 		so->so_options &= ~SCTP_SO_ACCEPTCONN;
   7895 #else
   7896 		so->so_options &= ~SO_ACCEPTCONN;
   7897 #endif
   7898 	}
   7899 
   7900 #if __FreeBSD_version >= 700000 || defined(__Windows__) || defined(__Userspace__)
   7901 	if (backlog == 0) {
   7902 		/* turning off listen */
   7903 #if defined(__Userspace__)
   7904 		so->so_options &= ~SCTP_SO_ACCEPTCONN;
   7905 #else
   7906 		so->so_options &= ~SO_ACCEPTCONN;
   7907 #endif
   7908 	}
   7909 #endif
   7910 	SOCK_UNLOCK(so);
   7911 	return (error);
   7912 }
   7913 
   7914 static int sctp_defered_wakeup_cnt = 0;
   7915 
   7916 int
   7917 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
   7918 sctp_accept(struct socket *so, struct sockaddr **addr)
   7919 {
   7920 #elif defined(__Panda__)
   7921 sctp_accept(struct socket *so, struct sockaddr *addr, int *namelen,
   7922 	    void *accept_info, int *accept_info_len)
   7923 {
   7924 #else
   7925 sctp_accept(struct socket *so, struct mbuf *nam)
   7926 {
   7927 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
   7928 #endif
   7929 	struct sctp_tcb *stcb;
   7930 	struct sctp_inpcb *inp;
   7931 	union sctp_sockstore store;
   7932 #ifdef INET6
   7933 #ifdef SCTP_KAME
   7934 	int error;
   7935 #endif /* SCTP_KAME */
   7936 #endif
   7937 	inp = (struct sctp_inpcb *)so->so_pcb;
   7938 
   7939 	if (inp == NULL) {
   7940 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7941 		return (ECONNRESET);
   7942 	}
   7943 	SCTP_INP_RLOCK(inp);
   7944 	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
   7945 		SCTP_INP_RUNLOCK(inp);
   7946 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   7947 		return (EOPNOTSUPP);
   7948 	}
   7949 	if (so->so_state & SS_ISDISCONNECTED) {
   7950 		SCTP_INP_RUNLOCK(inp);
   7951 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
   7952 		return (ECONNABORTED);
   7953 	}
   7954 	stcb = LIST_FIRST(&inp->sctp_asoc_list);
   7955 	if (stcb == NULL) {
   7956 		SCTP_INP_RUNLOCK(inp);
   7957 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7958 		return (ECONNRESET);
   7959 	}
   7960 	SCTP_TCB_LOCK(stcb);
   7961 	SCTP_INP_RUNLOCK(inp);
   7962 	store = stcb->asoc.primary_destination->ro._l_addr;
   7963 	stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
   7964 	SCTP_TCB_UNLOCK(stcb);
   7965 	switch (store.sa.sa_family) {
   7966 #ifdef INET
   7967 	case AF_INET:
   7968 	{
   7969 		struct sockaddr_in *sin;
   7970 
   7971 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
   7972 		SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
   7973 		if (sin == NULL)
   7974 			return (ENOMEM);
   7975 #else
   7976 		sin = (struct sockaddr_in *)addr;
   7977 		bzero((caddr_t)sin, sizeof(*sin));
   7978 #endif
   7979 		sin->sin_family = AF_INET;
   7980 #ifdef HAVE_SIN_LEN
   7981 		sin->sin_len = sizeof(*sin);
   7982 #endif
   7983 		sin->sin_port = store.sin.sin_port;
   7984 		sin->sin_addr = store.sin.sin_addr;
   7985 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
   7986 		*addr = (struct sockaddr *)sin;
   7987 #elif !defined(__Panda__)
   7988 		SCTP_BUF_LEN(nam) = sizeof(*sin);
   7989 #endif
   7990 		break;
   7991 	}
   7992 #endif
   7993 #ifdef INET6
   7994 	case AF_INET6:
   7995 	{
   7996 		struct sockaddr_in6 *sin6;
   7997 
   7998 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
   7999 		SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
   8000 		if (sin6 == NULL)
   8001 			return (ENOMEM);
   8002 #else
   8003 		sin6 = (struct sockaddr_in6 *)addr;
   8004 		bzero((caddr_t)sin6, sizeof(*sin6));
   8005 #endif
   8006 		sin6->sin6_family = AF_INET6;
   8007 #ifdef HAVE_SIN6_LEN
   8008 		sin6->sin6_len = sizeof(*sin6);
   8009 #endif
   8010 		sin6->sin6_port = store.sin6.sin6_port;
   8011 		sin6->sin6_addr = store.sin6.sin6_addr;
   8012 #if defined(SCTP_EMBEDDED_V6_SCOPE)
   8013 #ifdef SCTP_KAME
   8014 		if ((error = sa6_recoverscope(sin6)) != 0) {
   8015 			SCTP_FREE_SONAME(sin6);
   8016 			return (error);
   8017 		}
   8018 #else
   8019 		if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
   8020 			/*
   8021 			 * sin6->sin6_scope_id =
   8022 			 * ntohs(sin6->sin6_addr.s6_addr16[1]);
   8023 			 */
   8024 			in6_recoverscope(sin6, &sin6->sin6_addr, NULL);	/* skip ifp check */
   8025 		else
   8026 			sin6->sin6_scope_id = 0;	/* XXX */
   8027 #endif /* SCTP_KAME */
   8028 #endif /* SCTP_EMBEDDED_V6_SCOPE */
   8029 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
   8030 		*addr = (struct sockaddr *)sin6;
   8031 #elif !defined(__Panda__)
   8032 		SCTP_BUF_LEN(nam) = sizeof(*sin6);
   8033 #endif
   8034 		break;
   8035 	}
   8036 #endif
   8037 #if defined(__Userspace__)
   8038 	case AF_CONN:
   8039 	{
   8040 		struct sockaddr_conn *sconn;
   8041 
   8042 		SCTP_MALLOC_SONAME(sconn, struct sockaddr_conn *, sizeof(struct sockaddr_conn));
   8043 		if (sconn == NULL) {
   8044 			return (ENOMEM);
   8045 		}
   8046 		sconn->sconn_family = AF_CONN;
   8047 #ifdef HAVE_SCONN_LEN
   8048 		sconn->sconn_len = sizeof(struct sockaddr_conn);
   8049 #endif
   8050 		sconn->sconn_port = store.sconn.sconn_port;
   8051 		sconn->sconn_addr = store.sconn.sconn_addr;
   8052 		*addr = (struct sockaddr *)sconn;
   8053 		break;
   8054 	}
   8055 #endif
   8056 	default:
   8057 		/* TSNH */
   8058 		break;
   8059 	}
   8060 	/* Wake any delayed sleep action */
   8061 	if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
   8062 		SCTP_INP_WLOCK(inp);
   8063 		inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
   8064 		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
   8065 			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
   8066 			SCTP_INP_WUNLOCK(inp);
   8067 			SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
   8068 			if (sowriteable(inp->sctp_socket)) {
   8069 #if defined(__Userspace__)
   8070                             /*__Userspace__ calling sowwakup_locked because of SOCKBUF_LOCK above. */
   8071 #endif
   8072 #if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
   8073 				sowwakeup_locked(inp->sctp_socket);
   8074 #else
   8075 #if defined(__APPLE__)
   8076 				/* socket is locked */
   8077 #endif
   8078 				sowwakeup(inp->sctp_socket);
   8079 #endif
   8080 			} else {
   8081 				SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
   8082 			}
   8083 			SCTP_INP_WLOCK(inp);
   8084 		}
   8085 		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
   8086 			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
   8087 			SCTP_INP_WUNLOCK(inp);
   8088 			SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
   8089 			if (soreadable(inp->sctp_socket)) {
   8090 				sctp_defered_wakeup_cnt++;
   8091 #if defined(__Userspace__)
   8092                                 /*__Userspace__ calling sorwakup_locked because of SOCKBUF_LOCK above */
   8093 #endif
   8094 #if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
   8095 				sorwakeup_locked(inp->sctp_socket);
   8096 #else
   8097 #if defined(__APPLE__)
   8098 				/* socket is locked */
   8099 #endif
   8100 				sorwakeup(inp->sctp_socket);
   8101 #endif
   8102 			} else {
   8103 				SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
   8104 			}
   8105 			SCTP_INP_WLOCK(inp);
   8106 		}
   8107 		SCTP_INP_WUNLOCK(inp);
   8108 	}
   8109 	if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
   8110 		SCTP_TCB_LOCK(stcb);
   8111 		sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7);
   8112 	}
   8113 	return (0);
   8114 }
   8115 
   8116 #ifdef INET
   8117 int
   8118 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   8119 sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
   8120 {
   8121 	struct sockaddr_in *sin;
   8122 #elif defined(__Panda__)
   8123 sctp_ingetaddr(struct socket *so, struct sockaddr *addr)
   8124 {
   8125 	struct sockaddr_in *sin = (struct sockaddr_in *)addr;
   8126 #else
   8127 sctp_ingetaddr(struct socket *so, struct mbuf *nam)
   8128 {
   8129 	struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
   8130 #endif
   8131 	uint32_t vrf_id;
   8132 	struct sctp_inpcb *inp;
   8133 	struct sctp_ifa *sctp_ifa;
   8134 
   8135 	/*
   8136 	 * Do the malloc first in case it blocks.
   8137 	 */
   8138 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   8139 	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
   8140 	if (sin == NULL)
   8141 		return (ENOMEM);
   8142 #elif defined(__Panda__)
   8143 	bzero(sin, sizeof(*sin));
   8144 #else
   8145 	SCTP_BUF_LEN(nam) = sizeof(*sin);
   8146 	memset(sin, 0, sizeof(*sin));
   8147 #endif
   8148 	sin->sin_family = AF_INET;
   8149 #ifdef HAVE_SIN_LEN
   8150 	sin->sin_len = sizeof(*sin);
   8151 #endif
   8152 	inp = (struct sctp_inpcb *)so->so_pcb;
   8153 	if (!inp) {
   8154 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   8155 		SCTP_FREE_SONAME(sin);
   8156 #endif
   8157 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   8158 		return (ECONNRESET);
   8159 	}
   8160 	SCTP_INP_RLOCK(inp);
   8161 	sin->sin_port = inp->sctp_lport;
   8162 	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
   8163 		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
   8164 			struct sctp_tcb *stcb;
   8165 			struct sockaddr_in *sin_a;
   8166 			struct sctp_nets *net;
   8167 			int fnd;
   8168 
   8169 			stcb = LIST_FIRST(&inp->sctp_asoc_list);
   8170 			if (stcb == NULL) {
   8171 				goto notConn;
   8172 			}
   8173 			fnd = 0;
   8174 			sin_a = NULL;
   8175 			SCTP_TCB_LOCK(stcb);
   8176 			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   8177 				sin_a = (struct sockaddr_in *)&net->ro._l_addr;
   8178 				if (sin_a == NULL)
   8179 					/* this will make coverity happy */
   8180 					continue;
   8181 
   8182 				if (sin_a->sin_family == AF_INET) {
   8183 					fnd = 1;
   8184 					break;
   8185 				}
   8186 			}
   8187 			if ((!fnd) || (sin_a == NULL)) {
   8188 				/* punt */
   8189 				SCTP_TCB_UNLOCK(stcb);
   8190 				goto notConn;
   8191 			}
   8192 
   8193 			vrf_id = inp->def_vrf_id;
   8194 			sctp_ifa = sctp_source_address_selection(inp,
   8195 								 stcb,
   8196 								 (sctp_route_t *)&net->ro,
   8197 								 net, 0, vrf_id);
   8198 			if (sctp_ifa) {
   8199 				sin->sin_addr = sctp_ifa->address.sin.sin_addr;
   8200 				sctp_free_ifa(sctp_ifa);
   8201 			}
   8202 			SCTP_TCB_UNLOCK(stcb);
   8203 		} else {
   8204 			/* For the bound all case you get back 0 */
   8205 	notConn:
   8206 			sin->sin_addr.s_addr = 0;
   8207 		}
   8208 
   8209 	} else {
   8210 		/* Take the first IPv4 address in the list */
   8211 		struct sctp_laddr *laddr;
   8212 		int fnd = 0;
   8213 
   8214 		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
   8215 			if (laddr->ifa->address.sa.sa_family == AF_INET) {
   8216 				struct sockaddr_in *sin_a;
   8217 
   8218 				sin_a = &laddr->ifa->address.sin;
   8219 				sin->sin_addr = sin_a->sin_addr;
   8220 				fnd = 1;
   8221 				break;
   8222 			}
   8223 		}
   8224 		if (!fnd) {
   8225 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   8226 			SCTP_FREE_SONAME(sin);
   8227 #endif
   8228 			SCTP_INP_RUNLOCK(inp);
   8229 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   8230 			return (ENOENT);
   8231 		}
   8232 	}
   8233 	SCTP_INP_RUNLOCK(inp);
   8234 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   8235 	(*addr) = (struct sockaddr *)sin;
   8236 #endif
   8237 	return (0);
   8238 }
   8239 
   8240 int
   8241 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   8242 sctp_peeraddr(struct socket *so, struct sockaddr **addr)
   8243 {
   8244 	struct sockaddr_in *sin;
   8245 #elif defined(__Panda__)
   8246 sctp_peeraddr(struct socket *so, struct sockaddr *addr)
   8247 {
   8248 	struct sockaddr_in *sin = (struct sockaddr_in *)addr;
   8249 #else
   8250 sctp_peeraddr(struct socket *so, struct mbuf *nam)
   8251 {
   8252 	struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
   8253 
   8254 #endif
   8255 	int fnd;
   8256 	struct sockaddr_in *sin_a;
   8257 	struct sctp_inpcb *inp;
   8258 	struct sctp_tcb *stcb;
   8259 	struct sctp_nets *net;
   8260 
   8261 	/* Do the malloc first in case it blocks. */
   8262 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   8263 	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
   8264 	if (sin == NULL)
   8265 		return (ENOMEM);
   8266 #elif defined(__Panda__)
   8267 	memset(sin, 0, sizeof(*sin));
   8268 #else
   8269 	SCTP_BUF_LEN(nam) = sizeof(*sin);
   8270 	memset(sin, 0, sizeof(*sin));
   8271 #endif
   8272 	sin->sin_family = AF_INET;
   8273 #ifdef HAVE_SIN_LEN
   8274 	sin->sin_len = sizeof(*sin);
   8275 #endif
   8276 
   8277 	inp = (struct sctp_inpcb *)so->so_pcb;
   8278 	if ((inp == NULL) ||
   8279 	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
   8280 		/* UDP type and listeners will drop out here */
   8281 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   8282 		SCTP_FREE_SONAME(sin);
   8283 #endif
   8284 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
   8285 		return (ENOTCONN);
   8286 	}
   8287 	SCTP_INP_RLOCK(inp);
   8288 	stcb = LIST_FIRST(&inp->sctp_asoc_list);
   8289 	if (stcb) {
   8290 		SCTP_TCB_LOCK(stcb);
   8291 	}
   8292 	SCTP_INP_RUNLOCK(inp);
   8293 	if (stcb == NULL) {
   8294 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   8295 		SCTP_FREE_SONAME(sin);
   8296 #endif
   8297 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   8298 		return (ECONNRESET);
   8299 	}
   8300 	fnd = 0;
   8301 	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   8302 		sin_a = (struct sockaddr_in *)&net->ro._l_addr;
   8303 		if (sin_a->sin_family == AF_INET) {
   8304 			fnd = 1;
   8305 			sin->sin_port = stcb->rport;
   8306 			sin->sin_addr = sin_a->sin_addr;
   8307 			break;
   8308 		}
   8309 	}
   8310 	SCTP_TCB_UNLOCK(stcb);
   8311 	if (!fnd) {
   8312 		/* No IPv4 address */
   8313 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   8314 		SCTP_FREE_SONAME(sin);
   8315 #endif
   8316 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   8317 		return (ENOENT);
   8318 	}
   8319 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   8320 	(*addr) = (struct sockaddr *)sin;
   8321 #endif
   8322 	return (0);
   8323 }
   8324 
   8325 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   8326 struct pr_usrreqs sctp_usrreqs = {
   8327 #if defined(__FreeBSD__)
   8328 	.pru_abort = sctp_abort,
   8329 	.pru_accept = sctp_accept,
   8330 	.pru_attach = sctp_attach,
   8331 	.pru_bind = sctp_bind,
   8332 	.pru_connect = sctp_connect,
   8333 	.pru_control = in_control,
   8334 #if __FreeBSD_version >= 690000
   8335 	.pru_close = sctp_close,
   8336 	.pru_detach = sctp_close,
   8337 	.pru_sopoll = sopoll_generic,
   8338 	.pru_flush = sctp_flush,
   8339 #else
   8340 	.pru_detach = sctp_detach,
   8341 	.pru_sopoll = sopoll,
   8342 #endif
   8343 	.pru_disconnect = sctp_disconnect,
   8344 	.pru_listen = sctp_listen,
   8345 	.pru_peeraddr = sctp_peeraddr,
   8346 	.pru_send = sctp_sendm,
   8347 	.pru_shutdown = sctp_shutdown,
   8348 	.pru_sockaddr = sctp_ingetaddr,
   8349 	.pru_sosend = sctp_sosend,
   8350 	.pru_soreceive = sctp_soreceive
   8351 #elif defined(__APPLE__)
   8352 	.pru_abort = sctp_abort,
   8353 	.pru_accept = sctp_accept,
   8354 	.pru_attach = sctp_attach,
   8355 	.pru_bind = sctp_bind,
   8356 	.pru_connect = sctp_connect,
   8357 	.pru_connect2 = pru_connect2_notsupp,
   8358 	.pru_control = in_control,
   8359 	.pru_detach = sctp_detach,
   8360 	.pru_disconnect = sctp_disconnect,
   8361 	.pru_listen = sctp_listen,
   8362 	.pru_peeraddr = sctp_peeraddr,
   8363 	.pru_rcvd = NULL,
   8364 	.pru_rcvoob = pru_rcvoob_notsupp,
   8365 	.pru_send = sctp_sendm,
   8366 	.pru_sense = pru_sense_null,
   8367 	.pru_shutdown = sctp_shutdown,
   8368 	.pru_sockaddr = sctp_ingetaddr,
   8369 	.pru_sosend = sctp_sosend,
   8370 	.pru_soreceive = sctp_soreceive,
   8371 	.pru_sopoll = sopoll
   8372 #elif defined(__Windows__)
   8373 	sctp_abort,
   8374 	sctp_accept,
   8375 	sctp_attach,
   8376 	sctp_bind,
   8377 	sctp_connect,
   8378 	pru_connect2_notsupp,
   8379 	NULL,
   8380 	NULL,
   8381 	sctp_disconnect,
   8382 	sctp_listen,
   8383 	sctp_peeraddr,
   8384 	NULL,
   8385 	pru_rcvoob_notsupp,
   8386 	NULL,
   8387 	pru_sense_null,
   8388 	sctp_shutdown,
   8389 	sctp_flush,
   8390 	sctp_ingetaddr,
   8391 	sctp_sosend,
   8392 	sctp_soreceive,
   8393 	sopoll_generic,
   8394 	NULL,
   8395 	sctp_close
   8396 #endif
   8397 };
   8398 #elif !defined(__Panda__) && !defined(__Userspace__)
   8399 int
   8400 sctp_usrreq(so, req, m, nam, control)
   8401 	struct socket *so;
   8402 	int req;
   8403 	struct mbuf *m, *nam, *control;
   8404 {
   8405 	struct proc *p = curproc;
   8406 	uint32_t vrf_id;
   8407 	struct sctp_vrf *vrf;
   8408 	int error;
   8409 	int family;
   8410 	struct sctp_inpcb *inp = (struct sctp_inpcb *)so->so_pcb;
   8411 
   8412 	error = 0;
   8413 	family = so->so_proto->pr_domain->dom_family;
   8414 	if (req == PRU_CONTROL) {
   8415 		switch (family) {
   8416 		case PF_INET:
   8417 			error = in_control(so, (long)m, (caddr_t)nam,
   8418 			    (struct ifnet *)control);
   8419 			break;
   8420 #ifdef INET6
   8421 		case PF_INET6:
   8422 			error = in6_control(so, (long)m, (caddr_t)nam,
   8423 			    (struct ifnet *)control, p);
   8424 			break;
   8425 #endif
   8426 		default:
   8427 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
   8428 			error = EAFNOSUPPORT;
   8429 		}
   8430 		return (error);
   8431 	}
   8432 	switch (req) {
   8433 	case PRU_ATTACH:
   8434 		error = sctp_attach(so, family, p);
   8435 		break;
   8436 	case PRU_DETACH:
   8437 		error = sctp_detach(so);
   8438 		break;
   8439 	case PRU_BIND:
   8440 		if (nam == NULL) {
   8441 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   8442 			return (EINVAL);
   8443 		}
   8444 		error = sctp_bind(so, nam, p);
   8445 		break;
   8446 	case PRU_LISTEN:
   8447 		error = sctp_listen(so, p);
   8448 		break;
   8449 	case PRU_CONNECT:
   8450 		if (nam == NULL) {
   8451 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   8452 			return (EINVAL);
   8453 		}
   8454 		error = sctp_connect(so, nam, p);
   8455 		break;
   8456 	case PRU_DISCONNECT:
   8457 		error = sctp_disconnect(so);
   8458 		break;
   8459 	case PRU_ACCEPT:
   8460 		if (nam == NULL) {
   8461 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   8462 			return (EINVAL);
   8463 		}
   8464 		error = sctp_accept(so, nam);
   8465 		break;
   8466 	case PRU_SHUTDOWN:
   8467 		error = sctp_shutdown(so);
   8468 		break;
   8469 
   8470 	case PRU_RCVD:
   8471 		/*
   8472 		 * For Open and Net BSD, this is real ugly. The mbuf *nam
   8473 		 * that is passed (by soreceive()) is the int flags c ast as
   8474 		 * a (mbuf *) yuck!
   8475 		 */
   8476 		break;
   8477 
   8478 	case PRU_SEND:
   8479 		/* Flags are ignored */
   8480 		{
   8481 			struct sockaddr *addr;
   8482 
   8483 			if (nam == NULL)
   8484 				addr = NULL;
   8485 			else
   8486 				addr = mtod(nam, struct sockaddr *);
   8487 
   8488 			error = sctp_sendm(so, 0, m, addr, control, p);
   8489 		}
   8490 		break;
   8491 	case PRU_ABORT:
   8492 		error = sctp_abort(so);
   8493 		break;
   8494 
   8495 	case PRU_SENSE:
   8496 		error = 0;
   8497 		break;
   8498 	case PRU_RCVOOB:
   8499 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
   8500 		error = EAFNOSUPPORT;
   8501 		break;
   8502 	case PRU_SENDOOB:
   8503 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
   8504 		error = EAFNOSUPPORT;
   8505 		break;
   8506 	case PRU_PEERADDR:
   8507 		error = sctp_peeraddr(so, nam);
   8508 		break;
   8509 	case PRU_SOCKADDR:
   8510 		error = sctp_ingetaddr(so, nam);
   8511 		break;
   8512 	case PRU_SLOWTIMO:
   8513 		error = 0;
   8514 		break;
   8515 	default:
   8516 		break;
   8517 	}
   8518 	return (error);
   8519 }
   8520 
   8521 #endif
   8522 #endif
   8523 
   8524 #if defined(__Userspace__)
   8525 int
   8526 register_recv_cb(struct socket *so,
   8527                  int (*receive_cb)(struct socket *sock, union sctp_sockstore addr, void *data,
   8528                  size_t datalen, struct sctp_rcvinfo, int flags, void *ulp_info))
   8529 {
   8530 	struct sctp_inpcb *inp;
   8531 
   8532 	inp = (struct sctp_inpcb *) so->so_pcb;
   8533 	if (inp == NULL) {
   8534 		return (0);
   8535 	}
   8536 	SCTP_INP_WLOCK(inp);
   8537 	inp->recv_callback = receive_cb;
   8538 	SCTP_INP_WUNLOCK(inp);
   8539 	return (1);
   8540 }
   8541 
   8542 int
   8543 register_send_cb(struct socket *so, uint32_t sb_threshold, int (*send_cb)(struct socket *sock, uint32_t sb_free))
   8544 {
   8545 	struct sctp_inpcb *inp;
   8546 
   8547 	inp = (struct sctp_inpcb *) so->so_pcb;
   8548 	if (inp == NULL) {
   8549 		return (0);
   8550 	}
   8551 	SCTP_INP_WLOCK(inp);
   8552 	inp->send_callback = send_cb;
   8553 	inp->send_sb_threshold = sb_threshold;
   8554 	SCTP_INP_WUNLOCK(inp);
   8555 	/* FIXME change to current amount free. This will be the full buffer
   8556 	 * the first time this is registered but it could be only a portion
   8557 	 * of the send buffer if this is called a second time e.g. if the
   8558 	 * threshold changes.
   8559 	 */
   8560 	return (1);
   8561 }
   8562 
   8563 int
   8564 register_ulp_info (struct socket *so, void *ulp_info)
   8565 {
   8566 	struct sctp_inpcb *inp;
   8567 
   8568 	inp = (struct sctp_inpcb *) so->so_pcb;
   8569 	if (inp == NULL) {
   8570 		return (0);
   8571 	}
   8572 	SCTP_INP_WLOCK(inp);
   8573 	inp->ulp_info = ulp_info;
   8574 	SCTP_INP_WUNLOCK(inp);
   8575 	return (1);
   8576 }
   8577 #endif
   8578