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