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