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