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 263237 2014-03-16 12:32:16Z 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_os_Windows)
     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 #endif
    397 #endif
    398 
    399 void
    400 sctp_notify(struct sctp_inpcb *inp,
    401     struct ip *ip,
    402     struct sctphdr *sh,
    403     struct sockaddr *to,
    404     struct sctp_tcb *stcb,
    405     struct sctp_nets *net)
    406 {
    407 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    408 	struct socket *so;
    409 
    410 #endif
    411 	struct icmp *icmph;
    412 
    413 	/* protection */
    414 	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
    415 	    (sh == NULL) || (to == NULL)) {
    416 		if (stcb)
    417 			SCTP_TCB_UNLOCK(stcb);
    418 		return;
    419 	}
    420 	/* First job is to verify the vtag matches what I would send */
    421 	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
    422 		SCTP_TCB_UNLOCK(stcb);
    423 		return;
    424 	}
    425 
    426 	icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
    427 					       sizeof(struct ip)));
    428 	if (icmph->icmp_type != ICMP_UNREACH) {
    429 		/* We only care about unreachable */
    430 		SCTP_TCB_UNLOCK(stcb);
    431 		return;
    432 	}
    433 	if ((icmph->icmp_code == ICMP_UNREACH_NET) ||
    434 	    (icmph->icmp_code == ICMP_UNREACH_HOST) ||
    435 	    (icmph->icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
    436 	    (icmph->icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
    437 	    (icmph->icmp_code == ICMP_UNREACH_ISOLATED) ||
    438 	    (icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) ||
    439 	    (icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
    440 #if defined(__Panda__)
    441 	    (icmph->icmp_code == ICMP_UNREACH_ADMIN)) {
    442 #elif defined(__Userspace_os_NetBSD)
    443 	    (icmph->icmp_code == ICMP_UNREACH_ADMIN_PROHIBIT)) {
    444 #else
    445 	    (icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
    446 #endif
    447 
    448 		/*
    449 		 * Hmm reachablity problems we must examine closely. If its
    450 		 * not reachable, we may have lost a network. Or if there is
    451 		 * NO protocol at the other end named SCTP. well we consider
    452 		 * it a OOTB abort.
    453 		 */
    454 		if (net->dest_state & SCTP_ADDR_REACHABLE) {
    455 			/* Ok that destination is NOT reachable */
    456 			net->dest_state &= ~SCTP_ADDR_REACHABLE;
    457 			net->dest_state &= ~SCTP_ADDR_PF;
    458 			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
    459 					stcb, 0,
    460 					(void *)net, SCTP_SO_NOT_LOCKED);
    461 		}
    462 		SCTP_TCB_UNLOCK(stcb);
    463 	} else  if ((icmph->icmp_code == ICMP_UNREACH_PROTOCOL) ||
    464 		    (icmph->icmp_code == ICMP_UNREACH_PORT)) {
    465 		/*
    466 		 * Here the peer is either playing tricks on us,
    467 		 * including an address that belongs to someone who
    468 		 * does not support SCTP OR was a userland
    469 		 * implementation that shutdown and now is dead. In
    470 		 * either case treat it like a OOTB abort with no
    471 		 * TCB
    472 		 */
    473 		sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
    474 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    475 		so = SCTP_INP_SO(inp);
    476 		atomic_add_int(&stcb->asoc.refcnt, 1);
    477 		SCTP_TCB_UNLOCK(stcb);
    478 		SCTP_SOCKET_LOCK(so, 1);
    479 		SCTP_TCB_LOCK(stcb);
    480 		atomic_subtract_int(&stcb->asoc.refcnt, 1);
    481 #endif
    482 		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_2);
    483 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    484 		SCTP_SOCKET_UNLOCK(so, 1);
    485 		/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed.*/
    486 #endif
    487 		/* no need to unlock here, since the TCB is gone */
    488 	} else {
    489 		SCTP_TCB_UNLOCK(stcb);
    490 	}
    491 }
    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 = (struct sockaddr_in *)&sctp_ifa->address.sa;
   1680 						if (sin->sin_addr.s_addr == 0) {
   1681 							/*
   1682 							 * we skip unspecifed
   1683 							 * addresses
   1684 							 */
   1685 							continue;
   1686 						}
   1687 						if ((ipv4_local_scope == 0) &&
   1688 						    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
   1689 							continue;
   1690 						}
   1691 #ifdef INET6
   1692 						if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
   1693 							in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas);
   1694 							((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
   1695 							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6));
   1696 							actual += sizeof(struct sockaddr_in6);
   1697 						} else {
   1698 #endif
   1699 							memcpy(sas, sin, sizeof(*sin));
   1700 							((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
   1701 							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin));
   1702 							actual += sizeof(*sin);
   1703 #ifdef INET6
   1704 						}
   1705 #endif
   1706 						if (actual >= limit) {
   1707 							return (actual);
   1708 						}
   1709 					} else {
   1710 						continue;
   1711 					}
   1712 					break;
   1713 #endif
   1714 #ifdef INET6
   1715 				case AF_INET6:
   1716 					if (ipv6_addr_legal) {
   1717 						struct sockaddr_in6 *sin6;
   1718 
   1719 #if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME)
   1720 						struct sockaddr_in6 lsa6;
   1721 #endif
   1722 						sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
   1723 						if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   1724 							/*
   1725 							 * we skip unspecifed
   1726 							 * addresses
   1727 							 */
   1728 							continue;
   1729 						}
   1730 						if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
   1731 							if (local_scope == 0)
   1732 								continue;
   1733 #if defined(SCTP_EMBEDDED_V6_SCOPE)
   1734 							if (sin6->sin6_scope_id == 0) {
   1735 #ifdef SCTP_KAME
   1736 								if (sa6_recoverscope(sin6) != 0)
   1737 									/*
   1738 									 * bad link
   1739 									 * local
   1740 									 * address
   1741 									 */
   1742 									continue;
   1743 #else
   1744 								lsa6 = *sin6;
   1745 								if (in6_recoverscope(&lsa6,
   1746 										     &lsa6.sin6_addr,
   1747 										     NULL))
   1748 									/*
   1749 									 * bad link
   1750 									 * local
   1751 									 * address
   1752 									 */
   1753 								continue;
   1754 								sin6 = &lsa6;
   1755 #endif				/* SCTP_KAME */
   1756 							}
   1757 #endif /* SCTP_EMBEDDED_V6_SCOPE */
   1758 						}
   1759 						if ((site_scope == 0) &&
   1760 						    (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
   1761 							continue;
   1762 						}
   1763 						memcpy(sas, sin6, sizeof(*sin6));
   1764 						((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
   1765 						sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6));
   1766 						actual += sizeof(*sin6);
   1767 						if (actual >= limit) {
   1768 							return (actual);
   1769 						}
   1770 					} else {
   1771 						continue;
   1772 					}
   1773 					break;
   1774 #endif
   1775 #if defined(__Userspace__)
   1776 				case AF_CONN:
   1777 					if (conn_addr_legal) {
   1778 						memcpy(sas, &sctp_ifa->address.sconn, sizeof(struct sockaddr_conn));
   1779 						((struct sockaddr_conn *)sas)->sconn_port = inp->sctp_lport;
   1780 						sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_conn));
   1781 						actual += sizeof(struct sockaddr_conn);
   1782 						if (actual >= limit) {
   1783 							return (actual);
   1784 						}
   1785 					} else {
   1786 						continue;
   1787 					}
   1788 #endif
   1789 				default:
   1790 					/* TSNH */
   1791 					break;
   1792 				}
   1793 			}
   1794 		}
   1795 	} else {
   1796 		struct sctp_laddr *laddr;
   1797 #ifndef HAVE_SA_LEN
   1798 		uint32_t sa_len = 0;
   1799 #endif
   1800 
   1801 		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
   1802 			if (stcb) {
   1803 				if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
   1804 					continue;
   1805 				}
   1806 			}
   1807 			if (sctp_fill_user_address(sas, &laddr->ifa->address.sa))
   1808 				continue;
   1809 			switch (laddr->ifa->address.sa.sa_family) {
   1810 #ifdef INET
   1811 			case AF_INET:
   1812 				((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
   1813 				break;
   1814 #endif
   1815 #ifdef INET6
   1816 			case AF_INET6:
   1817 				((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
   1818 				break;
   1819 #endif
   1820 #if defined(__Userspace__)
   1821 			case AF_CONN:
   1822 				((struct sockaddr_conn *)sas)->sconn_port = inp->sctp_lport;
   1823 				break;
   1824 #endif
   1825 			default:
   1826 				/* TSNH */
   1827 				break;
   1828 			}
   1829 #ifdef HAVE_SA_LEN
   1830 			sas = (struct sockaddr_storage *)((caddr_t)sas +
   1831 							  laddr->ifa->address.sa.sa_len);
   1832 			actual += laddr->ifa->address.sa.sa_len;
   1833 #else
   1834 			switch (laddr->ifa->address.sa.sa_family) {
   1835 #ifdef INET
   1836 			case AF_INET:
   1837 				sa_len = sizeof(struct sockaddr_in);
   1838 				break;
   1839 #endif
   1840 #ifdef INET6
   1841 			case AF_INET6:
   1842 				sa_len = sizeof(struct sockaddr_in6);
   1843 				break;
   1844 #endif
   1845 #if defined(__Userspace__)
   1846 			case AF_CONN:
   1847 				sa_len = sizeof(struct sockaddr_conn);
   1848 				break;
   1849 #endif
   1850 			default:
   1851 				/* TSNH */
   1852 				break;
   1853 			}
   1854 			sas = (struct sockaddr_storage *)((caddr_t)sas + sa_len);
   1855 			actual += sa_len;
   1856 #endif
   1857 			if (actual >= limit) {
   1858 				return (actual);
   1859 			}
   1860 		}
   1861 	}
   1862 	return (actual);
   1863 }
   1864 
   1865 static size_t
   1866 sctp_fill_up_addresses(struct sctp_inpcb *inp,
   1867                        struct sctp_tcb *stcb,
   1868                        size_t limit,
   1869                        struct sockaddr_storage *sas)
   1870 {
   1871 	size_t size = 0;
   1872 #ifdef SCTP_MVRF
   1873 	uint32_t id;
   1874 #endif
   1875 
   1876 	SCTP_IPI_ADDR_RLOCK();
   1877 #ifdef SCTP_MVRF
   1878 /*
   1879  * FIX ME: ?? this WILL report duplicate addresses if they appear
   1880  * in more than one VRF.
   1881  */
   1882 	/* fill up addresses for all VRFs on the endpoint */
   1883 	for (id = 0; (id < inp->num_vrfs) && (size < limit); id++) {
   1884 		size += sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
   1885 						   inp->m_vrf_ids[id]);
   1886 		sas = (struct sockaddr_storage *)((caddr_t)sas + size);
   1887 	}
   1888 #else
   1889 	/* fill up addresses for the endpoint's default vrf */
   1890 	size = sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
   1891 					  inp->def_vrf_id);
   1892 #endif
   1893 	SCTP_IPI_ADDR_RUNLOCK();
   1894 	return (size);
   1895 }
   1896 
   1897 /*
   1898  * NOTE: assumes addr lock is held
   1899  */
   1900 static int
   1901 sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
   1902 {
   1903 	int cnt = 0;
   1904 	struct sctp_vrf *vrf = NULL;
   1905 
   1906 	/*
   1907 	 * In both sub-set bound an bound_all cases we return the MAXIMUM
   1908 	 * number of addresses that you COULD get. In reality the sub-set
   1909 	 * bound may have an exclusion list for a given TCB OR in the
   1910 	 * bound-all case a TCB may NOT include the loopback or other
   1911 	 * addresses as well.
   1912 	 */
   1913 	vrf = sctp_find_vrf(vrf_id);
   1914 	if (vrf == NULL) {
   1915 		return (0);
   1916 	}
   1917 	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
   1918 		struct sctp_ifn *sctp_ifn;
   1919 		struct sctp_ifa *sctp_ifa;
   1920 
   1921 		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
   1922 			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
   1923 				/* Count them if they are the right type */
   1924 				switch (sctp_ifa->address.sa.sa_family) {
   1925 #ifdef INET
   1926 				case AF_INET:
   1927 					if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
   1928 						cnt += sizeof(struct sockaddr_in6);
   1929 					else
   1930 						cnt += sizeof(struct sockaddr_in);
   1931 					break;
   1932 #endif
   1933 #ifdef INET6
   1934 				case AF_INET6:
   1935 					cnt += sizeof(struct sockaddr_in6);
   1936 					break;
   1937 #endif
   1938 #if defined(__Userspace__)
   1939 				case AF_CONN:
   1940 					cnt += sizeof(struct sockaddr_conn);
   1941 					break;
   1942 #endif
   1943 				default:
   1944 					break;
   1945 				}
   1946 			}
   1947 		}
   1948 	} else {
   1949 		struct sctp_laddr *laddr;
   1950 
   1951 		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
   1952 			switch (laddr->ifa->address.sa.sa_family) {
   1953 #ifdef INET
   1954 			case AF_INET:
   1955 				if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
   1956 					cnt += sizeof(struct sockaddr_in6);
   1957 				else
   1958 					cnt += sizeof(struct sockaddr_in);
   1959 				break;
   1960 #endif
   1961 #ifdef INET6
   1962 			case AF_INET6:
   1963 				cnt += sizeof(struct sockaddr_in6);
   1964 				break;
   1965 #endif
   1966 #if defined(__Userspace__)
   1967 			case AF_CONN:
   1968 				cnt += sizeof(struct sockaddr_conn);
   1969 				break;
   1970 #endif
   1971 			default:
   1972 				break;
   1973 			}
   1974 		}
   1975 	}
   1976 	return (cnt);
   1977 }
   1978 
   1979 static int
   1980 sctp_count_max_addresses(struct sctp_inpcb *inp)
   1981 {
   1982 	int cnt = 0;
   1983 #ifdef SCTP_MVRF
   1984 	int id;
   1985 #endif
   1986 
   1987 	SCTP_IPI_ADDR_RLOCK();
   1988 #ifdef SCTP_MVRF
   1989 /*
   1990  * FIX ME: ?? this WILL count duplicate addresses if they appear
   1991  * in more than one VRF.
   1992  */
   1993 	/* count addresses for all VRFs on the endpoint */
   1994 	for (id = 0; id < inp->num_vrfs; id++) {
   1995 		cnt += sctp_count_max_addresses_vrf(inp, inp->m_vrf_ids[id]);
   1996 	}
   1997 #else
   1998 	/* count addresses for the endpoint's default VRF */
   1999 	cnt = sctp_count_max_addresses_vrf(inp, inp->def_vrf_id);
   2000 #endif
   2001 	SCTP_IPI_ADDR_RUNLOCK();
   2002 	return (cnt);
   2003 }
   2004 
   2005 static int
   2006 sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
   2007 		  size_t optsize, void *p, int delay)
   2008 {
   2009 	int error = 0;
   2010 	int creat_lock_on = 0;
   2011 	struct sctp_tcb *stcb = NULL;
   2012 	struct sockaddr *sa;
   2013 	int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
   2014 	uint32_t vrf_id;
   2015 	int bad_addresses = 0;
   2016 	sctp_assoc_t *a_id;
   2017 
   2018 	SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
   2019 
   2020 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
   2021 	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
   2022 		/* We are already connected AND the TCP model */
   2023 		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
   2024 		return (EADDRINUSE);
   2025 	}
   2026 
   2027 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
   2028 	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
   2029 		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2030 		return (EINVAL);
   2031 	}
   2032 
   2033 	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
   2034 		SCTP_INP_RLOCK(inp);
   2035 		stcb = LIST_FIRST(&inp->sctp_asoc_list);
   2036 		SCTP_INP_RUNLOCK(inp);
   2037 	}
   2038 	if (stcb) {
   2039 		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   2040 		return (EALREADY);
   2041 	}
   2042 	SCTP_INP_INCR_REF(inp);
   2043 	SCTP_ASOC_CREATE_LOCK(inp);
   2044 	creat_lock_on = 1;
   2045 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
   2046 	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
   2047 		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
   2048 		error = EFAULT;
   2049 		goto out_now;
   2050 	}
   2051 	totaddrp = (int *)optval;
   2052 	totaddr = *totaddrp;
   2053 	sa = (struct sockaddr *)(totaddrp + 1);
   2054 	stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (optsize - sizeof(int)), &bad_addresses);
   2055 	if ((stcb != NULL) || bad_addresses) {
   2056 		/* Already have or am bring up an association */
   2057 		SCTP_ASOC_CREATE_UNLOCK(inp);
   2058 		creat_lock_on = 0;
   2059 		if (stcb)
   2060 			SCTP_TCB_UNLOCK(stcb);
   2061 		if (bad_addresses == 0) {
   2062 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   2063 			error = EALREADY;
   2064 		}
   2065 		goto out_now;
   2066 	}
   2067 #ifdef INET6
   2068 	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
   2069 	    (num_v6 > 0)) {
   2070 		error = EINVAL;
   2071 		goto out_now;
   2072 	}
   2073 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
   2074 	    (num_v4 > 0)) {
   2075 		struct in6pcb *inp6;
   2076 
   2077 		inp6 = (struct in6pcb *)inp;
   2078 		if (SCTP_IPV6_V6ONLY(inp6)) {
   2079 			/*
   2080 			 * if IPV6_V6ONLY flag, ignore connections destined
   2081 			 * to a v4 addr or v4-mapped addr
   2082 			 */
   2083 			SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2084 			error = EINVAL;
   2085 			goto out_now;
   2086 		}
   2087 	}
   2088 #endif				/* INET6 */
   2089 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
   2090 	    SCTP_PCB_FLAGS_UNBOUND) {
   2091 		/* Bind a ephemeral port */
   2092 		error = sctp_inpcb_bind(so, NULL, NULL, p);
   2093 		if (error) {
   2094 			goto out_now;
   2095 		}
   2096 	}
   2097 
   2098 	/* FIX ME: do we want to pass in a vrf on the connect call? */
   2099 	vrf_id = inp->def_vrf_id;
   2100 
   2101 
   2102 	/* We are GOOD to go */
   2103 	stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id,
   2104 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
   2105 			       (struct thread *)p
   2106 #elif defined(__Windows__)
   2107 			       (PKTHREAD)p
   2108 #else
   2109 			       (struct proc *)p
   2110 #endif
   2111 		);
   2112 	if (stcb == NULL) {
   2113 		/* Gak! no memory */
   2114 		goto out_now;
   2115 	}
   2116 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
   2117 		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
   2118 		/* Set the connected flag so we can queue data */
   2119 		soisconnecting(so);
   2120 	}
   2121 	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
   2122 	/* move to second address */
   2123 	switch (sa->sa_family) {
   2124 #ifdef INET
   2125 	case AF_INET:
   2126 		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
   2127 		break;
   2128 #endif
   2129 #ifdef INET6
   2130 	case AF_INET6:
   2131 		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
   2132 		break;
   2133 #endif
   2134 	default:
   2135 		break;
   2136 	}
   2137 
   2138 	error = 0;
   2139 	sctp_connectx_helper_add(stcb, sa, (totaddr-1), &error);
   2140 	/* Fill in the return id */
   2141 	if (error) {
   2142 		(void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_6);
   2143 		goto out_now;
   2144 	}
   2145 	a_id = (sctp_assoc_t *)optval;
   2146 	*a_id = sctp_get_associd(stcb);
   2147 
   2148 	/* initialize authentication parameters for the assoc */
   2149 	sctp_initialize_auth_params(inp, stcb);
   2150 
   2151 	if (delay) {
   2152 		/* doing delayed connection */
   2153 		stcb->asoc.delayed_connection = 1;
   2154 		sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
   2155 	} else {
   2156 		(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
   2157 		sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
   2158 	}
   2159 	SCTP_TCB_UNLOCK(stcb);
   2160 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
   2161 		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
   2162 		/* Set the connected flag so we can queue data */
   2163 		soisconnecting(so);
   2164 	}
   2165  out_now:
   2166 	if (creat_lock_on) {
   2167 		SCTP_ASOC_CREATE_UNLOCK(inp);
   2168 	}
   2169 	SCTP_INP_DECR_REF(inp);
   2170 	return (error);
   2171 }
   2172 
   2173 #define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
   2174 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
   2175 	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
   2176 		SCTP_INP_RLOCK(inp); \
   2177 		stcb = LIST_FIRST(&inp->sctp_asoc_list); \
   2178 		if (stcb) { \
   2179 			SCTP_TCB_LOCK(stcb); \
   2180                 } \
   2181 		SCTP_INP_RUNLOCK(inp); \
   2182 	} else if (assoc_id > SCTP_ALL_ASSOC) { \
   2183 		stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
   2184 		if (stcb == NULL) { \
   2185 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
   2186 			error = ENOENT; \
   2187 			break; \
   2188 		} \
   2189 	} else { \
   2190 		stcb = NULL; \
   2191         } \
   2192   }
   2193 
   2194 
   2195 #define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
   2196 	if (size < sizeof(type)) { \
   2197 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
   2198 		error = EINVAL; \
   2199 		break; \
   2200 	} else { \
   2201 		destp = (type *)srcp; \
   2202 	} \
   2203       }
   2204 
   2205 #if defined(__Panda__) || defined(__Userspace__)
   2206 int
   2207 #else
   2208 static int
   2209 #endif
   2210 sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
   2211 	    void *p) {
   2212 	struct sctp_inpcb *inp = NULL;
   2213 	int error, val = 0;
   2214 	struct sctp_tcb *stcb = NULL;
   2215 
   2216 	if (optval == NULL) {
   2217 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2218 		return (EINVAL);
   2219 	}
   2220 
   2221 	inp = (struct sctp_inpcb *)so->so_pcb;
   2222 	if (inp == NULL) {
   2223 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2224 		return EINVAL;
   2225 	}
   2226 	error = 0;
   2227 
   2228 	switch (optname) {
   2229 	case SCTP_NODELAY:
   2230 	case SCTP_AUTOCLOSE:
   2231 	case SCTP_EXPLICIT_EOR:
   2232 	case SCTP_AUTO_ASCONF:
   2233 	case SCTP_DISABLE_FRAGMENTS:
   2234 	case SCTP_I_WANT_MAPPED_V4_ADDR:
   2235 	case SCTP_USE_EXT_RCVINFO:
   2236 		SCTP_INP_RLOCK(inp);
   2237 		switch (optname) {
   2238 		case SCTP_DISABLE_FRAGMENTS:
   2239 			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
   2240 			break;
   2241 		case SCTP_I_WANT_MAPPED_V4_ADDR:
   2242 			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
   2243 			break;
   2244 		case SCTP_AUTO_ASCONF:
   2245 			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
   2246 				/* only valid for bound all sockets */
   2247 				val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
   2248 			} else {
   2249 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2250 				error = EINVAL;
   2251 				goto flags_out;
   2252 			}
   2253 			break;
   2254 		case SCTP_EXPLICIT_EOR:
   2255 			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
   2256 			break;
   2257 		case SCTP_NODELAY:
   2258 			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
   2259 			break;
   2260 		case SCTP_USE_EXT_RCVINFO:
   2261 			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
   2262 			break;
   2263 		case SCTP_AUTOCLOSE:
   2264 			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
   2265 				val = TICKS_TO_SEC(inp->sctp_ep.auto_close_time);
   2266 			else
   2267 				val = 0;
   2268 			break;
   2269 
   2270 		default:
   2271 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
   2272 			error = ENOPROTOOPT;
   2273 		} /* end switch (sopt->sopt_name) */
   2274 		if (*optsize < sizeof(val)) {
   2275 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2276 			error = EINVAL;
   2277 		}
   2278 	flags_out:
   2279 		SCTP_INP_RUNLOCK(inp);
   2280 		if (error == 0) {
   2281 			/* return the option value */
   2282 			*(int *)optval = val;
   2283 			*optsize = sizeof(val);
   2284 		}
   2285 		break;
   2286         case SCTP_GET_PACKET_LOG:
   2287 	{
   2288 #ifdef  SCTP_PACKET_LOGGING
   2289 		uint8_t *target;
   2290 		int ret;
   2291 
   2292 		SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize);
   2293 		ret = sctp_copy_out_packet_log(target , (int)*optsize);
   2294 		*optsize = ret;
   2295 #else
   2296 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   2297 		error = EOPNOTSUPP;
   2298 #endif
   2299 		break;
   2300 	}
   2301 	case SCTP_REUSE_PORT:
   2302 	{
   2303 		uint32_t *value;
   2304 
   2305 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
   2306 			/* Can't do this for a 1-m socket */
   2307 			error = EINVAL;
   2308 			break;
   2309 		}
   2310 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2311 		*value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
   2312 		*optsize = sizeof(uint32_t);
   2313 		break;
   2314 	}
   2315 	case SCTP_PARTIAL_DELIVERY_POINT:
   2316 	{
   2317 		uint32_t *value;
   2318 
   2319 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2320 		*value = inp->partial_delivery_point;
   2321 		*optsize = sizeof(uint32_t);
   2322 		break;
   2323 	}
   2324 	case SCTP_FRAGMENT_INTERLEAVE:
   2325 	{
   2326 		uint32_t *value;
   2327 
   2328 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2329 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) {
   2330 			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) {
   2331 				*value = SCTP_FRAG_LEVEL_2;
   2332 			} else {
   2333 				*value = SCTP_FRAG_LEVEL_1;
   2334 			}
   2335 		} else {
   2336 			*value = SCTP_FRAG_LEVEL_0;
   2337 		}
   2338 		*optsize = sizeof(uint32_t);
   2339 		break;
   2340 	}
   2341 	case SCTP_CMT_ON_OFF:
   2342 	{
   2343 		struct sctp_assoc_value *av;
   2344 
   2345 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2346 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2347 		if (stcb) {
   2348 			av->assoc_value = stcb->asoc.sctp_cmt_on_off;
   2349 			SCTP_TCB_UNLOCK(stcb);
   2350 		} else {
   2351 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2352 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2353 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   2354 				SCTP_INP_RLOCK(inp);
   2355 				av->assoc_value = inp->sctp_cmt_on_off;
   2356 				SCTP_INP_RUNLOCK(inp);
   2357 			} else {
   2358 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2359 				error = EINVAL;
   2360 			}
   2361 		}
   2362 		if (error == 0) {
   2363 			*optsize = sizeof(struct sctp_assoc_value);
   2364 		}
   2365 		break;
   2366 	}
   2367 	case SCTP_PLUGGABLE_CC:
   2368 	{
   2369 		struct sctp_assoc_value *av;
   2370 
   2371 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2372 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2373 		if (stcb) {
   2374 			av->assoc_value = stcb->asoc.congestion_control_module;
   2375 			SCTP_TCB_UNLOCK(stcb);
   2376 		} else {
   2377 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2378 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2379 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   2380 				SCTP_INP_RLOCK(inp);
   2381 				av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
   2382 				SCTP_INP_RUNLOCK(inp);
   2383 			} else {
   2384 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2385 				error = EINVAL;
   2386 			}
   2387 		}
   2388 		if (error == 0) {
   2389 			*optsize = sizeof(struct sctp_assoc_value);
   2390 		}
   2391 		break;
   2392 	}
   2393 	case SCTP_CC_OPTION:
   2394 	{
   2395 		struct sctp_cc_option *cc_opt;
   2396 
   2397 		SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
   2398 		SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
   2399 		if (stcb == NULL) {
   2400 			error = EINVAL;
   2401 		} else {
   2402 			if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
   2403 				error = ENOTSUP;
   2404 			} else {
   2405 				error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 0, cc_opt);
   2406 				*optsize = sizeof(struct sctp_cc_option);
   2407 			}
   2408 			SCTP_TCB_UNLOCK(stcb);
   2409 		}
   2410 		break;
   2411 	}
   2412 	case SCTP_PLUGGABLE_SS:
   2413 	{
   2414 		struct sctp_assoc_value *av;
   2415 
   2416 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2417 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2418 		if (stcb) {
   2419 			av->assoc_value = stcb->asoc.stream_scheduling_module;
   2420 			SCTP_TCB_UNLOCK(stcb);
   2421 		} else {
   2422 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2423 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2424 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   2425 				SCTP_INP_RLOCK(inp);
   2426 				av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
   2427 				SCTP_INP_RUNLOCK(inp);
   2428 			} else {
   2429 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2430 				error = EINVAL;
   2431 			}
   2432 		}
   2433 		if (error == 0) {
   2434 			*optsize = sizeof(struct sctp_assoc_value);
   2435 		}
   2436 		break;
   2437 	}
   2438 	case SCTP_SS_VALUE:
   2439 	{
   2440 		struct sctp_stream_value *av;
   2441 
   2442 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
   2443 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2444 		if (stcb) {
   2445 			if (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
   2446 			                                              &av->stream_value) < 0) {
   2447 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2448 				error = EINVAL;
   2449 			} else {
   2450 				*optsize = sizeof(struct sctp_stream_value);
   2451 			}
   2452 			SCTP_TCB_UNLOCK(stcb);
   2453 		} else {
   2454 			/* Can't get stream value without association */
   2455 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2456 			error = EINVAL;
   2457 		}
   2458 		break;
   2459 	}
   2460 	case SCTP_GET_ADDR_LEN:
   2461 	{
   2462 		struct sctp_assoc_value *av;
   2463 
   2464 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2465 		error = EINVAL;
   2466 #ifdef INET
   2467 		if (av->assoc_value == AF_INET) {
   2468 			av->assoc_value = sizeof(struct sockaddr_in);
   2469 			error = 0;
   2470 		}
   2471 #endif
   2472 #ifdef INET6
   2473 		if (av->assoc_value == AF_INET6) {
   2474 			av->assoc_value = sizeof(struct sockaddr_in6);
   2475 			error = 0;
   2476 		}
   2477 #endif
   2478 #if defined(__Userspace__)
   2479 		if (av->assoc_value == AF_CONN) {
   2480 			av->assoc_value = sizeof(struct sockaddr_conn);
   2481 			error = 0;
   2482 		}
   2483 #endif
   2484 		if (error) {
   2485 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   2486 		} else {
   2487 			*optsize = sizeof(struct sctp_assoc_value);
   2488 		}
   2489 		break;
   2490 	}
   2491 	case SCTP_GET_ASSOC_NUMBER:
   2492 	{
   2493 		uint32_t *value, cnt;
   2494 
   2495 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2496 		cnt = 0;
   2497 		SCTP_INP_RLOCK(inp);
   2498 		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   2499 			cnt++;
   2500 		}
   2501 		SCTP_INP_RUNLOCK(inp);
   2502 		*value = cnt;
   2503 		*optsize = sizeof(uint32_t);
   2504 		break;
   2505 	}
   2506 	case SCTP_GET_ASSOC_ID_LIST:
   2507 	{
   2508 		struct sctp_assoc_ids *ids;
   2509 		unsigned int at, limit;
   2510 
   2511 		SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
   2512 		at = 0;
   2513 		limit = (*optsize-sizeof(uint32_t))/ sizeof(sctp_assoc_t);
   2514 		SCTP_INP_RLOCK(inp);
   2515 		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   2516 			if (at < limit) {
   2517 				ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
   2518 			} else {
   2519 				error = EINVAL;
   2520 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   2521 				break;
   2522 			}
   2523 		}
   2524 		SCTP_INP_RUNLOCK(inp);
   2525 		if (error == 0) {
   2526 			ids->gaids_number_of_ids = at;
   2527 			*optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
   2528 		}
   2529 		break;
   2530 	}
   2531 	case SCTP_CONTEXT:
   2532 	{
   2533 		struct sctp_assoc_value *av;
   2534 
   2535 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2536 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2537 
   2538 		if (stcb) {
   2539 			av->assoc_value = stcb->asoc.context;
   2540 			SCTP_TCB_UNLOCK(stcb);
   2541 		} else {
   2542 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2543 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2544 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   2545 				SCTP_INP_RLOCK(inp);
   2546 				av->assoc_value = inp->sctp_context;
   2547 				SCTP_INP_RUNLOCK(inp);
   2548 			} else {
   2549 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2550 				error = EINVAL;
   2551 			}
   2552 		}
   2553 		if (error == 0) {
   2554 			*optsize = sizeof(struct sctp_assoc_value);
   2555 		}
   2556 		break;
   2557 	}
   2558 	case SCTP_VRF_ID:
   2559 	{
   2560 		uint32_t *default_vrfid;
   2561 
   2562 		SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
   2563 		*default_vrfid = inp->def_vrf_id;
   2564 		*optsize = sizeof(uint32_t);
   2565 		break;
   2566 	}
   2567 	case SCTP_GET_ASOC_VRF:
   2568 	{
   2569 		struct sctp_assoc_value *id;
   2570 
   2571 		SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
   2572 		SCTP_FIND_STCB(inp, stcb, id->assoc_id);
   2573 		if (stcb == NULL) {
   2574 			error = EINVAL;
   2575 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   2576 		} else {
   2577 			id->assoc_value = stcb->asoc.vrf_id;
   2578 			*optsize = sizeof(struct sctp_assoc_value);
   2579 		}
   2580 		break;
   2581 	}
   2582 	case SCTP_GET_VRF_IDS:
   2583 	{
   2584 #ifdef SCTP_MVRF
   2585 		int siz_needed;
   2586 		uint32_t *vrf_ids;
   2587 
   2588 		SCTP_CHECK_AND_CAST(vrf_ids, optval, uint32_t, *optsize);
   2589 		siz_needed = inp->num_vrfs * sizeof(uint32_t);
   2590 		if (*optsize < siz_needed) {
   2591 			error = EINVAL;
   2592 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   2593 		} else {
   2594 			memcpy(vrf_ids, inp->m_vrf_ids, siz_needed);
   2595 			*optsize = siz_needed;
   2596 		}
   2597 #else
   2598 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   2599 		error = EOPNOTSUPP;
   2600 #endif
   2601 		break;
   2602 	}
   2603 	case SCTP_GET_NONCE_VALUES:
   2604 	{
   2605 		struct sctp_get_nonce_values *gnv;
   2606 
   2607 		SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
   2608 		SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
   2609 
   2610 		if (stcb) {
   2611 			gnv->gn_peers_tag = stcb->asoc.peer_vtag;
   2612 			gnv->gn_local_tag = stcb->asoc.my_vtag;
   2613 			SCTP_TCB_UNLOCK(stcb);
   2614 			*optsize = sizeof(struct sctp_get_nonce_values);
   2615 		} else {
   2616 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
   2617 			error = ENOTCONN;
   2618 		}
   2619 		break;
   2620 	}
   2621 	case SCTP_DELAYED_SACK:
   2622 	{
   2623 		struct sctp_sack_info *sack;
   2624 
   2625 		SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, *optsize);
   2626 		SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
   2627 		if (stcb) {
   2628 			sack->sack_delay = stcb->asoc.delayed_ack;
   2629 			sack->sack_freq = stcb->asoc.sack_freq;
   2630 			SCTP_TCB_UNLOCK(stcb);
   2631 		} else {
   2632 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2633 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2634 			    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC)) {
   2635 				SCTP_INP_RLOCK(inp);
   2636 				sack->sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
   2637 				sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
   2638 				SCTP_INP_RUNLOCK(inp);
   2639 			} else {
   2640 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2641 				error = EINVAL;
   2642 			}
   2643 		}
   2644 		if (error == 0) {
   2645 			*optsize = sizeof(struct sctp_sack_info);
   2646 		}
   2647 		break;
   2648 	}
   2649 	case SCTP_GET_SNDBUF_USE:
   2650 	{
   2651 		struct sctp_sockstat *ss;
   2652 
   2653 		SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
   2654 		SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
   2655 
   2656 		if (stcb) {
   2657 			ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
   2658 			ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
   2659 						 stcb->asoc.size_on_all_streams);
   2660 			SCTP_TCB_UNLOCK(stcb);
   2661 			*optsize = sizeof(struct sctp_sockstat);
   2662 		} else {
   2663 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
   2664 			error = ENOTCONN;
   2665 		}
   2666 		break;
   2667 	}
   2668 	case SCTP_MAX_BURST:
   2669 	{
   2670 #if defined(__FreeBSD__) && __FreeBSD_version < 900000
   2671 		uint8_t *value;
   2672 
   2673 		SCTP_CHECK_AND_CAST(value, optval, uint8_t, *optsize);
   2674 
   2675 		SCTP_INP_RLOCK(inp);
   2676 		if (inp->sctp_ep.max_burst < 256) {
   2677 			*value = inp->sctp_ep.max_burst;
   2678 		} else {
   2679 			*value = 255;
   2680 		}
   2681 		SCTP_INP_RUNLOCK(inp);
   2682 		*optsize = sizeof(uint8_t);
   2683 #else
   2684 		struct sctp_assoc_value *av;
   2685 
   2686 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2687 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2688 
   2689 		if (stcb) {
   2690 			av->assoc_value = stcb->asoc.max_burst;
   2691 			SCTP_TCB_UNLOCK(stcb);
   2692 		} else {
   2693 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2694 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2695 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   2696 				SCTP_INP_RLOCK(inp);
   2697 				av->assoc_value = inp->sctp_ep.max_burst;
   2698 				SCTP_INP_RUNLOCK(inp);
   2699 			} else {
   2700 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2701 				error = EINVAL;
   2702 			}
   2703 		}
   2704 		if (error == 0) {
   2705 			*optsize = sizeof(struct sctp_assoc_value);
   2706 		}
   2707 #endif
   2708 		break;
   2709 	}
   2710 	case SCTP_MAXSEG:
   2711 	{
   2712 		struct sctp_assoc_value *av;
   2713 		int ovh;
   2714 
   2715 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   2716 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   2717 
   2718 		if (stcb) {
   2719 			av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
   2720 			SCTP_TCB_UNLOCK(stcb);
   2721 		} else {
   2722 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2723 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   2724 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   2725 				SCTP_INP_RLOCK(inp);
   2726 				if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   2727 					ovh = SCTP_MED_OVERHEAD;
   2728 				} else {
   2729 					ovh = SCTP_MED_V4_OVERHEAD;
   2730 				}
   2731 				if (inp->sctp_frag_point >= SCTP_DEFAULT_MAXSEGMENT)
   2732 					av->assoc_value = 0;
   2733 				else
   2734 					av->assoc_value = inp->sctp_frag_point - ovh;
   2735 				SCTP_INP_RUNLOCK(inp);
   2736 			} else {
   2737 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   2738 				error = EINVAL;
   2739 			}
   2740 		}
   2741 		if (error == 0) {
   2742 			*optsize = sizeof(struct sctp_assoc_value);
   2743 		}
   2744 		break;
   2745 	}
   2746 	case SCTP_GET_STAT_LOG:
   2747 		error = sctp_fill_stat_log(optval, optsize);
   2748 		break;
   2749 	case SCTP_EVENTS:
   2750 	{
   2751 		struct sctp_event_subscribe *events;
   2752 
   2753 		SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
   2754 		memset(events, 0, sizeof(struct sctp_event_subscribe));
   2755 		SCTP_INP_RLOCK(inp);
   2756 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
   2757 			events->sctp_data_io_event = 1;
   2758 
   2759 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT))
   2760 			events->sctp_association_event = 1;
   2761 
   2762 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT))
   2763 			events->sctp_address_event = 1;
   2764 
   2765 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
   2766 			events->sctp_send_failure_event = 1;
   2767 
   2768 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR))
   2769 			events->sctp_peer_error_event = 1;
   2770 
   2771 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
   2772 			events->sctp_shutdown_event = 1;
   2773 
   2774 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT))
   2775 			events->sctp_partial_delivery_event = 1;
   2776 
   2777 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT))
   2778 			events->sctp_adaptation_layer_event = 1;
   2779 
   2780 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT))
   2781 			events->sctp_authentication_event = 1;
   2782 
   2783 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT))
   2784 			events->sctp_sender_dry_event = 1;
   2785 
   2786 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
   2787 			events->sctp_stream_reset_event = 1;
   2788 		SCTP_INP_RUNLOCK(inp);
   2789 		*optsize = sizeof(struct sctp_event_subscribe);
   2790 		break;
   2791 	}
   2792 	case SCTP_ADAPTATION_LAYER:
   2793 	{
   2794 		uint32_t *value;
   2795 
   2796 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2797 
   2798 		SCTP_INP_RLOCK(inp);
   2799 		*value = inp->sctp_ep.adaptation_layer_indicator;
   2800 		SCTP_INP_RUNLOCK(inp);
   2801 		*optsize = sizeof(uint32_t);
   2802 		break;
   2803 	}
   2804 	case SCTP_SET_INITIAL_DBG_SEQ:
   2805 	{
   2806 		uint32_t *value;
   2807 
   2808 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2809 		SCTP_INP_RLOCK(inp);
   2810 		*value = inp->sctp_ep.initial_sequence_debug;
   2811 		SCTP_INP_RUNLOCK(inp);
   2812 		*optsize = sizeof(uint32_t);
   2813 		break;
   2814 	}
   2815 	case SCTP_GET_LOCAL_ADDR_SIZE:
   2816 	{
   2817 		uint32_t *value;
   2818 
   2819 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2820 		SCTP_INP_RLOCK(inp);
   2821 		*value = sctp_count_max_addresses(inp);
   2822 		SCTP_INP_RUNLOCK(inp);
   2823 		*optsize = sizeof(uint32_t);
   2824 		break;
   2825 	}
   2826 	case SCTP_GET_REMOTE_ADDR_SIZE:
   2827 	{
   2828 		uint32_t *value;
   2829 		size_t size;
   2830 		struct sctp_nets *net;
   2831 
   2832 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
   2833 		/* FIXME MT: change to sctp_assoc_value? */
   2834 		SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
   2835 
   2836 		if (stcb) {
   2837 			size = 0;
   2838 			/* Count the sizes */
   2839 			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   2840 				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
   2841 					size += sizeof(struct sockaddr_in6);
   2842 				} else {
   2843 					switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
   2844 #ifdef INET
   2845 					case AF_INET:
   2846 						size += sizeof(struct sockaddr_in);
   2847 						break;
   2848 #endif
   2849 #ifdef INET6
   2850 					case AF_INET6:
   2851 						size += sizeof(struct sockaddr_in6);
   2852 						break;
   2853 #endif
   2854 #if defined(__Userspace__)
   2855 					case AF_CONN:
   2856 						size += sizeof(struct sockaddr_conn);
   2857 						break;
   2858 #endif
   2859 					default:
   2860 						break;
   2861 					}
   2862 				}
   2863 			}
   2864 			SCTP_TCB_UNLOCK(stcb);
   2865 			*value = (uint32_t) size;
   2866 			*optsize = sizeof(uint32_t);
   2867 		} else {
   2868 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
   2869 			error = ENOTCONN;
   2870 		}
   2871 		break;
   2872 	}
   2873 	case SCTP_GET_PEER_ADDRESSES:
   2874 		/*
   2875 		 * Get the address information, an array is passed in to
   2876 		 * fill up we pack it.
   2877 		 */
   2878 	{
   2879 		size_t cpsz, left;
   2880 		struct sockaddr_storage *sas;
   2881 		struct sctp_nets *net;
   2882 		struct sctp_getaddresses *saddr;
   2883 
   2884 		SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
   2885 		SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
   2886 
   2887 		if (stcb) {
   2888 			left = (*optsize) - sizeof(struct sctp_getaddresses);
   2889 			*optsize = sizeof(struct sctp_getaddresses);
   2890 			sas = (struct sockaddr_storage *)&saddr->addr[0];
   2891 
   2892 			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   2893 				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
   2894 					cpsz = sizeof(struct sockaddr_in6);
   2895 				} else {
   2896 					switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
   2897 #ifdef INET
   2898 					case AF_INET:
   2899 						cpsz = sizeof(struct sockaddr_in);
   2900 						break;
   2901 #endif
   2902 #ifdef INET6
   2903 					case AF_INET6:
   2904 						cpsz = sizeof(struct sockaddr_in6);
   2905 						break;
   2906 #endif
   2907 #if defined(__Userspace__)
   2908 					case AF_CONN:
   2909 						cpsz = sizeof(struct sockaddr_conn);
   2910 						break;
   2911 #endif
   2912 					default:
   2913 						cpsz = 0;
   2914 						break;
   2915 					}
   2916 				}
   2917 				if (cpsz == 0) {
   2918 					break;
   2919 				}
   2920 				if (left < cpsz) {
   2921 					/* not enough room. */
   2922 					break;
   2923 				}
   2924 #if defined(INET) && defined(INET6)
   2925 				if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
   2926 				    (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
   2927 					/* Must map the address */
   2928 					in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr,
   2929 							    (struct sockaddr_in6 *)sas);
   2930 				} else {
   2931 #endif
   2932 					memcpy(sas, &net->ro._l_addr, cpsz);
   2933 #if defined(INET) && defined(INET6)
   2934 				}
   2935 #endif
   2936 				((struct sockaddr_in *)sas)->sin_port = stcb->rport;
   2937 
   2938 				sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz);
   2939 				left -= cpsz;
   2940 				*optsize += cpsz;
   2941 			}
   2942 			SCTP_TCB_UNLOCK(stcb);
   2943 		} else {
   2944 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   2945 			error = ENOENT;
   2946 		}
   2947 		break;
   2948 	}
   2949 	case SCTP_GET_LOCAL_ADDRESSES:
   2950 	{
   2951 		size_t limit, actual;
   2952 		struct sockaddr_storage *sas;
   2953 		struct sctp_getaddresses *saddr;
   2954 
   2955 		SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
   2956 		SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
   2957 
   2958 		sas = (struct sockaddr_storage *)&saddr->addr[0];
   2959 		limit = *optsize - sizeof(sctp_assoc_t);
   2960 		actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
   2961 		if (stcb) {
   2962 			SCTP_TCB_UNLOCK(stcb);
   2963 		}
   2964 		*optsize = sizeof(struct sockaddr_storage) + actual;
   2965 		break;
   2966 	}
   2967 	case SCTP_PEER_ADDR_PARAMS:
   2968 	{
   2969 		struct sctp_paddrparams *paddrp;
   2970 		struct sctp_nets *net;
   2971 
   2972 		SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
   2973 		SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
   2974 
   2975 		net = NULL;
   2976 		if (stcb) {
   2977 			net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
   2978 		} else {
   2979 			/* We increment here since sctp_findassociation_ep_addr() wil
   2980 			 * do a decrement if it finds the stcb as long as the locked
   2981 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   2982 			 */
   2983 			SCTP_INP_INCR_REF(inp);
   2984 			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddrp->spp_address, &net, NULL, NULL);
   2985 			if (stcb == NULL) {
   2986 				SCTP_INP_DECR_REF(inp);
   2987 			}
   2988 		}
   2989 		if (stcb && (net == NULL)) {
   2990 			struct sockaddr *sa;
   2991 
   2992 			sa = (struct sockaddr *)&paddrp->spp_address;
   2993 #ifdef INET
   2994 			if (sa->sa_family == AF_INET) {
   2995 				struct sockaddr_in *sin;
   2996 
   2997 				sin = (struct sockaddr_in *)sa;
   2998 				if (sin->sin_addr.s_addr) {
   2999 					error = EINVAL;
   3000 					SCTP_TCB_UNLOCK(stcb);
   3001 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3002 					break;
   3003 				}
   3004 			} else
   3005 #endif
   3006 #ifdef INET6
   3007 			if (sa->sa_family == AF_INET6) {
   3008 				struct sockaddr_in6 *sin6;
   3009 
   3010 				sin6 = (struct sockaddr_in6 *)sa;
   3011 				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   3012 					error = EINVAL;
   3013 					SCTP_TCB_UNLOCK(stcb);
   3014 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3015 					break;
   3016 				}
   3017 			} else
   3018 #endif
   3019 #if defined(__Userspace__)
   3020 			if (sa->sa_family == AF_CONN) {
   3021 				struct sockaddr_conn *sconn;
   3022 
   3023 				sconn = (struct sockaddr_conn *)sa;
   3024 				if (sconn->sconn_addr != NULL) {
   3025 					error = EINVAL;
   3026 					SCTP_TCB_UNLOCK(stcb);
   3027 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3028 					break;
   3029 				}
   3030 			} else
   3031 #endif
   3032 			{
   3033 				error = EAFNOSUPPORT;
   3034 				SCTP_TCB_UNLOCK(stcb);
   3035 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3036 				break;
   3037 			}
   3038 		}
   3039 
   3040 		if (stcb) {
   3041 			/* Applies to the specific association */
   3042 			paddrp->spp_flags = 0;
   3043 			if (net) {
   3044 				int ovh;
   3045 				if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   3046 					ovh = SCTP_MED_OVERHEAD;
   3047 				} else {
   3048 					ovh = SCTP_MED_V4_OVERHEAD;
   3049 				}
   3050 
   3051 				paddrp->spp_hbinterval = net->heart_beat_delay;
   3052 				paddrp->spp_pathmaxrxt = net->failure_threshold;
   3053 				paddrp->spp_pathmtu = net->mtu - ovh;
   3054 				/* get flags for HB */
   3055 				if (net->dest_state & SCTP_ADDR_NOHB) {
   3056 					paddrp->spp_flags |= SPP_HB_DISABLE;
   3057 				} else {
   3058 					paddrp->spp_flags |= SPP_HB_ENABLE;
   3059 				}
   3060 				/* get flags for PMTU */
   3061 				if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
   3062 					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
   3063 				} else {
   3064 					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
   3065 				}
   3066 				if (net->dscp & 0x01) {
   3067 					paddrp->spp_dscp = net->dscp & 0xfc;
   3068 					paddrp->spp_flags |= SPP_DSCP;
   3069 				}
   3070 #ifdef INET6
   3071 				if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
   3072 				    (net->flowlabel & 0x80000000)) {
   3073 					paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
   3074 					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
   3075 				}
   3076 #endif
   3077 			} else {
   3078 				/*
   3079 				 * No destination so return default
   3080 				 * value
   3081 				 */
   3082 				paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
   3083 				paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc);
   3084 				if (stcb->asoc.default_dscp & 0x01) {
   3085 					paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
   3086 					paddrp->spp_flags |= SPP_DSCP;
   3087 				}
   3088 #ifdef INET6
   3089 				if (stcb->asoc.default_flowlabel & 0x80000000) {
   3090 					paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
   3091 					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
   3092 				}
   3093 #endif
   3094 				/* default settings should be these */
   3095 				if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
   3096 					paddrp->spp_flags |= SPP_HB_DISABLE;
   3097 				} else {
   3098 					paddrp->spp_flags |= SPP_HB_ENABLE;
   3099 				}
   3100 				if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
   3101 					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
   3102 				} else {
   3103 					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
   3104 				}
   3105 				paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
   3106 			}
   3107 			paddrp->spp_assoc_id = sctp_get_associd(stcb);
   3108 			SCTP_TCB_UNLOCK(stcb);
   3109 		} else {
   3110 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3111 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3112 			    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
   3113 				/* Use endpoint defaults */
   3114 				SCTP_INP_RLOCK(inp);
   3115 				paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
   3116 				paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
   3117 				paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
   3118 				/* get inp's default */
   3119 				if (inp->sctp_ep.default_dscp & 0x01) {
   3120 					paddrp->spp_dscp = inp->sctp_ep.default_dscp & 0xfc;
   3121 					paddrp->spp_flags |= SPP_DSCP;
   3122 				}
   3123 #ifdef INET6
   3124 				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
   3125 				    (inp->sctp_ep.default_flowlabel & 0x80000000)) {
   3126 					paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
   3127 					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
   3128 				}
   3129 #endif
   3130 				/* can't return this */
   3131 				paddrp->spp_pathmtu = 0;
   3132 
   3133 				if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
   3134 					paddrp->spp_flags |= SPP_HB_ENABLE;
   3135 				} else {
   3136 					paddrp->spp_flags |= SPP_HB_DISABLE;
   3137 				}
   3138 				if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
   3139 					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
   3140 				} else {
   3141 					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
   3142 				}
   3143 				SCTP_INP_RUNLOCK(inp);
   3144 			} else {
   3145 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3146 				error = EINVAL;
   3147 			}
   3148 		}
   3149 		if (error == 0) {
   3150 			*optsize = sizeof(struct sctp_paddrparams);
   3151 		}
   3152 		break;
   3153 	}
   3154 	case SCTP_GET_PEER_ADDR_INFO:
   3155 	{
   3156 		struct sctp_paddrinfo *paddri;
   3157 		struct sctp_nets *net;
   3158 
   3159 		SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
   3160 		SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
   3161 
   3162 		net = NULL;
   3163 		if (stcb) {
   3164 			net = sctp_findnet(stcb, (struct sockaddr *)&paddri->spinfo_address);
   3165 		} else {
   3166 			/* We increment here since sctp_findassociation_ep_addr() wil
   3167 			 * do a decrement if it finds the stcb as long as the locked
   3168 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   3169 			 */
   3170 			SCTP_INP_INCR_REF(inp);
   3171 			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddri->spinfo_address, &net, NULL, NULL);
   3172 			if (stcb == NULL) {
   3173 				SCTP_INP_DECR_REF(inp);
   3174 			}
   3175 		}
   3176 
   3177 		if ((stcb) && (net)) {
   3178 			if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
   3179 				/* It's unconfirmed */
   3180 				paddri->spinfo_state = SCTP_UNCONFIRMED;
   3181 			} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
   3182 				/* It's active */
   3183 				paddri->spinfo_state = SCTP_ACTIVE;
   3184 			} else {
   3185 				/* It's inactive */
   3186 				paddri->spinfo_state = SCTP_INACTIVE;
   3187 			}
   3188 			paddri->spinfo_cwnd = net->cwnd;
   3189 			paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
   3190 			paddri->spinfo_rto = net->RTO;
   3191 			paddri->spinfo_assoc_id = sctp_get_associd(stcb);
   3192 			paddri->spinfo_mtu = net->mtu;
   3193 			SCTP_TCB_UNLOCK(stcb);
   3194 			*optsize = sizeof(struct sctp_paddrinfo);
   3195 		} else {
   3196 			if (stcb) {
   3197 				SCTP_TCB_UNLOCK(stcb);
   3198 			}
   3199 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   3200 			error = ENOENT;
   3201 		}
   3202 		break;
   3203 	}
   3204 	case SCTP_PCB_STATUS:
   3205 	{
   3206 		struct sctp_pcbinfo *spcb;
   3207 
   3208 		SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
   3209 		sctp_fill_pcbinfo(spcb);
   3210 		*optsize = sizeof(struct sctp_pcbinfo);
   3211 		break;
   3212 	}
   3213 	case SCTP_STATUS:
   3214 	{
   3215 		struct sctp_nets *net;
   3216 		struct sctp_status *sstat;
   3217 
   3218 		SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
   3219 		SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
   3220 
   3221 		if (stcb == NULL) {
   3222 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3223 			error = EINVAL;
   3224 			break;
   3225 		}
   3226 		/*
   3227 		 * I think passing the state is fine since
   3228 		 * sctp_constants.h will be available to the user
   3229 		 * land.
   3230 		 */
   3231 		sstat->sstat_state = stcb->asoc.state;
   3232 		sstat->sstat_assoc_id = sctp_get_associd(stcb);
   3233 		sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
   3234 		sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
   3235 		/*
   3236 		 * We can't include chunks that have been passed to
   3237 		 * the socket layer. Only things in queue.
   3238 		 */
   3239 		sstat->sstat_penddata = (stcb->asoc.cnt_on_reasm_queue +
   3240 					 stcb->asoc.cnt_on_all_streams);
   3241 
   3242 
   3243 		sstat->sstat_instrms = stcb->asoc.streamincnt;
   3244 		sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
   3245 		sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
   3246 #ifdef HAVE_SA_LEN
   3247 		memcpy(&sstat->sstat_primary.spinfo_address,
   3248 		       &stcb->asoc.primary_destination->ro._l_addr,
   3249 		       ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
   3250 #else
   3251 		if (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET) {
   3252 			memcpy(&sstat->sstat_primary.spinfo_address,
   3253 			       &stcb->asoc.primary_destination->ro._l_addr,
   3254 			       sizeof(struct sockaddr_in));
   3255 		} else {
   3256 			memcpy(&sstat->sstat_primary.spinfo_address,
   3257 			       &stcb->asoc.primary_destination->ro._l_addr,
   3258 			       sizeof(struct sockaddr_in6));
   3259 		}
   3260 #endif
   3261 		net = stcb->asoc.primary_destination;
   3262 		((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
   3263 		/*
   3264 		 * Again the user can get info from sctp_constants.h
   3265 		 * for what the state of the network is.
   3266 		 */
   3267 		if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
   3268 			/* It's unconfirmed */
   3269 			sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
   3270 		} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
   3271 			/* It's active */
   3272 			sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
   3273 		} else {
   3274 			/* It's inactive */
   3275 			sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
   3276 		}
   3277 		sstat->sstat_primary.spinfo_cwnd = net->cwnd;
   3278 		sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
   3279 		sstat->sstat_primary.spinfo_rto = net->RTO;
   3280 		sstat->sstat_primary.spinfo_mtu = net->mtu;
   3281 		sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
   3282 		SCTP_TCB_UNLOCK(stcb);
   3283 		*optsize = sizeof(struct sctp_status);
   3284 		break;
   3285 	}
   3286 	case SCTP_RTOINFO:
   3287 	{
   3288 		struct sctp_rtoinfo *srto;
   3289 
   3290 		SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
   3291 		SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
   3292 
   3293 		if (stcb) {
   3294 			srto->srto_initial = stcb->asoc.initial_rto;
   3295 			srto->srto_max = stcb->asoc.maxrto;
   3296 			srto->srto_min = stcb->asoc.minrto;
   3297 			SCTP_TCB_UNLOCK(stcb);
   3298 		} else {
   3299 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3300 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3301 			    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
   3302 				SCTP_INP_RLOCK(inp);
   3303 				srto->srto_initial = inp->sctp_ep.initial_rto;
   3304 				srto->srto_max = inp->sctp_ep.sctp_maxrto;
   3305 				srto->srto_min = inp->sctp_ep.sctp_minrto;
   3306 				SCTP_INP_RUNLOCK(inp);
   3307 			} else {
   3308 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3309 				error = EINVAL;
   3310 			}
   3311 		}
   3312 		if (error == 0) {
   3313 			*optsize = sizeof(struct sctp_rtoinfo);
   3314 		}
   3315 		break;
   3316 	}
   3317 	case SCTP_TIMEOUTS:
   3318 	{
   3319 		struct sctp_timeouts *stimo;
   3320 
   3321 		SCTP_CHECK_AND_CAST(stimo, optval, struct sctp_timeouts, *optsize);
   3322 		SCTP_FIND_STCB(inp, stcb, stimo->stimo_assoc_id);
   3323 
   3324 		if (stcb) {
   3325 			stimo->stimo_init= stcb->asoc.timoinit;
   3326 			stimo->stimo_data= stcb->asoc.timodata;
   3327 			stimo->stimo_sack= stcb->asoc.timosack;
   3328 			stimo->stimo_shutdown= stcb->asoc.timoshutdown;
   3329 			stimo->stimo_heartbeat= stcb->asoc.timoheartbeat;
   3330 			stimo->stimo_cookie= stcb->asoc.timocookie;
   3331 			stimo->stimo_shutdownack= stcb->asoc.timoshutdownack;
   3332 			SCTP_TCB_UNLOCK(stcb);
   3333 			*optsize = sizeof(struct sctp_timeouts);
   3334 		} else {
   3335 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3336 			error = EINVAL;
   3337 		}
   3338 		break;
   3339 	}
   3340 	case SCTP_ASSOCINFO:
   3341 	{
   3342 		struct sctp_assocparams *sasoc;
   3343 
   3344 		SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
   3345 		SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
   3346 
   3347 		if (stcb) {
   3348 			sasoc->sasoc_cookie_life = TICKS_TO_MSEC(stcb->asoc.cookie_life);
   3349 			sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
   3350 			sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
   3351 			sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
   3352 			sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
   3353 			SCTP_TCB_UNLOCK(stcb);
   3354 		} else {
   3355 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3356 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3357 			    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
   3358 				SCTP_INP_RLOCK(inp);
   3359 				sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
   3360 				sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
   3361 				sasoc->sasoc_number_peer_destinations = 0;
   3362 				sasoc->sasoc_peer_rwnd = 0;
   3363 				sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
   3364 				SCTP_INP_RUNLOCK(inp);
   3365 			} else {
   3366 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3367 				error = EINVAL;
   3368 			}
   3369 		}
   3370 		if (error == 0) {
   3371 			*optsize = sizeof(struct sctp_assocparams);
   3372 		}
   3373 		break;
   3374 	}
   3375 	case SCTP_DEFAULT_SEND_PARAM:
   3376 	{
   3377 		struct sctp_sndrcvinfo *s_info;
   3378 
   3379 		SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
   3380 		SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
   3381 
   3382 		if (stcb) {
   3383 			memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
   3384 			SCTP_TCB_UNLOCK(stcb);
   3385 		} else {
   3386 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3387 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3388 			    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC)) {
   3389 				SCTP_INP_RLOCK(inp);
   3390 				memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
   3391 				SCTP_INP_RUNLOCK(inp);
   3392 			} else {
   3393 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3394 				error = EINVAL;
   3395 			}
   3396 		}
   3397 		if (error == 0) {
   3398 			*optsize = sizeof(struct sctp_sndrcvinfo);
   3399 		}
   3400 		break;
   3401 	}
   3402 	case SCTP_INITMSG:
   3403 	{
   3404 		struct sctp_initmsg *sinit;
   3405 
   3406 		SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
   3407 		SCTP_INP_RLOCK(inp);
   3408 		sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
   3409 		sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
   3410 		sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
   3411 		sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
   3412 		SCTP_INP_RUNLOCK(inp);
   3413 		*optsize = sizeof(struct sctp_initmsg);
   3414 		break;
   3415 	}
   3416 	case SCTP_PRIMARY_ADDR:
   3417 		/* we allow a "get" operation on this */
   3418 	{
   3419 		struct sctp_setprim *ssp;
   3420 
   3421 		SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
   3422 		SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
   3423 
   3424 		if (stcb) {
   3425 			/* simply copy out the sockaddr_storage... */
   3426 			size_t len;
   3427 
   3428 			len = *optsize;
   3429 #ifdef HAVE_SA_LEN
   3430 			if (len > stcb->asoc.primary_destination->ro._l_addr.sa.sa_len)
   3431 				len = stcb->asoc.primary_destination->ro._l_addr.sa.sa_len;
   3432 #else
   3433 			if (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET &&
   3434 			    len > sizeof(struct sockaddr_in))
   3435 				len = sizeof(struct sockaddr_in);
   3436 			else if (
   3437 			    stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET6 &&
   3438 			    len > sizeof(struct sockaddr_in6))
   3439 				len = sizeof(struct sockaddr_in6);
   3440 #endif
   3441 
   3442 			memcpy(&ssp->ssp_addr,
   3443 			       &stcb->asoc.primary_destination->ro._l_addr,
   3444 			       len);
   3445 			SCTP_TCB_UNLOCK(stcb);
   3446 			*optsize = sizeof(struct sctp_setprim);
   3447 		} else {
   3448 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3449 			error = EINVAL;
   3450 		}
   3451 		break;
   3452 	}
   3453 	case SCTP_HMAC_IDENT:
   3454 	{
   3455 		struct sctp_hmacalgo *shmac;
   3456 		sctp_hmaclist_t *hmaclist;
   3457 		uint32_t size;
   3458 		int i;
   3459 
   3460 		SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
   3461 
   3462 		SCTP_INP_RLOCK(inp);
   3463 		hmaclist = inp->sctp_ep.local_hmacs;
   3464 		if (hmaclist == NULL) {
   3465 			/* no HMACs to return */
   3466 			*optsize = sizeof(*shmac);
   3467 			SCTP_INP_RUNLOCK(inp);
   3468 			break;
   3469 		}
   3470 		/* is there room for all of the hmac ids? */
   3471 		size = sizeof(*shmac) + (hmaclist->num_algo *
   3472 					 sizeof(shmac->shmac_idents[0]));
   3473 		if ((size_t)(*optsize) < size) {
   3474 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3475 			error = EINVAL;
   3476 			SCTP_INP_RUNLOCK(inp);
   3477 			break;
   3478 		}
   3479 		/* copy in the list */
   3480 		shmac->shmac_number_of_idents = hmaclist->num_algo;
   3481 		for (i = 0; i < hmaclist->num_algo; i++) {
   3482 			shmac->shmac_idents[i] = hmaclist->hmac[i];
   3483 		}
   3484 		SCTP_INP_RUNLOCK(inp);
   3485 		*optsize = size;
   3486 		break;
   3487 	}
   3488 	case SCTP_AUTH_ACTIVE_KEY:
   3489 	{
   3490 		struct sctp_authkeyid *scact;
   3491 
   3492 		SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
   3493 		SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
   3494 
   3495 		if (stcb) {
   3496 			/* get the active key on the assoc */
   3497 			scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
   3498 			SCTP_TCB_UNLOCK(stcb);
   3499 		} else {
   3500 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3501 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3502 			    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC)) {
   3503 				/* get the endpoint active key */
   3504 				SCTP_INP_RLOCK(inp);
   3505 				scact->scact_keynumber = inp->sctp_ep.default_keyid;
   3506 				SCTP_INP_RUNLOCK(inp);
   3507 			} else {
   3508 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3509 				error = EINVAL;
   3510 			}
   3511 		}
   3512 		if (error == 0) {
   3513 			*optsize = sizeof(struct sctp_authkeyid);
   3514 		}
   3515 		break;
   3516 	}
   3517 	case SCTP_LOCAL_AUTH_CHUNKS:
   3518 	{
   3519 		struct sctp_authchunks *sac;
   3520 		sctp_auth_chklist_t *chklist = NULL;
   3521 		size_t size = 0;
   3522 
   3523 		SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
   3524 		SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
   3525 
   3526 		if (stcb) {
   3527 			/* get off the assoc */
   3528 			chklist = stcb->asoc.local_auth_chunks;
   3529 			/* is there enough space? */
   3530 			size = sctp_auth_get_chklist_size(chklist);
   3531 			if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
   3532 				error = EINVAL;
   3533 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3534 			} else {
   3535 				/* copy in the chunks */
   3536 				(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
   3537 				sac->gauth_number_of_chunks = (uint32_t)size;
   3538 				*optsize = sizeof(struct sctp_authchunks) + size;
   3539 			}
   3540 			SCTP_TCB_UNLOCK(stcb);
   3541 		} else {
   3542 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3543 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3544 			    (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC)) {
   3545 				/* get off the endpoint */
   3546 				SCTP_INP_RLOCK(inp);
   3547 				chklist = inp->sctp_ep.local_auth_chunks;
   3548 				/* is there enough space? */
   3549 				size = sctp_auth_get_chklist_size(chklist);
   3550 				if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
   3551 					error = EINVAL;
   3552 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3553 				} else {
   3554 					/* copy in the chunks */
   3555 					(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
   3556 					sac->gauth_number_of_chunks = (uint32_t)size;
   3557 					*optsize = sizeof(struct sctp_authchunks) + size;
   3558 				}
   3559 				SCTP_INP_RUNLOCK(inp);
   3560 			} else {
   3561 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3562 				error = EINVAL;
   3563 			}
   3564 		}
   3565 		break;
   3566 	}
   3567 	case SCTP_PEER_AUTH_CHUNKS:
   3568 	{
   3569 		struct sctp_authchunks *sac;
   3570 		sctp_auth_chklist_t *chklist = NULL;
   3571 		size_t size = 0;
   3572 
   3573 		SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
   3574 		SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
   3575 
   3576 		if (stcb) {
   3577 			/* get off the assoc */
   3578 			chklist = stcb->asoc.peer_auth_chunks;
   3579 			/* is there enough space? */
   3580 			size = sctp_auth_get_chklist_size(chklist);
   3581 			if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
   3582 				error = EINVAL;
   3583 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3584 			} else {
   3585 				/* copy in the chunks */
   3586 				(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
   3587 				sac->gauth_number_of_chunks = (uint32_t)size;
   3588 				*optsize = sizeof(struct sctp_authchunks) + size;
   3589 			}
   3590 			SCTP_TCB_UNLOCK(stcb);
   3591 		} else {
   3592 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   3593 			error = ENOENT;
   3594 		}
   3595 		break;
   3596 	}
   3597 #if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
   3598 	case SCTP_PEELOFF:
   3599 	{
   3600 		struct sctp_peeloff_opt *peeloff;
   3601 
   3602 		SCTP_CHECK_AND_CAST(peeloff, optval, struct sctp_peeloff_opt, *optsize);
   3603 		/* do the peeloff */
   3604 		error = sctp_peeloff_option(p, peeloff);
   3605 		if (error == 0) {
   3606 			*optsize = sizeof(struct sctp_peeloff_opt);
   3607 		}
   3608 	}
   3609 	break;
   3610 #endif /* HAVE_SCTP_PEELOFF_SOCKOPT */
   3611 	case SCTP_EVENT:
   3612 	{
   3613 		struct sctp_event *event;
   3614 		uint32_t event_type;
   3615 
   3616 		SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
   3617 		SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
   3618 
   3619 		switch (event->se_type) {
   3620 		case SCTP_ASSOC_CHANGE:
   3621 			event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
   3622 			break;
   3623 		case SCTP_PEER_ADDR_CHANGE:
   3624 			event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
   3625 			break;
   3626 		case SCTP_REMOTE_ERROR:
   3627 			event_type = SCTP_PCB_FLAGS_RECVPEERERR;
   3628 			break;
   3629 		case SCTP_SEND_FAILED:
   3630 			event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
   3631 			break;
   3632 		case SCTP_SHUTDOWN_EVENT:
   3633 			event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
   3634 			break;
   3635 		case SCTP_ADAPTATION_INDICATION:
   3636 			event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
   3637 			break;
   3638 		case SCTP_PARTIAL_DELIVERY_EVENT:
   3639 			event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
   3640 			break;
   3641 		case SCTP_AUTHENTICATION_EVENT:
   3642 			event_type = SCTP_PCB_FLAGS_AUTHEVNT;
   3643 			break;
   3644 		case SCTP_STREAM_RESET_EVENT:
   3645 			event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
   3646 			break;
   3647 		case SCTP_SENDER_DRY_EVENT:
   3648 			event_type = SCTP_PCB_FLAGS_DRYEVNT;
   3649 			break;
   3650 		case SCTP_NOTIFICATIONS_STOPPED_EVENT:
   3651 			event_type = 0;
   3652 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
   3653 			error = ENOTSUP;
   3654 			break;
   3655 		case SCTP_ASSOC_RESET_EVENT:
   3656 			event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
   3657 			break;
   3658 		case SCTP_STREAM_CHANGE_EVENT:
   3659 			event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
   3660 			break;
   3661 		case SCTP_SEND_FAILED_EVENT:
   3662 			event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
   3663 			break;
   3664 		default:
   3665 			event_type = 0;
   3666 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3667 			error = EINVAL;
   3668 			break;
   3669 		}
   3670 		if (event_type > 0) {
   3671 			if (stcb) {
   3672 				event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
   3673 				SCTP_TCB_UNLOCK(stcb);
   3674 			} else {
   3675 				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3676 				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3677 				    (event->se_assoc_id == SCTP_FUTURE_ASSOC)) {
   3678 					SCTP_INP_RLOCK(inp);
   3679 					event->se_on = sctp_is_feature_on(inp, event_type);
   3680 					SCTP_INP_RUNLOCK(inp);
   3681 				} else {
   3682 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3683 					error = EINVAL;
   3684 				}
   3685 			}
   3686 		}
   3687 		if (error == 0) {
   3688 			*optsize = sizeof(struct sctp_event);
   3689 		}
   3690 		break;
   3691 	}
   3692 	case SCTP_RECVRCVINFO:
   3693 	{
   3694 		int onoff;
   3695 
   3696 		if (*optsize < sizeof(int)) {
   3697 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3698 			error = EINVAL;
   3699 		} else {
   3700 			SCTP_INP_RLOCK(inp);
   3701 			onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
   3702 			SCTP_INP_RUNLOCK(inp);
   3703 		}
   3704 		if (error == 0) {
   3705 			/* return the option value */
   3706 			*(int *)optval = onoff;
   3707 			*optsize = sizeof(int);
   3708 		}
   3709 		break;
   3710 	}
   3711 	case SCTP_RECVNXTINFO:
   3712 	{
   3713 		int onoff;
   3714 
   3715 		if (*optsize < sizeof(int)) {
   3716 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3717 			error = EINVAL;
   3718 		} else {
   3719 			SCTP_INP_RLOCK(inp);
   3720 			onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
   3721 			SCTP_INP_RUNLOCK(inp);
   3722 		}
   3723 		if (error == 0) {
   3724 			/* return the option value */
   3725 			*(int *)optval = onoff;
   3726 			*optsize = sizeof(int);
   3727 		}
   3728 		break;
   3729 	}
   3730 	case SCTP_DEFAULT_SNDINFO:
   3731 	{
   3732 		struct sctp_sndinfo *info;
   3733 
   3734 		SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
   3735 		SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
   3736 
   3737 		if (stcb) {
   3738 			info->snd_sid = stcb->asoc.def_send.sinfo_stream;
   3739 			info->snd_flags = stcb->asoc.def_send.sinfo_flags;
   3740 			info->snd_flags &= 0xfff0;
   3741 			info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
   3742 			info->snd_context = stcb->asoc.def_send.sinfo_context;
   3743 			SCTP_TCB_UNLOCK(stcb);
   3744 		} else {
   3745 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3746 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3747 			    (info->snd_assoc_id == SCTP_FUTURE_ASSOC)) {
   3748 				SCTP_INP_RLOCK(inp);
   3749 				info->snd_sid = inp->def_send.sinfo_stream;
   3750 				info->snd_flags = inp->def_send.sinfo_flags;
   3751 				info->snd_flags &= 0xfff0;
   3752 				info->snd_ppid = inp->def_send.sinfo_ppid;
   3753 				info->snd_context = inp->def_send.sinfo_context;
   3754 				SCTP_INP_RUNLOCK(inp);
   3755 			} else {
   3756 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3757 				error = EINVAL;
   3758 			}
   3759 		}
   3760 		if (error == 0) {
   3761 			*optsize = sizeof(struct sctp_sndinfo);
   3762 		}
   3763 		break;
   3764 	}
   3765 	case SCTP_DEFAULT_PRINFO:
   3766 	{
   3767 		struct sctp_default_prinfo *info;
   3768 
   3769 		SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
   3770 		SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
   3771 
   3772 		if (stcb) {
   3773 			info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
   3774 			info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
   3775 			SCTP_TCB_UNLOCK(stcb);
   3776 		} else {
   3777 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3778 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3779 			    (info->pr_assoc_id == SCTP_FUTURE_ASSOC)) {
   3780 				SCTP_INP_RLOCK(inp);
   3781 				info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
   3782 				info->pr_value = inp->def_send.sinfo_timetolive;
   3783 				SCTP_INP_RUNLOCK(inp);
   3784 			} else {
   3785 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3786 				error = EINVAL;
   3787 			}
   3788 		}
   3789 		if (error == 0) {
   3790 			*optsize = sizeof(struct sctp_default_prinfo);
   3791 		}
   3792 		break;
   3793 	}
   3794 	case SCTP_PEER_ADDR_THLDS:
   3795 	{
   3796 		struct sctp_paddrthlds *thlds;
   3797 		struct sctp_nets *net;
   3798 
   3799 		SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
   3800 		SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
   3801 
   3802 		net = NULL;
   3803 		if (stcb) {
   3804 			net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
   3805 		} else {
   3806 			/* We increment here since sctp_findassociation_ep_addr() wil
   3807 			 * do a decrement if it finds the stcb as long as the locked
   3808 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   3809 			 */
   3810 			SCTP_INP_INCR_REF(inp);
   3811 			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&thlds->spt_address, &net, NULL, NULL);
   3812 			if (stcb == NULL) {
   3813 				SCTP_INP_DECR_REF(inp);
   3814 			}
   3815 		}
   3816 		if (stcb && (net == NULL)) {
   3817 			struct sockaddr *sa;
   3818 
   3819 			sa = (struct sockaddr *)&thlds->spt_address;
   3820 #ifdef INET
   3821 			if (sa->sa_family == AF_INET) {
   3822 				struct sockaddr_in *sin;
   3823 
   3824 				sin = (struct sockaddr_in *)sa;
   3825 				if (sin->sin_addr.s_addr) {
   3826 					error = EINVAL;
   3827 					SCTP_TCB_UNLOCK(stcb);
   3828 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3829 					break;
   3830 				}
   3831 			} else
   3832 #endif
   3833 #ifdef INET6
   3834 			if (sa->sa_family == AF_INET6) {
   3835 				struct sockaddr_in6 *sin6;
   3836 
   3837 				sin6 = (struct sockaddr_in6 *)sa;
   3838 				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   3839 					error = EINVAL;
   3840 					SCTP_TCB_UNLOCK(stcb);
   3841 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3842 					break;
   3843 				}
   3844 			} else
   3845 #endif
   3846 #if defined(__Userspace__)
   3847 			if (sa->sa_family == AF_CONN) {
   3848 				struct sockaddr_conn *sconn;
   3849 
   3850 				sconn = (struct sockaddr_conn *)sa;
   3851 				if (sconn->sconn_addr != NULL) {
   3852 					error = EINVAL;
   3853 					SCTP_TCB_UNLOCK(stcb);
   3854 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3855 					break;
   3856 				}
   3857 			} else
   3858 #endif
   3859 			{
   3860 				error = EAFNOSUPPORT;
   3861 				SCTP_TCB_UNLOCK(stcb);
   3862 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3863 				break;
   3864 			}
   3865 		}
   3866 
   3867 		if (stcb) {
   3868 			if (net) {
   3869 				thlds->spt_pathmaxrxt = net->failure_threshold;
   3870 				thlds->spt_pathpfthld = net->pf_threshold;
   3871 			} else {
   3872 				thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
   3873 				thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
   3874 			}
   3875 			thlds->spt_assoc_id = sctp_get_associd(stcb);
   3876 			SCTP_TCB_UNLOCK(stcb);
   3877 		} else {
   3878 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3879 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3880 			    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
   3881 				/* Use endpoint defaults */
   3882 				SCTP_INP_RLOCK(inp);
   3883 				thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
   3884 				thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
   3885 				SCTP_INP_RUNLOCK(inp);
   3886 			} else {
   3887 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3888 				error = EINVAL;
   3889 			}
   3890 		}
   3891 		if (error == 0) {
   3892 			*optsize = sizeof(struct sctp_paddrthlds);
   3893 		}
   3894 		break;
   3895 	}
   3896 	case SCTP_REMOTE_UDP_ENCAPS_PORT:
   3897 	{
   3898 		struct sctp_udpencaps *encaps;
   3899 		struct sctp_nets *net;
   3900 
   3901 		SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
   3902 		SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
   3903 
   3904 		if (stcb) {
   3905 			net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
   3906 		} else {
   3907 			/* We increment here since sctp_findassociation_ep_addr() wil
   3908 			 * do a decrement if it finds the stcb as long as the locked
   3909 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   3910 			 */
   3911 			net = NULL;
   3912 			SCTP_INP_INCR_REF(inp);
   3913 			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
   3914 			if (stcb == NULL) {
   3915 				SCTP_INP_DECR_REF(inp);
   3916 			}
   3917 		}
   3918 		if (stcb && (net == NULL)) {
   3919 			struct sockaddr *sa;
   3920 
   3921 			sa = (struct sockaddr *)&encaps->sue_address;
   3922 #ifdef INET
   3923 			if (sa->sa_family == AF_INET) {
   3924 				struct sockaddr_in *sin;
   3925 
   3926 				sin = (struct sockaddr_in *)sa;
   3927 				if (sin->sin_addr.s_addr) {
   3928 					error = EINVAL;
   3929 					SCTP_TCB_UNLOCK(stcb);
   3930 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3931 					break;
   3932 				}
   3933 			} else
   3934 #endif
   3935 #ifdef INET6
   3936 			if (sa->sa_family == AF_INET6) {
   3937 				struct sockaddr_in6 *sin6;
   3938 
   3939 				sin6 = (struct sockaddr_in6 *)sa;
   3940 				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   3941 					error = EINVAL;
   3942 					SCTP_TCB_UNLOCK(stcb);
   3943 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3944 					break;
   3945 				}
   3946 			} else
   3947 #endif
   3948 #if defined(__Userspace__)
   3949 			if (sa->sa_family == AF_CONN) {
   3950 				struct sockaddr_conn *sconn;
   3951 
   3952 				sconn = (struct sockaddr_conn *)sa;
   3953 				if (sconn->sconn_addr != NULL) {
   3954 					error = EINVAL;
   3955 					SCTP_TCB_UNLOCK(stcb);
   3956 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3957 					break;
   3958 				}
   3959 			} else
   3960 #endif
   3961 			{
   3962 				error = EAFNOSUPPORT;
   3963 				SCTP_TCB_UNLOCK(stcb);
   3964 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   3965 				break;
   3966 			}
   3967 		}
   3968 
   3969 		if (stcb) {
   3970 			if (net) {
   3971 				encaps->sue_port = net->port;
   3972 			} else {
   3973 				encaps->sue_port = stcb->asoc.port;
   3974 			}
   3975 			SCTP_TCB_UNLOCK(stcb);
   3976 		} else {
   3977 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3978 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   3979 			    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
   3980 				SCTP_INP_RLOCK(inp);
   3981 				encaps->sue_port = inp->sctp_ep.port;
   3982 				SCTP_INP_RUNLOCK(inp);
   3983 			} else {
   3984 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   3985 				error = EINVAL;
   3986 			}
   3987 		}
   3988 		if (error == 0) {
   3989 			*optsize = sizeof(struct sctp_udpencaps);
   3990 		}
   3991 		break;
   3992 	}
   3993 	case SCTP_ENABLE_STREAM_RESET:
   3994 	{
   3995 		struct sctp_assoc_value *av;
   3996 
   3997 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
   3998 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   3999 
   4000 		if (stcb) {
   4001 			av->assoc_value = (uint32_t)stcb->asoc.local_strreset_support;
   4002 			SCTP_TCB_UNLOCK(stcb);
   4003 		} else {
   4004 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4005 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4006 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   4007 				SCTP_INP_RLOCK(inp);
   4008 				av->assoc_value = (uint32_t)inp->local_strreset_support;
   4009 				SCTP_INP_RUNLOCK(inp);
   4010 			} else {
   4011 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4012 				error = EINVAL;
   4013 			}
   4014 		}
   4015 		if (error == 0) {
   4016 			*optsize = sizeof(struct sctp_assoc_value);
   4017 		}
   4018 		break;
   4019 	}
   4020 	default:
   4021 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
   4022 		error = ENOPROTOOPT;
   4023 		break;
   4024 	} /* end switch (sopt->sopt_name) */
   4025 	if (error) {
   4026 		*optsize = 0;
   4027 	}
   4028 	return (error);
   4029 }
   4030 
   4031 #if defined(__Panda__) || defined(__Userspace__)
   4032 int
   4033 #else
   4034 static int
   4035 #endif
   4036 sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
   4037 	    void *p)
   4038 {
   4039 	int error, set_opt;
   4040 	uint32_t *mopt;
   4041 	struct sctp_tcb *stcb = NULL;
   4042 	struct sctp_inpcb *inp = NULL;
   4043 	uint32_t vrf_id;
   4044 
   4045 	if (optval == NULL) {
   4046 		SCTP_PRINTF("optval is NULL\n");
   4047 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4048 		return (EINVAL);
   4049 	}
   4050 	inp = (struct sctp_inpcb *)so->so_pcb;
   4051 	if (inp == NULL) {
   4052 		SCTP_PRINTF("inp is NULL?\n");
   4053 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4054 		return (EINVAL);
   4055 	}
   4056 	vrf_id = inp->def_vrf_id;
   4057 
   4058 	error = 0;
   4059 	switch (optname) {
   4060 	case SCTP_NODELAY:
   4061 	case SCTP_AUTOCLOSE:
   4062 	case SCTP_AUTO_ASCONF:
   4063 	case SCTP_EXPLICIT_EOR:
   4064 	case SCTP_DISABLE_FRAGMENTS:
   4065 	case SCTP_USE_EXT_RCVINFO:
   4066 	case SCTP_I_WANT_MAPPED_V4_ADDR:
   4067 		/* copy in the option value */
   4068 		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
   4069 		set_opt = 0;
   4070 		if (error)
   4071 			break;
   4072 		switch (optname) {
   4073 		case SCTP_DISABLE_FRAGMENTS:
   4074 			set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
   4075 			break;
   4076 		case SCTP_AUTO_ASCONF:
   4077 			/*
   4078 			 * NOTE: we don't really support this flag
   4079 			 */
   4080 			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
   4081 				/* only valid for bound all sockets */
   4082 				if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
   4083 				    (*mopt != 0)) {
   4084 					/* forbidden by admin */
   4085 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
   4086 					return (EPERM);
   4087 				}
   4088 				set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
   4089 			} else {
   4090 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4091 				return (EINVAL);
   4092 			}
   4093 			break;
   4094 		case SCTP_EXPLICIT_EOR:
   4095 			set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
   4096 			break;
   4097 		case SCTP_USE_EXT_RCVINFO:
   4098 			set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
   4099 			break;
   4100 		case SCTP_I_WANT_MAPPED_V4_ADDR:
   4101 			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   4102 				set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
   4103 			} else {
   4104 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4105 				return (EINVAL);
   4106 			}
   4107 			break;
   4108 		case SCTP_NODELAY:
   4109 			set_opt = SCTP_PCB_FLAGS_NODELAY;
   4110 			break;
   4111 		case SCTP_AUTOCLOSE:
   4112 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4113 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
   4114 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4115 				return (EINVAL);
   4116 			}
   4117 			set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
   4118 			/*
   4119 			 * The value is in ticks. Note this does not effect
   4120 			 * old associations, only new ones.
   4121 			 */
   4122 			inp->sctp_ep.auto_close_time = SEC_TO_TICKS(*mopt);
   4123 			break;
   4124 		}
   4125 		SCTP_INP_WLOCK(inp);
   4126 		if (*mopt != 0) {
   4127 			sctp_feature_on(inp, set_opt);
   4128 		} else {
   4129 			sctp_feature_off(inp, set_opt);
   4130 		}
   4131 		SCTP_INP_WUNLOCK(inp);
   4132 		break;
   4133 	case SCTP_REUSE_PORT:
   4134 	{
   4135 		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
   4136 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND)  == 0) {
   4137 			/* Can't set it after we are bound */
   4138 			error = EINVAL;
   4139 			break;
   4140 		}
   4141 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
   4142 			/* Can't do this for a 1-m socket */
   4143 			error = EINVAL;
   4144 			break;
   4145 		}
   4146 		if (optval)
   4147 			sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
   4148 		else
   4149 			sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
   4150 		break;
   4151 	}
   4152 	case SCTP_PARTIAL_DELIVERY_POINT:
   4153 	{
   4154 		uint32_t *value;
   4155 
   4156 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
   4157 		if (*value > SCTP_SB_LIMIT_RCV(so)) {
   4158 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4159 			error = EINVAL;
   4160 			break;
   4161 		}
   4162 		inp->partial_delivery_point = *value;
   4163 		break;
   4164 	}
   4165 	case SCTP_FRAGMENT_INTERLEAVE:
   4166 		/* not yet until we re-write sctp_recvmsg() */
   4167 	{
   4168 		uint32_t *level;
   4169 
   4170 		SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
   4171 		if (*level == SCTP_FRAG_LEVEL_2) {
   4172 			sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
   4173 			sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
   4174 		} else if (*level == SCTP_FRAG_LEVEL_1) {
   4175 			sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
   4176 			sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
   4177 		} else if (*level == SCTP_FRAG_LEVEL_0) {
   4178 			sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
   4179 			sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
   4180 
   4181 		} else {
   4182 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4183 			error = EINVAL;
   4184 		}
   4185 		break;
   4186 	}
   4187 	case SCTP_CMT_ON_OFF:
   4188 		if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
   4189 			struct sctp_assoc_value *av;
   4190 
   4191 			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   4192 			if (av->assoc_value > SCTP_CMT_MAX) {
   4193 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4194 				error = EINVAL;
   4195 				break;
   4196 			}
   4197 			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4198 			if (stcb) {
   4199 				stcb->asoc.sctp_cmt_on_off = av->assoc_value;
   4200 				SCTP_TCB_UNLOCK(stcb);
   4201 			} else {
   4202 				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4203 				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4204 				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
   4205 				    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4206 					SCTP_INP_WLOCK(inp);
   4207 					inp->sctp_cmt_on_off = av->assoc_value;
   4208 					SCTP_INP_WUNLOCK(inp);
   4209 				}
   4210 				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
   4211 				    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4212 					SCTP_INP_RLOCK(inp);
   4213 					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4214 						SCTP_TCB_LOCK(stcb);
   4215 						stcb->asoc.sctp_cmt_on_off = av->assoc_value;
   4216 						SCTP_TCB_UNLOCK(stcb);
   4217 					}
   4218 					SCTP_INP_RUNLOCK(inp);
   4219 				}
   4220 			}
   4221 		} else {
   4222 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
   4223 			error = ENOPROTOOPT;
   4224 		}
   4225 		break;
   4226 	case SCTP_PLUGGABLE_CC:
   4227 	{
   4228 		struct sctp_assoc_value *av;
   4229 		struct sctp_nets *net;
   4230 
   4231 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   4232 		if ((av->assoc_value != SCTP_CC_RFC2581) &&
   4233 		    (av->assoc_value != SCTP_CC_HSTCP) &&
   4234 		    (av->assoc_value != SCTP_CC_HTCP) &&
   4235 		    (av->assoc_value != SCTP_CC_RTCC)) {
   4236 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4237 			error = EINVAL;
   4238 			break;
   4239 		}
   4240 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4241 		if (stcb) {
   4242 			stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
   4243 			stcb->asoc.congestion_control_module = av->assoc_value;
   4244 			if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
   4245 				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   4246 					stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
   4247 				}
   4248 			}
   4249 			SCTP_TCB_UNLOCK(stcb);
   4250 		} else {
   4251 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4252 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4253 			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
   4254 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4255 				SCTP_INP_WLOCK(inp);
   4256 				inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
   4257 				SCTP_INP_WUNLOCK(inp);
   4258 			}
   4259 			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
   4260 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4261 				SCTP_INP_RLOCK(inp);
   4262 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4263 					SCTP_TCB_LOCK(stcb);
   4264 					stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
   4265 					stcb->asoc.congestion_control_module = av->assoc_value;
   4266 					if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
   4267 						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   4268 							stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
   4269 						}
   4270 					}
   4271 					SCTP_TCB_UNLOCK(stcb);
   4272 				}
   4273 				SCTP_INP_RUNLOCK(inp);
   4274 			}
   4275 		}
   4276 		break;
   4277 	}
   4278 	case SCTP_CC_OPTION:
   4279 	{
   4280 		struct sctp_cc_option *cc_opt;
   4281 
   4282 		SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
   4283 		SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
   4284 		if (stcb == NULL) {
   4285 			if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
   4286 				SCTP_INP_RLOCK(inp);
   4287 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4288 					SCTP_TCB_LOCK(stcb);
   4289 					if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
   4290 						(*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1, cc_opt);
   4291 					}
   4292 					SCTP_TCB_UNLOCK(stcb);
   4293 				}
   4294 				SCTP_INP_RUNLOCK(inp);
   4295 			} else {
   4296 				error = EINVAL;
   4297 			}
   4298 		} else {
   4299 			if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
   4300 				error = ENOTSUP;
   4301 			} else {
   4302 				error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1,
   4303 											   cc_opt);
   4304 			}
   4305 			SCTP_TCB_UNLOCK(stcb);
   4306 		}
   4307 		break;
   4308 	}
   4309 	case SCTP_PLUGGABLE_SS:
   4310 	{
   4311 		struct sctp_assoc_value *av;
   4312 
   4313 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   4314 		if ((av->assoc_value != SCTP_SS_DEFAULT) &&
   4315 		    (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
   4316 		    (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
   4317 		    (av->assoc_value != SCTP_SS_PRIORITY) &&
   4318 		    (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
   4319 		    (av->assoc_value != SCTP_SS_FIRST_COME)) {
   4320 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4321 			error = EINVAL;
   4322 			break;
   4323 		}
   4324 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4325 		if (stcb) {
   4326 			stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
   4327 			stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
   4328 			stcb->asoc.stream_scheduling_module = av->assoc_value;
   4329 			stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
   4330 			SCTP_TCB_UNLOCK(stcb);
   4331 		} else {
   4332 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4333 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4334 			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
   4335 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4336 				SCTP_INP_WLOCK(inp);
   4337 				inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
   4338 				SCTP_INP_WUNLOCK(inp);
   4339 			}
   4340 			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
   4341 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4342 				SCTP_INP_RLOCK(inp);
   4343 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4344 					SCTP_TCB_LOCK(stcb);
   4345 					stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
   4346 					stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
   4347 					stcb->asoc.stream_scheduling_module = av->assoc_value;
   4348 					stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
   4349 					SCTP_TCB_UNLOCK(stcb);
   4350 				}
   4351 				SCTP_INP_RUNLOCK(inp);
   4352 			}
   4353 		}
   4354 		break;
   4355 	}
   4356 	case SCTP_SS_VALUE:
   4357 	{
   4358 		struct sctp_stream_value *av;
   4359 
   4360 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
   4361 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4362 		if (stcb) {
   4363 			if (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
   4364 			                                              av->stream_value) < 0) {
   4365 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4366 				error = EINVAL;
   4367 			}
   4368 			SCTP_TCB_UNLOCK(stcb);
   4369 		} else {
   4370 			if (av->assoc_id == SCTP_CURRENT_ASSOC) {
   4371 				SCTP_INP_RLOCK(inp);
   4372 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4373 					SCTP_TCB_LOCK(stcb);
   4374 					stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
   4375 					                                          &stcb->asoc,
   4376 					                                          &stcb->asoc.strmout[av->stream_id],
   4377 					                                          av->stream_value);
   4378 					SCTP_TCB_UNLOCK(stcb);
   4379 				}
   4380 				SCTP_INP_RUNLOCK(inp);
   4381 
   4382 			} else {
   4383 				/* Can't set stream value without association */
   4384 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4385 				error = EINVAL;
   4386 			}
   4387 		}
   4388 		break;
   4389 	}
   4390 	case SCTP_CLR_STAT_LOG:
   4391 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   4392 		error = EOPNOTSUPP;
   4393 		break;
   4394 	case SCTP_CONTEXT:
   4395 	{
   4396 		struct sctp_assoc_value *av;
   4397 
   4398 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   4399 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4400 
   4401 		if (stcb) {
   4402 			stcb->asoc.context = av->assoc_value;
   4403 			SCTP_TCB_UNLOCK(stcb);
   4404 		} else {
   4405 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4406 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4407 			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
   4408 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4409 				SCTP_INP_WLOCK(inp);
   4410 				inp->sctp_context = av->assoc_value;
   4411 				SCTP_INP_WUNLOCK(inp);
   4412 			}
   4413 			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
   4414 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4415 				SCTP_INP_RLOCK(inp);
   4416 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4417 					SCTP_TCB_LOCK(stcb);
   4418 					stcb->asoc.context = av->assoc_value;
   4419 					SCTP_TCB_UNLOCK(stcb);
   4420 				}
   4421 				SCTP_INP_RUNLOCK(inp);
   4422 			}
   4423 		}
   4424 		break;
   4425 	}
   4426 	case SCTP_VRF_ID:
   4427 	{
   4428 		uint32_t *default_vrfid;
   4429 #ifdef SCTP_MVRF
   4430 		int i;
   4431 #endif
   4432 		SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
   4433 		if (*default_vrfid > SCTP_MAX_VRF_ID) {
   4434 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4435 			error = EINVAL;
   4436 			break;
   4437 		}
   4438 #ifdef SCTP_MVRF
   4439 		for (i = 0; i < inp->num_vrfs; i++) {
   4440 			/* The VRF must be in the VRF list */
   4441 			if (*default_vrfid == inp->m_vrf_ids[i]) {
   4442 				SCTP_INP_WLOCK(inp);
   4443  				inp->def_vrf_id = *default_vrfid;
   4444 				SCTP_INP_WUNLOCK(inp);
   4445 				goto sctp_done;
   4446 			}
   4447 		}
   4448 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4449 		error = EINVAL;
   4450 #else
   4451 		inp->def_vrf_id = *default_vrfid;
   4452 #endif
   4453 #ifdef SCTP_MVRF
   4454 	sctp_done:
   4455 #endif
   4456 		break;
   4457 	}
   4458 	case SCTP_DEL_VRF_ID:
   4459 	{
   4460 #ifdef SCTP_MVRF
   4461 		uint32_t *del_vrfid;
   4462 		int i, fnd = 0;
   4463 
   4464 		SCTP_CHECK_AND_CAST(del_vrfid, optval, uint32_t, optsize);
   4465 		if (*del_vrfid > SCTP_MAX_VRF_ID) {
   4466 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4467 			error = EINVAL;
   4468 			break;
   4469 		}
   4470 		if (inp->num_vrfs == 1) {
   4471 			/* Can't delete last one */
   4472 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4473 			error = EINVAL;
   4474 			break;
   4475 		}
   4476 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
   4477 			/* Can't add more once you are bound */
   4478 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4479 			error = EINVAL;
   4480 			break;
   4481 		}
   4482 		SCTP_INP_WLOCK(inp);
   4483 		for (i = 0; i < inp->num_vrfs; i++) {
   4484 			if (*del_vrfid == inp->m_vrf_ids[i]) {
   4485 				fnd = 1;
   4486 				break;
   4487 			}
   4488 		}
   4489 		if (!fnd) {
   4490 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4491 			error = EINVAL;
   4492 			break;
   4493 		}
   4494 		if (i != (inp->num_vrfs - 1)) {
   4495 			/* Take bottom one and move to this slot */
   4496 			inp->m_vrf_ids[i] = inp->m_vrf_ids[(inp->num_vrfs-1)];
   4497 		}
   4498 		if (*del_vrfid == inp->def_vrf_id) {
   4499 			/* Take the first one as the new default */
   4500 			inp->def_vrf_id = inp->m_vrf_ids[0];
   4501 		}
   4502 		/* Drop the number by one killing last one */
   4503 		inp->num_vrfs--;
   4504 #else
   4505 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   4506 		error = EOPNOTSUPP;
   4507 #endif
   4508 		break;
   4509 	}
   4510 	case SCTP_ADD_VRF_ID:
   4511 	{
   4512 #ifdef SCTP_MVRF
   4513 		uint32_t *add_vrfid;
   4514 		int i;
   4515 
   4516 		SCTP_CHECK_AND_CAST(add_vrfid, optval, uint32_t, optsize);
   4517 		if (*add_vrfid > SCTP_MAX_VRF_ID) {
   4518 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4519 			error = EINVAL;
   4520 			break;
   4521 		}
   4522 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
   4523 			/* Can't add more once you are bound */
   4524 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4525 			error = EINVAL;
   4526 			break;
   4527 		}
   4528 		SCTP_INP_WLOCK(inp);
   4529 		/* Verify its not already here */
   4530 		for (i = 0; i < inp->num_vrfs; i++) {
   4531 			if (*add_vrfid == inp->m_vrf_ids[i]) {
   4532 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   4533 				error = EALREADY;
   4534 				SCTP_INP_WUNLOCK(inp);
   4535 				break;
   4536 			}
   4537 		}
   4538 		if ((inp->num_vrfs + 1) > inp->vrf_size) {
   4539 			/* need to grow array */
   4540 			uint32_t *tarray;
   4541 			SCTP_MALLOC(tarray, uint32_t *,
   4542 				    (sizeof(uint32_t) * (inp->vrf_size + SCTP_DEFAULT_VRF_SIZE)),
   4543 				    SCTP_M_MVRF);
   4544 			if (tarray == NULL) {
   4545 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
   4546 				error = ENOMEM;
   4547 				SCTP_INP_WUNLOCK(inp);
   4548 				break;
   4549 			}
   4550 			memcpy(tarray, inp->m_vrf_ids, (sizeof(uint32_t) * inp->vrf_size));
   4551 			SCTP_FREE(inp->m_vrf_ids, SCTP_M_MVRF);
   4552 			inp->m_vrf_ids = tarray;
   4553 			inp->vrf_size += SCTP_DEFAULT_VRF_SIZE;
   4554 		}
   4555 		inp->m_vrf_ids[inp->num_vrfs] = *add_vrfid;
   4556 		inp->num_vrfs++;
   4557 		SCTP_INP_WUNLOCK(inp);
   4558 #else
   4559 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   4560 		error = EOPNOTSUPP;
   4561 #endif
   4562 	 	break;
   4563 	}
   4564 	case SCTP_DELAYED_SACK:
   4565 	{
   4566 		struct sctp_sack_info *sack;
   4567 
   4568 		SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
   4569 		SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
   4570 		if (sack->sack_delay) {
   4571 			if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
   4572 				sack->sack_delay = SCTP_MAX_SACK_DELAY;
   4573 			if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
   4574 				sack->sack_delay = TICKS_TO_MSEC(1);
   4575 			}
   4576 		}
   4577 		if (stcb) {
   4578 			if (sack->sack_delay) {
   4579 				stcb->asoc.delayed_ack = sack->sack_delay;
   4580 			}
   4581 			if (sack->sack_freq) {
   4582 				stcb->asoc.sack_freq = sack->sack_freq;
   4583 			}
   4584 			SCTP_TCB_UNLOCK(stcb);
   4585 		} else {
   4586 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4587 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4588 			    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
   4589 			    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
   4590 				SCTP_INP_WLOCK(inp);
   4591 				if (sack->sack_delay) {
   4592 					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
   4593 				}
   4594 				if (sack->sack_freq) {
   4595 					inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
   4596 				}
   4597 				SCTP_INP_WUNLOCK(inp);
   4598 			}
   4599 			if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
   4600 			    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
   4601 				SCTP_INP_RLOCK(inp);
   4602 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4603 					SCTP_TCB_LOCK(stcb);
   4604 					if (sack->sack_delay) {
   4605 						stcb->asoc.delayed_ack = sack->sack_delay;
   4606 					}
   4607 					if (sack->sack_freq) {
   4608 						stcb->asoc.sack_freq = sack->sack_freq;
   4609 					}
   4610 					SCTP_TCB_UNLOCK(stcb);
   4611 				}
   4612 				SCTP_INP_RUNLOCK(inp);
   4613 			}
   4614 		}
   4615 		break;
   4616 	}
   4617 	case SCTP_AUTH_CHUNK:
   4618 	{
   4619 		struct sctp_authchunk *sauth;
   4620 
   4621 		SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
   4622 
   4623 		SCTP_INP_WLOCK(inp);
   4624 		if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
   4625 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4626 			error = EINVAL;
   4627 		}
   4628 		SCTP_INP_WUNLOCK(inp);
   4629 		break;
   4630 	}
   4631 	case SCTP_AUTH_KEY:
   4632 	{
   4633 		struct sctp_authkey *sca;
   4634 		struct sctp_keyhead *shared_keys;
   4635 		sctp_sharedkey_t *shared_key;
   4636 		sctp_key_t *key = NULL;
   4637 		size_t size;
   4638 
   4639 		SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
   4640 		if (sca->sca_keylength == 0) {
   4641 			size = optsize - sizeof(struct sctp_authkey);
   4642 		} else {
   4643 		        if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
   4644 				size = sca->sca_keylength;
   4645 			} else {
   4646 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4647 				error = EINVAL;
   4648 				break;
   4649 			}
   4650 		}
   4651 		SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
   4652 
   4653 		if (stcb) {
   4654 			shared_keys = &stcb->asoc.shared_keys;
   4655 			/* clear the cached keys for this key id */
   4656 			sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
   4657 			/*
   4658 			 * create the new shared key and
   4659 			 * insert/replace it
   4660 			 */
   4661 			if (size > 0) {
   4662 				key = sctp_set_key(sca->sca_key, (uint32_t) size);
   4663 				if (key == NULL) {
   4664 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
   4665 					error = ENOMEM;
   4666 					SCTP_TCB_UNLOCK(stcb);
   4667 					break;
   4668 				}
   4669 			}
   4670 			shared_key = sctp_alloc_sharedkey();
   4671 			if (shared_key == NULL) {
   4672 				sctp_free_key(key);
   4673 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
   4674 				error = ENOMEM;
   4675 				SCTP_TCB_UNLOCK(stcb);
   4676 				break;
   4677 			}
   4678 			shared_key->key = key;
   4679 			shared_key->keyid = sca->sca_keynumber;
   4680 			error = sctp_insert_sharedkey(shared_keys, shared_key);
   4681 			SCTP_TCB_UNLOCK(stcb);
   4682 		} else {
   4683 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4684 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4685 			    (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
   4686 			    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
   4687 				SCTP_INP_WLOCK(inp);
   4688 				shared_keys = &inp->sctp_ep.shared_keys;
   4689 				/*
   4690 				 * clear the cached keys on all assocs for
   4691 				 * this key id
   4692 				 */
   4693 				sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
   4694 				/*
   4695 				 * create the new shared key and
   4696 				 * insert/replace it
   4697 				 */
   4698 				if (size > 0) {
   4699 					key = sctp_set_key(sca->sca_key, (uint32_t) size);
   4700 					if (key == NULL) {
   4701 						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
   4702 						error = ENOMEM;
   4703 						SCTP_INP_WUNLOCK(inp);
   4704 						break;
   4705 					}
   4706 				}
   4707 				shared_key = sctp_alloc_sharedkey();
   4708 				if (shared_key == NULL) {
   4709 					sctp_free_key(key);
   4710 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
   4711 					error = ENOMEM;
   4712 					SCTP_INP_WUNLOCK(inp);
   4713 					break;
   4714 				}
   4715 				shared_key->key = key;
   4716 				shared_key->keyid = sca->sca_keynumber;
   4717 				error = sctp_insert_sharedkey(shared_keys, shared_key);
   4718 				SCTP_INP_WUNLOCK(inp);
   4719 			}
   4720 			if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
   4721 			    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
   4722 				SCTP_INP_RLOCK(inp);
   4723 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4724 					SCTP_TCB_LOCK(stcb);
   4725 					shared_keys = &stcb->asoc.shared_keys;
   4726 					/* clear the cached keys for this key id */
   4727 					sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
   4728 					/*
   4729 					 * create the new shared key and
   4730 					 * insert/replace it
   4731 					 */
   4732 					if (size > 0) {
   4733 						key = sctp_set_key(sca->sca_key, (uint32_t) size);
   4734 						if (key == NULL) {
   4735 							SCTP_TCB_UNLOCK(stcb);
   4736 							continue;
   4737 						}
   4738 					}
   4739 					shared_key = sctp_alloc_sharedkey();
   4740 					if (shared_key == NULL) {
   4741 						sctp_free_key(key);
   4742 						SCTP_TCB_UNLOCK(stcb);
   4743 						continue;
   4744 					}
   4745 					shared_key->key = key;
   4746 					shared_key->keyid = sca->sca_keynumber;
   4747 					error = sctp_insert_sharedkey(shared_keys, shared_key);
   4748 					SCTP_TCB_UNLOCK(stcb);
   4749 				}
   4750 				SCTP_INP_RUNLOCK(inp);
   4751 			}
   4752 		}
   4753 		break;
   4754 	}
   4755 	case SCTP_HMAC_IDENT:
   4756 	{
   4757 		struct sctp_hmacalgo *shmac;
   4758 		sctp_hmaclist_t *hmaclist;
   4759 		uint16_t hmacid;
   4760 		uint32_t i;
   4761 
   4762 		SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
   4763 		if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) {
   4764 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4765 			error = EINVAL;
   4766 			break;
   4767 		}
   4768 
   4769 		hmaclist = sctp_alloc_hmaclist(shmac->shmac_number_of_idents);
   4770 		if (hmaclist == NULL) {
   4771 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
   4772 			error = ENOMEM;
   4773 			break;
   4774 		}
   4775 		for (i = 0; i < shmac->shmac_number_of_idents; i++) {
   4776 			hmacid = shmac->shmac_idents[i];
   4777 			if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
   4778 				/* invalid HMACs were found */;
   4779 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4780 				error = EINVAL;
   4781 				sctp_free_hmaclist(hmaclist);
   4782 				goto sctp_set_hmac_done;
   4783 			}
   4784 		}
   4785 		for (i = 0; i < hmaclist->num_algo; i++) {
   4786 			if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
   4787 				/* already in list */
   4788 				break;
   4789 			}
   4790 		}
   4791 		if (i == hmaclist->num_algo) {
   4792 			/* not found in list */
   4793 			sctp_free_hmaclist(hmaclist);
   4794 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4795 			error = EINVAL;
   4796 			break;
   4797 		}
   4798 		/* set it on the endpoint */
   4799 		SCTP_INP_WLOCK(inp);
   4800 		if (inp->sctp_ep.local_hmacs)
   4801 			sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
   4802 		inp->sctp_ep.local_hmacs = hmaclist;
   4803 		SCTP_INP_WUNLOCK(inp);
   4804 	sctp_set_hmac_done:
   4805 		break;
   4806 	}
   4807 	case SCTP_AUTH_ACTIVE_KEY:
   4808 	{
   4809 		struct sctp_authkeyid *scact;
   4810 
   4811 		SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
   4812 		SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
   4813 
   4814 		/* set the active key on the right place */
   4815 		if (stcb) {
   4816 			/* set the active key on the assoc */
   4817 			if (sctp_auth_setactivekey(stcb,
   4818 						   scact->scact_keynumber)) {
   4819 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
   4820 						    SCTP_FROM_SCTP_USRREQ,
   4821 						    EINVAL);
   4822 				error = EINVAL;
   4823 			}
   4824 			SCTP_TCB_UNLOCK(stcb);
   4825 		} else {
   4826 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4827 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4828 			    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
   4829 			    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
   4830 				SCTP_INP_WLOCK(inp);
   4831 				if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
   4832 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4833 					error = EINVAL;
   4834 				}
   4835 				SCTP_INP_WUNLOCK(inp);
   4836 			}
   4837 			if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
   4838 			    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
   4839 				SCTP_INP_RLOCK(inp);
   4840 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4841 					SCTP_TCB_LOCK(stcb);
   4842 					sctp_auth_setactivekey(stcb, scact->scact_keynumber);
   4843 					SCTP_TCB_UNLOCK(stcb);
   4844 				}
   4845 				SCTP_INP_RUNLOCK(inp);
   4846 			}
   4847 		}
   4848 		break;
   4849 	}
   4850 	case SCTP_AUTH_DELETE_KEY:
   4851 	{
   4852 		struct sctp_authkeyid *scdel;
   4853 
   4854 		SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
   4855 		SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
   4856 
   4857 		/* delete the key from the right place */
   4858 		if (stcb) {
   4859 			if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
   4860 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4861 				error = EINVAL;
   4862 			}
   4863 			SCTP_TCB_UNLOCK(stcb);
   4864 		} else {
   4865 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4866 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4867 			    (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
   4868 			    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
   4869 				SCTP_INP_WLOCK(inp);
   4870 				if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
   4871 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4872 					error = EINVAL;
   4873 				}
   4874 				SCTP_INP_WUNLOCK(inp);
   4875 			}
   4876 			if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
   4877 			    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
   4878 				SCTP_INP_RLOCK(inp);
   4879 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4880 					SCTP_TCB_LOCK(stcb);
   4881 					sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
   4882 					SCTP_TCB_UNLOCK(stcb);
   4883 				}
   4884 				SCTP_INP_RUNLOCK(inp);
   4885 			}
   4886 		}
   4887 		break;
   4888 	}
   4889 	case SCTP_AUTH_DEACTIVATE_KEY:
   4890 	{
   4891 		struct sctp_authkeyid *keyid;
   4892 
   4893 		SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
   4894 		SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
   4895 
   4896 		/* deactivate the key from the right place */
   4897 		if (stcb) {
   4898 			if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
   4899 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4900 				error = EINVAL;
   4901 			}
   4902 			SCTP_TCB_UNLOCK(stcb);
   4903 		} else {
   4904 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4905 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4906 			    (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
   4907 			    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
   4908 				SCTP_INP_WLOCK(inp);
   4909 				if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
   4910 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4911 					error = EINVAL;
   4912 				}
   4913 				SCTP_INP_WUNLOCK(inp);
   4914 			}
   4915 			if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
   4916 			    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
   4917 				SCTP_INP_RLOCK(inp);
   4918 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4919 					SCTP_TCB_LOCK(stcb);
   4920 					sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
   4921 					SCTP_TCB_UNLOCK(stcb);
   4922 				}
   4923 				SCTP_INP_RUNLOCK(inp);
   4924 			}
   4925 		}
   4926 		break;
   4927 	}
   4928 	case SCTP_ENABLE_STREAM_RESET:
   4929 	{
   4930 		struct sctp_assoc_value *av;
   4931 
   4932 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   4933 		if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
   4934 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   4935 			error = EINVAL;
   4936 			break;
   4937 		}
   4938 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   4939 		if (stcb) {
   4940 			stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
   4941 			SCTP_TCB_UNLOCK(stcb);
   4942 		} else {
   4943 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   4944 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   4945 			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
   4946 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4947 				SCTP_INP_WLOCK(inp);
   4948 				inp->local_strreset_support = (uint8_t)av->assoc_value;
   4949 				SCTP_INP_WUNLOCK(inp);
   4950 			}
   4951 			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
   4952 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   4953 				SCTP_INP_RLOCK(inp);
   4954 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   4955 					SCTP_TCB_LOCK(stcb);
   4956 					stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
   4957 					SCTP_TCB_UNLOCK(stcb);
   4958 				}
   4959 				SCTP_INP_RUNLOCK(inp);
   4960 			}
   4961 
   4962 		}
   4963 		break;
   4964 	}
   4965 	case SCTP_RESET_STREAMS:
   4966 	{
   4967 		struct sctp_reset_streams *strrst;
   4968 		int i, send_out = 0;
   4969 		int send_in = 0;
   4970 
   4971 		SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
   4972 		SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
   4973 		if (stcb == NULL) {
   4974 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   4975 			error = ENOENT;
   4976 			break;
   4977 		}
   4978 		if (stcb->asoc.peer_supports_strreset == 0) {
   4979 			/*
   4980 			 * Peer does not support the chunk type.
   4981 			 */
   4982 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   4983 			error = EOPNOTSUPP;
   4984 			SCTP_TCB_UNLOCK(stcb);
   4985 			break;
   4986 		}
   4987 		if (stcb->asoc.stream_reset_outstanding) {
   4988 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   4989 			error = EALREADY;
   4990 			SCTP_TCB_UNLOCK(stcb);
   4991 			break;
   4992 		}
   4993 		if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
   4994 			send_in = 1;
   4995 		}
   4996 		if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
   4997 			send_out = 1;
   4998 		}
   4999 		if ((send_in == 0) && (send_out == 0)) {
   5000 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5001 			error = EINVAL;
   5002 			SCTP_TCB_UNLOCK(stcb);
   5003 			break;
   5004 		}
   5005 		for (i = 0; i < strrst->srs_number_streams; i++) {
   5006 			if ((send_in) &&
   5007 			    (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
   5008 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5009 				error = EINVAL;
   5010 				break;
   5011 			}
   5012 			if ((send_out) &&
   5013 			    (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
   5014 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5015 				error = EINVAL;
   5016 				break;
   5017 			}
   5018 		}
   5019 		if (error) {
   5020 			SCTP_TCB_UNLOCK(stcb);
   5021 			break;
   5022 		}
   5023 		error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
   5024 						strrst->srs_stream_list,
   5025 						send_out, send_in, 0, 0, 0, 0, 0);
   5026 
   5027 		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
   5028 		SCTP_TCB_UNLOCK(stcb);
   5029 		break;
   5030 	}
   5031 	case SCTP_ADD_STREAMS:
   5032 	{
   5033 		struct sctp_add_streams *stradd;
   5034 		uint8_t addstream = 0;
   5035 		uint16_t add_o_strmcnt = 0;
   5036 		uint16_t add_i_strmcnt = 0;
   5037 
   5038 		SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
   5039 		SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
   5040 		if (stcb == NULL) {
   5041 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   5042 			error = ENOENT;
   5043 			break;
   5044 		}
   5045 		if (stcb->asoc.peer_supports_strreset == 0) {
   5046 			/*
   5047 			 * Peer does not support the chunk type.
   5048 			 */
   5049 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   5050 			error = EOPNOTSUPP;
   5051 			SCTP_TCB_UNLOCK(stcb);
   5052 			break;
   5053 		}
   5054 		if (stcb->asoc.stream_reset_outstanding) {
   5055 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   5056 			error = EALREADY;
   5057 			SCTP_TCB_UNLOCK(stcb);
   5058 			break;
   5059 		}
   5060 		if ((stradd->sas_outstrms == 0) &&
   5061 		    (stradd->sas_instrms == 0)) {
   5062 			error = EINVAL;
   5063 			goto skip_stuff;
   5064 		}
   5065 		if (stradd->sas_outstrms) {
   5066 			addstream = 1;
   5067 			/* We allocate here */
   5068 			add_o_strmcnt = stradd->sas_outstrms;
   5069 			if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
   5070 				/* You can't have more than 64k */
   5071 				error = EINVAL;
   5072 				goto skip_stuff;
   5073 			}
   5074 		}
   5075 		if (stradd->sas_instrms) {
   5076 			int cnt;
   5077 
   5078 			addstream |= 2;
   5079 			/* We allocate inside sctp_send_str_reset_req() */
   5080 			add_i_strmcnt = stradd->sas_instrms;
   5081 			cnt = add_i_strmcnt;
   5082 			cnt += stcb->asoc.streamincnt;
   5083 			if (cnt > 0x0000ffff) {
   5084 				/* You can't have more than 64k */
   5085 				error = EINVAL;
   5086 				goto skip_stuff;
   5087 			}
   5088 			if (cnt > (int)stcb->asoc.max_inbound_streams) {
   5089 				/* More than you are allowed */
   5090 				error = EINVAL;
   5091 				goto skip_stuff;
   5092 			}
   5093 		}
   5094 		error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
   5095 		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
   5096 	skip_stuff:
   5097 		SCTP_TCB_UNLOCK(stcb);
   5098 		break;
   5099 	}
   5100 	case SCTP_RESET_ASSOC:
   5101 	{
   5102 		uint32_t *value;
   5103 
   5104 		SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
   5105 		SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
   5106 		if (stcb == NULL) {
   5107 		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   5108 			error = ENOENT;
   5109 			break;
   5110 		}
   5111 		if (stcb->asoc.peer_supports_strreset == 0) {
   5112 			/*
   5113 			 * Peer does not support the chunk type.
   5114 			 */
   5115 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   5116 			error = EOPNOTSUPP;
   5117 			SCTP_TCB_UNLOCK(stcb);
   5118 			break;
   5119 		}
   5120 		if (stcb->asoc.stream_reset_outstanding) {
   5121 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   5122 			error = EALREADY;
   5123 			SCTP_TCB_UNLOCK(stcb);
   5124 			break;
   5125 		}
   5126 		error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0);
   5127 		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
   5128 		SCTP_TCB_UNLOCK(stcb);
   5129 		break;
   5130 	}
   5131 	case SCTP_CONNECT_X:
   5132 		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
   5133 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5134 			error = EINVAL;
   5135 			break;
   5136 		}
   5137 		error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
   5138 		break;
   5139 	case SCTP_CONNECT_X_DELAYED:
   5140 		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
   5141 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5142 			error = EINVAL;
   5143 			break;
   5144 		}
   5145 		error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
   5146 		break;
   5147 	case SCTP_CONNECT_X_COMPLETE:
   5148 	{
   5149 		struct sockaddr *sa;
   5150 		struct sctp_nets *net;
   5151 
   5152 		/* FIXME MT: check correct? */
   5153 		SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
   5154 
   5155 		/* find tcb */
   5156 		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
   5157 			SCTP_INP_RLOCK(inp);
   5158 			stcb = LIST_FIRST(&inp->sctp_asoc_list);
   5159 			if (stcb) {
   5160 				SCTP_TCB_LOCK(stcb);
   5161 				net = sctp_findnet(stcb, sa);
   5162 			}
   5163 			SCTP_INP_RUNLOCK(inp);
   5164 		} else {
   5165 			/* We increment here since sctp_findassociation_ep_addr() wil
   5166 			 * do a decrement if it finds the stcb as long as the locked
   5167 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   5168 			 */
   5169 			SCTP_INP_INCR_REF(inp);
   5170 			stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
   5171 			if (stcb == NULL) {
   5172 				SCTP_INP_DECR_REF(inp);
   5173 			}
   5174 		}
   5175 
   5176 		if (stcb == NULL) {
   5177 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   5178 			error = ENOENT;
   5179 			break;
   5180 		}
   5181 		if (stcb->asoc.delayed_connection == 1) {
   5182 			stcb->asoc.delayed_connection = 0;
   5183 			(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
   5184 			sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
   5185 					stcb->asoc.primary_destination,
   5186 					SCTP_FROM_SCTP_USRREQ+SCTP_LOC_9);
   5187 			sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
   5188 		} else {
   5189 			/*
   5190 			 * already expired or did not use delayed
   5191 			 * connectx
   5192 			 */
   5193 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   5194 			error = EALREADY;
   5195 		}
   5196 		SCTP_TCB_UNLOCK(stcb);
   5197 		break;
   5198 	}
   5199 	case SCTP_MAX_BURST:
   5200 	{
   5201 #if defined(__FreeBSD__) && __FreeBSD_version < 900000
   5202 		uint8_t *burst;
   5203 
   5204 		SCTP_CHECK_AND_CAST(burst, optval, uint8_t, optsize);
   5205 
   5206 		SCTP_INP_WLOCK(inp);
   5207 		inp->sctp_ep.max_burst = *burst;
   5208 		SCTP_INP_WUNLOCK(inp);
   5209 #else
   5210 		struct sctp_assoc_value *av;
   5211 
   5212 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   5213 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   5214 
   5215 		if (stcb) {
   5216 			stcb->asoc.max_burst = av->assoc_value;
   5217 			SCTP_TCB_UNLOCK(stcb);
   5218 		} else {
   5219 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5220 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   5221 			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
   5222 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   5223 				SCTP_INP_WLOCK(inp);
   5224 				inp->sctp_ep.max_burst = av->assoc_value;
   5225 				SCTP_INP_WUNLOCK(inp);
   5226 			}
   5227 			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
   5228 			    (av->assoc_id == SCTP_ALL_ASSOC)) {
   5229 				SCTP_INP_RLOCK(inp);
   5230 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   5231 					SCTP_TCB_LOCK(stcb);
   5232 					stcb->asoc.max_burst = av->assoc_value;
   5233 					SCTP_TCB_UNLOCK(stcb);
   5234 				}
   5235 				SCTP_INP_RUNLOCK(inp);
   5236 			}
   5237 		}
   5238 #endif
   5239 		break;
   5240 	}
   5241 	case SCTP_MAXSEG:
   5242 	{
   5243 		struct sctp_assoc_value *av;
   5244 		int ovh;
   5245 
   5246 		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
   5247 		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
   5248 
   5249 		if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   5250 			ovh = SCTP_MED_OVERHEAD;
   5251 		} else {
   5252 			ovh = SCTP_MED_V4_OVERHEAD;
   5253 		}
   5254 		if (stcb) {
   5255 			if (av->assoc_value) {
   5256 				stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
   5257 			} else {
   5258 				stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
   5259 			}
   5260 			SCTP_TCB_UNLOCK(stcb);
   5261 		} else {
   5262 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5263 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   5264 			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
   5265 				SCTP_INP_WLOCK(inp);
   5266 				/* FIXME MT: I think this is not in tune with the API ID */
   5267 				if (av->assoc_value) {
   5268 					inp->sctp_frag_point = (av->assoc_value + ovh);
   5269 				} else {
   5270 					inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
   5271 				}
   5272 				SCTP_INP_WUNLOCK(inp);
   5273 			} else {
   5274 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5275 				error = EINVAL;
   5276 			}
   5277 		}
   5278 		break;
   5279 	}
   5280 	case SCTP_EVENTS:
   5281 	{
   5282 		struct sctp_event_subscribe *events;
   5283 
   5284 		SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
   5285 
   5286 		SCTP_INP_WLOCK(inp);
   5287 		if (events->sctp_data_io_event) {
   5288 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
   5289 		} else {
   5290 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
   5291 		}
   5292 
   5293 		if (events->sctp_association_event) {
   5294 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
   5295 		} else {
   5296 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
   5297 		}
   5298 
   5299 		if (events->sctp_address_event) {
   5300 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
   5301 		} else {
   5302 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
   5303 		}
   5304 
   5305 		if (events->sctp_send_failure_event) {
   5306 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
   5307 		} else {
   5308 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
   5309 		}
   5310 
   5311 		if (events->sctp_peer_error_event) {
   5312 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
   5313 		} else {
   5314 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
   5315 		}
   5316 
   5317 		if (events->sctp_shutdown_event) {
   5318 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
   5319 		} else {
   5320 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
   5321 		}
   5322 
   5323 		if (events->sctp_partial_delivery_event) {
   5324 			sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
   5325 		} else {
   5326 			sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
   5327 		}
   5328 
   5329 		if (events->sctp_adaptation_layer_event) {
   5330 			sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
   5331 		} else {
   5332 			sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
   5333 		}
   5334 
   5335 		if (events->sctp_authentication_event) {
   5336 			sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
   5337 		} else {
   5338 			sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
   5339 		}
   5340 
   5341 		if (events->sctp_sender_dry_event) {
   5342 			sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
   5343 		} else {
   5344 			sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
   5345 		}
   5346 
   5347 		if (events->sctp_stream_reset_event) {
   5348 			sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
   5349 		} else {
   5350 			sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
   5351 		}
   5352 		SCTP_INP_WUNLOCK(inp);
   5353 
   5354 		SCTP_INP_RLOCK(inp);
   5355 		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   5356 			SCTP_TCB_LOCK(stcb);
   5357 			if (events->sctp_association_event) {
   5358 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
   5359 			} else {
   5360 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
   5361 			}
   5362 			if (events->sctp_address_event) {
   5363 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
   5364 			} else {
   5365 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
   5366 			}
   5367 			if (events->sctp_send_failure_event) {
   5368 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
   5369 			} else {
   5370 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
   5371 			}
   5372 			if (events->sctp_peer_error_event) {
   5373 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
   5374 			} else {
   5375 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
   5376 			}
   5377 			if (events->sctp_shutdown_event) {
   5378 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
   5379 			} else {
   5380 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
   5381 			}
   5382 			if (events->sctp_partial_delivery_event) {
   5383 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
   5384 			} else {
   5385 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
   5386 			}
   5387 			if (events->sctp_adaptation_layer_event) {
   5388 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
   5389 			} else {
   5390 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
   5391 			}
   5392 			if (events->sctp_authentication_event) {
   5393 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
   5394 			} else {
   5395 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
   5396 			}
   5397 			if (events->sctp_sender_dry_event) {
   5398 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
   5399 			} else {
   5400 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
   5401 			}
   5402 			if (events->sctp_stream_reset_event) {
   5403 				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
   5404 			} else {
   5405 				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
   5406 			}
   5407 			SCTP_TCB_UNLOCK(stcb);
   5408 		}
   5409 		/* Send up the sender dry event only for 1-to-1 style sockets. */
   5410 		if (events->sctp_sender_dry_event) {
   5411 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5412 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
   5413 				stcb = LIST_FIRST(&inp->sctp_asoc_list);
   5414 				if (stcb) {
   5415 					SCTP_TCB_LOCK(stcb);
   5416 					if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
   5417 					    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
   5418 					    (stcb->asoc.stream_queue_cnt == 0)) {
   5419 						sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb,  0, NULL, SCTP_SO_LOCKED);
   5420 					}
   5421 					SCTP_TCB_UNLOCK(stcb);
   5422 				}
   5423 			}
   5424 		}
   5425 		SCTP_INP_RUNLOCK(inp);
   5426 		break;
   5427 	}
   5428 	case SCTP_ADAPTATION_LAYER:
   5429 	{
   5430 		struct sctp_setadaptation *adap_bits;
   5431 
   5432 		SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
   5433 		SCTP_INP_WLOCK(inp);
   5434 		inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
   5435 		inp->sctp_ep.adaptation_layer_indicator_provided = 1;
   5436 		SCTP_INP_WUNLOCK(inp);
   5437 		break;
   5438 	}
   5439 #ifdef SCTP_DEBUG
   5440 	case SCTP_SET_INITIAL_DBG_SEQ:
   5441 	{
   5442 		uint32_t *vvv;
   5443 
   5444 		SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
   5445 		SCTP_INP_WLOCK(inp);
   5446 		inp->sctp_ep.initial_sequence_debug = *vvv;
   5447 		SCTP_INP_WUNLOCK(inp);
   5448 		break;
   5449 	}
   5450 #endif
   5451 	case SCTP_DEFAULT_SEND_PARAM:
   5452 	{
   5453 		struct sctp_sndrcvinfo *s_info;
   5454 
   5455 		SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
   5456 		SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
   5457 
   5458 		if (stcb) {
   5459 			if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
   5460 				memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
   5461 			} else {
   5462 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5463 				error = EINVAL;
   5464 			}
   5465 			SCTP_TCB_UNLOCK(stcb);
   5466 		} else {
   5467 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5468 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   5469 			    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
   5470 			    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
   5471 				SCTP_INP_WLOCK(inp);
   5472 				memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
   5473 				SCTP_INP_WUNLOCK(inp);
   5474 			}
   5475 			if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
   5476 			    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
   5477 				SCTP_INP_RLOCK(inp);
   5478 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   5479 					SCTP_TCB_LOCK(stcb);
   5480 					if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
   5481 						memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
   5482 					}
   5483 					SCTP_TCB_UNLOCK(stcb);
   5484 				}
   5485 				SCTP_INP_RUNLOCK(inp);
   5486 			}
   5487 		}
   5488 		break;
   5489 	}
   5490 	case SCTP_PEER_ADDR_PARAMS:
   5491 	{
   5492 		struct sctp_paddrparams *paddrp;
   5493 		struct sctp_nets *net;
   5494 
   5495 		SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
   5496 		SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
   5497 		net = NULL;
   5498 		if (stcb) {
   5499 			net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
   5500 		} else {
   5501 			/* We increment here since sctp_findassociation_ep_addr() wil
   5502 			 * do a decrement if it finds the stcb as long as the locked
   5503 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   5504 			 */
   5505 			SCTP_INP_INCR_REF(inp);
   5506 			stcb = sctp_findassociation_ep_addr(&inp,
   5507 							    (struct sockaddr *)&paddrp->spp_address,
   5508 							    &net, NULL, NULL);
   5509 			if (stcb == NULL) {
   5510 				SCTP_INP_DECR_REF(inp);
   5511 			}
   5512 		}
   5513 		if (stcb && (net == NULL)) {
   5514 			struct sockaddr *sa;
   5515 
   5516 			sa = (struct sockaddr *)&paddrp->spp_address;
   5517 #ifdef INET
   5518 			if (sa->sa_family == AF_INET) {
   5519 
   5520 				struct sockaddr_in *sin;
   5521 				sin = (struct sockaddr_in *)sa;
   5522 				if (sin->sin_addr.s_addr) {
   5523 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5524 					SCTP_TCB_UNLOCK(stcb);
   5525 					error = EINVAL;
   5526 					break;
   5527 				}
   5528 			} else
   5529 #endif
   5530 #ifdef INET6
   5531 			if (sa->sa_family == AF_INET6) {
   5532 				struct sockaddr_in6 *sin6;
   5533 
   5534 				sin6 = (struct sockaddr_in6 *)sa;
   5535 				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   5536 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5537 					SCTP_TCB_UNLOCK(stcb);
   5538 					error = EINVAL;
   5539 					break;
   5540 				}
   5541 			} else
   5542 #endif
   5543 #if defined(__Userspace__)
   5544 			if (sa->sa_family == AF_CONN) {
   5545 				struct sockaddr_conn *sconn;
   5546 
   5547 				sconn = (struct sockaddr_conn *)sa;
   5548 				if (sconn->sconn_addr != NULL) {
   5549 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5550 					SCTP_TCB_UNLOCK(stcb);
   5551 					error = EINVAL;
   5552 					break;
   5553 				}
   5554 			} else
   5555 #endif
   5556 			{
   5557 				error = EAFNOSUPPORT;
   5558 				SCTP_TCB_UNLOCK(stcb);
   5559 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   5560 				break;
   5561 			}
   5562 		}
   5563 		/* sanity checks */
   5564 		if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
   5565 			if (stcb)
   5566 				SCTP_TCB_UNLOCK(stcb);
   5567 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5568 			return (EINVAL);
   5569 		}
   5570 
   5571 		if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
   5572 			if (stcb)
   5573 				SCTP_TCB_UNLOCK(stcb);
   5574 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5575 			return (EINVAL);
   5576 		}
   5577 
   5578 		if (stcb) {
   5579 			/************************TCB SPECIFIC SET ******************/
   5580 			/*
   5581 			 * do we change the timer for HB, we run
   5582 			 * only one?
   5583 			 */
   5584 			int ovh = 0;
   5585 
   5586 			if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   5587 				ovh = SCTP_MED_OVERHEAD;
   5588 			} else {
   5589 				ovh = SCTP_MED_V4_OVERHEAD;
   5590 			}
   5591 
   5592 			/* network sets ? */
   5593 			if (net) {
   5594 				/************************NET SPECIFIC SET ******************/
   5595 				if (paddrp->spp_flags & SPP_HB_DISABLE) {
   5596 					if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
   5597 					    !(net->dest_state & SCTP_ADDR_NOHB)) {
   5598 						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
   5599 								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
   5600 					}
   5601 					net->dest_state |= SCTP_ADDR_NOHB;
   5602 				}
   5603 				if (paddrp->spp_flags & SPP_HB_ENABLE) {
   5604 					if (paddrp->spp_hbinterval) {
   5605 						net->heart_beat_delay = paddrp->spp_hbinterval;
   5606 					} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
   5607 						net->heart_beat_delay = 0;
   5608 					}
   5609 					sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
   5610 					                SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
   5611 					sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
   5612 					net->dest_state &= ~SCTP_ADDR_NOHB;
   5613 				}
   5614 				if (paddrp->spp_flags & SPP_HB_DEMAND) {
   5615 					/* on demand HB */
   5616 					sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
   5617 					sctp_chunk_output(inp, stcb,  SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
   5618 					sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
   5619 				}
   5620 				if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
   5621 					if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
   5622 						sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
   5623 								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
   5624 					}
   5625 					net->dest_state |= SCTP_ADDR_NO_PMTUD;
   5626 					net->mtu = paddrp->spp_pathmtu + ovh;
   5627 					if (net->mtu < stcb->asoc.smallest_mtu) {
   5628 						sctp_pathmtu_adjustment(stcb, net->mtu);
   5629 					}
   5630 				}
   5631 				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
   5632 					if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
   5633 						sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
   5634 					}
   5635 					net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
   5636 				}
   5637 				if (paddrp->spp_pathmaxrxt) {
   5638 					if (net->dest_state & SCTP_ADDR_PF) {
   5639 						if (net->error_count > paddrp->spp_pathmaxrxt) {
   5640 							net->dest_state &= ~SCTP_ADDR_PF;
   5641 						}
   5642 					} else {
   5643 						if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
   5644 						    (net->error_count > net->pf_threshold)) {
   5645 							net->dest_state |= SCTP_ADDR_PF;
   5646 							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
   5647 							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
   5648 							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
   5649 						}
   5650 					}
   5651 					if (net->dest_state & SCTP_ADDR_REACHABLE) {
   5652 						if (net->error_count > paddrp->spp_pathmaxrxt) {
   5653 					    		net->dest_state &= ~SCTP_ADDR_REACHABLE;
   5654 							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
   5655 						}
   5656 					} else {
   5657 						if (net->error_count <= paddrp->spp_pathmaxrxt) {
   5658 							net->dest_state |= SCTP_ADDR_REACHABLE;
   5659 							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
   5660 						}
   5661 					}
   5662 					net->failure_threshold = paddrp->spp_pathmaxrxt;
   5663 				}
   5664 				if (paddrp->spp_flags & SPP_DSCP) {
   5665 					net->dscp = paddrp->spp_dscp & 0xfc;
   5666 					net->dscp |= 0x01;
   5667 				}
   5668 #ifdef INET6
   5669 				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
   5670 					if (net->ro._l_addr.sa.sa_family == AF_INET6) {
   5671 						net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
   5672 						net->flowlabel |= 0x80000000;
   5673 					}
   5674 				}
   5675 #endif
   5676 			} else {
   5677 				/************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
   5678 				if (paddrp->spp_pathmaxrxt) {
   5679 					stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
   5680 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   5681 						if (net->dest_state & SCTP_ADDR_PF) {
   5682 							if (net->error_count > paddrp->spp_pathmaxrxt) {
   5683 								net->dest_state &= ~SCTP_ADDR_PF;
   5684 							}
   5685 						} else {
   5686 							if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
   5687 							    (net->error_count > net->pf_threshold)) {
   5688 								net->dest_state |= SCTP_ADDR_PF;
   5689 								sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
   5690 								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
   5691 								sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
   5692 							}
   5693 						}
   5694 						if (net->dest_state & SCTP_ADDR_REACHABLE) {
   5695 							if (net->error_count > paddrp->spp_pathmaxrxt) {
   5696 						    		net->dest_state &= ~SCTP_ADDR_REACHABLE;
   5697 								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
   5698 							}
   5699 						} else {
   5700 							if (net->error_count <= paddrp->spp_pathmaxrxt) {
   5701 								net->dest_state |= SCTP_ADDR_REACHABLE;
   5702 								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
   5703 							}
   5704 						}
   5705 						net->failure_threshold = paddrp->spp_pathmaxrxt;
   5706 					}
   5707 				}
   5708 
   5709 				if (paddrp->spp_flags & SPP_HB_ENABLE) {
   5710 					if (paddrp->spp_hbinterval) {
   5711 						stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
   5712 					} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
   5713 						stcb->asoc.heart_beat_delay = 0;
   5714 					}
   5715 					/* Turn back on the timer */
   5716 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   5717 						if (paddrp->spp_hbinterval) {
   5718 							net->heart_beat_delay = paddrp->spp_hbinterval;
   5719 						} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
   5720 							net->heart_beat_delay = 0;
   5721 						}
   5722 						if (net->dest_state & SCTP_ADDR_NOHB) {
   5723 							net->dest_state &= ~SCTP_ADDR_NOHB;
   5724 						}
   5725 						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
   5726 								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
   5727 						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
   5728 					}
   5729 					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
   5730 				}
   5731 				if (paddrp->spp_flags & SPP_HB_DISABLE) {
   5732 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   5733 						if (!(net->dest_state & SCTP_ADDR_NOHB)) {
   5734 							net->dest_state |= SCTP_ADDR_NOHB;
   5735 							if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
   5736 								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
   5737 							}
   5738 						}
   5739 					}
   5740 					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
   5741 				}
   5742 				if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
   5743 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   5744 						if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
   5745 							sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
   5746 									SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
   5747 						}
   5748 						net->dest_state |= SCTP_ADDR_NO_PMTUD;
   5749 						net->mtu = paddrp->spp_pathmtu + ovh;
   5750 						if (net->mtu < stcb->asoc.smallest_mtu) {
   5751 							sctp_pathmtu_adjustment(stcb, net->mtu);
   5752 						}
   5753 					}
   5754 					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
   5755 				}
   5756 				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
   5757 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   5758 						if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
   5759 							sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
   5760 						}
   5761 						net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
   5762 					}
   5763 					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
   5764 				}
   5765 				if (paddrp->spp_flags & SPP_DSCP) {
   5766 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   5767 						net->dscp = paddrp->spp_dscp & 0xfc;
   5768 						net->dscp |= 0x01;
   5769 					}
   5770 					stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
   5771 					stcb->asoc.default_dscp |= 0x01;
   5772 				}
   5773 #ifdef INET6
   5774 				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
   5775 					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   5776 						if (net->ro._l_addr.sa.sa_family == AF_INET6) {
   5777 							net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
   5778 							net->flowlabel |= 0x80000000;
   5779 						}
   5780 					}
   5781 					stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
   5782 					stcb->asoc.default_flowlabel |= 0x80000000;
   5783 				}
   5784 #endif
   5785 			}
   5786 			SCTP_TCB_UNLOCK(stcb);
   5787 		} else {
   5788 			/************************NO TCB, SET TO default stuff ******************/
   5789 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5790 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   5791 			    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
   5792 				SCTP_INP_WLOCK(inp);
   5793 				/*
   5794 				 * For the TOS/FLOWLABEL stuff you set it
   5795 				 * with the options on the socket
   5796 				 */
   5797 				if (paddrp->spp_pathmaxrxt) {
   5798 					inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
   5799 				}
   5800 
   5801 				if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
   5802 					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
   5803 				else if (paddrp->spp_hbinterval) {
   5804 					if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
   5805 						paddrp->spp_hbinterval= SCTP_MAX_HB_INTERVAL;
   5806 					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
   5807 				}
   5808 
   5809 				if (paddrp->spp_flags & SPP_HB_ENABLE) {
   5810 					if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
   5811 						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
   5812 					} else if (paddrp->spp_hbinterval) {
   5813 						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
   5814 					}
   5815 					sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
   5816 				} else if (paddrp->spp_flags & SPP_HB_DISABLE) {
   5817 					sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
   5818 				}
   5819 				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
   5820 					sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
   5821 				} else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
   5822 					sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
   5823 				}
   5824 				if (paddrp->spp_flags & SPP_DSCP) {
   5825 					inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
   5826 					inp->sctp_ep.default_dscp |= 0x01;
   5827 				}
   5828 #ifdef INET6
   5829 				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
   5830 					if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   5831 						inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
   5832 						inp->sctp_ep.default_flowlabel |= 0x80000000;
   5833 					}
   5834 				}
   5835 #endif
   5836 				SCTP_INP_WUNLOCK(inp);
   5837 			} else {
   5838 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5839 				error = EINVAL;
   5840 			}
   5841 		}
   5842 		break;
   5843 	}
   5844 	case SCTP_RTOINFO:
   5845 	{
   5846 		struct sctp_rtoinfo *srto;
   5847 		uint32_t new_init, new_min, new_max;
   5848 
   5849 		SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
   5850 		SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
   5851 
   5852 		if (stcb) {
   5853 			if (srto->srto_initial)
   5854 				new_init = srto->srto_initial;
   5855 			else
   5856 				new_init = stcb->asoc.initial_rto;
   5857 			if (srto->srto_max)
   5858 				new_max = srto->srto_max;
   5859 			else
   5860 				new_max = stcb->asoc.maxrto;
   5861 			if (srto->srto_min)
   5862 				new_min = srto->srto_min;
   5863 			else
   5864 				new_min = stcb->asoc.minrto;
   5865 			if ((new_min <= new_init) && (new_init <= new_max)) {
   5866 				stcb->asoc.initial_rto = new_init;
   5867 				stcb->asoc.maxrto = new_max;
   5868 				stcb->asoc.minrto = new_min;
   5869 			} else {
   5870 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5871 				error = EINVAL;
   5872 			}
   5873 			SCTP_TCB_UNLOCK(stcb);
   5874 		} else {
   5875 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5876 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   5877 			    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
   5878 				SCTP_INP_WLOCK(inp);
   5879 				if (srto->srto_initial)
   5880 					new_init = srto->srto_initial;
   5881 				else
   5882 					new_init = inp->sctp_ep.initial_rto;
   5883 				if (srto->srto_max)
   5884 					new_max = srto->srto_max;
   5885 				else
   5886 					new_max = inp->sctp_ep.sctp_maxrto;
   5887 				if (srto->srto_min)
   5888 					new_min = srto->srto_min;
   5889 				else
   5890 					new_min = inp->sctp_ep.sctp_minrto;
   5891 				if ((new_min <= new_init) && (new_init <= new_max)) {
   5892 					inp->sctp_ep.initial_rto = new_init;
   5893 					inp->sctp_ep.sctp_maxrto = new_max;
   5894 					inp->sctp_ep.sctp_minrto = new_min;
   5895 				} else {
   5896 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5897 					error = EINVAL;
   5898 				}
   5899 				SCTP_INP_WUNLOCK(inp);
   5900 			} else {
   5901 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5902 				error = EINVAL;
   5903 			}
   5904 		}
   5905 		break;
   5906 	}
   5907 	case SCTP_ASSOCINFO:
   5908 	{
   5909 		struct sctp_assocparams *sasoc;
   5910 
   5911 		SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
   5912 		SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
   5913 		if (sasoc->sasoc_cookie_life) {
   5914 			/* boundary check the cookie life */
   5915 			if (sasoc->sasoc_cookie_life < 1000)
   5916 				sasoc->sasoc_cookie_life = 1000;
   5917 			if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
   5918 				sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
   5919 			}
   5920 		}
   5921 		if (stcb) {
   5922 			if (sasoc->sasoc_asocmaxrxt)
   5923 				stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
   5924 			if (sasoc->sasoc_cookie_life) {
   5925 				stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
   5926 			}
   5927 			SCTP_TCB_UNLOCK(stcb);
   5928 		} else {
   5929 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   5930 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   5931 			    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
   5932 				SCTP_INP_WLOCK(inp);
   5933 				if (sasoc->sasoc_asocmaxrxt)
   5934 					inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
   5935 				if (sasoc->sasoc_cookie_life) {
   5936 					inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
   5937 				}
   5938 				SCTP_INP_WUNLOCK(inp);
   5939 			} else {
   5940 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   5941 				error = EINVAL;
   5942 			}
   5943 		}
   5944 		break;
   5945 	}
   5946 	case SCTP_INITMSG:
   5947 	{
   5948 		struct sctp_initmsg *sinit;
   5949 
   5950 		SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
   5951 		SCTP_INP_WLOCK(inp);
   5952 		if (sinit->sinit_num_ostreams)
   5953 			inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
   5954 
   5955 		if (sinit->sinit_max_instreams)
   5956 			inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
   5957 
   5958 		if (sinit->sinit_max_attempts)
   5959 			inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
   5960 
   5961 		if (sinit->sinit_max_init_timeo)
   5962 			inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
   5963 		SCTP_INP_WUNLOCK(inp);
   5964 		break;
   5965 	}
   5966 	case SCTP_PRIMARY_ADDR:
   5967 	{
   5968 		struct sctp_setprim *spa;
   5969 		struct sctp_nets *net;
   5970 
   5971 		SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
   5972 		SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
   5973 
   5974 		net = NULL;
   5975 		if (stcb) {
   5976 			net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
   5977 		} else {
   5978 			/* We increment here since sctp_findassociation_ep_addr() wil
   5979 			 * do a decrement if it finds the stcb as long as the locked
   5980 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   5981 			 */
   5982 			SCTP_INP_INCR_REF(inp);
   5983 			stcb = sctp_findassociation_ep_addr(&inp,
   5984 							    (struct sockaddr *)&spa->ssp_addr,
   5985 							    &net, NULL, NULL);
   5986 			if (stcb == NULL) {
   5987 				SCTP_INP_DECR_REF(inp);
   5988 			}
   5989 		}
   5990 
   5991 		if ((stcb) && (net)) {
   5992 			if ((net != stcb->asoc.primary_destination) &&
   5993 			    (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
   5994 				/* Ok we need to set it */
   5995 				if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
   5996 					if ((stcb->asoc.alternate) &&
   5997 					    (!(net->dest_state & SCTP_ADDR_PF)) &&
   5998 					    (net->dest_state & SCTP_ADDR_REACHABLE)) {
   5999 						sctp_free_remote_addr(stcb->asoc.alternate);
   6000 						stcb->asoc.alternate = NULL;
   6001 					}
   6002 				}
   6003 			}
   6004 		} else {
   6005 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6006 			error = EINVAL;
   6007 		}
   6008 		if (stcb) {
   6009 			SCTP_TCB_UNLOCK(stcb);
   6010 		}
   6011 		break;
   6012 	}
   6013 	case SCTP_SET_DYNAMIC_PRIMARY:
   6014 	{
   6015 		union sctp_sockstore *ss;
   6016 #ifdef SCTP_MVRF
   6017 		int i, fnd = 0;
   6018 #endif
   6019 #if !defined(__Windows__) && !defined(__Userspace__)
   6020 #if defined(__APPLE__)
   6021 		struct proc *proc;
   6022 #endif
   6023 #ifdef __FreeBSD__
   6024 #if __FreeBSD_version > 602000
   6025 		error = priv_check(curthread,
   6026 				   PRIV_NETINET_RESERVEDPORT);
   6027 #elif __FreeBSD_version >= 500000
   6028 		error = suser((struct thread *)p);
   6029 #else
   6030 		error = suser(p);
   6031 #endif
   6032 #elif defined(__APPLE__)
   6033 		proc = (struct proc *)p;
   6034 		if (p) {
   6035 			error = suser(proc->p_ucred, &proc->p_acflag);
   6036 		} else {
   6037 			break;
   6038 		}
   6039 #else
   6040 		error = suser(p, 0);
   6041 #endif
   6042 #endif
   6043 		if (error)
   6044 			break;
   6045 
   6046 		SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
   6047 		/* SUPER USER CHECK? */
   6048 #ifdef SCTP_MVRF
   6049 		for (i = 0; i < inp->num_vrfs; i++) {
   6050 			if (vrf_id == inp->m_vrf_ids[i]) {
   6051 				fnd = 1;
   6052 				break;
   6053 			}
   6054 		}
   6055 		if (!fnd) {
   6056 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6057 			error = EINVAL;
   6058 			break;
   6059 		}
   6060 #endif
   6061 		error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
   6062 		break;
   6063 	}
   6064 	case SCTP_SET_PEER_PRIMARY_ADDR:
   6065 	{
   6066 		struct sctp_setpeerprim *sspp;
   6067 
   6068 		SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
   6069 		SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
   6070 		if (stcb != NULL) {
   6071 			struct sctp_ifa *ifa;
   6072 			ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
   6073 						    stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
   6074 			if (ifa == NULL) {
   6075 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6076 				error = EINVAL;
   6077 				goto out_of_it;
   6078 			}
   6079 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
   6080 				/* Must validate the ifa found is in our ep */
   6081 				struct sctp_laddr *laddr;
   6082 				int found = 0;
   6083 				LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
   6084 					if (laddr->ifa == NULL) {
   6085 						SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
   6086 							__FUNCTION__);
   6087 						continue;
   6088 					}
   6089 					if (laddr->ifa == ifa) {
   6090 						found = 1;
   6091 						break;
   6092 					}
   6093 				}
   6094 				if (!found) {
   6095 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6096 					error = EINVAL;
   6097 					goto out_of_it;
   6098 				}
   6099 			}
   6100 			if (sctp_set_primary_ip_address_sa(stcb,
   6101 							   (struct sockaddr *)&sspp->sspp_addr) != 0) {
   6102 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6103 				error = EINVAL;
   6104 			}
   6105 		out_of_it:
   6106 			SCTP_TCB_UNLOCK(stcb);
   6107 		} else {
   6108 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6109 			error = EINVAL;
   6110 		}
   6111 		break;
   6112 	}
   6113 	case SCTP_BINDX_ADD_ADDR:
   6114 	{
   6115 		struct sctp_getaddresses *addrs;
   6116 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
   6117 		struct thread *td;
   6118 
   6119 		td = (struct thread *)p;
   6120 #endif
   6121 		SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
   6122 				    optsize);
   6123 #ifdef INET
   6124 		if (addrs->addr->sa_family == AF_INET) {
   6125 			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
   6126 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6127 				error = EINVAL;
   6128 				break;
   6129 			}
   6130 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   6131 			if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
   6132 				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6133 				break;
   6134 			}
   6135 #endif
   6136 		} else
   6137 #endif
   6138 #ifdef INET6
   6139 		if (addrs->addr->sa_family == AF_INET6) {
   6140 			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
   6141 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6142 				error = EINVAL;
   6143 				break;
   6144 			}
   6145 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   6146 			if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
   6147 											   (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
   6148 			  SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6149 			  break;
   6150 			}
   6151 #endif
   6152 		} else
   6153 #endif
   6154 		{
   6155 		       error = EAFNOSUPPORT;
   6156   		       break;
   6157 		}
   6158 		sctp_bindx_add_address(so, inp, addrs->addr,
   6159 				       addrs->sget_assoc_id, vrf_id,
   6160 				       &error, p);
   6161 		break;
   6162 	}
   6163 	case SCTP_BINDX_REM_ADDR:
   6164 	{
   6165 		struct sctp_getaddresses *addrs;
   6166 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
   6167 		struct thread *td;
   6168 		td = (struct thread *)p;
   6169 
   6170 #endif
   6171 		SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
   6172 #ifdef INET
   6173 		if (addrs->addr->sa_family == AF_INET) {
   6174 			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
   6175 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6176 				error = EINVAL;
   6177 				break;
   6178 			}
   6179 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   6180 		if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
   6181 				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6182 				break;
   6183 			}
   6184 #endif
   6185 		} else
   6186 #endif
   6187 #ifdef INET6
   6188 		if (addrs->addr->sa_family == AF_INET6) {
   6189 			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
   6190 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6191 				error = EINVAL;
   6192 				break;
   6193 			}
   6194 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   6195 			if (td != NULL &&
   6196 			    (error = prison_local_ip6(td->td_ucred,
   6197 			                              &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
   6198 			                              (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
   6199 				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6200 				break;
   6201 			}
   6202 #endif
   6203 		} else
   6204 #endif
   6205 		{
   6206 			error = EAFNOSUPPORT;
   6207 			break;
   6208 		}
   6209 		sctp_bindx_delete_address(inp, addrs->addr,
   6210 					  addrs->sget_assoc_id, vrf_id,
   6211 					  &error);
   6212 		break;
   6213 	}
   6214 #ifdef __APPLE__
   6215 	case SCTP_LISTEN_FIX:
   6216 		/* only applies to one-to-many sockets */
   6217 		if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
   6218 			/* make sure the ACCEPTCONN flag is OFF */
   6219 			so->so_options &= ~SO_ACCEPTCONN;
   6220 		} else {
   6221 			/* otherwise, not allowed */
   6222 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6223 			error = EINVAL;
   6224 		}
   6225 		break;
   6226 #endif				/* __APPLE__ */
   6227 	case SCTP_EVENT:
   6228 	{
   6229 		struct sctp_event *event;
   6230 		uint32_t event_type;
   6231 
   6232 		SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
   6233 		SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
   6234 		switch (event->se_type) {
   6235 		case SCTP_ASSOC_CHANGE:
   6236 			event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
   6237 			break;
   6238 		case SCTP_PEER_ADDR_CHANGE:
   6239 			event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
   6240 			break;
   6241 		case SCTP_REMOTE_ERROR:
   6242 			event_type = SCTP_PCB_FLAGS_RECVPEERERR;
   6243 			break;
   6244 		case SCTP_SEND_FAILED:
   6245 			event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
   6246 			break;
   6247 		case SCTP_SHUTDOWN_EVENT:
   6248 			event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
   6249 			break;
   6250 		case SCTP_ADAPTATION_INDICATION:
   6251 			event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
   6252 			break;
   6253 		case SCTP_PARTIAL_DELIVERY_EVENT:
   6254 			event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
   6255 			break;
   6256 		case SCTP_AUTHENTICATION_EVENT:
   6257 			event_type = SCTP_PCB_FLAGS_AUTHEVNT;
   6258 			break;
   6259 		case SCTP_STREAM_RESET_EVENT:
   6260 			event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
   6261 			break;
   6262 		case SCTP_SENDER_DRY_EVENT:
   6263 			event_type = SCTP_PCB_FLAGS_DRYEVNT;
   6264 			break;
   6265 		case SCTP_NOTIFICATIONS_STOPPED_EVENT:
   6266 			event_type = 0;
   6267 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
   6268 			error = ENOTSUP;
   6269 			break;
   6270 		case SCTP_ASSOC_RESET_EVENT:
   6271 			event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
   6272 			break;
   6273 		case SCTP_STREAM_CHANGE_EVENT:
   6274 			event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
   6275 			break;
   6276 		case SCTP_SEND_FAILED_EVENT:
   6277 			event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
   6278 			break;
   6279 		default:
   6280 			event_type = 0;
   6281 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6282 			error = EINVAL;
   6283 			break;
   6284 		}
   6285 		if (event_type > 0) {
   6286 			if (stcb) {
   6287 				if (event->se_on) {
   6288 					sctp_stcb_feature_on(inp, stcb, event_type);
   6289 					if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
   6290 						if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
   6291 						    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
   6292 						    (stcb->asoc.stream_queue_cnt == 0)) {
   6293 							sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb,  0, NULL, SCTP_SO_LOCKED);
   6294 						}
   6295 					}
   6296 				} else {
   6297 					sctp_stcb_feature_off(inp, stcb, event_type);
   6298 				}
   6299 				SCTP_TCB_UNLOCK(stcb);
   6300 			} else {
   6301 				/*
   6302 				 * We don't want to send up a storm of events,
   6303 				 * so return an error for sender dry events
   6304 				 */
   6305 				if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
   6306 				    ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
   6307 				    ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
   6308 				    ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
   6309 				     (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
   6310 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
   6311 					error = ENOTSUP;
   6312 					break;
   6313 				}
   6314 				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   6315 				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   6316 				    (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
   6317 				    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
   6318 					SCTP_INP_WLOCK(inp);
   6319 					if (event->se_on) {
   6320 						sctp_feature_on(inp, event_type);
   6321 					} else {
   6322 						sctp_feature_off(inp, event_type);
   6323 					}
   6324 					SCTP_INP_WUNLOCK(inp);
   6325 				}
   6326 				if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
   6327 				    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
   6328 					SCTP_INP_RLOCK(inp);
   6329 					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   6330 						SCTP_TCB_LOCK(stcb);
   6331 						if (event->se_on) {
   6332 							sctp_stcb_feature_on(inp, stcb, event_type);
   6333 						} else {
   6334 							sctp_stcb_feature_off(inp, stcb, event_type);
   6335 						}
   6336 						SCTP_TCB_UNLOCK(stcb);
   6337 					}
   6338 					SCTP_INP_RUNLOCK(inp);
   6339 				}
   6340 			}
   6341 		}
   6342 		break;
   6343 	}
   6344 	case SCTP_RECVRCVINFO:
   6345 	{
   6346 		int *onoff;
   6347 
   6348 		SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
   6349 		SCTP_INP_WLOCK(inp);
   6350 		if (*onoff != 0) {
   6351 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
   6352 		} else {
   6353 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
   6354 		}
   6355 		SCTP_INP_WUNLOCK(inp);
   6356 		break;
   6357 	}
   6358 	case SCTP_RECVNXTINFO:
   6359 	{
   6360 		int *onoff;
   6361 
   6362 		SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
   6363 		SCTP_INP_WLOCK(inp);
   6364 		if (*onoff != 0) {
   6365 			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
   6366 		} else {
   6367 			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
   6368 		}
   6369 		SCTP_INP_WUNLOCK(inp);
   6370 		break;
   6371 	}
   6372 	case SCTP_DEFAULT_SNDINFO:
   6373 	{
   6374 		struct sctp_sndinfo *info;
   6375 		uint16_t policy;
   6376 
   6377 		SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
   6378 		SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
   6379 
   6380 		if (stcb) {
   6381 			if (info->snd_sid < stcb->asoc.streamoutcnt) {
   6382 				stcb->asoc.def_send.sinfo_stream = info->snd_sid;
   6383 				policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
   6384 				stcb->asoc.def_send.sinfo_flags = info->snd_flags;
   6385 				stcb->asoc.def_send.sinfo_flags |= policy;
   6386 				stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
   6387 				stcb->asoc.def_send.sinfo_context = info->snd_context;
   6388 			} else {
   6389 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6390 				error = EINVAL;
   6391 			}
   6392 			SCTP_TCB_UNLOCK(stcb);
   6393 		} else {
   6394 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   6395 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   6396 			    (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
   6397 			    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
   6398 				SCTP_INP_WLOCK(inp);
   6399 				inp->def_send.sinfo_stream = info->snd_sid;
   6400 				policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
   6401 				inp->def_send.sinfo_flags = info->snd_flags;
   6402 				inp->def_send.sinfo_flags |= policy;
   6403 				inp->def_send.sinfo_ppid = info->snd_ppid;
   6404 				inp->def_send.sinfo_context = info->snd_context;
   6405 				SCTP_INP_WUNLOCK(inp);
   6406 			}
   6407 			if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
   6408 			    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
   6409 				SCTP_INP_RLOCK(inp);
   6410 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   6411 					SCTP_TCB_LOCK(stcb);
   6412 					if (info->snd_sid < stcb->asoc.streamoutcnt) {
   6413 						stcb->asoc.def_send.sinfo_stream = info->snd_sid;
   6414 						policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
   6415 						stcb->asoc.def_send.sinfo_flags = info->snd_flags;
   6416 						stcb->asoc.def_send.sinfo_flags |= policy;
   6417 						stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
   6418 						stcb->asoc.def_send.sinfo_context = info->snd_context;
   6419 					}
   6420 					SCTP_TCB_UNLOCK(stcb);
   6421 				}
   6422 				SCTP_INP_RUNLOCK(inp);
   6423 			}
   6424 		}
   6425 		break;
   6426 	}
   6427 	case SCTP_DEFAULT_PRINFO:
   6428 	{
   6429 		struct sctp_default_prinfo *info;
   6430 
   6431 		SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
   6432 		SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
   6433 
   6434 		if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
   6435 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6436 			error = EINVAL;
   6437 			break;
   6438 		}
   6439 		if (stcb) {
   6440 			stcb->asoc.def_send.sinfo_flags &= 0xfff0;
   6441 			stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
   6442 			stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
   6443 			SCTP_TCB_UNLOCK(stcb);
   6444 		} else {
   6445 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   6446 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   6447 			    (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
   6448 			    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
   6449 				SCTP_INP_WLOCK(inp);
   6450 				inp->def_send.sinfo_flags &= 0xfff0;
   6451 				inp->def_send.sinfo_flags |= info->pr_policy;
   6452 				inp->def_send.sinfo_timetolive = info->pr_value;
   6453 				SCTP_INP_WUNLOCK(inp);
   6454 			}
   6455 			if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
   6456 			    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
   6457 				SCTP_INP_RLOCK(inp);
   6458 				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
   6459 					SCTP_TCB_LOCK(stcb);
   6460 					stcb->asoc.def_send.sinfo_flags &= 0xfff0;
   6461 					stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
   6462 					stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
   6463 					SCTP_TCB_UNLOCK(stcb);
   6464 				}
   6465 				SCTP_INP_RUNLOCK(inp);
   6466 			}
   6467 		}
   6468 		break;
   6469 	}
   6470 	case SCTP_PEER_ADDR_THLDS:
   6471 		/* Applies to the specific association */
   6472 	{
   6473 		struct sctp_paddrthlds *thlds;
   6474 		struct sctp_nets *net;
   6475 
   6476 		SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
   6477 		SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
   6478 		net = NULL;
   6479 		if (stcb) {
   6480 			net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_assoc_id);
   6481 		} else {
   6482 			/* We increment here since sctp_findassociation_ep_addr() wil
   6483 			 * do a decrement if it finds the stcb as long as the locked
   6484 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   6485 			 */
   6486 			SCTP_INP_INCR_REF(inp);
   6487 			stcb = sctp_findassociation_ep_addr(&inp,
   6488 							    (struct sockaddr *)&thlds->spt_assoc_id,
   6489 							    &net, NULL, NULL);
   6490 			if (stcb == NULL) {
   6491 				SCTP_INP_DECR_REF(inp);
   6492 			}
   6493 		}
   6494 		if (stcb && (net == NULL)) {
   6495 			struct sockaddr *sa;
   6496 
   6497 			sa = (struct sockaddr *)&thlds->spt_assoc_id;
   6498 #ifdef INET
   6499 			if (sa->sa_family == AF_INET) {
   6500 
   6501 				struct sockaddr_in *sin;
   6502 				sin = (struct sockaddr_in *)sa;
   6503 				if (sin->sin_addr.s_addr) {
   6504 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6505 					SCTP_TCB_UNLOCK(stcb);
   6506 					error = EINVAL;
   6507 					break;
   6508 				}
   6509 			} else
   6510 #endif
   6511 #ifdef INET6
   6512 			if (sa->sa_family == AF_INET6) {
   6513 				struct sockaddr_in6 *sin6;
   6514 
   6515 				sin6 = (struct sockaddr_in6 *)sa;
   6516 				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   6517 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6518 					SCTP_TCB_UNLOCK(stcb);
   6519 					error = EINVAL;
   6520 					break;
   6521 				}
   6522 			} else
   6523 #endif
   6524 #if defined(__Userspace__)
   6525 			if (sa->sa_family == AF_CONN) {
   6526 				struct sockaddr_conn *sconn;
   6527 
   6528 				sconn = (struct sockaddr_conn *)sa;
   6529 				if (sconn->sconn_addr != NULL) {
   6530 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6531 					SCTP_TCB_UNLOCK(stcb);
   6532 					error = EINVAL;
   6533 					break;
   6534 				}
   6535 			} else
   6536 #endif
   6537 			{
   6538 				error = EAFNOSUPPORT;
   6539 				SCTP_TCB_UNLOCK(stcb);
   6540 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6541 				break;
   6542 			}
   6543 		}
   6544 		if (stcb) {
   6545 			if (net) {
   6546 				if (net->dest_state & SCTP_ADDR_PF) {
   6547 					if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
   6548 					    (net->failure_threshold <= thlds->spt_pathpfthld)) {
   6549 						net->dest_state &= ~SCTP_ADDR_PF;
   6550 					}
   6551 				} else {
   6552 					if ((net->failure_threshold > thlds->spt_pathpfthld) &&
   6553 					    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
   6554 					    	net->dest_state |= SCTP_ADDR_PF;
   6555 						sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
   6556 						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
   6557 						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
   6558 					}
   6559 				}
   6560 				if (net->dest_state & SCTP_ADDR_REACHABLE) {
   6561 					if (net->failure_threshold > thlds->spt_pathmaxrxt) {
   6562 						net->dest_state &= ~SCTP_ADDR_REACHABLE;
   6563 						sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
   6564 					}
   6565 				} else {
   6566 					if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
   6567 						net->dest_state |= SCTP_ADDR_REACHABLE;
   6568 						sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
   6569 					}
   6570 				}
   6571 				net->failure_threshold = thlds->spt_pathmaxrxt;
   6572 				net->pf_threshold = thlds->spt_pathpfthld;
   6573 			} else {
   6574 				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   6575 					if (net->dest_state & SCTP_ADDR_PF) {
   6576 						if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
   6577 						    (net->failure_threshold <= thlds->spt_pathpfthld)) {
   6578 							net->dest_state &= ~SCTP_ADDR_PF;
   6579 						}
   6580 					} else {
   6581 						if ((net->failure_threshold > thlds->spt_pathpfthld) &&
   6582 						    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
   6583 						    	net->dest_state |= SCTP_ADDR_PF;
   6584 							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
   6585 							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
   6586 							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
   6587 						}
   6588 					}
   6589 					if (net->dest_state & SCTP_ADDR_REACHABLE) {
   6590 						if (net->failure_threshold > thlds->spt_pathmaxrxt) {
   6591 							net->dest_state &= ~SCTP_ADDR_REACHABLE;
   6592 							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
   6593 						}
   6594 					} else {
   6595 						if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
   6596 							net->dest_state |= SCTP_ADDR_REACHABLE;
   6597 							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
   6598 						}
   6599 					}
   6600 					net->failure_threshold = thlds->spt_pathmaxrxt;
   6601 					net->pf_threshold = thlds->spt_pathpfthld;
   6602 				}
   6603 				stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
   6604 				stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
   6605 			}
   6606 		} else {
   6607 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   6608 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   6609 			    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
   6610 				SCTP_INP_WLOCK(inp);
   6611 				inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
   6612 				inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
   6613 				SCTP_INP_WUNLOCK(inp);
   6614 			} else {
   6615 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6616 				error = EINVAL;
   6617 			}
   6618 		}
   6619 		break;
   6620 	}
   6621 	case SCTP_REMOTE_UDP_ENCAPS_PORT:
   6622 	{
   6623 		struct sctp_udpencaps *encaps;
   6624 		struct sctp_nets *net;
   6625 
   6626 		SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
   6627 		SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
   6628 		if (stcb) {
   6629 			net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
   6630 		} else {
   6631 			/* We increment here since sctp_findassociation_ep_addr() wil
   6632 			 * do a decrement if it finds the stcb as long as the locked
   6633 			 * tcb (last argument) is NOT a TCB.. aka NULL.
   6634 			 */
   6635 			net = NULL;
   6636 			SCTP_INP_INCR_REF(inp);
   6637 			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
   6638 			if (stcb == NULL) {
   6639 				SCTP_INP_DECR_REF(inp);
   6640 			}
   6641 		}
   6642 		if (stcb && (net == NULL)) {
   6643 			struct sockaddr *sa;
   6644 
   6645 			sa = (struct sockaddr *)&encaps->sue_address;
   6646 #ifdef INET
   6647 			if (sa->sa_family == AF_INET) {
   6648 
   6649 				struct sockaddr_in *sin;
   6650 				sin = (struct sockaddr_in *)sa;
   6651 				if (sin->sin_addr.s_addr) {
   6652 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6653 					SCTP_TCB_UNLOCK(stcb);
   6654 					error = EINVAL;
   6655 					break;
   6656 				}
   6657 			} else
   6658 #endif
   6659 #ifdef INET6
   6660 			if (sa->sa_family == AF_INET6) {
   6661 				struct sockaddr_in6 *sin6;
   6662 
   6663 				sin6 = (struct sockaddr_in6 *)sa;
   6664 				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
   6665 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6666 					SCTP_TCB_UNLOCK(stcb);
   6667 					error = EINVAL;
   6668 					break;
   6669 				}
   6670 			} else
   6671 #endif
   6672 #if defined(__Userspace__)
   6673 			if (sa->sa_family == AF_CONN) {
   6674 				struct sockaddr_conn *sconn;
   6675 
   6676 				sconn = (struct sockaddr_conn *)sa;
   6677 				if (sconn->sconn_addr != NULL) {
   6678 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6679 					SCTP_TCB_UNLOCK(stcb);
   6680 					error = EINVAL;
   6681 					break;
   6682 				}
   6683 			} else
   6684 #endif
   6685 			{
   6686 					error = EAFNOSUPPORT;
   6687 					SCTP_TCB_UNLOCK(stcb);
   6688 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6689 					break;
   6690 				}
   6691 		}
   6692 
   6693 		if (stcb) {
   6694 			if (net) {
   6695 				net->port = encaps->sue_port;
   6696 			} else {
   6697 				stcb->asoc.port = encaps->sue_port;
   6698 			}
   6699 			SCTP_TCB_UNLOCK(stcb);
   6700 		} else {
   6701 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   6702 			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
   6703 			    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
   6704 				SCTP_INP_WLOCK(inp);
   6705 				inp->sctp_ep.port = encaps->sue_port;
   6706 				SCTP_INP_WUNLOCK(inp);
   6707 			} else {
   6708 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6709 				error = EINVAL;
   6710 			}
   6711 		}
   6712 		break;
   6713 	}
   6714 	default:
   6715 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
   6716 		error = ENOPROTOOPT;
   6717 		break;
   6718 	} /* end switch (opt) */
   6719 	return (error);
   6720 }
   6721 
   6722 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   6723 int
   6724 sctp_ctloutput(struct socket *so, struct sockopt *sopt)
   6725 {
   6726 	void *optval = NULL;
   6727 	size_t optsize = 0;
   6728 	void *p;
   6729 	int error = 0;
   6730 
   6731 	if (sopt->sopt_level != IPPROTO_SCTP) {
   6732 		/* wrong proto level... send back up to IP */
   6733 #ifdef INET6
   6734 		if (INP_CHECK_SOCKAF(so, AF_INET6))
   6735 			error = ip6_ctloutput(so, sopt);
   6736 #endif				/* INET6 */
   6737 #if defined(INET) && defined(INET6)
   6738 		else
   6739 #endif
   6740 #ifdef INET
   6741 			error = ip_ctloutput(so, sopt);
   6742 #endif
   6743 		return (error);
   6744 	}
   6745 	optsize = sopt->sopt_valsize;
   6746 	if (optsize) {
   6747 		SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
   6748 		if (optval == NULL) {
   6749 			SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
   6750 			return (ENOBUFS);
   6751 		}
   6752 		error = sooptcopyin(sopt, optval, optsize, optsize);
   6753 		if (error) {
   6754 			SCTP_FREE(optval, SCTP_M_SOCKOPT);
   6755 			goto out;
   6756 		}
   6757 	}
   6758 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__Windows__)
   6759 	p = (void *)sopt->sopt_td;
   6760 #else
   6761 	p = (void *)sopt->sopt_p;
   6762 #endif
   6763 	if (sopt->sopt_dir == SOPT_SET) {
   6764 		error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
   6765 	} else if (sopt->sopt_dir == SOPT_GET) {
   6766 		error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
   6767 	} else {
   6768 		SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6769 		error = EINVAL;
   6770 	}
   6771 	if ((error == 0) && (optval != NULL)) {
   6772 		error = sooptcopyout(sopt, optval, optsize);
   6773 		SCTP_FREE(optval, SCTP_M_SOCKOPT);
   6774 	} else if (optval != NULL) {
   6775 		SCTP_FREE(optval, SCTP_M_SOCKOPT);
   6776 	}
   6777 out:
   6778 	return (error);
   6779 }
   6780 #endif
   6781 
   6782 #ifdef INET
   6783 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
   6784 static int
   6785 sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
   6786 {
   6787 #else
   6788 #if defined(__FreeBSD__) || defined(__APPLE__)
   6789 static int
   6790 sctp_connect(struct socket *so, struct sockaddr *addr, struct proc *p)
   6791 {
   6792 #elif defined(__Panda__) || defined(__Userspace__)
   6793 int
   6794 sctp_connect(struct socket *so, struct sockaddr *addr)
   6795 {
   6796 	void *p = NULL;
   6797 #elif defined(__Windows__)
   6798 static int
   6799 sctp_connect(struct socket *so, struct sockaddr *addr, PKTHREAD p)
   6800 {
   6801 #else
   6802 static int
   6803 sctp_connect(struct socket *so, struct mbuf *nam, struct proc *p)
   6804 {
   6805 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
   6806 
   6807 #endif
   6808 #endif
   6809 #ifdef SCTP_MVRF
   6810 	int i, fnd = 0;
   6811 #endif
   6812 	int error = 0;
   6813 	int create_lock_on = 0;
   6814 	uint32_t vrf_id;
   6815 	struct sctp_inpcb *inp;
   6816 	struct sctp_tcb *stcb = NULL;
   6817 
   6818 	inp = (struct sctp_inpcb *)so->so_pcb;
   6819 	if (inp == NULL) {
   6820 		/* I made the same as TCP since we are not setup? */
   6821 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6822 		return (ECONNRESET);
   6823 	}
   6824 	if (addr == NULL) {
   6825 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6826 		return EINVAL;
   6827 	}
   6828 
   6829 #if defined(__Userspace__)
   6830         /* TODO __Userspace__ falls into this code for IPv6 stuff at the moment... */
   6831 #endif
   6832 #if !defined(__Windows__) && !defined(__Userspace_os_Linux) && !defined(__Userspace_os_Windows)
   6833 	switch (addr->sa_family) {
   6834 #ifdef INET6
   6835 	case AF_INET6:
   6836 	{
   6837 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   6838 		struct sockaddr_in6 *sin6p;
   6839 
   6840 #endif
   6841 		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
   6842 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6843 			return (EINVAL);
   6844 		}
   6845 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   6846 		sin6p = (struct sockaddr_in6 *)addr;
   6847 		if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
   6848 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6849 			return (error);
   6850 		}
   6851 #endif
   6852 		break;
   6853 	}
   6854 #endif
   6855 #ifdef INET
   6856 	case AF_INET:
   6857 	{
   6858 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   6859 		struct sockaddr_in *sinp;
   6860 
   6861 #endif
   6862 #if !defined(__Userspace_os_Windows)
   6863 		if (addr->sa_len != sizeof(struct sockaddr_in)) {
   6864 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6865 			return (EINVAL);
   6866 		}
   6867 #endif
   6868 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
   6869 		sinp = (struct sockaddr_in *)addr;
   6870 		if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
   6871 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
   6872 			return (error);
   6873 		}
   6874 #endif
   6875 		break;
   6876 	}
   6877 #endif
   6878 	default:
   6879 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
   6880  		return (EAFNOSUPPORT);
   6881 	}
   6882 #endif
   6883 	SCTP_INP_INCR_REF(inp);
   6884 	SCTP_ASOC_CREATE_LOCK(inp);
   6885 	create_lock_on = 1;
   6886 
   6887 
   6888 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
   6889 	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
   6890 		/* Should I really unlock ? */
   6891 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
   6892 	        error = EFAULT;
   6893 		goto out_now;
   6894 	}
   6895 #ifdef INET6
   6896 	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
   6897 	    (addr->sa_family == AF_INET6)) {
   6898 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6899 		error = EINVAL;
   6900 		goto out_now;
   6901 	}
   6902 #endif
   6903 #if defined(__Userspace__)
   6904 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) &&
   6905 	    (addr->sa_family != AF_CONN)) {
   6906 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6907 		error = EINVAL;
   6908 		goto out_now;
   6909 	}
   6910 #endif
   6911 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
   6912 	    SCTP_PCB_FLAGS_UNBOUND) {
   6913 		/* Bind a ephemeral port */
   6914 		error = sctp_inpcb_bind(so, NULL, NULL, p);
   6915 		if (error) {
   6916 			goto out_now;
   6917 		}
   6918 	}
   6919 	/* Now do we connect? */
   6920 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
   6921 	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
   6922 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6923 		error = EINVAL;
   6924 		goto out_now;
   6925 	}
   6926 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
   6927 	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
   6928 		/* We are already connected AND the TCP model */
   6929 		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
   6930 		error = EADDRINUSE;
   6931 		goto out_now;
   6932 	}
   6933 	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
   6934 		SCTP_INP_RLOCK(inp);
   6935 		stcb = LIST_FIRST(&inp->sctp_asoc_list);
   6936 		SCTP_INP_RUNLOCK(inp);
   6937 	} else {
   6938 		/* We increment here since sctp_findassociation_ep_addr() will
   6939 		 * do a decrement if it finds the stcb as long as the locked
   6940 		 * tcb (last argument) is NOT a TCB.. aka NULL.
   6941 		 */
   6942 		SCTP_INP_INCR_REF(inp);
   6943 		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
   6944 		if (stcb == NULL) {
   6945 			SCTP_INP_DECR_REF(inp);
   6946 		} else {
   6947 			SCTP_TCB_UNLOCK(stcb);
   6948 		}
   6949 	}
   6950 	if (stcb != NULL) {
   6951 		/* Already have or am bring up an association */
   6952 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   6953 		error = EALREADY;
   6954 		goto out_now;
   6955 	}
   6956 
   6957 	vrf_id = inp->def_vrf_id;
   6958 #ifdef SCTP_MVRF
   6959 	for (i = 0; i < inp->num_vrfs; i++) {
   6960 		if (vrf_id == inp->m_vrf_ids[i]) {
   6961 			fnd = 1;
   6962 			break;
   6963 		}
   6964 	}
   6965 	if (!fnd) {
   6966 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   6967 		error = EINVAL;
   6968 		goto out_now;
   6969 	}
   6970 #endif
   6971 	/* We are GOOD to go */
   6972 	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
   6973 	if (stcb == NULL) {
   6974 		/* Gak! no memory */
   6975 		goto out_now;
   6976 	}
   6977 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
   6978 		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
   6979 		/* Set the connected flag so we can queue data */
   6980 		soisconnecting(so);
   6981 	}
   6982 	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
   6983 	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
   6984 
   6985 	/* initialize authentication parameters for the assoc */
   6986 	sctp_initialize_auth_params(inp, stcb);
   6987 
   6988 	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
   6989 	SCTP_TCB_UNLOCK(stcb);
   6990  out_now:
   6991 	if (create_lock_on) {
   6992 		SCTP_ASOC_CREATE_UNLOCK(inp);
   6993 	}
   6994 
   6995 	SCTP_INP_DECR_REF(inp);
   6996 	return (error);
   6997 }
   6998 #endif
   6999 
   7000 #if defined(__Userspace__)
   7001 int
   7002 sctpconn_connect(struct socket *so, struct sockaddr *addr)
   7003 {
   7004 #ifdef SCTP_MVRF
   7005 	int i, fnd = 0;
   7006 #endif
   7007 	void *p = NULL;
   7008 	int error = 0;
   7009 	int create_lock_on = 0;
   7010 	uint32_t vrf_id;
   7011 	struct sctp_inpcb *inp;
   7012 	struct sctp_tcb *stcb = NULL;
   7013 
   7014 	inp = (struct sctp_inpcb *)so->so_pcb;
   7015 	if (inp == NULL) {
   7016 		/* I made the same as TCP since we are not setup? */
   7017 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7018 		return (ECONNRESET);
   7019 	}
   7020 	if (addr == NULL) {
   7021 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7022 		return EINVAL;
   7023 	}
   7024 	switch (addr->sa_family) {
   7025 #ifdef INET
   7026 	case AF_INET:
   7027 #ifdef HAVE_SA_LEN
   7028 		if (addr->sa_len != sizeof(struct sockaddr_in)) {
   7029 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7030 			return (EINVAL);
   7031 		}
   7032 #endif
   7033 		break;
   7034 #endif
   7035 #ifdef INET6
   7036 	case AF_INET6:
   7037 #ifdef HAVE_SA_LEN
   7038 		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
   7039 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7040 			return (EINVAL);
   7041 		}
   7042 #endif
   7043 		break;
   7044 #endif
   7045 	case AF_CONN:
   7046 #ifdef HAVE_SA_LEN
   7047 		if (addr->sa_len != sizeof(struct sockaddr_conn)) {
   7048 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7049 			return (EINVAL);
   7050 		}
   7051 #endif
   7052 		break;
   7053 	default:
   7054 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
   7055  		return (EAFNOSUPPORT);
   7056 	}
   7057 	SCTP_INP_INCR_REF(inp);
   7058 	SCTP_ASOC_CREATE_LOCK(inp);
   7059 	create_lock_on = 1;
   7060 
   7061 
   7062 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
   7063 	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
   7064 		/* Should I really unlock ? */
   7065 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
   7066 	        error = EFAULT;
   7067 		goto out_now;
   7068 	}
   7069 #ifdef INET6
   7070 	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
   7071 	    (addr->sa_family == AF_INET6)) {
   7072 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7073 		error = EINVAL;
   7074 		goto out_now;
   7075 	}
   7076 #endif
   7077 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == SCTP_PCB_FLAGS_UNBOUND) {
   7078 		/* Bind a ephemeral port */
   7079 		error = sctp_inpcb_bind(so, NULL, NULL, p);
   7080 		if (error) {
   7081 			goto out_now;
   7082 		}
   7083 	}
   7084 	/* Now do we connect? */
   7085 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
   7086 	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
   7087 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7088 		error = EINVAL;
   7089 		goto out_now;
   7090 	}
   7091 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
   7092 	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
   7093 		/* We are already connected AND the TCP model */
   7094 		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
   7095 		error = EADDRINUSE;
   7096 		goto out_now;
   7097 	}
   7098 	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
   7099 		SCTP_INP_RLOCK(inp);
   7100 		stcb = LIST_FIRST(&inp->sctp_asoc_list);
   7101 		SCTP_INP_RUNLOCK(inp);
   7102 	} else {
   7103 		/* We increment here since sctp_findassociation_ep_addr() will
   7104 		 * do a decrement if it finds the stcb as long as the locked
   7105 		 * tcb (last argument) is NOT a TCB.. aka NULL.
   7106 		 */
   7107 		SCTP_INP_INCR_REF(inp);
   7108 		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
   7109 		if (stcb == NULL) {
   7110 			SCTP_INP_DECR_REF(inp);
   7111 		} else {
   7112 			SCTP_TCB_UNLOCK(stcb);
   7113 		}
   7114 	}
   7115 	if (stcb != NULL) {
   7116 		/* Already have or am bring up an association */
   7117 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
   7118 		error = EALREADY;
   7119 		goto out_now;
   7120 	}
   7121 
   7122 	vrf_id = inp->def_vrf_id;
   7123 #ifdef SCTP_MVRF
   7124 	for (i = 0; i < inp->num_vrfs; i++) {
   7125 		if (vrf_id == inp->m_vrf_ids[i]) {
   7126 			fnd = 1;
   7127 			break;
   7128 		}
   7129 	}
   7130 	if (!fnd) {
   7131 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7132 		error = EINVAL;
   7133 		goto out_now;
   7134 	}
   7135 #endif
   7136 	/* We are GOOD to go */
   7137 	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
   7138 	if (stcb == NULL) {
   7139 		/* Gak! no memory */
   7140 		goto out_now;
   7141 	}
   7142 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
   7143 		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
   7144 		/* Set the connected flag so we can queue data */
   7145 		soisconnecting(so);
   7146 	}
   7147 	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
   7148 	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
   7149 
   7150 	/* initialize authentication parameters for the assoc */
   7151 	sctp_initialize_auth_params(inp, stcb);
   7152 
   7153 	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
   7154 	SCTP_TCB_UNLOCK(stcb);
   7155  out_now:
   7156 	if (create_lock_on) {
   7157 		SCTP_ASOC_CREATE_UNLOCK(inp);
   7158 	}
   7159 
   7160 	SCTP_INP_DECR_REF(inp);
   7161 	return (error);
   7162 }
   7163 #endif
   7164 int
   7165 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
   7166 #if __FreeBSD_version >= 700000
   7167 sctp_listen(struct socket *so, int backlog, struct thread *p)
   7168 #else
   7169 sctp_listen(struct socket *so, struct thread *p)
   7170 #endif
   7171 #elif defined(__Windows__)
   7172 sctp_listen(struct socket *so, int backlog, PKTHREAD p)
   7173 #elif defined(__Userspace__)
   7174 sctp_listen(struct socket *so, int backlog, struct proc *p)
   7175 #else
   7176 sctp_listen(struct socket *so, struct proc *p)
   7177 #endif
   7178 {
   7179 	/*
   7180 	 * Note this module depends on the protocol processing being called
   7181 	 * AFTER any socket level flags and backlog are applied to the
   7182 	 * socket. The traditional way that the socket flags are applied is
   7183 	 * AFTER protocol processing. We have made a change to the
   7184 	 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
   7185 	 * place if the socket API for SCTP is to work properly.
   7186 	 */
   7187 
   7188 	int error = 0;
   7189 	struct sctp_inpcb *inp;
   7190 
   7191 	inp = (struct sctp_inpcb *)so->so_pcb;
   7192 	if (inp == NULL) {
   7193 		/* I made the same as TCP since we are not setup? */
   7194 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7195 		return (ECONNRESET);
   7196 	}
   7197 	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
   7198 		/* See if we have a listener */
   7199 		struct sctp_inpcb *tinp;
   7200 		union sctp_sockstore store, *sp;
   7201 
   7202 		sp = &store;
   7203 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
   7204 			/* not bound all */
   7205 			struct sctp_laddr *laddr;
   7206 
   7207 			LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
   7208 				memcpy(&store, &laddr->ifa->address, sizeof(store));
   7209 				switch (sp->sa.sa_family) {
   7210 #ifdef INET
   7211 				case AF_INET:
   7212 					sp->sin.sin_port = inp->sctp_lport;
   7213 					break;
   7214 #endif
   7215 #ifdef INET6
   7216 				case AF_INET6:
   7217 					sp->sin6.sin6_port = inp->sctp_lport;
   7218 					break;
   7219 #endif
   7220 #if defined(__Userspace__)
   7221 				case AF_CONN:
   7222 					sp->sconn.sconn_port = inp->sctp_lport;
   7223 					break;
   7224 #endif
   7225 				default:
   7226 					break;
   7227 				}
   7228 				tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
   7229 				if (tinp && (tinp != inp) &&
   7230 				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
   7231 				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
   7232 				    (tinp->sctp_socket->so_qlimit)) {
   7233 					/* we have a listener already and its not this inp. */
   7234 					SCTP_INP_DECR_REF(tinp);
   7235 					return (EADDRINUSE);
   7236 				} else if (tinp) {
   7237 					SCTP_INP_DECR_REF(tinp);
   7238 				}
   7239 			}
   7240 		} else {
   7241 			/* Setup a local addr bound all */
   7242 			memset(&store, 0, sizeof(store));
   7243 			switch (sp->sa.sa_family) {
   7244 #ifdef INET
   7245 			case AF_INET:
   7246 				store.sin.sin_port = inp->sctp_lport;
   7247 				break;
   7248 #endif
   7249 #ifdef INET6
   7250 			case AF_INET6:
   7251 				sp->sin6.sin6_port = inp->sctp_lport;
   7252 				break;
   7253 #endif
   7254 #if defined(__Userspace__)
   7255 			case AF_CONN:
   7256 				sp->sconn.sconn_port = inp->sctp_lport;
   7257 				break;
   7258 #endif
   7259 			default:
   7260 				break;
   7261 			}
   7262 #ifdef INET6
   7263 			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   7264 				store.sa.sa_family = AF_INET6;
   7265 #ifdef HAVE_SA_LEN
   7266 				store.sa.sa_len = sizeof(struct sockaddr_in6);
   7267 #endif
   7268 			}
   7269 #endif
   7270 #ifdef INET
   7271 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
   7272 				store.sa.sa_family = AF_INET;
   7273 #ifdef HAVE_SA_LEN
   7274 				store.sa.sa_len = sizeof(struct sockaddr_in);
   7275 #endif
   7276 			}
   7277 #endif
   7278 			tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
   7279 			if (tinp && (tinp != inp) &&
   7280 			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
   7281 			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
   7282 			    (tinp->sctp_socket->so_qlimit)) {
   7283 				/* we have a listener already and its not this inp. */
   7284 				SCTP_INP_DECR_REF(tinp);
   7285 				return (EADDRINUSE);
   7286 			} else if (tinp) {
   7287 				SCTP_INP_DECR_REF(inp);
   7288 			}
   7289 		}
   7290 	}
   7291 	SCTP_INP_RLOCK(inp);
   7292 #ifdef SCTP_LOCK_LOGGING
   7293 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
   7294 		sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
   7295 	}
   7296 #endif
   7297 	SOCK_LOCK(so);
   7298 #if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Userspace__)
   7299 	error = solisten_proto_check(so);
   7300 	if (error) {
   7301 		SOCK_UNLOCK(so);
   7302 		SCTP_INP_RUNLOCK(inp);
   7303 		return (error);
   7304 	}
   7305 #endif
   7306 	if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
   7307 	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
   7308 		/* The unlucky case
   7309 		 * - We are in the tcp pool with this guy.
   7310 		 * - Someone else is in the main inp slot.
   7311 		 * - We must move this guy (the listener) to the main slot
   7312 		 * - We must then move the guy that was listener to the TCP Pool.
   7313 		 */
   7314 		if (sctp_swap_inpcb_for_listen(inp)) {
   7315 			goto in_use;
   7316 		}
   7317 	}
   7318 
   7319 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
   7320 	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
   7321 		/* We are already connected AND the TCP model */
   7322 	in_use:
   7323 		SCTP_INP_RUNLOCK(inp);
   7324 		SOCK_UNLOCK(so);
   7325 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
   7326 		return (EADDRINUSE);
   7327 	}
   7328 	SCTP_INP_RUNLOCK(inp);
   7329 	if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
   7330 		/* We must do a bind. */
   7331 		SOCK_UNLOCK(so);
   7332 		if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
   7333 			/* bind error, probably perm */
   7334 			return (error);
   7335 		}
   7336 		SOCK_LOCK(so);
   7337 	}
   7338 #if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__) || defined(__Userspace__)
   7339 #if __FreeBSD_version >= 700000 || defined(__Windows__) || defined(__Userspace__)
   7340 	/* It appears for 7.0 and on, we must always call this. */
   7341 	solisten_proto(so, backlog);
   7342 #else
   7343 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) == 0) {
   7344 		solisten_proto(so);
   7345 	}
   7346 #endif
   7347 #endif
   7348 	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
   7349 		/* remove the ACCEPTCONN flag for one-to-many sockets */
   7350 #if defined(__Userspace__)
   7351 		so->so_options &= ~SCTP_SO_ACCEPTCONN;
   7352 #else
   7353 		so->so_options &= ~SO_ACCEPTCONN;
   7354 #endif
   7355 	}
   7356 
   7357 #if __FreeBSD_version >= 700000 || defined(__Windows__) || defined(__Userspace__)
   7358 	if (backlog == 0) {
   7359 		/* turning off listen */
   7360 #if defined(__Userspace__)
   7361 		so->so_options &= ~SCTP_SO_ACCEPTCONN;
   7362 #else
   7363 		so->so_options &= ~SO_ACCEPTCONN;
   7364 #endif
   7365 	}
   7366 #endif
   7367 	SOCK_UNLOCK(so);
   7368 	return (error);
   7369 }
   7370 
   7371 static int sctp_defered_wakeup_cnt = 0;
   7372 
   7373 int
   7374 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
   7375 sctp_accept(struct socket *so, struct sockaddr **addr)
   7376 {
   7377 #elif defined(__Panda__)
   7378 sctp_accept(struct socket *so, struct sockaddr *addr, int *namelen,
   7379 	    void *accept_info, int *accept_info_len)
   7380 {
   7381 #else
   7382 sctp_accept(struct socket *so, struct mbuf *nam)
   7383 {
   7384 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
   7385 #endif
   7386 	struct sctp_tcb *stcb;
   7387 	struct sctp_inpcb *inp;
   7388 	union sctp_sockstore store;
   7389 #ifdef INET6
   7390 #ifdef SCTP_KAME
   7391 	int error;
   7392 #endif /* SCTP_KAME */
   7393 #endif
   7394 	inp = (struct sctp_inpcb *)so->so_pcb;
   7395 
   7396 	if (inp == NULL) {
   7397 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7398 		return (ECONNRESET);
   7399 	}
   7400 	SCTP_INP_RLOCK(inp);
   7401 	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
   7402 		SCTP_INP_RUNLOCK(inp);
   7403 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
   7404 		return (EOPNOTSUPP);
   7405 	}
   7406 	if (so->so_state & SS_ISDISCONNECTED) {
   7407 		SCTP_INP_RUNLOCK(inp);
   7408 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
   7409 		return (ECONNABORTED);
   7410 	}
   7411 	stcb = LIST_FIRST(&inp->sctp_asoc_list);
   7412 	if (stcb == NULL) {
   7413 		SCTP_INP_RUNLOCK(inp);
   7414 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7415 		return (ECONNRESET);
   7416 	}
   7417 	SCTP_TCB_LOCK(stcb);
   7418 	SCTP_INP_RUNLOCK(inp);
   7419 	store = stcb->asoc.primary_destination->ro._l_addr;
   7420 	stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
   7421 	SCTP_TCB_UNLOCK(stcb);
   7422 	switch (store.sa.sa_family) {
   7423 #ifdef INET
   7424 	case AF_INET:
   7425 	{
   7426 		struct sockaddr_in *sin;
   7427 
   7428 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
   7429 		SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
   7430 		if (sin == NULL)
   7431 			return (ENOMEM);
   7432 #else
   7433 		sin = (struct sockaddr_in *)addr;
   7434 		bzero((caddr_t)sin, sizeof(*sin));
   7435 #endif
   7436 		sin->sin_family = AF_INET;
   7437 #ifdef HAVE_SIN_LEN
   7438 		sin->sin_len = sizeof(*sin);
   7439 #endif
   7440 		sin->sin_port = store.sin.sin_port;
   7441 		sin->sin_addr = store.sin.sin_addr;
   7442 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
   7443 		*addr = (struct sockaddr *)sin;
   7444 #elif !defined(__Panda__)
   7445 		SCTP_BUF_LEN(nam) = sizeof(*sin);
   7446 #endif
   7447 		break;
   7448 	}
   7449 #endif
   7450 #ifdef INET6
   7451 	case AF_INET6:
   7452 	{
   7453 		struct sockaddr_in6 *sin6;
   7454 
   7455 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
   7456 		SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
   7457 		if (sin6 == NULL)
   7458 			return (ENOMEM);
   7459 #else
   7460 		sin6 = (struct sockaddr_in6 *)addr;
   7461 		bzero((caddr_t)sin6, sizeof(*sin6));
   7462 #endif
   7463 		sin6->sin6_family = AF_INET6;
   7464 #ifdef HAVE_SIN6_LEN
   7465 		sin6->sin6_len = sizeof(*sin6);
   7466 #endif
   7467 		sin6->sin6_port = store.sin6.sin6_port;
   7468 		sin6->sin6_addr = store.sin6.sin6_addr;
   7469 #if defined(SCTP_EMBEDDED_V6_SCOPE)
   7470 #ifdef SCTP_KAME
   7471 		if ((error = sa6_recoverscope(sin6)) != 0) {
   7472 			SCTP_FREE_SONAME(sin6);
   7473 			return (error);
   7474 		}
   7475 #else
   7476 		if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
   7477 			/*
   7478 			 * sin6->sin6_scope_id =
   7479 			 * ntohs(sin6->sin6_addr.s6_addr16[1]);
   7480 			 */
   7481 			in6_recoverscope(sin6, &sin6->sin6_addr, NULL);	/* skip ifp check */
   7482 		else
   7483 			sin6->sin6_scope_id = 0;	/* XXX */
   7484 #endif /* SCTP_KAME */
   7485 #endif /* SCTP_EMBEDDED_V6_SCOPE */
   7486 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
   7487 		*addr = (struct sockaddr *)sin6;
   7488 #elif !defined(__Panda__)
   7489 		SCTP_BUF_LEN(nam) = sizeof(*sin6);
   7490 #endif
   7491 		break;
   7492 	}
   7493 #endif
   7494 #if defined(__Userspace__)
   7495 	case AF_CONN:
   7496 	{
   7497 		struct sockaddr_conn *sconn;
   7498 
   7499 		SCTP_MALLOC_SONAME(sconn, struct sockaddr_conn *, sizeof(struct sockaddr_conn));
   7500 		if (sconn == NULL) {
   7501 			return (ENOMEM);
   7502 		}
   7503 		sconn->sconn_family = AF_CONN;
   7504 #ifdef HAVE_SCONN_LEN
   7505 		sconn->sconn_len = sizeof(struct sockaddr_conn);
   7506 #endif
   7507 		sconn->sconn_port = store.sconn.sconn_port;
   7508 		sconn->sconn_addr = store.sconn.sconn_addr;
   7509 		*addr = (struct sockaddr *)sconn;
   7510 		break;
   7511 	}
   7512 #endif
   7513 	default:
   7514 		/* TSNH */
   7515 		break;
   7516 	}
   7517 	/* Wake any delayed sleep action */
   7518 	if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
   7519 		SCTP_INP_WLOCK(inp);
   7520 		inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
   7521 		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
   7522 			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
   7523 			SCTP_INP_WUNLOCK(inp);
   7524 			SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
   7525 			if (sowriteable(inp->sctp_socket)) {
   7526 #if defined(__Userspace__)
   7527                             /*__Userspace__ calling sowwakup_locked because of SOCKBUF_LOCK above. */
   7528 #endif
   7529 #if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
   7530 				sowwakeup_locked(inp->sctp_socket);
   7531 #else
   7532 #if defined(__APPLE__)
   7533 				/* socket is locked */
   7534 #endif
   7535 				sowwakeup(inp->sctp_socket);
   7536 #endif
   7537 			} else {
   7538 				SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
   7539 			}
   7540 			SCTP_INP_WLOCK(inp);
   7541 		}
   7542 		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
   7543 			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
   7544 			SCTP_INP_WUNLOCK(inp);
   7545 			SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
   7546 			if (soreadable(inp->sctp_socket)) {
   7547 				sctp_defered_wakeup_cnt++;
   7548 #if defined(__Userspace__)
   7549                                 /*__Userspace__ calling sorwakup_locked because of SOCKBUF_LOCK above */
   7550 #endif
   7551 #if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
   7552 				sorwakeup_locked(inp->sctp_socket);
   7553 #else
   7554 #if defined(__APPLE__)
   7555 				/* socket is locked */
   7556 #endif
   7557 				sorwakeup(inp->sctp_socket);
   7558 #endif
   7559 			} else {
   7560 				SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
   7561 			}
   7562 			SCTP_INP_WLOCK(inp);
   7563 		}
   7564 		SCTP_INP_WUNLOCK(inp);
   7565 	}
   7566 	if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
   7567 		SCTP_TCB_LOCK(stcb);
   7568 		sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7);
   7569 	}
   7570 	return (0);
   7571 }
   7572 
   7573 #ifdef INET
   7574 int
   7575 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   7576 sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
   7577 {
   7578 	struct sockaddr_in *sin;
   7579 #elif defined(__Panda__)
   7580 sctp_ingetaddr(struct socket *so, struct sockaddr *addr)
   7581 {
   7582 	struct sockaddr_in *sin = (struct sockaddr_in *)addr;
   7583 #else
   7584 sctp_ingetaddr(struct socket *so, struct mbuf *nam)
   7585 {
   7586 	struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
   7587 #endif
   7588 	uint32_t vrf_id;
   7589 	struct sctp_inpcb *inp;
   7590 	struct sctp_ifa *sctp_ifa;
   7591 
   7592 	/*
   7593 	 * Do the malloc first in case it blocks.
   7594 	 */
   7595 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   7596 	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
   7597 	if (sin == NULL)
   7598 		return (ENOMEM);
   7599 #elif defined(__Panda__)
   7600 	bzero(sin, sizeof(*sin));
   7601 #else
   7602 	SCTP_BUF_LEN(nam) = sizeof(*sin);
   7603 	memset(sin, 0, sizeof(*sin));
   7604 #endif
   7605 	sin->sin_family = AF_INET;
   7606 #ifdef HAVE_SIN_LEN
   7607 	sin->sin_len = sizeof(*sin);
   7608 #endif
   7609 	inp = (struct sctp_inpcb *)so->so_pcb;
   7610 	if (!inp) {
   7611 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   7612 		SCTP_FREE_SONAME(sin);
   7613 #endif
   7614 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7615 		return (ECONNRESET);
   7616 	}
   7617 	SCTP_INP_RLOCK(inp);
   7618 	sin->sin_port = inp->sctp_lport;
   7619 	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
   7620 		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
   7621 			struct sctp_tcb *stcb;
   7622 			struct sockaddr_in *sin_a;
   7623 			struct sctp_nets *net;
   7624 			int fnd;
   7625 
   7626 			stcb = LIST_FIRST(&inp->sctp_asoc_list);
   7627 			if (stcb == NULL) {
   7628 				goto notConn;
   7629 			}
   7630 			fnd = 0;
   7631 			sin_a = NULL;
   7632 			SCTP_TCB_LOCK(stcb);
   7633 			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   7634 				sin_a = (struct sockaddr_in *)&net->ro._l_addr;
   7635 				if (sin_a == NULL)
   7636 					/* this will make coverity happy */
   7637 					continue;
   7638 
   7639 				if (sin_a->sin_family == AF_INET) {
   7640 					fnd = 1;
   7641 					break;
   7642 				}
   7643 			}
   7644 			if ((!fnd) || (sin_a == NULL)) {
   7645 				/* punt */
   7646 				SCTP_TCB_UNLOCK(stcb);
   7647 				goto notConn;
   7648 			}
   7649 
   7650 			vrf_id = inp->def_vrf_id;
   7651 			sctp_ifa = sctp_source_address_selection(inp,
   7652 								 stcb,
   7653 								 (sctp_route_t *)&net->ro,
   7654 								 net, 0, vrf_id);
   7655 			if (sctp_ifa) {
   7656 				sin->sin_addr = sctp_ifa->address.sin.sin_addr;
   7657 				sctp_free_ifa(sctp_ifa);
   7658 			}
   7659 			SCTP_TCB_UNLOCK(stcb);
   7660 		} else {
   7661 			/* For the bound all case you get back 0 */
   7662 	notConn:
   7663 			sin->sin_addr.s_addr = 0;
   7664 		}
   7665 
   7666 	} else {
   7667 		/* Take the first IPv4 address in the list */
   7668 		struct sctp_laddr *laddr;
   7669 		int fnd = 0;
   7670 
   7671 		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
   7672 			if (laddr->ifa->address.sa.sa_family == AF_INET) {
   7673 				struct sockaddr_in *sin_a;
   7674 
   7675 				sin_a = (struct sockaddr_in *)&laddr->ifa->address.sa;
   7676 				sin->sin_addr = sin_a->sin_addr;
   7677 				fnd = 1;
   7678 				break;
   7679 			}
   7680 		}
   7681 		if (!fnd) {
   7682 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   7683 			SCTP_FREE_SONAME(sin);
   7684 #endif
   7685 			SCTP_INP_RUNLOCK(inp);
   7686 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   7687 			return (ENOENT);
   7688 		}
   7689 	}
   7690 	SCTP_INP_RUNLOCK(inp);
   7691 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   7692 	(*addr) = (struct sockaddr *)sin;
   7693 #endif
   7694 	return (0);
   7695 }
   7696 
   7697 int
   7698 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   7699 sctp_peeraddr(struct socket *so, struct sockaddr **addr)
   7700 {
   7701 	struct sockaddr_in *sin;
   7702 #elif defined(__Panda__)
   7703 sctp_peeraddr(struct socket *so, struct sockaddr *addr)
   7704 {
   7705 	struct sockaddr_in *sin = (struct sockaddr_in *)addr;
   7706 #else
   7707 sctp_peeraddr(struct socket *so, struct mbuf *nam)
   7708 {
   7709 	struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
   7710 
   7711 #endif
   7712 	int fnd;
   7713 	struct sockaddr_in *sin_a;
   7714 	struct sctp_inpcb *inp;
   7715 	struct sctp_tcb *stcb;
   7716 	struct sctp_nets *net;
   7717 
   7718 	/* Do the malloc first in case it blocks. */
   7719 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   7720 	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
   7721 	if (sin == NULL)
   7722 		return (ENOMEM);
   7723 #elif defined(__Panda__)
   7724 	memset(sin, 0, sizeof(*sin));
   7725 #else
   7726 	SCTP_BUF_LEN(nam) = sizeof(*sin);
   7727 	memset(sin, 0, sizeof(*sin));
   7728 #endif
   7729 	sin->sin_family = AF_INET;
   7730 #ifdef HAVE_SIN_LEN
   7731 	sin->sin_len = sizeof(*sin);
   7732 #endif
   7733 
   7734 	inp = (struct sctp_inpcb *)so->so_pcb;
   7735 	if ((inp == NULL) ||
   7736 	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
   7737 		/* UDP type and listeners will drop out here */
   7738 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   7739 		SCTP_FREE_SONAME(sin);
   7740 #endif
   7741 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
   7742 		return (ENOTCONN);
   7743 	}
   7744 	SCTP_INP_RLOCK(inp);
   7745 	stcb = LIST_FIRST(&inp->sctp_asoc_list);
   7746 	if (stcb) {
   7747 		SCTP_TCB_LOCK(stcb);
   7748 	}
   7749 	SCTP_INP_RUNLOCK(inp);
   7750 	if (stcb == NULL) {
   7751 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   7752 		SCTP_FREE_SONAME(sin);
   7753 #endif
   7754 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7755 		return (ECONNRESET);
   7756 	}
   7757 	fnd = 0;
   7758 	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   7759 		sin_a = (struct sockaddr_in *)&net->ro._l_addr;
   7760 		if (sin_a->sin_family == AF_INET) {
   7761 			fnd = 1;
   7762 			sin->sin_port = stcb->rport;
   7763 			sin->sin_addr = sin_a->sin_addr;
   7764 			break;
   7765 		}
   7766 	}
   7767 	SCTP_TCB_UNLOCK(stcb);
   7768 	if (!fnd) {
   7769 		/* No IPv4 address */
   7770 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   7771 		SCTP_FREE_SONAME(sin);
   7772 #endif
   7773 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
   7774 		return (ENOENT);
   7775 	}
   7776 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   7777 	(*addr) = (struct sockaddr *)sin;
   7778 #endif
   7779 	return (0);
   7780 }
   7781 
   7782 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
   7783 struct pr_usrreqs sctp_usrreqs = {
   7784 #if defined(__FreeBSD__)
   7785 	.pru_abort = sctp_abort,
   7786 	.pru_accept = sctp_accept,
   7787 	.pru_attach = sctp_attach,
   7788 	.pru_bind = sctp_bind,
   7789 	.pru_connect = sctp_connect,
   7790 	.pru_control = in_control,
   7791 #if __FreeBSD_version >= 690000
   7792 	.pru_close = sctp_close,
   7793 	.pru_detach = sctp_close,
   7794 	.pru_sopoll = sopoll_generic,
   7795 	.pru_flush = sctp_flush,
   7796 #else
   7797 	.pru_detach = sctp_detach,
   7798 	.pru_sopoll = sopoll,
   7799 #endif
   7800 	.pru_disconnect = sctp_disconnect,
   7801 	.pru_listen = sctp_listen,
   7802 	.pru_peeraddr = sctp_peeraddr,
   7803 	.pru_send = sctp_sendm,
   7804 	.pru_shutdown = sctp_shutdown,
   7805 	.pru_sockaddr = sctp_ingetaddr,
   7806 	.pru_sosend = sctp_sosend,
   7807 	.pru_soreceive = sctp_soreceive
   7808 #elif defined(__APPLE__)
   7809 	.pru_abort = sctp_abort,
   7810 	.pru_accept = sctp_accept,
   7811 	.pru_attach = sctp_attach,
   7812 	.pru_bind = sctp_bind,
   7813 	.pru_connect = sctp_connect,
   7814 	.pru_connect2 = pru_connect2_notsupp,
   7815 	.pru_control = in_control,
   7816 	.pru_detach = sctp_detach,
   7817 	.pru_disconnect = sctp_disconnect,
   7818 	.pru_listen = sctp_listen,
   7819 	.pru_peeraddr = sctp_peeraddr,
   7820 	.pru_rcvd = NULL,
   7821 	.pru_rcvoob = pru_rcvoob_notsupp,
   7822 	.pru_send = sctp_sendm,
   7823 	.pru_sense = pru_sense_null,
   7824 	.pru_shutdown = sctp_shutdown,
   7825 	.pru_sockaddr = sctp_ingetaddr,
   7826 	.pru_sosend = sctp_sosend,
   7827 	.pru_soreceive = sctp_soreceive,
   7828 	.pru_sopoll = sopoll
   7829 #elif defined(__Windows__)
   7830 	sctp_abort,
   7831 	sctp_accept,
   7832 	sctp_attach,
   7833 	sctp_bind,
   7834 	sctp_connect,
   7835 	pru_connect2_notsupp,
   7836 	NULL,
   7837 	NULL,
   7838 	sctp_disconnect,
   7839 	sctp_listen,
   7840 	sctp_peeraddr,
   7841 	NULL,
   7842 	pru_rcvoob_notsupp,
   7843 	NULL,
   7844 	pru_sense_null,
   7845 	sctp_shutdown,
   7846 	sctp_flush,
   7847 	sctp_ingetaddr,
   7848 	sctp_sosend,
   7849 	sctp_soreceive,
   7850 	sopoll_generic,
   7851 	NULL,
   7852 	sctp_close
   7853 #endif
   7854 };
   7855 #elif !defined(__Panda__) && !defined(__Userspace__)
   7856 int
   7857 sctp_usrreq(so, req, m, nam, control)
   7858 	struct socket *so;
   7859 	int req;
   7860 	struct mbuf *m, *nam, *control;
   7861 {
   7862 	struct proc *p = curproc;
   7863 	uint32_t vrf_id;
   7864 	struct sctp_vrf *vrf;
   7865 	int error;
   7866 	int family;
   7867 	struct sctp_inpcb *inp = (struct sctp_inpcb *)so->so_pcb;
   7868 
   7869 	error = 0;
   7870 	family = so->so_proto->pr_domain->dom_family;
   7871 	if (req == PRU_CONTROL) {
   7872 		switch (family) {
   7873 		case PF_INET:
   7874 			error = in_control(so, (long)m, (caddr_t)nam,
   7875 			    (struct ifnet *)control);
   7876 			break;
   7877 #ifdef INET6
   7878 		case PF_INET6:
   7879 			error = in6_control(so, (long)m, (caddr_t)nam,
   7880 			    (struct ifnet *)control, p);
   7881 			break;
   7882 #endif
   7883 		default:
   7884 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
   7885 			error = EAFNOSUPPORT;
   7886 		}
   7887 		return (error);
   7888 	}
   7889 	switch (req) {
   7890 	case PRU_ATTACH:
   7891 		error = sctp_attach(so, family, p);
   7892 		break;
   7893 	case PRU_DETACH:
   7894 		error = sctp_detach(so);
   7895 		break;
   7896 	case PRU_BIND:
   7897 		if (nam == NULL) {
   7898 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7899 			return (EINVAL);
   7900 		}
   7901 		error = sctp_bind(so, nam, p);
   7902 		break;
   7903 	case PRU_LISTEN:
   7904 		error = sctp_listen(so, p);
   7905 		break;
   7906 	case PRU_CONNECT:
   7907 		if (nam == NULL) {
   7908 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7909 			return (EINVAL);
   7910 		}
   7911 		error = sctp_connect(so, nam, p);
   7912 		break;
   7913 	case PRU_DISCONNECT:
   7914 		error = sctp_disconnect(so);
   7915 		break;
   7916 	case PRU_ACCEPT:
   7917 		if (nam == NULL) {
   7918 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
   7919 			return (EINVAL);
   7920 		}
   7921 		error = sctp_accept(so, nam);
   7922 		break;
   7923 	case PRU_SHUTDOWN:
   7924 		error = sctp_shutdown(so);
   7925 		break;
   7926 
   7927 	case PRU_RCVD:
   7928 		/*
   7929 		 * For Open and Net BSD, this is real ugly. The mbuf *nam
   7930 		 * that is passed (by soreceive()) is the int flags c ast as
   7931 		 * a (mbuf *) yuck!
   7932 		 */
   7933 		break;
   7934 
   7935 	case PRU_SEND:
   7936 		/* Flags are ignored */
   7937 		{
   7938 			struct sockaddr *addr;
   7939 
   7940 			if (nam == NULL)
   7941 				addr = NULL;
   7942 			else
   7943 				addr = mtod(nam, struct sockaddr *);
   7944 
   7945 			error = sctp_sendm(so, 0, m, addr, control, p);
   7946 		}
   7947 		break;
   7948 	case PRU_ABORT:
   7949 		error = sctp_abort(so);
   7950 		break;
   7951 
   7952 	case PRU_SENSE:
   7953 		error = 0;
   7954 		break;
   7955 	case PRU_RCVOOB:
   7956 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
   7957 		error = EAFNOSUPPORT;
   7958 		break;
   7959 	case PRU_SENDOOB:
   7960 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
   7961 		error = EAFNOSUPPORT;
   7962 		break;
   7963 	case PRU_PEERADDR:
   7964 		error = sctp_peeraddr(so, nam);
   7965 		break;
   7966 	case PRU_SOCKADDR:
   7967 		error = sctp_ingetaddr(so, nam);
   7968 		break;
   7969 	case PRU_SLOWTIMO:
   7970 		error = 0;
   7971 		break;
   7972 	default:
   7973 		break;
   7974 	}
   7975 	return (error);
   7976 }
   7977 
   7978 #endif
   7979 #endif
   7980 
   7981 #if defined(__Userspace__)
   7982 int
   7983 register_recv_cb(struct socket *so,
   7984                  int (*receive_cb)(struct socket *sock, union sctp_sockstore addr, void *data,
   7985                  size_t datalen, struct sctp_rcvinfo, int flags, void *ulp_info))
   7986 {
   7987 	struct sctp_inpcb *inp;
   7988 
   7989 	inp = (struct sctp_inpcb *) so->so_pcb;
   7990 	if (inp == NULL) {
   7991 		return (0);
   7992 	}
   7993 	SCTP_INP_WLOCK(inp);
   7994 	inp->recv_callback = receive_cb;
   7995 	SCTP_INP_WUNLOCK(inp);
   7996 	return (1);
   7997 }
   7998 
   7999 int
   8000 register_send_cb(struct socket *so, uint32_t sb_threshold, int (*send_cb)(struct socket *sock, uint32_t sb_free))
   8001 {
   8002 	struct sctp_inpcb *inp;
   8003 
   8004 	inp = (struct sctp_inpcb *) so->so_pcb;
   8005 	if (inp == NULL) {
   8006 		return (0);
   8007 	}
   8008 	SCTP_INP_WLOCK(inp);
   8009 	inp->send_callback = send_cb;
   8010 	inp->send_sb_threshold = sb_threshold;
   8011 	SCTP_INP_WUNLOCK(inp);
   8012 	/* FIXME change to current amount free. This will be the full buffer
   8013 	 * the first time this is registered but it could be only a portion
   8014 	 * of the send buffer if this is called a second time e.g. if the
   8015 	 * threshold changes.
   8016 	 */
   8017 	return (1);
   8018 }
   8019 
   8020 int
   8021 register_ulp_info (struct socket *so, void *ulp_info)
   8022 {
   8023 	struct sctp_inpcb *inp;
   8024 
   8025 	inp = (struct sctp_inpcb *) so->so_pcb;
   8026 	if (inp == NULL) {
   8027 		return (0);
   8028 	}
   8029 	SCTP_INP_WLOCK(inp);
   8030 	inp->ulp_info = ulp_info;
   8031 	SCTP_INP_WUNLOCK(inp);
   8032 	return (1);
   8033 }
   8034 #endif
   8035