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