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