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