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