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