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