sctp_usrreq.c revision 223697
1/*-
2 * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
3 * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved.
4 * Copyright (c) 2008-2011, by Michael Tuexen. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * a) Redistributions of source code must retain the above copyright notice,
10 *   this list of conditions and the following disclaimer.
11 *
12 * b) Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in
14 *   the documentation and/or other materials provided with the distribution.
15 *
16 * c) Neither the name of Cisco Systems, Inc. nor the names of its
17 *    contributors may be used to endorse or promote products derived
18 *    from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/* $KAME: sctp_usrreq.c,v 1.48 2005/03/07 23:26:08 itojun Exp $	 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 223697 2011-06-30 16:56:55Z tuexen $");
37#include <netinet/sctp_os.h>
38#include <sys/proc.h>
39#include <netinet/sctp_pcb.h>
40#include <netinet/sctp_header.h>
41#include <netinet/sctp_var.h>
42#if defined(INET6)
43#endif
44#include <netinet/sctp_sysctl.h>
45#include <netinet/sctp_output.h>
46#include <netinet/sctp_uio.h>
47#include <netinet/sctp_asconf.h>
48#include <netinet/sctputil.h>
49#include <netinet/sctp_indata.h>
50#include <netinet/sctp_timer.h>
51#include <netinet/sctp_auth.h>
52#include <netinet/sctp_bsd_addr.h>
53#include <netinet/udp.h>
54
55
56
57extern struct sctp_cc_functions sctp_cc_functions[];
58extern struct sctp_ss_functions sctp_ss_functions[];
59
60void
61sctp_init(void)
62{
63	u_long sb_max_adj;
64
65	/* Initialize and modify the sysctled variables */
66	sctp_init_sysctls();
67	if ((nmbclusters / 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
68		SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = (nmbclusters / 8);
69	/*
70	 * Allow a user to take no more than 1/2 the number of clusters or
71	 * the SB_MAX whichever is smaller for the send window.
72	 */
73	sb_max_adj = (u_long)((u_quad_t) (SB_MAX) * MCLBYTES / (MSIZE + MCLBYTES));
74	SCTP_BASE_SYSCTL(sctp_sendspace) = min(sb_max_adj,
75	    (((uint32_t) nmbclusters / 2) * SCTP_DEFAULT_MAXSEGMENT));
76	/*
77	 * Now for the recv window, should we take the same amount? or
78	 * should I do 1/2 the SB_MAX instead in the SB_MAX min above. For
79	 * now I will just copy.
80	 */
81	SCTP_BASE_SYSCTL(sctp_recvspace) = SCTP_BASE_SYSCTL(sctp_sendspace);
82
83	SCTP_BASE_VAR(first_time) = 0;
84	SCTP_BASE_VAR(sctp_pcb_initialized) = 0;
85	sctp_pcb_init();
86#if defined(SCTP_PACKET_LOGGING)
87	SCTP_BASE_VAR(packet_log_writers) = 0;
88	SCTP_BASE_VAR(packet_log_end) = 0;
89	bzero(&SCTP_BASE_VAR(packet_log_buffer), SCTP_PACKET_LOG_SIZE);
90#endif
91
92
93}
94
95void
96sctp_finish(void)
97{
98	sctp_pcb_finish();
99}
100
101
102
103void
104sctp_pathmtu_adjustment(struct sctp_inpcb *inp,
105    struct sctp_tcb *stcb,
106    struct sctp_nets *net,
107    uint16_t nxtsz)
108{
109	struct sctp_tmit_chunk *chk;
110	uint16_t overhead;
111
112	/* Adjust that too */
113	stcb->asoc.smallest_mtu = nxtsz;
114	/* now off to subtract IP_DF flag if needed */
115	overhead = IP_HDR_SIZE;
116	if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
117		overhead += sctp_get_auth_chunk_len(stcb->asoc.peer_hmac_id);
118	}
119	TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
120		if ((chk->send_size + overhead) > nxtsz) {
121			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
122		}
123	}
124	TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
125		if ((chk->send_size + overhead) > nxtsz) {
126			/*
127			 * For this guy we also mark for immediate resend
128			 * since we sent to big of chunk
129			 */
130			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
131			if (chk->sent < SCTP_DATAGRAM_RESEND) {
132				sctp_flight_size_decrease(chk);
133				sctp_total_flight_decrease(stcb, chk);
134			}
135			if (chk->sent != SCTP_DATAGRAM_RESEND) {
136				sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
137			}
138			chk->sent = SCTP_DATAGRAM_RESEND;
139			chk->rec.data.doing_fast_retransmit = 0;
140			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
141				sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
142				    chk->whoTo->flight_size,
143				    chk->book_size,
144				    (uintptr_t) chk->whoTo,
145				    chk->rec.data.TSN_seq);
146			}
147			/* Clear any time so NO RTT is being done */
148			chk->do_rtt = 0;
149		}
150	}
151}
152
153#ifdef INET
154static void
155sctp_notify_mbuf(struct sctp_inpcb *inp,
156    struct sctp_tcb *stcb,
157    struct sctp_nets *net,
158    struct ip *ip,
159    struct sctphdr *sh)
160{
161	struct icmp *icmph;
162	int totsz, tmr_stopped = 0;
163	uint16_t nxtsz;
164
165	/* protection */
166	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
167	    (ip == NULL) || (sh == NULL)) {
168		if (stcb != NULL) {
169			SCTP_TCB_UNLOCK(stcb);
170		}
171		return;
172	}
173	/* First job is to verify the vtag matches what I would send */
174	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
175		SCTP_TCB_UNLOCK(stcb);
176		return;
177	}
178	icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
179	    sizeof(struct ip)));
180	if (icmph->icmp_type != ICMP_UNREACH) {
181		/* We only care about unreachable */
182		SCTP_TCB_UNLOCK(stcb);
183		return;
184	}
185	if (icmph->icmp_code != ICMP_UNREACH_NEEDFRAG) {
186		/* not a unreachable message due to frag. */
187		SCTP_TCB_UNLOCK(stcb);
188		return;
189	}
190	totsz = ip->ip_len;
191
192	nxtsz = ntohs(icmph->icmp_nextmtu);
193	if (nxtsz == 0) {
194		/*
195		 * old type router that does not tell us what the next size
196		 * mtu is. Rats we will have to guess (in a educated fashion
197		 * of course)
198		 */
199		nxtsz = sctp_get_prev_mtu(totsz);
200	}
201	/* Stop any PMTU timer */
202	if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
203		tmr_stopped = 1;
204		sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
205		    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1);
206	}
207	/* Adjust destination size limit */
208	if (net->mtu > nxtsz) {
209		net->mtu = nxtsz;
210		if (net->port) {
211			net->mtu -= sizeof(struct udphdr);
212		}
213	}
214	/* now what about the ep? */
215	if (stcb->asoc.smallest_mtu > nxtsz) {
216		sctp_pathmtu_adjustment(inp, stcb, net, nxtsz);
217	}
218	if (tmr_stopped)
219		sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
220
221	SCTP_TCB_UNLOCK(stcb);
222}
223
224#endif
225
226void
227sctp_notify(struct sctp_inpcb *inp,
228    struct ip *ip,
229    struct sctphdr *sh,
230    struct sockaddr *to,
231    struct sctp_tcb *stcb,
232    struct sctp_nets *net)
233{
234#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
235	struct socket *so;
236
237#endif
238	/* protection */
239	int reason;
240	struct icmp *icmph;
241
242
243	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
244	    (sh == NULL) || (to == NULL)) {
245		if (stcb)
246			SCTP_TCB_UNLOCK(stcb);
247		return;
248	}
249	/* First job is to verify the vtag matches what I would send */
250	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
251		SCTP_TCB_UNLOCK(stcb);
252		return;
253	}
254	icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
255	    sizeof(struct ip)));
256	if (icmph->icmp_type != ICMP_UNREACH) {
257		/* We only care about unreachable */
258		SCTP_TCB_UNLOCK(stcb);
259		return;
260	}
261	if ((icmph->icmp_code == ICMP_UNREACH_NET) ||
262	    (icmph->icmp_code == ICMP_UNREACH_HOST) ||
263	    (icmph->icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
264	    (icmph->icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
265	    (icmph->icmp_code == ICMP_UNREACH_ISOLATED) ||
266	    (icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) ||
267	    (icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
268	    (icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
269
270		/*
271		 * Hmm reachablity problems we must examine closely. If its
272		 * not reachable, we may have lost a network. Or if there is
273		 * NO protocol at the other end named SCTP. well we consider
274		 * it a OOTB abort.
275		 */
276		if (net->dest_state & SCTP_ADDR_REACHABLE) {
277			/* Ok that destination is NOT reachable */
278			SCTP_PRINTF("ICMP (thresh %d/%d) takes interface %p down\n",
279			    net->error_count,
280			    net->failure_threshold,
281			    net);
282
283			net->dest_state &= ~SCTP_ADDR_REACHABLE;
284			net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
285			/*
286			 * JRS 5/14/07 - If a destination is unreachable,
287			 * the PF bit is turned off.  This allows an
288			 * unambiguous use of the PF bit for destinations
289			 * that are reachable but potentially failed. If the
290			 * destination is set to the unreachable state, also
291			 * set the destination to the PF state.
292			 */
293			/*
294			 * Add debug message here if destination is not in
295			 * PF state.
296			 */
297			/* Stop any running T3 timers here? */
298			if ((stcb->asoc.sctp_cmt_on_off > 0) &&
299			    (stcb->asoc.sctp_cmt_pf > 0)) {
300				net->dest_state &= ~SCTP_ADDR_PF;
301				SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
302				    net);
303			}
304			net->error_count = net->failure_threshold + 1;
305			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
306			    stcb, SCTP_FAILED_THRESHOLD,
307			    (void *)net, SCTP_SO_NOT_LOCKED);
308		}
309		SCTP_TCB_UNLOCK(stcb);
310	} else if ((icmph->icmp_code == ICMP_UNREACH_PROTOCOL) ||
311	    (icmph->icmp_code == ICMP_UNREACH_PORT)) {
312		/*
313		 * Here the peer is either playing tricks on us, including
314		 * an address that belongs to someone who does not support
315		 * SCTP OR was a userland implementation that shutdown and
316		 * now is dead. In either case treat it like a OOTB abort
317		 * with no TCB
318		 */
319		reason = SCTP_PEER_FAULTY;
320		sctp_abort_notification(stcb, reason, SCTP_SO_NOT_LOCKED);
321#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
322		so = SCTP_INP_SO(inp);
323		atomic_add_int(&stcb->asoc.refcnt, 1);
324		SCTP_TCB_UNLOCK(stcb);
325		SCTP_SOCKET_LOCK(so, 1);
326		SCTP_TCB_LOCK(stcb);
327		atomic_subtract_int(&stcb->asoc.refcnt, 1);
328#endif
329		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
330#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
331		SCTP_SOCKET_UNLOCK(so, 1);
332		/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */
333#endif
334		/* no need to unlock here, since the TCB is gone */
335	} else {
336		SCTP_TCB_UNLOCK(stcb);
337	}
338}
339
340#ifdef INET
341void
342sctp_ctlinput(cmd, sa, vip)
343	int cmd;
344	struct sockaddr *sa;
345	void *vip;
346{
347	struct ip *ip = vip;
348	struct sctphdr *sh;
349	uint32_t vrf_id;
350
351	/* FIX, for non-bsd is this right? */
352	vrf_id = SCTP_DEFAULT_VRFID;
353	if (sa->sa_family != AF_INET ||
354	    ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
355		return;
356	}
357	if (PRC_IS_REDIRECT(cmd)) {
358		ip = 0;
359	} else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
360		return;
361	}
362	if (ip) {
363		struct sctp_inpcb *inp = NULL;
364		struct sctp_tcb *stcb = NULL;
365		struct sctp_nets *net = NULL;
366		struct sockaddr_in to, from;
367
368		sh = (struct sctphdr *)((caddr_t)ip + (ip->ip_hl << 2));
369		bzero(&to, sizeof(to));
370		bzero(&from, sizeof(from));
371		from.sin_family = to.sin_family = AF_INET;
372		from.sin_len = to.sin_len = sizeof(to);
373		from.sin_port = sh->src_port;
374		from.sin_addr = ip->ip_src;
375		to.sin_port = sh->dest_port;
376		to.sin_addr = ip->ip_dst;
377
378		/*
379		 * 'to' holds the dest of the packet that failed to be sent.
380		 * 'from' holds our local endpoint address. Thus we reverse
381		 * the to and the from in the lookup.
382		 */
383		stcb = sctp_findassociation_addr_sa((struct sockaddr *)&from,
384		    (struct sockaddr *)&to,
385		    &inp, &net, 1, vrf_id);
386		if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
387			if (cmd != PRC_MSGSIZE) {
388				sctp_notify(inp, ip, sh,
389				    (struct sockaddr *)&to, stcb,
390				    net);
391			} else {
392				/* handle possible ICMP size messages */
393				sctp_notify_mbuf(inp, stcb, net, ip, sh);
394			}
395		} else {
396			if ((stcb == NULL) && (inp != NULL)) {
397				/* reduce ref-count */
398				SCTP_INP_WLOCK(inp);
399				SCTP_INP_DECR_REF(inp);
400				SCTP_INP_WUNLOCK(inp);
401			}
402			if (stcb) {
403				SCTP_TCB_UNLOCK(stcb);
404			}
405		}
406	}
407	return;
408}
409
410#endif
411
412static int
413sctp_getcred(SYSCTL_HANDLER_ARGS)
414{
415	struct xucred xuc;
416	struct sockaddr_in addrs[2];
417	struct sctp_inpcb *inp;
418	struct sctp_nets *net;
419	struct sctp_tcb *stcb;
420	int error;
421	uint32_t vrf_id;
422
423	/* FIX, for non-bsd is this right? */
424	vrf_id = SCTP_DEFAULT_VRFID;
425
426	error = priv_check(req->td, PRIV_NETINET_GETCRED);
427
428	if (error)
429		return (error);
430
431	error = SYSCTL_IN(req, addrs, sizeof(addrs));
432	if (error)
433		return (error);
434
435	stcb = sctp_findassociation_addr_sa(sintosa(&addrs[0]),
436	    sintosa(&addrs[1]),
437	    &inp, &net, 1, vrf_id);
438	if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
439		if ((inp != NULL) && (stcb == NULL)) {
440			/* reduce ref-count */
441			SCTP_INP_WLOCK(inp);
442			SCTP_INP_DECR_REF(inp);
443			goto cred_can_cont;
444		}
445		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
446		error = ENOENT;
447		goto out;
448	}
449	SCTP_TCB_UNLOCK(stcb);
450	/*
451	 * We use the write lock here, only since in the error leg we need
452	 * it. If we used RLOCK, then we would have to
453	 * wlock/decr/unlock/rlock. Which in theory could create a hole.
454	 * Better to use higher wlock.
455	 */
456	SCTP_INP_WLOCK(inp);
457cred_can_cont:
458	error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
459	if (error) {
460		SCTP_INP_WUNLOCK(inp);
461		goto out;
462	}
463	cru2x(inp->sctp_socket->so_cred, &xuc);
464	SCTP_INP_WUNLOCK(inp);
465	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
466out:
467	return (error);
468}
469
470SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
471    0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection");
472
473
474#ifdef INET
475static void
476sctp_abort(struct socket *so)
477{
478	struct sctp_inpcb *inp;
479	uint32_t flags;
480
481	inp = (struct sctp_inpcb *)so->so_pcb;
482	if (inp == 0) {
483		return;
484	}
485sctp_must_try_again:
486	flags = inp->sctp_flags;
487#ifdef SCTP_LOG_CLOSING
488	sctp_log_closing(inp, NULL, 17);
489#endif
490	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
491	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
492#ifdef SCTP_LOG_CLOSING
493		sctp_log_closing(inp, NULL, 16);
494#endif
495		sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
496		    SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
497		SOCK_LOCK(so);
498		SCTP_SB_CLEAR(so->so_snd);
499		/*
500		 * same for the rcv ones, they are only here for the
501		 * accounting/select.
502		 */
503		SCTP_SB_CLEAR(so->so_rcv);
504
505		/* Now null out the reference, we are completely detached. */
506		so->so_pcb = NULL;
507		SOCK_UNLOCK(so);
508	} else {
509		flags = inp->sctp_flags;
510		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
511			goto sctp_must_try_again;
512		}
513	}
514	return;
515}
516
517static int
518sctp_attach(struct socket *so, int proto, struct thread *p)
519{
520	struct sctp_inpcb *inp;
521	struct inpcb *ip_inp;
522	int error;
523	uint32_t vrf_id = SCTP_DEFAULT_VRFID;
524
525#ifdef IPSEC
526	uint32_t flags;
527
528#endif
529
530	inp = (struct sctp_inpcb *)so->so_pcb;
531	if (inp != 0) {
532		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
533		return EINVAL;
534	}
535	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
536		error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
537		if (error) {
538			return error;
539		}
540	}
541	error = sctp_inpcb_alloc(so, vrf_id);
542	if (error) {
543		return error;
544	}
545	inp = (struct sctp_inpcb *)so->so_pcb;
546	SCTP_INP_WLOCK(inp);
547	inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6;	/* I'm not v6! */
548	ip_inp = &inp->ip_inp.inp;
549	ip_inp->inp_vflag |= INP_IPV4;
550	ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
551#ifdef IPSEC
552	error = ipsec_init_policy(so, &ip_inp->inp_sp);
553#ifdef SCTP_LOG_CLOSING
554	sctp_log_closing(inp, NULL, 17);
555#endif
556	if (error != 0) {
557try_again:
558		flags = inp->sctp_flags;
559		if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
560		    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
561#ifdef SCTP_LOG_CLOSING
562			sctp_log_closing(inp, NULL, 15);
563#endif
564			SCTP_INP_WUNLOCK(inp);
565			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
566			    SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
567		} else {
568			flags = inp->sctp_flags;
569			if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
570				goto try_again;
571			} else {
572				SCTP_INP_WUNLOCK(inp);
573			}
574		}
575		return error;
576	}
577#endif				/* IPSEC */
578	SCTP_INP_WUNLOCK(inp);
579	return 0;
580}
581
582static int
583sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
584{
585	struct sctp_inpcb *inp = NULL;
586	int error;
587
588#ifdef INET6
589	if (addr && addr->sa_family != AF_INET) {
590		/* must be a v4 address! */
591		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
592		return EINVAL;
593	}
594#endif				/* INET6 */
595	if (addr && (addr->sa_len != sizeof(struct sockaddr_in))) {
596		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
597		return EINVAL;
598	}
599	inp = (struct sctp_inpcb *)so->so_pcb;
600	if (inp == 0) {
601		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
602		return EINVAL;
603	}
604	error = sctp_inpcb_bind(so, addr, NULL, p);
605	return error;
606}
607
608#endif
609void
610sctp_close(struct socket *so)
611{
612	struct sctp_inpcb *inp;
613	uint32_t flags;
614
615	inp = (struct sctp_inpcb *)so->so_pcb;
616	if (inp == 0)
617		return;
618
619	/*
620	 * Inform all the lower layer assoc that we are done.
621	 */
622sctp_must_try_again:
623	flags = inp->sctp_flags;
624#ifdef SCTP_LOG_CLOSING
625	sctp_log_closing(inp, NULL, 17);
626#endif
627	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
628	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
629		if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
630		    (so->so_rcv.sb_cc > 0)) {
631#ifdef SCTP_LOG_CLOSING
632			sctp_log_closing(inp, NULL, 13);
633#endif
634			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
635			    SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
636		} else {
637#ifdef SCTP_LOG_CLOSING
638			sctp_log_closing(inp, NULL, 14);
639#endif
640			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
641			    SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
642		}
643		/*
644		 * The socket is now detached, no matter what the state of
645		 * the SCTP association.
646		 */
647		SOCK_LOCK(so);
648		SCTP_SB_CLEAR(so->so_snd);
649		/*
650		 * same for the rcv ones, they are only here for the
651		 * accounting/select.
652		 */
653		SCTP_SB_CLEAR(so->so_rcv);
654
655		/* Now null out the reference, we are completely detached. */
656		so->so_pcb = NULL;
657		SOCK_UNLOCK(so);
658	} else {
659		flags = inp->sctp_flags;
660		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
661			goto sctp_must_try_again;
662		}
663	}
664	return;
665}
666
667
668int
669sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
670    struct mbuf *control, struct thread *p);
671
672
673int
674sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
675    struct mbuf *control, struct thread *p)
676{
677	struct sctp_inpcb *inp;
678	int error;
679
680	inp = (struct sctp_inpcb *)so->so_pcb;
681	if (inp == 0) {
682		if (control) {
683			sctp_m_freem(control);
684			control = NULL;
685		}
686		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
687		sctp_m_freem(m);
688		return EINVAL;
689	}
690	/* Got to have an to address if we are NOT a connected socket */
691	if ((addr == NULL) &&
692	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) ||
693	    (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))
694	    ) {
695		goto connected_type;
696	} else if (addr == NULL) {
697		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
698		error = EDESTADDRREQ;
699		sctp_m_freem(m);
700		if (control) {
701			sctp_m_freem(control);
702			control = NULL;
703		}
704		return (error);
705	}
706#ifdef INET6
707	if (addr->sa_family != AF_INET) {
708		/* must be a v4 address! */
709		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
710		sctp_m_freem(m);
711		if (control) {
712			sctp_m_freem(control);
713			control = NULL;
714		}
715		error = EDESTADDRREQ;
716		return (error);
717	}
718#endif				/* INET6 */
719connected_type:
720	/* now what about control */
721	if (control) {
722		if (inp->control) {
723			SCTP_PRINTF("huh? control set?\n");
724			sctp_m_freem(inp->control);
725			inp->control = NULL;
726		}
727		inp->control = control;
728	}
729	/* Place the data */
730	if (inp->pkt) {
731		SCTP_BUF_NEXT(inp->pkt_last) = m;
732		inp->pkt_last = m;
733	} else {
734		inp->pkt_last = inp->pkt = m;
735	}
736	if (
737	/* FreeBSD uses a flag passed */
738	    ((flags & PRUS_MORETOCOME) == 0)
739	    ) {
740		/*
741		 * note with the current version this code will only be used
742		 * by OpenBSD-- NetBSD, FreeBSD, and MacOS have methods for
743		 * re-defining sosend to use the sctp_sosend. One can
744		 * optionally switch back to this code (by changing back the
745		 * definitions) but this is not advisable. This code is used
746		 * by FreeBSD when sending a file with sendfile() though.
747		 */
748		int ret;
749
750		ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
751		inp->pkt = NULL;
752		inp->control = NULL;
753		return (ret);
754	} else {
755		return (0);
756	}
757}
758
759int
760sctp_disconnect(struct socket *so)
761{
762	struct sctp_inpcb *inp;
763
764	inp = (struct sctp_inpcb *)so->so_pcb;
765	if (inp == NULL) {
766		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
767		return (ENOTCONN);
768	}
769	SCTP_INP_RLOCK(inp);
770	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
771	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
772		if (LIST_EMPTY(&inp->sctp_asoc_list)) {
773			/* No connection */
774			SCTP_INP_RUNLOCK(inp);
775			return (0);
776		} else {
777			struct sctp_association *asoc;
778			struct sctp_tcb *stcb;
779
780			stcb = LIST_FIRST(&inp->sctp_asoc_list);
781			if (stcb == NULL) {
782				SCTP_INP_RUNLOCK(inp);
783				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
784				return (EINVAL);
785			}
786			SCTP_TCB_LOCK(stcb);
787			asoc = &stcb->asoc;
788			if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
789				/* We are about to be freed, out of here */
790				SCTP_TCB_UNLOCK(stcb);
791				SCTP_INP_RUNLOCK(inp);
792				return (0);
793			}
794			if (((so->so_options & SO_LINGER) &&
795			    (so->so_linger == 0)) ||
796			    (so->so_rcv.sb_cc > 0)) {
797				if (SCTP_GET_STATE(asoc) !=
798				    SCTP_STATE_COOKIE_WAIT) {
799					/* Left with Data unread */
800					struct mbuf *err;
801
802					err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_DONTWAIT, 1, MT_DATA);
803					if (err) {
804						/*
805						 * Fill in the user
806						 * initiated abort
807						 */
808						struct sctp_paramhdr *ph;
809
810						ph = mtod(err, struct sctp_paramhdr *);
811						SCTP_BUF_LEN(err) = sizeof(struct sctp_paramhdr);
812						ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
813						ph->param_length = htons(SCTP_BUF_LEN(err));
814					}
815#if defined(SCTP_PANIC_ON_ABORT)
816					panic("disconnect does an abort");
817#endif
818					sctp_send_abort_tcb(stcb, err, SCTP_SO_LOCKED);
819					SCTP_STAT_INCR_COUNTER32(sctps_aborted);
820				}
821				SCTP_INP_RUNLOCK(inp);
822				if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
823				    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
824					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
825				}
826				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3);
827				/* No unlock tcb assoc is gone */
828				return (0);
829			}
830			if (TAILQ_EMPTY(&asoc->send_queue) &&
831			    TAILQ_EMPTY(&asoc->sent_queue) &&
832			    (asoc->stream_queue_cnt == 0)) {
833				/* there is nothing queued to send, so done */
834				if (asoc->locked_on_sending) {
835					goto abort_anyway;
836				}
837				if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
838				    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
839					/* only send SHUTDOWN 1st time thru */
840					sctp_stop_timers_for_shutdown(stcb);
841					sctp_send_shutdown(stcb,
842					    stcb->asoc.primary_destination);
843					sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
844					if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
845					    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
846						SCTP_STAT_DECR_GAUGE32(sctps_currestab);
847					}
848					SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
849					SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
850					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
851					    stcb->sctp_ep, stcb,
852					    asoc->primary_destination);
853					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
854					    stcb->sctp_ep, stcb,
855					    asoc->primary_destination);
856				}
857			} else {
858				/*
859				 * we still got (or just got) data to send,
860				 * so set SHUTDOWN_PENDING
861				 */
862				/*
863				 * XXX sockets draft says that SCTP_EOF
864				 * should be sent with no data. currently,
865				 * we will allow user data to be sent first
866				 * and move to SHUTDOWN-PENDING
867				 */
868				asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
869				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
870				    asoc->primary_destination);
871				if (asoc->locked_on_sending) {
872					/* Locked to send out the data */
873					struct sctp_stream_queue_pending *sp;
874
875					sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
876					if (sp == NULL) {
877						SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
878						    asoc->locked_on_sending->stream_no);
879					} else {
880						if ((sp->length == 0) && (sp->msg_is_complete == 0))
881							asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
882					}
883				}
884				if (TAILQ_EMPTY(&asoc->send_queue) &&
885				    TAILQ_EMPTY(&asoc->sent_queue) &&
886				    (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
887					struct mbuf *op_err;
888
889			abort_anyway:
890					op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
891					    0, M_DONTWAIT, 1, MT_DATA);
892					if (op_err) {
893						/*
894						 * Fill in the user
895						 * initiated abort
896						 */
897						struct sctp_paramhdr *ph;
898						uint32_t *ippp;
899
900						SCTP_BUF_LEN(op_err) =
901						    (sizeof(struct sctp_paramhdr) + sizeof(uint32_t));
902						ph = mtod(op_err,
903						    struct sctp_paramhdr *);
904						ph->param_type = htons(
905						    SCTP_CAUSE_USER_INITIATED_ABT);
906						ph->param_length = htons(SCTP_BUF_LEN(op_err));
907						ippp = (uint32_t *) (ph + 1);
908						*ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4);
909					}
910#if defined(SCTP_PANIC_ON_ABORT)
911					panic("disconnect does an abort");
912#endif
913
914					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
915					sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
916					SCTP_STAT_INCR_COUNTER32(sctps_aborted);
917					if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
918					    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
919						SCTP_STAT_DECR_GAUGE32(sctps_currestab);
920					}
921					SCTP_INP_RUNLOCK(inp);
922					(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
923					return (0);
924				} else {
925					sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
926				}
927			}
928			soisdisconnecting(so);
929			SCTP_TCB_UNLOCK(stcb);
930			SCTP_INP_RUNLOCK(inp);
931			return (0);
932		}
933		/* not reached */
934	} else {
935		/* UDP model does not support this */
936		SCTP_INP_RUNLOCK(inp);
937		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
938		return EOPNOTSUPP;
939	}
940}
941
942int
943sctp_flush(struct socket *so, int how)
944{
945	/*
946	 * We will just clear out the values and let subsequent close clear
947	 * out the data, if any. Note if the user did a shutdown(SHUT_RD)
948	 * they will not be able to read the data, the socket will block
949	 * that from happening.
950	 */
951	struct sctp_inpcb *inp;
952
953	inp = (struct sctp_inpcb *)so->so_pcb;
954	if (inp == NULL) {
955		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
956		return EINVAL;
957	}
958	SCTP_INP_RLOCK(inp);
959	/* For the 1 to many model this does nothing */
960	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
961		SCTP_INP_RUNLOCK(inp);
962		return (0);
963	}
964	SCTP_INP_RUNLOCK(inp);
965	if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) {
966		/*
967		 * First make sure the sb will be happy, we don't use these
968		 * except maybe the count
969		 */
970		SCTP_INP_WLOCK(inp);
971		SCTP_INP_READ_LOCK(inp);
972		inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ;
973		SCTP_INP_READ_UNLOCK(inp);
974		SCTP_INP_WUNLOCK(inp);
975		so->so_rcv.sb_cc = 0;
976		so->so_rcv.sb_mbcnt = 0;
977		so->so_rcv.sb_mb = NULL;
978	}
979	if ((how == PRU_FLUSH_WR) || (how == PRU_FLUSH_RDWR)) {
980		/*
981		 * First make sure the sb will be happy, we don't use these
982		 * except maybe the count
983		 */
984		so->so_snd.sb_cc = 0;
985		so->so_snd.sb_mbcnt = 0;
986		so->so_snd.sb_mb = NULL;
987
988	}
989	return (0);
990}
991
992int
993sctp_shutdown(struct socket *so)
994{
995	struct sctp_inpcb *inp;
996
997	inp = (struct sctp_inpcb *)so->so_pcb;
998	if (inp == 0) {
999		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1000		return EINVAL;
1001	}
1002	SCTP_INP_RLOCK(inp);
1003	/* For UDP model this is a invalid call */
1004	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
1005		/* Restore the flags that the soshutdown took away. */
1006		SOCKBUF_LOCK(&so->so_rcv);
1007		so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
1008		SOCKBUF_UNLOCK(&so->so_rcv);
1009		/* This proc will wakeup for read and do nothing (I hope) */
1010		SCTP_INP_RUNLOCK(inp);
1011		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1012		return (EOPNOTSUPP);
1013	}
1014	/*
1015	 * Ok if we reach here its the TCP model and it is either a SHUT_WR
1016	 * or SHUT_RDWR. This means we put the shutdown flag against it.
1017	 */
1018	{
1019		struct sctp_tcb *stcb;
1020		struct sctp_association *asoc;
1021
1022		if ((so->so_state &
1023		    (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
1024			SCTP_INP_RUNLOCK(inp);
1025			return (ENOTCONN);
1026		}
1027		socantsendmore(so);
1028
1029		stcb = LIST_FIRST(&inp->sctp_asoc_list);
1030		if (stcb == NULL) {
1031			/*
1032			 * Ok we hit the case that the shutdown call was
1033			 * made after an abort or something. Nothing to do
1034			 * now.
1035			 */
1036			SCTP_INP_RUNLOCK(inp);
1037			return (0);
1038		}
1039		SCTP_TCB_LOCK(stcb);
1040		asoc = &stcb->asoc;
1041		if (TAILQ_EMPTY(&asoc->send_queue) &&
1042		    TAILQ_EMPTY(&asoc->sent_queue) &&
1043		    (asoc->stream_queue_cnt == 0)) {
1044			if (asoc->locked_on_sending) {
1045				goto abort_anyway;
1046			}
1047			/* there is nothing queued to send, so I'm done... */
1048			if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
1049				/* only send SHUTDOWN the first time through */
1050				sctp_stop_timers_for_shutdown(stcb);
1051				sctp_send_shutdown(stcb,
1052				    stcb->asoc.primary_destination);
1053				sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
1054				if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
1055				    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1056					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1057				}
1058				SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
1059				SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
1060				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1061				    stcb->sctp_ep, stcb,
1062				    asoc->primary_destination);
1063				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1064				    stcb->sctp_ep, stcb,
1065				    asoc->primary_destination);
1066			}
1067		} else {
1068			/*
1069			 * we still got (or just got) data to send, so set
1070			 * SHUTDOWN_PENDING
1071			 */
1072			asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
1073			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
1074			    asoc->primary_destination);
1075
1076			if (asoc->locked_on_sending) {
1077				/* Locked to send out the data */
1078				struct sctp_stream_queue_pending *sp;
1079
1080				sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
1081				if (sp == NULL) {
1082					SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
1083					    asoc->locked_on_sending->stream_no);
1084				} else {
1085					if ((sp->length == 0) && (sp->msg_is_complete == 0)) {
1086						asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
1087					}
1088				}
1089			}
1090			if (TAILQ_EMPTY(&asoc->send_queue) &&
1091			    TAILQ_EMPTY(&asoc->sent_queue) &&
1092			    (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
1093				struct mbuf *op_err;
1094
1095		abort_anyway:
1096				op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
1097				    0, M_DONTWAIT, 1, MT_DATA);
1098				if (op_err) {
1099					/* Fill in the user initiated abort */
1100					struct sctp_paramhdr *ph;
1101					uint32_t *ippp;
1102
1103					SCTP_BUF_LEN(op_err) =
1104					    sizeof(struct sctp_paramhdr) + sizeof(uint32_t);
1105					ph = mtod(op_err,
1106					    struct sctp_paramhdr *);
1107					ph->param_type = htons(
1108					    SCTP_CAUSE_USER_INITIATED_ABT);
1109					ph->param_length = htons(SCTP_BUF_LEN(op_err));
1110					ippp = (uint32_t *) (ph + 1);
1111					*ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6);
1112				}
1113#if defined(SCTP_PANIC_ON_ABORT)
1114				panic("shutdown does an abort");
1115#endif
1116				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
1117				sctp_abort_an_association(stcb->sctp_ep, stcb,
1118				    SCTP_RESPONSE_TO_USER_REQ,
1119				    op_err, SCTP_SO_LOCKED);
1120				goto skip_unlock;
1121			} else {
1122				sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
1123			}
1124		}
1125		SCTP_TCB_UNLOCK(stcb);
1126	}
1127skip_unlock:
1128	SCTP_INP_RUNLOCK(inp);
1129	return 0;
1130}
1131
1132/*
1133 * copies a "user" presentable address and removes embedded scope, etc.
1134 * returns 0 on success, 1 on error
1135 */
1136static uint32_t
1137sctp_fill_user_address(struct sockaddr_storage *ss, struct sockaddr *sa)
1138{
1139#ifdef INET6
1140	struct sockaddr_in6 lsa6;
1141
1142	sa = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)sa,
1143	    &lsa6);
1144#endif
1145	memcpy(ss, sa, sa->sa_len);
1146	return (0);
1147}
1148
1149
1150
1151/*
1152 * NOTE: assumes addr lock is held
1153 */
1154static size_t
1155sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
1156    struct sctp_tcb *stcb,
1157    size_t limit,
1158    struct sockaddr_storage *sas,
1159    uint32_t vrf_id)
1160{
1161	struct sctp_ifn *sctp_ifn;
1162	struct sctp_ifa *sctp_ifa;
1163	int loopback_scope, ipv4_local_scope, local_scope, site_scope;
1164	size_t actual;
1165	int ipv4_addr_legal, ipv6_addr_legal;
1166	struct sctp_vrf *vrf;
1167
1168	actual = 0;
1169	if (limit <= 0)
1170		return (actual);
1171
1172	if (stcb) {
1173		/* Turn on all the appropriate scope */
1174		loopback_scope = stcb->asoc.loopback_scope;
1175		ipv4_local_scope = stcb->asoc.ipv4_local_scope;
1176		local_scope = stcb->asoc.local_scope;
1177		site_scope = stcb->asoc.site_scope;
1178	} else {
1179		/* Turn on ALL scope, since we look at the EP */
1180		loopback_scope = ipv4_local_scope = local_scope =
1181		    site_scope = 1;
1182	}
1183	ipv4_addr_legal = ipv6_addr_legal = 0;
1184	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1185		ipv6_addr_legal = 1;
1186		if (SCTP_IPV6_V6ONLY(inp) == 0) {
1187			ipv4_addr_legal = 1;
1188		}
1189	} else {
1190		ipv4_addr_legal = 1;
1191	}
1192	vrf = sctp_find_vrf(vrf_id);
1193	if (vrf == NULL) {
1194		return (0);
1195	}
1196	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1197		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1198			if ((loopback_scope == 0) &&
1199			    SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
1200				/* Skip loopback if loopback_scope not set */
1201				continue;
1202			}
1203			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1204				if (stcb) {
1205					/*
1206					 * For the BOUND-ALL case, the list
1207					 * associated with a TCB is Always
1208					 * considered a reverse list.. i.e.
1209					 * it lists addresses that are NOT
1210					 * part of the association. If this
1211					 * is one of those we must skip it.
1212					 */
1213					if (sctp_is_addr_restricted(stcb,
1214					    sctp_ifa)) {
1215						continue;
1216					}
1217				}
1218				switch (sctp_ifa->address.sa.sa_family) {
1219#ifdef INET
1220				case AF_INET:
1221					if (ipv4_addr_legal) {
1222						struct sockaddr_in *sin;
1223
1224						sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
1225						if (sin->sin_addr.s_addr == 0) {
1226							/*
1227							 * we skip
1228							 * unspecifed
1229							 * addresses
1230							 */
1231							continue;
1232						}
1233						if ((ipv4_local_scope == 0) &&
1234						    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
1235							continue;
1236						}
1237#ifdef INET6
1238						if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
1239							in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas);
1240							((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1241							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6));
1242							actual += sizeof(struct sockaddr_in6);
1243						} else {
1244#endif
1245							memcpy(sas, sin, sizeof(*sin));
1246							((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
1247							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin));
1248							actual += sizeof(*sin);
1249#ifdef INET6
1250						}
1251#endif
1252						if (actual >= limit) {
1253							return (actual);
1254						}
1255					} else {
1256						continue;
1257					}
1258					break;
1259#endif
1260#ifdef INET6
1261				case AF_INET6:
1262					if (ipv6_addr_legal) {
1263						struct sockaddr_in6 *sin6;
1264
1265						sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
1266						if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1267							/*
1268							 * we skip
1269							 * unspecifed
1270							 * addresses
1271							 */
1272							continue;
1273						}
1274						if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1275							if (local_scope == 0)
1276								continue;
1277							if (sin6->sin6_scope_id == 0) {
1278								if (sa6_recoverscope(sin6) != 0)
1279									/*
1280									 *
1281									 * bad
1282									 *
1283									 * li
1284									 * nk
1285									 *
1286									 * loc
1287									 * al
1288									 *
1289									 * add
1290									 * re
1291									 * ss
1292									 * */
1293									continue;
1294							}
1295						}
1296						if ((site_scope == 0) &&
1297						    (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
1298							continue;
1299						}
1300						memcpy(sas, sin6, sizeof(*sin6));
1301						((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1302						sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6));
1303						actual += sizeof(*sin6);
1304						if (actual >= limit) {
1305							return (actual);
1306						}
1307					} else {
1308						continue;
1309					}
1310					break;
1311#endif
1312				default:
1313					/* TSNH */
1314					break;
1315				}
1316			}
1317		}
1318	} else {
1319		struct sctp_laddr *laddr;
1320
1321		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1322			if (stcb) {
1323				if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
1324					continue;
1325				}
1326			}
1327			if (sctp_fill_user_address(sas, &laddr->ifa->address.sa))
1328				continue;
1329
1330			((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1331			sas = (struct sockaddr_storage *)((caddr_t)sas +
1332			    laddr->ifa->address.sa.sa_len);
1333			actual += laddr->ifa->address.sa.sa_len;
1334			if (actual >= limit) {
1335				return (actual);
1336			}
1337		}
1338	}
1339	return (actual);
1340}
1341
1342static size_t
1343sctp_fill_up_addresses(struct sctp_inpcb *inp,
1344    struct sctp_tcb *stcb,
1345    size_t limit,
1346    struct sockaddr_storage *sas)
1347{
1348	size_t size = 0;
1349
1350	SCTP_IPI_ADDR_RLOCK();
1351	/* fill up addresses for the endpoint's default vrf */
1352	size = sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
1353	    inp->def_vrf_id);
1354	SCTP_IPI_ADDR_RUNLOCK();
1355	return (size);
1356}
1357
1358/*
1359 * NOTE: assumes addr lock is held
1360 */
1361static int
1362sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
1363{
1364	int cnt = 0;
1365	struct sctp_vrf *vrf = NULL;
1366
1367	/*
1368	 * In both sub-set bound an bound_all cases we return the MAXIMUM
1369	 * number of addresses that you COULD get. In reality the sub-set
1370	 * bound may have an exclusion list for a given TCB OR in the
1371	 * bound-all case a TCB may NOT include the loopback or other
1372	 * addresses as well.
1373	 */
1374	vrf = sctp_find_vrf(vrf_id);
1375	if (vrf == NULL) {
1376		return (0);
1377	}
1378	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1379		struct sctp_ifn *sctp_ifn;
1380		struct sctp_ifa *sctp_ifa;
1381
1382		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1383			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1384				/* Count them if they are the right type */
1385				switch (sctp_ifa->address.sa.sa_family) {
1386#ifdef INET
1387				case AF_INET:
1388					if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1389						cnt += sizeof(struct sockaddr_in6);
1390					else
1391						cnt += sizeof(struct sockaddr_in);
1392					break;
1393#endif
1394#ifdef INET6
1395				case AF_INET6:
1396					cnt += sizeof(struct sockaddr_in6);
1397					break;
1398#endif
1399				default:
1400					break;
1401				}
1402			}
1403		}
1404	} else {
1405		struct sctp_laddr *laddr;
1406
1407		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1408			switch (laddr->ifa->address.sa.sa_family) {
1409#ifdef INET
1410			case AF_INET:
1411				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1412					cnt += sizeof(struct sockaddr_in6);
1413				else
1414					cnt += sizeof(struct sockaddr_in);
1415				break;
1416#endif
1417#ifdef INET6
1418			case AF_INET6:
1419				cnt += sizeof(struct sockaddr_in6);
1420				break;
1421#endif
1422			default:
1423				break;
1424			}
1425		}
1426	}
1427	return (cnt);
1428}
1429
1430static int
1431sctp_count_max_addresses(struct sctp_inpcb *inp)
1432{
1433	int cnt = 0;
1434
1435	SCTP_IPI_ADDR_RLOCK();
1436	/* count addresses for the endpoint's default VRF */
1437	cnt = sctp_count_max_addresses_vrf(inp, inp->def_vrf_id);
1438	SCTP_IPI_ADDR_RUNLOCK();
1439	return (cnt);
1440}
1441
1442static int
1443sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
1444    size_t optsize, void *p, int delay)
1445{
1446	int error = 0;
1447	int creat_lock_on = 0;
1448	struct sctp_tcb *stcb = NULL;
1449	struct sockaddr *sa;
1450	int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
1451	uint32_t vrf_id;
1452	int bad_addresses = 0;
1453	sctp_assoc_t *a_id;
1454
1455	SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
1456
1457	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
1458	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
1459		/* We are already connected AND the TCP model */
1460		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
1461		return (EADDRINUSE);
1462	}
1463	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
1464	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
1465		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1466		return (EINVAL);
1467	}
1468	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1469		SCTP_INP_RLOCK(inp);
1470		stcb = LIST_FIRST(&inp->sctp_asoc_list);
1471		SCTP_INP_RUNLOCK(inp);
1472	}
1473	if (stcb) {
1474		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
1475		return (EALREADY);
1476	}
1477	SCTP_INP_INCR_REF(inp);
1478	SCTP_ASOC_CREATE_LOCK(inp);
1479	creat_lock_on = 1;
1480	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
1481	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
1482		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
1483		error = EFAULT;
1484		goto out_now;
1485	}
1486	totaddrp = (int *)optval;
1487	totaddr = *totaddrp;
1488	sa = (struct sockaddr *)(totaddrp + 1);
1489	stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (optsize - sizeof(int)), &bad_addresses);
1490	if ((stcb != NULL) || bad_addresses) {
1491		/* Already have or am bring up an association */
1492		SCTP_ASOC_CREATE_UNLOCK(inp);
1493		creat_lock_on = 0;
1494		if (stcb)
1495			SCTP_TCB_UNLOCK(stcb);
1496		if (bad_addresses == 0) {
1497			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
1498			error = EALREADY;
1499		}
1500		goto out_now;
1501	}
1502#ifdef INET6
1503	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
1504	    (num_v6 > 0)) {
1505		error = EINVAL;
1506		goto out_now;
1507	}
1508	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1509	    (num_v4 > 0)) {
1510		struct in6pcb *inp6;
1511
1512		inp6 = (struct in6pcb *)inp;
1513		if (SCTP_IPV6_V6ONLY(inp6)) {
1514			/*
1515			 * if IPV6_V6ONLY flag, ignore connections destined
1516			 * to a v4 addr or v4-mapped addr
1517			 */
1518			SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1519			error = EINVAL;
1520			goto out_now;
1521		}
1522	}
1523#endif				/* INET6 */
1524	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
1525	    SCTP_PCB_FLAGS_UNBOUND) {
1526		/* Bind a ephemeral port */
1527		error = sctp_inpcb_bind(so, NULL, NULL, p);
1528		if (error) {
1529			goto out_now;
1530		}
1531	}
1532	/* FIX ME: do we want to pass in a vrf on the connect call? */
1533	vrf_id = inp->def_vrf_id;
1534
1535
1536	/* We are GOOD to go */
1537	stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id,
1538	    (struct thread *)p
1539	    );
1540	if (stcb == NULL) {
1541		/* Gak! no memory */
1542		goto out_now;
1543	}
1544	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
1545	/* move to second address */
1546	switch (sa->sa_family) {
1547#ifdef INET
1548	case AF_INET:
1549		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
1550		break;
1551#endif
1552#ifdef INET6
1553	case AF_INET6:
1554		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
1555		break;
1556#endif
1557	default:
1558		break;
1559	}
1560
1561	error = 0;
1562	sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error);
1563	/* Fill in the return id */
1564	if (error) {
1565		(void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6);
1566		goto out_now;
1567	}
1568	a_id = (sctp_assoc_t *) optval;
1569	*a_id = sctp_get_associd(stcb);
1570
1571	/* initialize authentication parameters for the assoc */
1572	sctp_initialize_auth_params(inp, stcb);
1573
1574	if (delay) {
1575		/* doing delayed connection */
1576		stcb->asoc.delayed_connection = 1;
1577		sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
1578	} else {
1579		(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
1580		sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
1581	}
1582	SCTP_TCB_UNLOCK(stcb);
1583	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
1584		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
1585		/* Set the connected flag so we can queue data */
1586		soisconnecting(so);
1587	}
1588out_now:
1589	if (creat_lock_on) {
1590		SCTP_ASOC_CREATE_UNLOCK(inp);
1591	}
1592	SCTP_INP_DECR_REF(inp);
1593	return error;
1594}
1595
1596#define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
1597	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
1598	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
1599		SCTP_INP_RLOCK(inp); \
1600		stcb = LIST_FIRST(&inp->sctp_asoc_list); \
1601		if (stcb) { \
1602			SCTP_TCB_LOCK(stcb); \
1603                } \
1604		SCTP_INP_RUNLOCK(inp); \
1605	} else if (assoc_id > SCTP_ALL_ASSOC) { \
1606		stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
1607		if (stcb == NULL) { \
1608		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
1609			error = ENOENT; \
1610			break; \
1611		} \
1612	} else { \
1613		stcb = NULL; \
1614        } \
1615  }
1616
1617
1618#define SCTP_CHECK_AND_CAST(destp, srcp, type, size)  {\
1619	if (size < sizeof(type)) { \
1620		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
1621		error = EINVAL; \
1622		break; \
1623	} else { \
1624		destp = (type *)srcp; \
1625	} \
1626      }
1627
1628static int
1629sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
1630    void *p)
1631{
1632	struct sctp_inpcb *inp = NULL;
1633	int error, val = 0;
1634	struct sctp_tcb *stcb = NULL;
1635
1636	if (optval == NULL) {
1637		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1638		return (EINVAL);
1639	}
1640	inp = (struct sctp_inpcb *)so->so_pcb;
1641	if (inp == 0) {
1642		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1643		return EINVAL;
1644	}
1645	error = 0;
1646
1647	switch (optname) {
1648	case SCTP_NODELAY:
1649	case SCTP_AUTOCLOSE:
1650	case SCTP_EXPLICIT_EOR:
1651	case SCTP_AUTO_ASCONF:
1652	case SCTP_DISABLE_FRAGMENTS:
1653	case SCTP_I_WANT_MAPPED_V4_ADDR:
1654	case SCTP_USE_EXT_RCVINFO:
1655		SCTP_INP_RLOCK(inp);
1656		switch (optname) {
1657		case SCTP_DISABLE_FRAGMENTS:
1658			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
1659			break;
1660		case SCTP_I_WANT_MAPPED_V4_ADDR:
1661			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
1662			break;
1663		case SCTP_AUTO_ASCONF:
1664			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1665				/* only valid for bound all sockets */
1666				val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
1667			} else {
1668				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1669				error = EINVAL;
1670				goto flags_out;
1671			}
1672			break;
1673		case SCTP_EXPLICIT_EOR:
1674			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
1675			break;
1676		case SCTP_NODELAY:
1677			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
1678			break;
1679		case SCTP_USE_EXT_RCVINFO:
1680			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
1681			break;
1682		case SCTP_AUTOCLOSE:
1683			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
1684				val = TICKS_TO_SEC(inp->sctp_ep.auto_close_time);
1685			else
1686				val = 0;
1687			break;
1688
1689		default:
1690			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
1691			error = ENOPROTOOPT;
1692		}		/* end switch (sopt->sopt_name) */
1693		if (*optsize < sizeof(val)) {
1694			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1695			error = EINVAL;
1696		}
1697flags_out:
1698		SCTP_INP_RUNLOCK(inp);
1699		if (error == 0) {
1700			/* return the option value */
1701			*(int *)optval = val;
1702			*optsize = sizeof(val);
1703		}
1704		break;
1705	case SCTP_GET_PACKET_LOG:
1706		{
1707#ifdef  SCTP_PACKET_LOGGING
1708			uint8_t *target;
1709			int ret;
1710
1711			SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize);
1712			ret = sctp_copy_out_packet_log(target, (int)*optsize);
1713			*optsize = ret;
1714#else
1715			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1716			error = EOPNOTSUPP;
1717#endif
1718			break;
1719		}
1720	case SCTP_REUSE_PORT:
1721		{
1722			uint32_t *value;
1723
1724			if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
1725				/* Can't do this for a 1-m socket */
1726				error = EINVAL;
1727				break;
1728			}
1729			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1730			*value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
1731			*optsize = sizeof(uint32_t);
1732			break;
1733		}
1734	case SCTP_PARTIAL_DELIVERY_POINT:
1735		{
1736			uint32_t *value;
1737
1738			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1739			*value = inp->partial_delivery_point;
1740			*optsize = sizeof(uint32_t);
1741			break;
1742		}
1743	case SCTP_FRAGMENT_INTERLEAVE:
1744		{
1745			uint32_t *value;
1746
1747			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1748			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) {
1749				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) {
1750					*value = SCTP_FRAG_LEVEL_2;
1751				} else {
1752					*value = SCTP_FRAG_LEVEL_1;
1753				}
1754			} else {
1755				*value = SCTP_FRAG_LEVEL_0;
1756			}
1757			*optsize = sizeof(uint32_t);
1758			break;
1759		}
1760	case SCTP_CMT_ON_OFF:
1761		{
1762			struct sctp_assoc_value *av;
1763
1764			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1765			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1766			if (stcb) {
1767				av->assoc_value = stcb->asoc.sctp_cmt_on_off;
1768				SCTP_TCB_UNLOCK(stcb);
1769			} else {
1770				if (av->assoc_id == SCTP_FUTURE_ASSOC) {
1771					SCTP_INP_RLOCK(inp);
1772					av->assoc_value = inp->sctp_cmt_on_off;
1773					SCTP_INP_RUNLOCK(inp);
1774				} else {
1775					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1776					error = EINVAL;
1777				}
1778			}
1779			if (error == 0) {
1780				*optsize = sizeof(struct sctp_assoc_value);
1781			}
1782			break;
1783		}
1784	case SCTP_PLUGGABLE_CC:
1785		{
1786			struct sctp_assoc_value *av;
1787
1788			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1789			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1790			if (stcb) {
1791				av->assoc_value = stcb->asoc.congestion_control_module;
1792				SCTP_TCB_UNLOCK(stcb);
1793			} else {
1794				if (av->assoc_id == SCTP_FUTURE_ASSOC) {
1795					SCTP_INP_RLOCK(inp);
1796					av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
1797					SCTP_INP_RUNLOCK(inp);
1798				} else {
1799					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1800					error = EINVAL;
1801				}
1802			}
1803			if (error == 0) {
1804				*optsize = sizeof(struct sctp_assoc_value);
1805			}
1806			break;
1807		}
1808	case SCTP_CC_OPTION:
1809		{
1810			struct sctp_cc_option *cc_opt;
1811
1812			SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
1813			SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
1814			if (stcb == NULL) {
1815				error = EINVAL;
1816			} else {
1817				if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
1818					error = ENOTSUP;
1819				} else {
1820					error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 0, cc_opt);
1821					*optsize = sizeof(struct sctp_cc_option);
1822				}
1823				SCTP_TCB_UNLOCK(stcb);
1824			}
1825			break;
1826		}
1827	case SCTP_PLUGGABLE_SS:
1828		{
1829			struct sctp_assoc_value *av;
1830
1831			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1832			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1833			if (stcb) {
1834				av->assoc_value = stcb->asoc.stream_scheduling_module;
1835				SCTP_TCB_UNLOCK(stcb);
1836			} else {
1837				if (av->assoc_id == SCTP_FUTURE_ASSOC) {
1838					SCTP_INP_RLOCK(inp);
1839					av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
1840					SCTP_INP_RUNLOCK(inp);
1841				} else {
1842					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1843					error = EINVAL;
1844				}
1845			}
1846			if (error == 0) {
1847				*optsize = sizeof(struct sctp_assoc_value);
1848			}
1849			break;
1850		}
1851	case SCTP_SS_VALUE:
1852		{
1853			struct sctp_stream_value *av;
1854
1855			SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
1856			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1857			if (stcb) {
1858				if (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
1859				    &av->stream_value) < 0) {
1860					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1861					error = EINVAL;
1862				} else {
1863					*optsize = sizeof(struct sctp_stream_value);
1864				}
1865				SCTP_TCB_UNLOCK(stcb);
1866			} else {
1867				/*
1868				 * Can't get stream value without
1869				 * association
1870				 */
1871				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1872				error = EINVAL;
1873			}
1874			break;
1875		}
1876	case SCTP_GET_ADDR_LEN:
1877		{
1878			struct sctp_assoc_value *av;
1879
1880			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1881			error = EINVAL;
1882#ifdef INET
1883			if (av->assoc_value == AF_INET) {
1884				av->assoc_value = sizeof(struct sockaddr_in);
1885				error = 0;
1886			}
1887#endif
1888#ifdef INET6
1889			if (av->assoc_value == AF_INET6) {
1890				av->assoc_value = sizeof(struct sockaddr_in6);
1891				error = 0;
1892			}
1893#endif
1894			if (error) {
1895				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1896			} else {
1897				*optsize = sizeof(struct sctp_assoc_value);
1898			}
1899			break;
1900		}
1901	case SCTP_GET_ASSOC_NUMBER:
1902		{
1903			uint32_t *value, cnt;
1904
1905			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1906			cnt = 0;
1907			SCTP_INP_RLOCK(inp);
1908			LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
1909				cnt++;
1910			}
1911			SCTP_INP_RUNLOCK(inp);
1912			*value = cnt;
1913			*optsize = sizeof(uint32_t);
1914			break;
1915		}
1916	case SCTP_GET_ASSOC_ID_LIST:
1917		{
1918			struct sctp_assoc_ids *ids;
1919			unsigned int at, limit;
1920
1921			SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
1922			at = 0;
1923			limit = (*optsize - sizeof(uint32_t)) / sizeof(sctp_assoc_t);
1924			SCTP_INP_RLOCK(inp);
1925			LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
1926				if (at < limit) {
1927					ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
1928				} else {
1929					error = EINVAL;
1930					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1931					break;
1932				}
1933			}
1934			SCTP_INP_RUNLOCK(inp);
1935			if (error == 0) {
1936				ids->gaids_number_of_ids = at;
1937				*optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
1938			}
1939			break;
1940		}
1941	case SCTP_CONTEXT:
1942		{
1943			struct sctp_assoc_value *av;
1944
1945			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1946			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1947
1948			if (stcb) {
1949				av->assoc_value = stcb->asoc.context;
1950				SCTP_TCB_UNLOCK(stcb);
1951			} else {
1952				if (av->assoc_id == SCTP_FUTURE_ASSOC) {
1953					SCTP_INP_RLOCK(inp);
1954					av->assoc_value = inp->sctp_context;
1955					SCTP_INP_RUNLOCK(inp);
1956				} else {
1957					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1958					error = EINVAL;
1959				}
1960			}
1961			if (error == 0) {
1962				*optsize = sizeof(struct sctp_assoc_value);
1963			}
1964			break;
1965		}
1966	case SCTP_VRF_ID:
1967		{
1968			uint32_t *default_vrfid;
1969
1970			SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
1971			*default_vrfid = inp->def_vrf_id;
1972			*optsize = sizeof(uint32_t);
1973			break;
1974		}
1975	case SCTP_GET_ASOC_VRF:
1976		{
1977			struct sctp_assoc_value *id;
1978
1979			SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
1980			SCTP_FIND_STCB(inp, stcb, id->assoc_id);
1981			if (stcb == NULL) {
1982				error = EINVAL;
1983				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1984			} else {
1985				id->assoc_value = stcb->asoc.vrf_id;
1986				*optsize = sizeof(struct sctp_assoc_value);
1987			}
1988			break;
1989		}
1990	case SCTP_GET_VRF_IDS:
1991		{
1992			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1993			error = EOPNOTSUPP;
1994			break;
1995		}
1996	case SCTP_GET_NONCE_VALUES:
1997		{
1998			struct sctp_get_nonce_values *gnv;
1999
2000			SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
2001			SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
2002
2003			if (stcb) {
2004				gnv->gn_peers_tag = stcb->asoc.peer_vtag;
2005				gnv->gn_local_tag = stcb->asoc.my_vtag;
2006				SCTP_TCB_UNLOCK(stcb);
2007				*optsize = sizeof(struct sctp_get_nonce_values);
2008			} else {
2009				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2010				error = ENOTCONN;
2011			}
2012			break;
2013		}
2014	case SCTP_DELAYED_SACK:
2015		{
2016			struct sctp_sack_info *sack;
2017
2018			SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, *optsize);
2019			SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
2020			if (stcb) {
2021				sack->sack_delay = stcb->asoc.delayed_ack;
2022				sack->sack_freq = stcb->asoc.sack_freq;
2023				SCTP_TCB_UNLOCK(stcb);
2024			} else {
2025				if (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) {
2026					SCTP_INP_RLOCK(inp);
2027					sack->sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
2028					sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
2029					SCTP_INP_RUNLOCK(inp);
2030				} else {
2031					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2032					error = EINVAL;
2033				}
2034			}
2035			if (error == 0) {
2036				*optsize = sizeof(struct sctp_sack_info);
2037			}
2038			break;
2039		}
2040	case SCTP_GET_SNDBUF_USE:
2041		{
2042			struct sctp_sockstat *ss;
2043
2044			SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
2045			SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
2046
2047			if (stcb) {
2048				ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
2049				ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
2050				    stcb->asoc.size_on_all_streams);
2051				SCTP_TCB_UNLOCK(stcb);
2052				*optsize = sizeof(struct sctp_sockstat);
2053			} else {
2054				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2055				error = ENOTCONN;
2056			}
2057			break;
2058		}
2059	case SCTP_MAX_BURST:
2060		{
2061			struct sctp_assoc_value *av;
2062
2063			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2064			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2065
2066			if (stcb) {
2067				av->assoc_value = stcb->asoc.max_burst;
2068				SCTP_TCB_UNLOCK(stcb);
2069			} else {
2070				if (av->assoc_id == SCTP_FUTURE_ASSOC) {
2071					SCTP_INP_RLOCK(inp);
2072					av->assoc_value = inp->sctp_ep.max_burst;
2073					SCTP_INP_RUNLOCK(inp);
2074				} else {
2075					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2076					error = EINVAL;
2077				}
2078			}
2079			if (error == 0) {
2080				*optsize = sizeof(struct sctp_assoc_value);
2081			}
2082			break;
2083		}
2084	case SCTP_MAXSEG:
2085		{
2086			struct sctp_assoc_value *av;
2087			int ovh;
2088
2089			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2090			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2091
2092			if (stcb) {
2093				av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
2094				SCTP_TCB_UNLOCK(stcb);
2095			} else {
2096				if (av->assoc_id == SCTP_FUTURE_ASSOC) {
2097					SCTP_INP_RLOCK(inp);
2098					if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2099						ovh = SCTP_MED_OVERHEAD;
2100					} else {
2101						ovh = SCTP_MED_V4_OVERHEAD;
2102					}
2103					if (inp->sctp_frag_point >= SCTP_DEFAULT_MAXSEGMENT)
2104						av->assoc_value = 0;
2105					else
2106						av->assoc_value = inp->sctp_frag_point - ovh;
2107					SCTP_INP_RUNLOCK(inp);
2108				} else {
2109					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2110					error = EINVAL;
2111				}
2112			}
2113			if (error == 0) {
2114				*optsize = sizeof(struct sctp_assoc_value);
2115			}
2116			break;
2117		}
2118	case SCTP_GET_STAT_LOG:
2119		error = sctp_fill_stat_log(optval, optsize);
2120		break;
2121	case SCTP_EVENTS:
2122		{
2123			struct sctp_event_subscribe *events;
2124
2125			SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
2126			memset(events, 0, sizeof(struct sctp_event_subscribe));
2127			SCTP_INP_RLOCK(inp);
2128			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
2129				events->sctp_data_io_event = 1;
2130
2131			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT))
2132				events->sctp_association_event = 1;
2133
2134			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT))
2135				events->sctp_address_event = 1;
2136
2137			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
2138				events->sctp_send_failure_event = 1;
2139
2140			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR))
2141				events->sctp_peer_error_event = 1;
2142
2143			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
2144				events->sctp_shutdown_event = 1;
2145
2146			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT))
2147				events->sctp_partial_delivery_event = 1;
2148
2149			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT))
2150				events->sctp_adaptation_layer_event = 1;
2151
2152			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT))
2153				events->sctp_authentication_event = 1;
2154
2155			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT))
2156				events->sctp_sender_dry_event = 1;
2157
2158			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
2159				events->sctp_stream_reset_event = 1;
2160			SCTP_INP_RUNLOCK(inp);
2161			*optsize = sizeof(struct sctp_event_subscribe);
2162			break;
2163		}
2164	case SCTP_ADAPTATION_LAYER:
2165		{
2166			uint32_t *value;
2167
2168			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2169
2170			SCTP_INP_RLOCK(inp);
2171			*value = inp->sctp_ep.adaptation_layer_indicator;
2172			SCTP_INP_RUNLOCK(inp);
2173			*optsize = sizeof(uint32_t);
2174			break;
2175		}
2176	case SCTP_SET_INITIAL_DBG_SEQ:
2177		{
2178			uint32_t *value;
2179
2180			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2181			SCTP_INP_RLOCK(inp);
2182			*value = inp->sctp_ep.initial_sequence_debug;
2183			SCTP_INP_RUNLOCK(inp);
2184			*optsize = sizeof(uint32_t);
2185			break;
2186		}
2187	case SCTP_GET_LOCAL_ADDR_SIZE:
2188		{
2189			uint32_t *value;
2190
2191			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2192			SCTP_INP_RLOCK(inp);
2193			*value = sctp_count_max_addresses(inp);
2194			SCTP_INP_RUNLOCK(inp);
2195			*optsize = sizeof(uint32_t);
2196			break;
2197		}
2198	case SCTP_GET_REMOTE_ADDR_SIZE:
2199		{
2200			uint32_t *value;
2201			size_t size;
2202			struct sctp_nets *net;
2203
2204			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2205			/* FIXME MT: change to sctp_assoc_value? */
2206			SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) * value);
2207
2208			if (stcb) {
2209				size = 0;
2210				/* Count the sizes */
2211				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2212					if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2213						size += sizeof(struct sockaddr_in6);
2214					} else {
2215						switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
2216#ifdef INET
2217						case AF_INET:
2218							size += sizeof(struct sockaddr_in);
2219							break;
2220#endif
2221#ifdef INET6
2222						case AF_INET6:
2223							size += sizeof(struct sockaddr_in6);
2224							break;
2225#endif
2226						default:
2227							break;
2228						}
2229					}
2230				}
2231				SCTP_TCB_UNLOCK(stcb);
2232				*value = (uint32_t) size;
2233				*optsize = sizeof(uint32_t);
2234			} else {
2235				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2236				error = ENOTCONN;
2237			}
2238			break;
2239		}
2240	case SCTP_GET_PEER_ADDRESSES:
2241		/*
2242		 * Get the address information, an array is passed in to
2243		 * fill up we pack it.
2244		 */
2245		{
2246			size_t cpsz, left;
2247			struct sockaddr_storage *sas;
2248			struct sctp_nets *net;
2249			struct sctp_getaddresses *saddr;
2250
2251			SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2252			SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2253
2254			if (stcb) {
2255				left = (*optsize) - sizeof(struct sctp_getaddresses);
2256				*optsize = sizeof(struct sctp_getaddresses);
2257				sas = (struct sockaddr_storage *)&saddr->addr[0];
2258
2259				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2260					if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2261						cpsz = sizeof(struct sockaddr_in6);
2262					} else {
2263						switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
2264#ifdef INET
2265						case AF_INET:
2266							cpsz = sizeof(struct sockaddr_in);
2267							break;
2268#endif
2269#ifdef INET6
2270						case AF_INET6:
2271							cpsz = sizeof(struct sockaddr_in6);
2272							break;
2273#endif
2274						default:
2275							cpsz = 0;
2276							break;
2277						}
2278					}
2279					if (cpsz == 0) {
2280						break;
2281					}
2282					if (left < cpsz) {
2283						/* not enough room. */
2284						break;
2285					}
2286#if defined(INET) && defined(INET6)
2287					if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
2288					    (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
2289						/* Must map the address */
2290						in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr,
2291						    (struct sockaddr_in6 *)sas);
2292					} else {
2293#endif
2294						memcpy(sas, &net->ro._l_addr, cpsz);
2295#if defined(INET) && defined(INET6)
2296					}
2297#endif
2298					((struct sockaddr_in *)sas)->sin_port = stcb->rport;
2299
2300					sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz);
2301					left -= cpsz;
2302					*optsize += cpsz;
2303				}
2304				SCTP_TCB_UNLOCK(stcb);
2305			} else {
2306				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2307				error = ENOENT;
2308			}
2309			break;
2310		}
2311	case SCTP_GET_LOCAL_ADDRESSES:
2312		{
2313			size_t limit, actual;
2314			struct sockaddr_storage *sas;
2315			struct sctp_getaddresses *saddr;
2316
2317			SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2318			SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2319
2320			sas = (struct sockaddr_storage *)&saddr->addr[0];
2321			limit = *optsize - sizeof(sctp_assoc_t);
2322			actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
2323			if (stcb) {
2324				SCTP_TCB_UNLOCK(stcb);
2325			}
2326			*optsize = sizeof(struct sockaddr_storage) + actual;
2327			break;
2328		}
2329	case SCTP_PEER_ADDR_PARAMS:
2330		{
2331			struct sctp_paddrparams *paddrp;
2332			struct sctp_nets *net;
2333
2334			SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
2335			SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
2336
2337			net = NULL;
2338			if (stcb) {
2339				net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
2340			} else {
2341				/*
2342				 * We increment here since
2343				 * sctp_findassociation_ep_addr() wil do a
2344				 * decrement if it finds the stcb as long as
2345				 * the locked tcb (last argument) is NOT a
2346				 * TCB.. aka NULL.
2347				 */
2348				SCTP_INP_INCR_REF(inp);
2349				stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddrp->spp_address, &net, NULL, NULL);
2350				if (stcb == NULL) {
2351					SCTP_INP_DECR_REF(inp);
2352				}
2353			}
2354			if (stcb && (net == NULL)) {
2355				struct sockaddr *sa;
2356
2357				sa = (struct sockaddr *)&paddrp->spp_address;
2358#ifdef INET
2359				if (sa->sa_family == AF_INET) {
2360					struct sockaddr_in *sin;
2361
2362					sin = (struct sockaddr_in *)sa;
2363					if (sin->sin_addr.s_addr) {
2364						error = EINVAL;
2365						SCTP_TCB_UNLOCK(stcb);
2366						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2367						break;
2368					}
2369				} else
2370#endif
2371#ifdef INET6
2372				if (sa->sa_family == AF_INET6) {
2373					struct sockaddr_in6 *sin6;
2374
2375					sin6 = (struct sockaddr_in6 *)sa;
2376					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
2377						error = EINVAL;
2378						SCTP_TCB_UNLOCK(stcb);
2379						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2380						break;
2381					}
2382				} else
2383#endif
2384				{
2385					error = EAFNOSUPPORT;
2386					SCTP_TCB_UNLOCK(stcb);
2387					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2388					break;
2389				}
2390			}
2391			if (stcb) {
2392				/* Applys to the specific association */
2393				paddrp->spp_flags = 0;
2394				if (net) {
2395					int ovh;
2396
2397					if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2398						ovh = SCTP_MED_OVERHEAD;
2399					} else {
2400						ovh = SCTP_MED_V4_OVERHEAD;
2401					}
2402
2403
2404					paddrp->spp_pathmaxrxt = net->failure_threshold;
2405					paddrp->spp_pathmtu = net->mtu - ovh;
2406					/* get flags for HB */
2407					if (net->dest_state & SCTP_ADDR_NOHB)
2408						paddrp->spp_flags |= SPP_HB_DISABLE;
2409					else
2410						paddrp->spp_flags |= SPP_HB_ENABLE;
2411					/* get flags for PMTU */
2412					if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
2413						paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2414					} else {
2415						paddrp->spp_flags |= SPP_PMTUD_DISABLE;
2416					}
2417#ifdef INET
2418					if (net->ro._l_addr.sin.sin_family == AF_INET) {
2419						paddrp->spp_ipv4_tos = net->tos_flowlabel & 0x000000fc;
2420						paddrp->spp_flags |= SPP_IPV4_TOS;
2421					}
2422#endif
2423#ifdef INET6
2424					if (net->ro._l_addr.sin6.sin6_family == AF_INET6) {
2425						paddrp->spp_ipv6_flowlabel = net->tos_flowlabel;
2426						paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2427					}
2428#endif
2429				} else {
2430					/*
2431					 * No destination so return default
2432					 * value
2433					 */
2434					int cnt = 0;
2435
2436					paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
2437					paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc);
2438#ifdef INET
2439					paddrp->spp_ipv4_tos = stcb->asoc.default_tos & 0x000000fc;
2440					paddrp->spp_flags |= SPP_IPV4_TOS;
2441#endif
2442#ifdef INET6
2443					paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel;
2444					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2445#endif
2446					/* default settings should be these */
2447					if (stcb->asoc.hb_is_disabled == 0) {
2448						paddrp->spp_flags |= SPP_HB_ENABLE;
2449					} else {
2450						paddrp->spp_flags |= SPP_HB_DISABLE;
2451					}
2452					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2453						if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
2454							cnt++;
2455						}
2456					}
2457					if (cnt) {
2458						paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2459					}
2460				}
2461				paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
2462				paddrp->spp_assoc_id = sctp_get_associd(stcb);
2463				SCTP_TCB_UNLOCK(stcb);
2464			} else {
2465				if (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC) {
2466					/* Use endpoint defaults */
2467					SCTP_INP_RLOCK(inp);
2468					paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
2469					paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
2470					paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
2471					/* get inp's default */
2472#ifdef INET
2473					paddrp->spp_ipv4_tos = inp->ip_inp.inp.inp_ip_tos;
2474					paddrp->spp_flags |= SPP_IPV4_TOS;
2475#endif
2476#ifdef INET6
2477					if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2478						paddrp->spp_ipv6_flowlabel = ((struct in6pcb *)inp)->in6p_flowinfo;
2479						paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2480					}
2481#endif
2482					/* can't return this */
2483					paddrp->spp_pathmtu = 0;
2484
2485					/* default behavior, no stcb */
2486					paddrp->spp_flags = SPP_PMTUD_ENABLE;
2487
2488					if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
2489						paddrp->spp_flags |= SPP_HB_ENABLE;
2490					} else {
2491						paddrp->spp_flags |= SPP_HB_DISABLE;
2492					}
2493					SCTP_INP_RUNLOCK(inp);
2494				} else {
2495					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2496					error = EINVAL;
2497				}
2498			}
2499			if (error == 0) {
2500				*optsize = sizeof(struct sctp_paddrparams);
2501			}
2502			break;
2503		}
2504	case SCTP_GET_PEER_ADDR_INFO:
2505		{
2506			struct sctp_paddrinfo *paddri;
2507			struct sctp_nets *net;
2508
2509			SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
2510			SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
2511
2512			net = NULL;
2513			if (stcb) {
2514				net = sctp_findnet(stcb, (struct sockaddr *)&paddri->spinfo_address);
2515			} else {
2516				/*
2517				 * We increment here since
2518				 * sctp_findassociation_ep_addr() wil do a
2519				 * decrement if it finds the stcb as long as
2520				 * the locked tcb (last argument) is NOT a
2521				 * TCB.. aka NULL.
2522				 */
2523				SCTP_INP_INCR_REF(inp);
2524				stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddri->spinfo_address, &net, NULL, NULL);
2525				if (stcb == NULL) {
2526					SCTP_INP_DECR_REF(inp);
2527				}
2528			}
2529
2530			if ((stcb) && (net)) {
2531				if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
2532					/* It's unconfirmed */
2533					paddri->spinfo_state = SCTP_UNCONFIRMED;
2534				} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
2535					/* It's active */
2536					paddri->spinfo_state = SCTP_ACTIVE;
2537				} else {
2538					/* It's inactive */
2539					paddri->spinfo_state = SCTP_INACTIVE;
2540				}
2541				paddri->spinfo_cwnd = net->cwnd;
2542				paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
2543				paddri->spinfo_rto = net->RTO;
2544				paddri->spinfo_assoc_id = sctp_get_associd(stcb);
2545				paddri->spinfo_mtu = net->mtu;
2546				SCTP_TCB_UNLOCK(stcb);
2547				*optsize = sizeof(struct sctp_paddrinfo);
2548			} else {
2549				if (stcb) {
2550					SCTP_TCB_UNLOCK(stcb);
2551				}
2552				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2553				error = ENOENT;
2554			}
2555			break;
2556		}
2557	case SCTP_PCB_STATUS:
2558		{
2559			struct sctp_pcbinfo *spcb;
2560
2561			SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
2562			sctp_fill_pcbinfo(spcb);
2563			*optsize = sizeof(struct sctp_pcbinfo);
2564			break;
2565		}
2566	case SCTP_STATUS:
2567		{
2568			struct sctp_nets *net;
2569			struct sctp_status *sstat;
2570
2571			SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
2572			SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
2573
2574			if (stcb == NULL) {
2575				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2576				error = EINVAL;
2577				break;
2578			}
2579			/*
2580			 * I think passing the state is fine since
2581			 * sctp_constants.h will be available to the user
2582			 * land.
2583			 */
2584			sstat->sstat_state = stcb->asoc.state;
2585			sstat->sstat_assoc_id = sctp_get_associd(stcb);
2586			sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
2587			sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
2588			/*
2589			 * We can't include chunks that have been passed to
2590			 * the socket layer. Only things in queue.
2591			 */
2592			sstat->sstat_penddata = (stcb->asoc.cnt_on_reasm_queue +
2593			    stcb->asoc.cnt_on_all_streams);
2594
2595
2596			sstat->sstat_instrms = stcb->asoc.streamincnt;
2597			sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
2598			sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
2599			memcpy(&sstat->sstat_primary.spinfo_address,
2600			    &stcb->asoc.primary_destination->ro._l_addr,
2601			    ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
2602			net = stcb->asoc.primary_destination;
2603			((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
2604			/*
2605			 * Again the user can get info from sctp_constants.h
2606			 * for what the state of the network is.
2607			 */
2608			if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
2609				/* It's unconfirmed */
2610				sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
2611			} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
2612				/* It's active */
2613				sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
2614			} else {
2615				/* It's inactive */
2616				sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
2617			}
2618			sstat->sstat_primary.spinfo_cwnd = net->cwnd;
2619			sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
2620			sstat->sstat_primary.spinfo_rto = net->RTO;
2621			sstat->sstat_primary.spinfo_mtu = net->mtu;
2622			sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
2623			SCTP_TCB_UNLOCK(stcb);
2624			*optsize = sizeof(struct sctp_status);
2625			break;
2626		}
2627	case SCTP_RTOINFO:
2628		{
2629			struct sctp_rtoinfo *srto;
2630
2631			SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
2632			SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
2633
2634			if (stcb) {
2635				srto->srto_initial = stcb->asoc.initial_rto;
2636				srto->srto_max = stcb->asoc.maxrto;
2637				srto->srto_min = stcb->asoc.minrto;
2638				SCTP_TCB_UNLOCK(stcb);
2639			} else {
2640				if (srto->srto_assoc_id == SCTP_FUTURE_ASSOC) {
2641					SCTP_INP_RLOCK(inp);
2642					srto->srto_initial = inp->sctp_ep.initial_rto;
2643					srto->srto_max = inp->sctp_ep.sctp_maxrto;
2644					srto->srto_min = inp->sctp_ep.sctp_minrto;
2645					SCTP_INP_RUNLOCK(inp);
2646				} else {
2647					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2648					error = EINVAL;
2649				}
2650			}
2651			if (error == 0) {
2652				*optsize = sizeof(struct sctp_rtoinfo);
2653			}
2654			break;
2655		}
2656	case SCTP_TIMEOUTS:
2657		{
2658			struct sctp_timeouts *stimo;
2659
2660			SCTP_CHECK_AND_CAST(stimo, optval, struct sctp_timeouts, *optsize);
2661			SCTP_FIND_STCB(inp, stcb, stimo->stimo_assoc_id);
2662
2663			if (stcb) {
2664				stimo->stimo_init = stcb->asoc.timoinit;
2665				stimo->stimo_data = stcb->asoc.timodata;
2666				stimo->stimo_sack = stcb->asoc.timosack;
2667				stimo->stimo_shutdown = stcb->asoc.timoshutdown;
2668				stimo->stimo_heartbeat = stcb->asoc.timoheartbeat;
2669				stimo->stimo_cookie = stcb->asoc.timocookie;
2670				stimo->stimo_shutdownack = stcb->asoc.timoshutdownack;
2671				SCTP_TCB_UNLOCK(stcb);
2672				*optsize = sizeof(struct sctp_timeouts);
2673			} else {
2674				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2675				error = EINVAL;
2676			}
2677			break;
2678		}
2679	case SCTP_ASSOCINFO:
2680		{
2681			struct sctp_assocparams *sasoc;
2682
2683			SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
2684			SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
2685
2686			if (stcb) {
2687				sasoc->sasoc_cookie_life = TICKS_TO_MSEC(stcb->asoc.cookie_life);
2688				sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
2689				sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
2690				sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
2691				sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
2692				SCTP_TCB_UNLOCK(stcb);
2693			} else {
2694				if (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC) {
2695					SCTP_INP_RLOCK(inp);
2696					sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
2697					sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
2698					sasoc->sasoc_number_peer_destinations = 0;
2699					sasoc->sasoc_peer_rwnd = 0;
2700					sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
2701					SCTP_INP_RUNLOCK(inp);
2702				} else {
2703					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2704					error = EINVAL;
2705				}
2706			}
2707			if (error == 0) {
2708				*optsize = sizeof(struct sctp_assocparams);
2709			}
2710			break;
2711		}
2712	case SCTP_DEFAULT_SEND_PARAM:
2713		{
2714			struct sctp_sndrcvinfo *s_info;
2715
2716			SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
2717			SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
2718
2719			if (stcb) {
2720				memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
2721				SCTP_TCB_UNLOCK(stcb);
2722			} else {
2723				if (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) {
2724					SCTP_INP_RLOCK(inp);
2725					memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
2726					SCTP_INP_RUNLOCK(inp);
2727				} else {
2728					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2729					error = EINVAL;
2730				}
2731			}
2732			if (error == 0) {
2733				*optsize = sizeof(struct sctp_sndrcvinfo);
2734			}
2735			break;
2736		}
2737	case SCTP_INITMSG:
2738		{
2739			struct sctp_initmsg *sinit;
2740
2741			SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
2742			SCTP_INP_RLOCK(inp);
2743			sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
2744			sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
2745			sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
2746			sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
2747			SCTP_INP_RUNLOCK(inp);
2748			*optsize = sizeof(struct sctp_initmsg);
2749			break;
2750		}
2751	case SCTP_PRIMARY_ADDR:
2752		/* we allow a "get" operation on this */
2753		{
2754			struct sctp_setprim *ssp;
2755
2756			SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
2757			SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
2758
2759			if (stcb) {
2760				/* simply copy out the sockaddr_storage... */
2761				int len;
2762
2763				len = *optsize;
2764				if (len > stcb->asoc.primary_destination->ro._l_addr.sa.sa_len)
2765					len = stcb->asoc.primary_destination->ro._l_addr.sa.sa_len;
2766
2767				memcpy(&ssp->ssp_addr,
2768				    &stcb->asoc.primary_destination->ro._l_addr,
2769				    len);
2770				SCTP_TCB_UNLOCK(stcb);
2771				*optsize = sizeof(struct sctp_setprim);
2772			} else {
2773				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2774				error = EINVAL;
2775			}
2776			break;
2777		}
2778	case SCTP_HMAC_IDENT:
2779		{
2780			struct sctp_hmacalgo *shmac;
2781			sctp_hmaclist_t *hmaclist;
2782			uint32_t size;
2783			int i;
2784
2785			SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
2786
2787			SCTP_INP_RLOCK(inp);
2788			hmaclist = inp->sctp_ep.local_hmacs;
2789			if (hmaclist == NULL) {
2790				/* no HMACs to return */
2791				*optsize = sizeof(*shmac);
2792				SCTP_INP_RUNLOCK(inp);
2793				break;
2794			}
2795			/* is there room for all of the hmac ids? */
2796			size = sizeof(*shmac) + (hmaclist->num_algo *
2797			    sizeof(shmac->shmac_idents[0]));
2798			if ((size_t)(*optsize) < size) {
2799				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2800				error = EINVAL;
2801				SCTP_INP_RUNLOCK(inp);
2802				break;
2803			}
2804			/* copy in the list */
2805			shmac->shmac_number_of_idents = hmaclist->num_algo;
2806			for (i = 0; i < hmaclist->num_algo; i++) {
2807				shmac->shmac_idents[i] = hmaclist->hmac[i];
2808			}
2809			SCTP_INP_RUNLOCK(inp);
2810			*optsize = size;
2811			break;
2812		}
2813	case SCTP_AUTH_ACTIVE_KEY:
2814		{
2815			struct sctp_authkeyid *scact;
2816
2817			SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
2818			SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
2819
2820			if (stcb) {
2821				/* get the active key on the assoc */
2822				scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
2823				SCTP_TCB_UNLOCK(stcb);
2824			} else {
2825				if (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) {
2826					/* get the endpoint active key */
2827					SCTP_INP_RLOCK(inp);
2828					scact->scact_keynumber = inp->sctp_ep.default_keyid;
2829					SCTP_INP_RUNLOCK(inp);
2830				} else {
2831					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2832					error = EINVAL;
2833				}
2834			}
2835			if (error == 0) {
2836				*optsize = sizeof(struct sctp_authkeyid);
2837			}
2838			break;
2839		}
2840	case SCTP_LOCAL_AUTH_CHUNKS:
2841		{
2842			struct sctp_authchunks *sac;
2843			sctp_auth_chklist_t *chklist = NULL;
2844			size_t size = 0;
2845
2846			SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
2847			SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
2848
2849			if (stcb) {
2850				/* get off the assoc */
2851				chklist = stcb->asoc.local_auth_chunks;
2852				/* is there enough space? */
2853				size = sctp_auth_get_chklist_size(chklist);
2854				if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2855					error = EINVAL;
2856					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2857				} else {
2858					/* copy in the chunks */
2859					(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2860					*optsize = sizeof(struct sctp_authchunks) + size;
2861				}
2862				SCTP_TCB_UNLOCK(stcb);
2863			} else {
2864				if (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC) {
2865					/* get off the endpoint */
2866					SCTP_INP_RLOCK(inp);
2867					chklist = inp->sctp_ep.local_auth_chunks;
2868					/* is there enough space? */
2869					size = sctp_auth_get_chklist_size(chklist);
2870					if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2871						error = EINVAL;
2872						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2873					} else {
2874						/* copy in the chunks */
2875						(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2876						*optsize = sizeof(struct sctp_authchunks) + size;
2877					}
2878					SCTP_INP_RUNLOCK(inp);
2879				} else {
2880					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2881					error = EINVAL;
2882				}
2883			}
2884			break;
2885		}
2886	case SCTP_PEER_AUTH_CHUNKS:
2887		{
2888			struct sctp_authchunks *sac;
2889			sctp_auth_chklist_t *chklist = NULL;
2890			size_t size = 0;
2891
2892			SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
2893			SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
2894
2895			if (stcb) {
2896				/* get off the assoc */
2897				chklist = stcb->asoc.peer_auth_chunks;
2898				/* is there enough space? */
2899				size = sctp_auth_get_chklist_size(chklist);
2900				if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2901					error = EINVAL;
2902					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2903				} else {
2904					/* copy in the chunks */
2905					(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2906					*optsize = sizeof(struct sctp_authchunks) + size;
2907				}
2908				SCTP_TCB_UNLOCK(stcb);
2909			} else {
2910				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2911				error = ENOENT;
2912			}
2913			break;
2914		}
2915	case SCTP_EVENT:
2916		{
2917			struct sctp_event *event;
2918			uint32_t event_type;
2919
2920			SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
2921			SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
2922
2923			switch (event->se_type) {
2924			case SCTP_ASSOC_CHANGE:
2925				event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
2926				break;
2927			case SCTP_PEER_ADDR_CHANGE:
2928				event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
2929				break;
2930			case SCTP_REMOTE_ERROR:
2931				event_type = SCTP_PCB_FLAGS_RECVPEERERR;
2932				break;
2933			case SCTP_SEND_FAILED:
2934				event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
2935				break;
2936			case SCTP_SHUTDOWN_EVENT:
2937				event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
2938				break;
2939			case SCTP_ADAPTATION_INDICATION:
2940				event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
2941				break;
2942			case SCTP_PARTIAL_DELIVERY_EVENT:
2943				event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
2944				break;
2945			case SCTP_AUTHENTICATION_EVENT:
2946				event_type = SCTP_PCB_FLAGS_AUTHEVNT;
2947				break;
2948			case SCTP_STREAM_RESET_EVENT:
2949				event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
2950				break;
2951			case SCTP_SENDER_DRY_EVENT:
2952				event_type = SCTP_PCB_FLAGS_DRYEVNT;
2953				break;
2954			case SCTP_NOTIFICATIONS_STOPPED_EVENT:
2955				event_type = 0;
2956				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
2957				error = ENOTSUP;
2958				break;
2959			default:
2960				event_type = 0;
2961				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2962				error = EINVAL;
2963				break;
2964			}
2965			if (event_type > 0) {
2966				if (stcb) {
2967					event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
2968					SCTP_TCB_UNLOCK(stcb);
2969				} else {
2970					if (event->se_assoc_id == SCTP_FUTURE_ASSOC) {
2971						SCTP_INP_RLOCK(inp);
2972						event->se_on = sctp_is_feature_on(inp, event_type);
2973						SCTP_INP_RUNLOCK(inp);
2974					} else {
2975						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2976						error = EINVAL;
2977					}
2978				}
2979			}
2980			if (error == 0) {
2981				*optsize = sizeof(struct sctp_event);
2982			}
2983			break;
2984		}
2985	case SCTP_RECVRCVINFO:
2986		{
2987			int onoff;
2988
2989			if (*optsize < sizeof(int)) {
2990				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2991				error = EINVAL;
2992			} else {
2993				SCTP_INP_RUNLOCK(inp);
2994				onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
2995				SCTP_INP_RUNLOCK(inp);
2996			}
2997			if (error == 0) {
2998				/* return the option value */
2999				*(int *)optval = onoff;
3000				*optsize = sizeof(int);
3001			}
3002			break;
3003		}
3004	case SCTP_RECVNXTINFO:
3005		{
3006			int onoff;
3007
3008			if (*optsize < sizeof(int)) {
3009				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3010				error = EINVAL;
3011			} else {
3012				SCTP_INP_RUNLOCK(inp);
3013				onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
3014				SCTP_INP_RUNLOCK(inp);
3015			}
3016			if (error == 0) {
3017				/* return the option value */
3018				*(int *)optval = onoff;
3019				*optsize = sizeof(int);
3020			}
3021			break;
3022		}
3023	case SCTP_DEFAULT_SNDINFO:
3024		{
3025			struct sctp_sndinfo *info;
3026
3027			SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
3028			SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
3029
3030			if (stcb) {
3031				info->snd_sid = stcb->asoc.def_send.sinfo_stream;
3032				info->snd_flags = stcb->asoc.def_send.sinfo_flags;
3033				info->snd_flags &= 0xfff0;
3034				info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
3035				info->snd_context = stcb->asoc.def_send.sinfo_context;
3036				SCTP_TCB_UNLOCK(stcb);
3037			} else {
3038				if (info->snd_assoc_id == SCTP_FUTURE_ASSOC) {
3039					SCTP_INP_RLOCK(inp);
3040					info->snd_sid = inp->def_send.sinfo_stream;
3041					info->snd_flags = inp->def_send.sinfo_flags;
3042					info->snd_flags &= 0xfff0;
3043					info->snd_ppid = inp->def_send.sinfo_ppid;
3044					info->snd_context = inp->def_send.sinfo_context;
3045					SCTP_INP_RUNLOCK(inp);
3046				} else {
3047					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3048					error = EINVAL;
3049				}
3050			}
3051			if (error == 0) {
3052				*optsize = sizeof(struct sctp_sndinfo);
3053			}
3054			break;
3055		}
3056	case SCTP_DEFAULT_PRINFO:
3057		{
3058			struct sctp_default_prinfo *info;
3059
3060			SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
3061			SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
3062
3063			if (stcb) {
3064				info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
3065				info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
3066				SCTP_TCB_UNLOCK(stcb);
3067			} else {
3068				if (info->pr_assoc_id == SCTP_FUTURE_ASSOC) {
3069					SCTP_INP_RLOCK(inp);
3070					info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
3071					info->pr_value = inp->def_send.sinfo_timetolive;
3072					SCTP_INP_RUNLOCK(inp);
3073				} else {
3074					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3075					error = EINVAL;
3076				}
3077			}
3078			if (error == 0) {
3079				*optsize = sizeof(struct sctp_default_prinfo);
3080			}
3081			break;
3082		}
3083	default:
3084		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3085		error = ENOPROTOOPT;
3086		break;
3087	}			/* end switch (sopt->sopt_name) */
3088	if (error) {
3089		*optsize = 0;
3090	}
3091	return (error);
3092}
3093
3094static int
3095sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
3096    void *p)
3097{
3098	int error, set_opt;
3099	uint32_t *mopt;
3100	struct sctp_tcb *stcb = NULL;
3101	struct sctp_inpcb *inp = NULL;
3102	uint32_t vrf_id;
3103
3104	if (optval == NULL) {
3105		SCTP_PRINTF("optval is NULL\n");
3106		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3107		return (EINVAL);
3108	}
3109	inp = (struct sctp_inpcb *)so->so_pcb;
3110	if (inp == 0) {
3111		SCTP_PRINTF("inp is NULL?\n");
3112		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3113		return EINVAL;
3114	}
3115	vrf_id = inp->def_vrf_id;
3116
3117	error = 0;
3118	switch (optname) {
3119	case SCTP_NODELAY:
3120	case SCTP_AUTOCLOSE:
3121	case SCTP_AUTO_ASCONF:
3122	case SCTP_EXPLICIT_EOR:
3123	case SCTP_DISABLE_FRAGMENTS:
3124	case SCTP_USE_EXT_RCVINFO:
3125	case SCTP_I_WANT_MAPPED_V4_ADDR:
3126		/* copy in the option value */
3127		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3128		set_opt = 0;
3129		if (error)
3130			break;
3131		switch (optname) {
3132		case SCTP_DISABLE_FRAGMENTS:
3133			set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
3134			break;
3135		case SCTP_AUTO_ASCONF:
3136			/*
3137			 * NOTE: we don't really support this flag
3138			 */
3139			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3140				/* only valid for bound all sockets */
3141				set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
3142			} else {
3143				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3144				return (EINVAL);
3145			}
3146			break;
3147		case SCTP_EXPLICIT_EOR:
3148			set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
3149			break;
3150		case SCTP_USE_EXT_RCVINFO:
3151			set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
3152			break;
3153		case SCTP_I_WANT_MAPPED_V4_ADDR:
3154			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
3155				set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
3156			} else {
3157				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3158				return (EINVAL);
3159			}
3160			break;
3161		case SCTP_NODELAY:
3162			set_opt = SCTP_PCB_FLAGS_NODELAY;
3163			break;
3164		case SCTP_AUTOCLOSE:
3165			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3166			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
3167				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3168				return (EINVAL);
3169			}
3170			set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
3171			/*
3172			 * The value is in ticks. Note this does not effect
3173			 * old associations, only new ones.
3174			 */
3175			inp->sctp_ep.auto_close_time = SEC_TO_TICKS(*mopt);
3176			break;
3177		}
3178		SCTP_INP_WLOCK(inp);
3179		if (*mopt != 0) {
3180			sctp_feature_on(inp, set_opt);
3181		} else {
3182			sctp_feature_off(inp, set_opt);
3183		}
3184		SCTP_INP_WUNLOCK(inp);
3185		break;
3186	case SCTP_REUSE_PORT:
3187		{
3188			SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3189			if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
3190				/* Can't set it after we are bound */
3191				error = EINVAL;
3192				break;
3193			}
3194			if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
3195				/* Can't do this for a 1-m socket */
3196				error = EINVAL;
3197				break;
3198			}
3199			if (optval)
3200				sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
3201			else
3202				sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
3203			break;
3204		}
3205	case SCTP_PARTIAL_DELIVERY_POINT:
3206		{
3207			uint32_t *value;
3208
3209			SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
3210			if (*value > SCTP_SB_LIMIT_RCV(so)) {
3211				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3212				error = EINVAL;
3213				break;
3214			}
3215			inp->partial_delivery_point = *value;
3216			break;
3217		}
3218	case SCTP_FRAGMENT_INTERLEAVE:
3219		/* not yet until we re-write sctp_recvmsg() */
3220		{
3221			uint32_t *level;
3222
3223			SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
3224			if (*level == SCTP_FRAG_LEVEL_2) {
3225				sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3226				sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3227			} else if (*level == SCTP_FRAG_LEVEL_1) {
3228				sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3229				sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3230			} else if (*level == SCTP_FRAG_LEVEL_0) {
3231				sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3232				sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3233
3234			} else {
3235				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3236				error = EINVAL;
3237			}
3238			break;
3239		}
3240	case SCTP_CMT_ON_OFF:
3241		if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
3242			struct sctp_assoc_value *av;
3243
3244			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3245			if (av->assoc_value > SCTP_CMT_MAX) {
3246				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3247				error = EINVAL;
3248				break;
3249			}
3250			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3251			if (stcb) {
3252				stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3253				SCTP_TCB_UNLOCK(stcb);
3254			} else {
3255				if ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
3256				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3257					SCTP_INP_WLOCK(inp);
3258					inp->sctp_cmt_on_off = av->assoc_value;
3259					SCTP_INP_WUNLOCK(inp);
3260				}
3261				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3262				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3263					SCTP_INP_RLOCK(inp);
3264					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3265						SCTP_TCB_LOCK(stcb);
3266						stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3267						SCTP_TCB_UNLOCK(stcb);
3268						SCTP_INP_RUNLOCK(inp);
3269					}
3270				}
3271			}
3272		} else {
3273			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3274			error = ENOPROTOOPT;
3275		}
3276		break;
3277	case SCTP_PLUGGABLE_CC:
3278		{
3279			struct sctp_assoc_value *av;
3280			struct sctp_nets *net;
3281
3282			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3283			if ((av->assoc_value != SCTP_CC_RFC2581) &&
3284			    (av->assoc_value != SCTP_CC_HSTCP) &&
3285			    (av->assoc_value != SCTP_CC_HTCP) &&
3286			    (av->assoc_value != SCTP_CC_RTCC)) {
3287				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3288				error = EINVAL;
3289				break;
3290			}
3291			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3292			if (stcb) {
3293				stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
3294				stcb->asoc.congestion_control_module = av->assoc_value;
3295				if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
3296					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3297						stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
3298					}
3299				}
3300				SCTP_TCB_UNLOCK(stcb);
3301			} else {
3302				if ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
3303				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3304					SCTP_INP_WLOCK(inp);
3305					inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
3306					SCTP_INP_WUNLOCK(inp);
3307				}
3308				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3309				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3310					SCTP_INP_RLOCK(inp);
3311					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3312						SCTP_TCB_LOCK(stcb);
3313						stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
3314						stcb->asoc.congestion_control_module = av->assoc_value;
3315						if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
3316							TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3317								stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
3318							}
3319						}
3320						SCTP_TCB_UNLOCK(stcb);
3321					}
3322					SCTP_INP_RUNLOCK(inp);
3323				}
3324			}
3325			break;
3326		}
3327	case SCTP_CC_OPTION:
3328		{
3329			struct sctp_cc_option *cc_opt;
3330
3331			SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
3332			SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
3333			if (stcb == NULL) {
3334				if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
3335					SCTP_INP_RLOCK(inp);
3336					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3337						SCTP_TCB_LOCK(stcb);
3338						if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
3339							(*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1, cc_opt);
3340						}
3341						SCTP_TCB_UNLOCK(stcb);
3342					}
3343					SCTP_INP_RUNLOCK(inp);
3344				} else {
3345					error = EINVAL;
3346				}
3347			} else {
3348				if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
3349					error = ENOTSUP;
3350				} else {
3351					error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1,
3352					    cc_opt);
3353				}
3354				SCTP_TCB_UNLOCK(stcb);
3355			}
3356			break;
3357		}
3358	case SCTP_PLUGGABLE_SS:
3359		{
3360			struct sctp_assoc_value *av;
3361
3362			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3363			if ((av->assoc_value != SCTP_SS_DEFAULT) &&
3364			    (av->assoc_value != SCTP_SS_DEFAULT) &&
3365			    (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
3366			    (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
3367			    (av->assoc_value != SCTP_SS_PRIORITY) &&
3368			    (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
3369			    (av->assoc_value != SCTP_SS_FIRST_COME)) {
3370				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3371				error = EINVAL;
3372				break;
3373			}
3374			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3375			if (stcb) {
3376				stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
3377				stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
3378				stcb->asoc.stream_scheduling_module = av->assoc_value;
3379				stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
3380				SCTP_TCB_UNLOCK(stcb);
3381			} else {
3382				if ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
3383				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3384					SCTP_INP_WLOCK(inp);
3385					inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
3386					SCTP_INP_WUNLOCK(inp);
3387				}
3388				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3389				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3390					SCTP_INP_RLOCK(inp);
3391					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3392						SCTP_TCB_LOCK(stcb);
3393						stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
3394						stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
3395						stcb->asoc.stream_scheduling_module = av->assoc_value;
3396						stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
3397						SCTP_TCB_UNLOCK(stcb);
3398					}
3399					SCTP_INP_RUNLOCK(inp);
3400				}
3401			}
3402			break;
3403		}
3404	case SCTP_SS_VALUE:
3405		{
3406			struct sctp_stream_value *av;
3407
3408			SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
3409			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3410			if (stcb) {
3411				if (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
3412				    av->stream_value) < 0) {
3413					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3414					error = EINVAL;
3415				}
3416				SCTP_TCB_UNLOCK(stcb);
3417			} else {
3418				if (av->assoc_id == SCTP_CURRENT_ASSOC) {
3419					SCTP_INP_RLOCK(inp);
3420					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3421						SCTP_TCB_LOCK(stcb);
3422						stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
3423						    &stcb->asoc,
3424						    &stcb->asoc.strmout[av->stream_id],
3425						    av->stream_value);
3426						SCTP_TCB_UNLOCK(stcb);
3427					}
3428					SCTP_INP_RUNLOCK(inp);
3429
3430				} else {
3431					/*
3432					 * Can't set stream value without
3433					 * association
3434					 */
3435					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3436					error = EINVAL;
3437				}
3438			}
3439			break;
3440		}
3441	case SCTP_CLR_STAT_LOG:
3442		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3443		error = EOPNOTSUPP;
3444		break;
3445	case SCTP_CONTEXT:
3446		{
3447			struct sctp_assoc_value *av;
3448
3449			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3450			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3451
3452			if (stcb) {
3453				stcb->asoc.context = av->assoc_value;
3454				SCTP_TCB_UNLOCK(stcb);
3455			} else {
3456				if ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
3457				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3458					SCTP_INP_WLOCK(inp);
3459					inp->sctp_context = av->assoc_value;
3460					SCTP_INP_WUNLOCK(inp);
3461				}
3462				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3463				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3464					SCTP_INP_RLOCK(inp);
3465					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3466						SCTP_TCB_LOCK(stcb);
3467						stcb->asoc.context = av->assoc_value;
3468						SCTP_TCB_UNLOCK(stcb);
3469					}
3470					SCTP_INP_RUNLOCK(inp);
3471				}
3472			}
3473			break;
3474		}
3475	case SCTP_VRF_ID:
3476		{
3477			uint32_t *default_vrfid;
3478
3479			SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
3480			if (*default_vrfid > SCTP_MAX_VRF_ID) {
3481				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3482				error = EINVAL;
3483				break;
3484			}
3485			inp->def_vrf_id = *default_vrfid;
3486			break;
3487		}
3488	case SCTP_DEL_VRF_ID:
3489		{
3490			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3491			error = EOPNOTSUPP;
3492			break;
3493		}
3494	case SCTP_ADD_VRF_ID:
3495		{
3496			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3497			error = EOPNOTSUPP;
3498			break;
3499		}
3500	case SCTP_DELAYED_SACK:
3501		{
3502			struct sctp_sack_info *sack;
3503
3504			SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
3505			SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
3506			if (sack->sack_delay) {
3507				if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
3508					sack->sack_delay = SCTP_MAX_SACK_DELAY;
3509				if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
3510					sack->sack_delay = TICKS_TO_MSEC(1);
3511				}
3512			}
3513			if (stcb) {
3514				if (sack->sack_delay) {
3515					stcb->asoc.delayed_ack = sack->sack_delay;
3516				}
3517				if (sack->sack_freq) {
3518					stcb->asoc.sack_freq = sack->sack_freq;
3519				}
3520				SCTP_TCB_UNLOCK(stcb);
3521			} else {
3522				if ((sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
3523				    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
3524					SCTP_INP_WLOCK(inp);
3525					if (sack->sack_delay) {
3526						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
3527					}
3528					if (sack->sack_freq) {
3529						inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
3530					}
3531					SCTP_INP_WUNLOCK(inp);
3532				}
3533				if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
3534				    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
3535					SCTP_INP_RLOCK(inp);
3536					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3537						SCTP_TCB_LOCK(stcb);
3538						if (sack->sack_delay) {
3539							stcb->asoc.delayed_ack = sack->sack_delay;
3540						}
3541						if (sack->sack_freq) {
3542							stcb->asoc.sack_freq = sack->sack_freq;
3543						}
3544						SCTP_TCB_UNLOCK(stcb);
3545					}
3546					SCTP_INP_RUNLOCK(inp);
3547				}
3548			}
3549			break;
3550		}
3551	case SCTP_AUTH_CHUNK:
3552		{
3553			struct sctp_authchunk *sauth;
3554
3555			SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
3556
3557			SCTP_INP_WLOCK(inp);
3558			if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
3559				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3560				error = EINVAL;
3561			}
3562			SCTP_INP_WUNLOCK(inp);
3563			break;
3564		}
3565	case SCTP_AUTH_KEY:
3566		{
3567			struct sctp_authkey *sca;
3568			struct sctp_keyhead *shared_keys;
3569			sctp_sharedkey_t *shared_key;
3570			sctp_key_t *key = NULL;
3571			size_t size;
3572
3573			SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
3574			if (sca->sca_keylength == 0) {
3575				size = optsize - sizeof(struct sctp_authkey);
3576			} else {
3577				if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
3578					size = sca->sca_keylength;
3579				} else {
3580					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3581					error = EINVAL;
3582					break;
3583				}
3584			}
3585			SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
3586
3587			if (stcb) {
3588				shared_keys = &stcb->asoc.shared_keys;
3589				/* clear the cached keys for this key id */
3590				sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
3591				/*
3592				 * create the new shared key and
3593				 * insert/replace it
3594				 */
3595				if (size > 0) {
3596					key = sctp_set_key(sca->sca_key, (uint32_t) size);
3597					if (key == NULL) {
3598						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3599						error = ENOMEM;
3600						SCTP_TCB_UNLOCK(stcb);
3601						break;
3602					}
3603				}
3604				shared_key = sctp_alloc_sharedkey();
3605				if (shared_key == NULL) {
3606					sctp_free_key(key);
3607					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3608					error = ENOMEM;
3609					SCTP_TCB_UNLOCK(stcb);
3610					break;
3611				}
3612				shared_key->key = key;
3613				shared_key->keyid = sca->sca_keynumber;
3614				error = sctp_insert_sharedkey(shared_keys, shared_key);
3615				SCTP_TCB_UNLOCK(stcb);
3616			} else {
3617				if ((sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
3618				    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
3619					SCTP_INP_WLOCK(inp);
3620					shared_keys = &inp->sctp_ep.shared_keys;
3621					/*
3622					 * clear the cached keys on all
3623					 * assocs for this key id
3624					 */
3625					sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
3626					/*
3627					 * create the new shared key and
3628					 * insert/replace it
3629					 */
3630					if (size > 0) {
3631						key = sctp_set_key(sca->sca_key, (uint32_t) size);
3632						if (key == NULL) {
3633							SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3634							error = ENOMEM;
3635							SCTP_INP_WUNLOCK(inp);
3636							break;
3637						}
3638					}
3639					shared_key = sctp_alloc_sharedkey();
3640					if (shared_key == NULL) {
3641						sctp_free_key(key);
3642						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3643						error = ENOMEM;
3644						SCTP_INP_WUNLOCK(inp);
3645						break;
3646					}
3647					shared_key->key = key;
3648					shared_key->keyid = sca->sca_keynumber;
3649					error = sctp_insert_sharedkey(shared_keys, shared_key);
3650					SCTP_INP_WUNLOCK(inp);
3651				}
3652				if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
3653				    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
3654					SCTP_INP_RLOCK(inp);
3655					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3656						SCTP_TCB_LOCK(stcb);
3657						shared_keys = &stcb->asoc.shared_keys;
3658						/*
3659						 * clear the cached keys for
3660						 * this key id
3661						 */
3662						sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
3663						/*
3664						 * create the new shared key
3665						 * and insert/replace it
3666						 */
3667						if (size > 0) {
3668							key = sctp_set_key(sca->sca_key, (uint32_t) size);
3669							if (key == NULL) {
3670								SCTP_TCB_UNLOCK(stcb);
3671								continue;
3672							}
3673						}
3674						shared_key = sctp_alloc_sharedkey();
3675						if (shared_key == NULL) {
3676							sctp_free_key(key);
3677							SCTP_TCB_UNLOCK(stcb);
3678							continue;
3679						}
3680						shared_key->key = key;
3681						shared_key->keyid = sca->sca_keynumber;
3682						error = sctp_insert_sharedkey(shared_keys, shared_key);
3683						SCTP_TCB_UNLOCK(stcb);
3684					}
3685					SCTP_INP_RUNLOCK(inp);
3686				}
3687			}
3688			break;
3689		}
3690	case SCTP_HMAC_IDENT:
3691		{
3692			struct sctp_hmacalgo *shmac;
3693			sctp_hmaclist_t *hmaclist;
3694			uint16_t hmacid;
3695			uint32_t i;
3696			size_t found;
3697
3698			SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
3699			if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) {
3700				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3701				error = EINVAL;
3702				break;
3703			}
3704			hmaclist = sctp_alloc_hmaclist(shmac->shmac_number_of_idents);
3705			if (hmaclist == NULL) {
3706				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3707				error = ENOMEM;
3708				break;
3709			}
3710			for (i = 0; i < shmac->shmac_number_of_idents; i++) {
3711				hmacid = shmac->shmac_idents[i];
3712				if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
3713					 /* invalid HMACs were found */ ;
3714					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3715					error = EINVAL;
3716					sctp_free_hmaclist(hmaclist);
3717					goto sctp_set_hmac_done;
3718				}
3719			}
3720			found = 0;
3721			for (i = 0; i < hmaclist->num_algo; i++) {
3722				if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
3723					/* already in list */
3724					found = 1;
3725				}
3726			}
3727			if (!found) {
3728				sctp_free_hmaclist(hmaclist);
3729				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3730				error = EINVAL;
3731				break;
3732			}
3733			/* set it on the endpoint */
3734			SCTP_INP_WLOCK(inp);
3735			if (inp->sctp_ep.local_hmacs)
3736				sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
3737			inp->sctp_ep.local_hmacs = hmaclist;
3738			SCTP_INP_WUNLOCK(inp);
3739	sctp_set_hmac_done:
3740			break;
3741		}
3742	case SCTP_AUTH_ACTIVE_KEY:
3743		{
3744			struct sctp_authkeyid *scact;
3745
3746			SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
3747			SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
3748
3749			/* set the active key on the right place */
3750			if (stcb) {
3751				/* set the active key on the assoc */
3752				if (sctp_auth_setactivekey(stcb,
3753				    scact->scact_keynumber)) {
3754					SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
3755					    SCTP_FROM_SCTP_USRREQ,
3756					    EINVAL);
3757					error = EINVAL;
3758				}
3759				SCTP_TCB_UNLOCK(stcb);
3760			} else {
3761				if ((scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
3762				    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
3763					SCTP_INP_WLOCK(inp);
3764					if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
3765						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3766						error = EINVAL;
3767					}
3768					SCTP_INP_WUNLOCK(inp);
3769				}
3770				if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
3771				    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
3772					SCTP_INP_RLOCK(inp);
3773					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3774						SCTP_TCB_LOCK(stcb);
3775						sctp_auth_setactivekey(stcb, scact->scact_keynumber);
3776						SCTP_TCB_UNLOCK(stcb);
3777					}
3778					SCTP_INP_RUNLOCK(inp);
3779				}
3780			}
3781			break;
3782		}
3783	case SCTP_AUTH_DELETE_KEY:
3784		{
3785			struct sctp_authkeyid *scdel;
3786
3787			SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
3788			SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
3789
3790			/* delete the key from the right place */
3791			if (stcb) {
3792				if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
3793					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3794					error = EINVAL;
3795				}
3796				SCTP_TCB_UNLOCK(stcb);
3797			} else {
3798				if ((scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
3799				    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
3800					SCTP_INP_WLOCK(inp);
3801					if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
3802						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3803						error = EINVAL;
3804					}
3805					SCTP_INP_WUNLOCK(inp);
3806				}
3807				if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
3808				    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
3809					SCTP_INP_RLOCK(inp);
3810					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3811						SCTP_TCB_LOCK(stcb);
3812						sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
3813						SCTP_TCB_UNLOCK(stcb);
3814					}
3815					SCTP_INP_RUNLOCK(inp);
3816				}
3817			}
3818			break;
3819		}
3820	case SCTP_AUTH_DEACTIVATE_KEY:
3821		{
3822			struct sctp_authkeyid *keyid;
3823
3824			SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
3825			SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
3826
3827			/* deactivate the key from the right place */
3828			if (stcb) {
3829				if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
3830					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3831					error = EINVAL;
3832				}
3833				SCTP_TCB_UNLOCK(stcb);
3834			} else {
3835				if ((keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
3836				    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
3837					SCTP_INP_WLOCK(inp);
3838					if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
3839						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3840						error = EINVAL;
3841					}
3842					SCTP_INP_WUNLOCK(inp);
3843				}
3844				if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
3845				    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
3846					SCTP_INP_RLOCK(inp);
3847					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3848						SCTP_TCB_LOCK(stcb);
3849						sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
3850						SCTP_TCB_UNLOCK(stcb);
3851					}
3852					SCTP_INP_RUNLOCK(inp);
3853				}
3854			}
3855			break;
3856		}
3857
3858	case SCTP_RESET_STREAMS:
3859		{
3860			struct sctp_stream_reset *strrst;
3861			uint8_t send_in = 0, send_tsn = 0, send_out = 0,
3862			        addstream = 0;
3863			uint16_t addstrmcnt = 0;
3864			int i;
3865
3866			SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_stream_reset, optsize);
3867			SCTP_FIND_STCB(inp, stcb, strrst->strrst_assoc_id);
3868
3869			if (stcb == NULL) {
3870				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
3871				error = ENOENT;
3872				break;
3873			}
3874			if (stcb->asoc.peer_supports_strreset == 0) {
3875				/*
3876				 * Peer does not support it, we return
3877				 * protocol not supported since this is true
3878				 * for this feature and this peer, not the
3879				 * socket request in general.
3880				 */
3881				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPROTONOSUPPORT);
3882				error = EPROTONOSUPPORT;
3883				SCTP_TCB_UNLOCK(stcb);
3884				break;
3885			}
3886			if (stcb->asoc.stream_reset_outstanding) {
3887				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
3888				error = EALREADY;
3889				SCTP_TCB_UNLOCK(stcb);
3890				break;
3891			}
3892			if (strrst->strrst_flags == SCTP_RESET_LOCAL_RECV) {
3893				send_in = 1;
3894			} else if (strrst->strrst_flags == SCTP_RESET_LOCAL_SEND) {
3895				send_out = 1;
3896			} else if (strrst->strrst_flags == SCTP_RESET_BOTH) {
3897				send_in = 1;
3898				send_out = 1;
3899			} else if (strrst->strrst_flags == SCTP_RESET_TSN) {
3900				send_tsn = 1;
3901			} else if (strrst->strrst_flags == SCTP_RESET_ADD_STREAMS) {
3902				if (send_tsn ||
3903				    send_in ||
3904				    send_out) {
3905					/* We can't do that and add streams */
3906					error = EINVAL;
3907					goto skip_stuff;
3908				}
3909				if (stcb->asoc.stream_reset_outstanding) {
3910					error = EBUSY;
3911					goto skip_stuff;
3912				}
3913				addstream = 1;
3914				/* We allocate here */
3915				addstrmcnt = strrst->strrst_num_streams;
3916				if ((int)(addstrmcnt + stcb->asoc.streamoutcnt) > 0xffff) {
3917					/* You can't have more than 64k */
3918					error = EINVAL;
3919					goto skip_stuff;
3920				}
3921				if ((stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt) < addstrmcnt) {
3922					/* Need to allocate more */
3923					struct sctp_stream_out *oldstream;
3924					struct sctp_stream_queue_pending *sp,
3925					                         *nsp;
3926
3927					oldstream = stcb->asoc.strmout;
3928					/* get some more */
3929					SCTP_MALLOC(stcb->asoc.strmout, struct sctp_stream_out *,
3930					    ((stcb->asoc.streamoutcnt + addstrmcnt) * sizeof(struct sctp_stream_out)),
3931					    SCTP_M_STRMO);
3932					if (stcb->asoc.strmout == NULL) {
3933						stcb->asoc.strmout = oldstream;
3934						error = ENOMEM;
3935						goto skip_stuff;
3936					}
3937					/*
3938					 * Ok now we proceed with copying
3939					 * the old out stuff and
3940					 * initializing the new stuff.
3941					 */
3942					SCTP_TCB_SEND_LOCK(stcb);
3943					stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 0, 1);
3944					for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
3945						TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
3946						stcb->asoc.strmout[i].next_sequence_sent = oldstream[i].next_sequence_sent;
3947						stcb->asoc.strmout[i].last_msg_incomplete = oldstream[i].last_msg_incomplete;
3948						stcb->asoc.strmout[i].stream_no = i;
3949						stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], &oldstream[i]);
3950						/*
3951						 * now anything on those
3952						 * queues?
3953						 */
3954						TAILQ_FOREACH_SAFE(sp, &oldstream[i].outqueue, next, nsp) {
3955							TAILQ_REMOVE(&oldstream[i].outqueue, sp, next);
3956							TAILQ_INSERT_TAIL(&stcb->asoc.strmout[i].outqueue, sp, next);
3957						}
3958						/*
3959						 * Now move assoc pointers
3960						 * too
3961						 */
3962						if (stcb->asoc.last_out_stream == &oldstream[i]) {
3963							stcb->asoc.last_out_stream = &stcb->asoc.strmout[i];
3964						}
3965						if (stcb->asoc.locked_on_sending == &oldstream[i]) {
3966							stcb->asoc.locked_on_sending = &stcb->asoc.strmout[i];
3967						}
3968					}
3969					/* now the new streams */
3970					stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
3971					for (i = stcb->asoc.streamoutcnt; i < (stcb->asoc.streamoutcnt + addstrmcnt); i++) {
3972						stcb->asoc.strmout[i].next_sequence_sent = 0x0;
3973						TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
3974						stcb->asoc.strmout[i].stream_no = i;
3975						stcb->asoc.strmout[i].last_msg_incomplete = 0;
3976						stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL);
3977					}
3978					stcb->asoc.strm_realoutsize = stcb->asoc.streamoutcnt + addstrmcnt;
3979					SCTP_FREE(oldstream, SCTP_M_STRMO);
3980				}
3981				SCTP_TCB_SEND_UNLOCK(stcb);
3982				goto skip_stuff;
3983			} else {
3984				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3985				error = EINVAL;
3986				SCTP_TCB_UNLOCK(stcb);
3987				break;
3988			}
3989			for (i = 0; i < strrst->strrst_num_streams; i++) {
3990				if ((send_in) &&
3991
3992				    (strrst->strrst_list[i] > stcb->asoc.streamincnt)) {
3993					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3994					error = EINVAL;
3995					goto get_out;
3996				}
3997				if ((send_out) &&
3998				    (strrst->strrst_list[i] > stcb->asoc.streamoutcnt)) {
3999					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4000					error = EINVAL;
4001					goto get_out;
4002				}
4003			}
4004	skip_stuff:
4005			if (error) {
4006		get_out:
4007				SCTP_TCB_UNLOCK(stcb);
4008				break;
4009			}
4010			error = sctp_send_str_reset_req(stcb, strrst->strrst_num_streams,
4011			    strrst->strrst_list,
4012			    send_out, (stcb->asoc.str_reset_seq_in - 3),
4013			    send_in, send_tsn, addstream, addstrmcnt);
4014
4015			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4016			SCTP_TCB_UNLOCK(stcb);
4017			break;
4018		}
4019	case SCTP_CONNECT_X:
4020		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4021			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4022			error = EINVAL;
4023			break;
4024		}
4025		error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
4026		break;
4027	case SCTP_CONNECT_X_DELAYED:
4028		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4029			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4030			error = EINVAL;
4031			break;
4032		}
4033		error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
4034		break;
4035	case SCTP_CONNECT_X_COMPLETE:
4036		{
4037			struct sockaddr *sa;
4038			struct sctp_nets *net;
4039
4040			/* FIXME MT: check correct? */
4041			SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
4042
4043			/* find tcb */
4044			if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
4045				SCTP_INP_RLOCK(inp);
4046				stcb = LIST_FIRST(&inp->sctp_asoc_list);
4047				if (stcb) {
4048					SCTP_TCB_LOCK(stcb);
4049					net = sctp_findnet(stcb, sa);
4050				}
4051				SCTP_INP_RUNLOCK(inp);
4052			} else {
4053				/*
4054				 * We increment here since
4055				 * sctp_findassociation_ep_addr() wil do a
4056				 * decrement if it finds the stcb as long as
4057				 * the locked tcb (last argument) is NOT a
4058				 * TCB.. aka NULL.
4059				 */
4060				SCTP_INP_INCR_REF(inp);
4061				stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
4062				if (stcb == NULL) {
4063					SCTP_INP_DECR_REF(inp);
4064				}
4065			}
4066
4067			if (stcb == NULL) {
4068				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4069				error = ENOENT;
4070				break;
4071			}
4072			if (stcb->asoc.delayed_connection == 1) {
4073				stcb->asoc.delayed_connection = 0;
4074				(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
4075				sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
4076				    stcb->asoc.primary_destination,
4077				    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
4078				sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
4079			} else {
4080				/*
4081				 * already expired or did not use delayed
4082				 * connectx
4083				 */
4084				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4085				error = EALREADY;
4086			}
4087			SCTP_TCB_UNLOCK(stcb);
4088			break;
4089		}
4090	case SCTP_MAX_BURST:
4091		{
4092			struct sctp_assoc_value *av;
4093
4094			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4095			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4096
4097			if (stcb) {
4098				stcb->asoc.max_burst = av->assoc_value;
4099				SCTP_TCB_UNLOCK(stcb);
4100			} else {
4101				if ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4102				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4103					SCTP_INP_WLOCK(inp);
4104					inp->sctp_ep.max_burst = av->assoc_value;
4105					SCTP_INP_WUNLOCK(inp);
4106				}
4107				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4108				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4109					SCTP_INP_RLOCK(inp);
4110					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4111						SCTP_TCB_LOCK(stcb);
4112						stcb->asoc.max_burst = av->assoc_value;
4113						SCTP_TCB_UNLOCK(stcb);
4114					}
4115					SCTP_INP_RUNLOCK(inp);
4116				}
4117			}
4118			break;
4119		}
4120	case SCTP_MAXSEG:
4121		{
4122			struct sctp_assoc_value *av;
4123			int ovh;
4124
4125			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4126			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4127
4128			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4129				ovh = SCTP_MED_OVERHEAD;
4130			} else {
4131				ovh = SCTP_MED_V4_OVERHEAD;
4132			}
4133			if (stcb) {
4134				if (av->assoc_value) {
4135					stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
4136				} else {
4137					stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4138				}
4139				SCTP_TCB_UNLOCK(stcb);
4140			} else {
4141				if (av->assoc_id == SCTP_FUTURE_ASSOC) {
4142					SCTP_INP_WLOCK(inp);
4143					/*
4144					 * FIXME MT: I think this is not in
4145					 * tune with the API ID
4146					 */
4147					if (av->assoc_value) {
4148						inp->sctp_frag_point = (av->assoc_value + ovh);
4149					} else {
4150						inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4151					}
4152					SCTP_INP_WUNLOCK(inp);
4153				} else {
4154					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4155					error = EINVAL;
4156				}
4157			}
4158			break;
4159		}
4160	case SCTP_EVENTS:
4161		{
4162			struct sctp_event_subscribe *events;
4163
4164			SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
4165
4166			SCTP_INP_WLOCK(inp);
4167			if (events->sctp_data_io_event) {
4168				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4169			} else {
4170				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4171			}
4172
4173			if (events->sctp_association_event) {
4174				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4175			} else {
4176				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4177			}
4178
4179			if (events->sctp_address_event) {
4180				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4181			} else {
4182				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4183			}
4184
4185			if (events->sctp_send_failure_event) {
4186				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4187			} else {
4188				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4189			}
4190
4191			if (events->sctp_peer_error_event) {
4192				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4193			} else {
4194				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4195			}
4196
4197			if (events->sctp_shutdown_event) {
4198				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4199			} else {
4200				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4201			}
4202
4203			if (events->sctp_partial_delivery_event) {
4204				sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4205			} else {
4206				sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4207			}
4208
4209			if (events->sctp_adaptation_layer_event) {
4210				sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4211			} else {
4212				sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4213			}
4214
4215			if (events->sctp_authentication_event) {
4216				sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4217			} else {
4218				sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4219			}
4220
4221			if (events->sctp_sender_dry_event) {
4222				sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
4223			} else {
4224				sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
4225			}
4226
4227			if (events->sctp_stream_reset_event) {
4228				sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4229			} else {
4230				sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4231			}
4232			SCTP_INP_WUNLOCK(inp);
4233
4234			SCTP_INP_RLOCK(inp);
4235			LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4236				SCTP_TCB_LOCK(stcb);
4237				if (events->sctp_association_event) {
4238					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4239				} else {
4240					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4241				}
4242				if (events->sctp_address_event) {
4243					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4244				} else {
4245					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4246				}
4247				if (events->sctp_send_failure_event) {
4248					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4249				} else {
4250					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4251				}
4252				if (events->sctp_peer_error_event) {
4253					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4254				} else {
4255					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4256				}
4257				if (events->sctp_shutdown_event) {
4258					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4259				} else {
4260					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4261				}
4262				if (events->sctp_partial_delivery_event) {
4263					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4264				} else {
4265					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4266				}
4267				if (events->sctp_adaptation_layer_event) {
4268					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4269				} else {
4270					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4271				}
4272				if (events->sctp_authentication_event) {
4273					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4274				} else {
4275					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4276				}
4277				if (events->sctp_sender_dry_event) {
4278					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4279				} else {
4280					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4281				}
4282				if (events->sctp_stream_reset_event) {
4283					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4284				} else {
4285					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4286				}
4287				SCTP_TCB_UNLOCK(stcb);
4288			}
4289			/*
4290			 * Send up the sender dry event only for 1-to-1
4291			 * style sockets.
4292			 */
4293			if (events->sctp_sender_dry_event) {
4294				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4295				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
4296					stcb = LIST_FIRST(&inp->sctp_asoc_list);
4297					if (stcb) {
4298						SCTP_TCB_LOCK(stcb);
4299						if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
4300						    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
4301						    (stcb->asoc.stream_queue_cnt == 0)) {
4302							sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
4303						}
4304						SCTP_TCB_UNLOCK(stcb);
4305					}
4306				}
4307			}
4308			SCTP_INP_RUNLOCK(inp);
4309			break;
4310		}
4311	case SCTP_ADAPTATION_LAYER:
4312		{
4313			struct sctp_setadaptation *adap_bits;
4314
4315			SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
4316			SCTP_INP_WLOCK(inp);
4317			inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
4318			SCTP_INP_WUNLOCK(inp);
4319			break;
4320		}
4321#ifdef SCTP_DEBUG
4322	case SCTP_SET_INITIAL_DBG_SEQ:
4323		{
4324			uint32_t *vvv;
4325
4326			SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
4327			SCTP_INP_WLOCK(inp);
4328			inp->sctp_ep.initial_sequence_debug = *vvv;
4329			SCTP_INP_WUNLOCK(inp);
4330			break;
4331		}
4332#endif
4333	case SCTP_DEFAULT_SEND_PARAM:
4334		{
4335			struct sctp_sndrcvinfo *s_info;
4336
4337			SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
4338			SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
4339
4340			if (stcb) {
4341				if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4342					memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4343				} else {
4344					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4345					error = EINVAL;
4346				}
4347				SCTP_TCB_UNLOCK(stcb);
4348			} else {
4349				if ((s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
4350				    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
4351					SCTP_INP_WLOCK(inp);
4352					memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
4353					SCTP_INP_WUNLOCK(inp);
4354				}
4355				if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
4356				    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
4357					SCTP_INP_RLOCK(inp);
4358					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4359						SCTP_TCB_LOCK(stcb);
4360						if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4361							memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4362						}
4363						SCTP_TCB_UNLOCK(stcb);
4364					}
4365					SCTP_INP_RUNLOCK(inp);
4366				}
4367			}
4368			break;
4369		}
4370	case SCTP_PEER_ADDR_PARAMS:
4371		/* Applys to the specific association */
4372		{
4373			struct sctp_paddrparams *paddrp;
4374			struct sctp_nets *net;
4375
4376			SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
4377			SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
4378			net = NULL;
4379			if (stcb) {
4380				net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
4381			} else {
4382				/*
4383				 * We increment here since
4384				 * sctp_findassociation_ep_addr() wil do a
4385				 * decrement if it finds the stcb as long as
4386				 * the locked tcb (last argument) is NOT a
4387				 * TCB.. aka NULL.
4388				 */
4389				SCTP_INP_INCR_REF(inp);
4390				stcb = sctp_findassociation_ep_addr(&inp,
4391				    (struct sockaddr *)&paddrp->spp_address,
4392				    &net, NULL, NULL);
4393				if (stcb == NULL) {
4394					SCTP_INP_DECR_REF(inp);
4395				}
4396			}
4397			if (stcb && (net == NULL)) {
4398				struct sockaddr *sa;
4399
4400				sa = (struct sockaddr *)&paddrp->spp_address;
4401#ifdef INET
4402				if (sa->sa_family == AF_INET) {
4403
4404					struct sockaddr_in *sin;
4405
4406					sin = (struct sockaddr_in *)sa;
4407					if (sin->sin_addr.s_addr) {
4408						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4409						SCTP_TCB_UNLOCK(stcb);
4410						error = EINVAL;
4411						break;
4412					}
4413				} else
4414#endif
4415#ifdef INET6
4416				if (sa->sa_family == AF_INET6) {
4417					struct sockaddr_in6 *sin6;
4418
4419					sin6 = (struct sockaddr_in6 *)sa;
4420					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
4421						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4422						SCTP_TCB_UNLOCK(stcb);
4423						error = EINVAL;
4424						break;
4425					}
4426				} else
4427#endif
4428				{
4429					error = EAFNOSUPPORT;
4430					SCTP_TCB_UNLOCK(stcb);
4431					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4432					break;
4433				}
4434			}
4435			/* sanity checks */
4436			if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
4437				if (stcb)
4438					SCTP_TCB_UNLOCK(stcb);
4439				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4440				return (EINVAL);
4441			}
4442			if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
4443				if (stcb)
4444					SCTP_TCB_UNLOCK(stcb);
4445				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4446				return (EINVAL);
4447			}
4448			if (stcb) {
4449				/************************TCB SPECIFIC SET ******************/
4450				/*
4451				 * do we change the timer for HB, we run
4452				 * only one?
4453				 */
4454				int ovh = 0;
4455
4456				if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4457					ovh = SCTP_MED_OVERHEAD;
4458				} else {
4459					ovh = SCTP_MED_V4_OVERHEAD;
4460				}
4461
4462				if (paddrp->spp_hbinterval)
4463					stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
4464				else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
4465					stcb->asoc.heart_beat_delay = 0;
4466
4467				/* network sets ? */
4468				if (net) {
4469					/************************NET SPECIFIC SET ******************/
4470					if (paddrp->spp_flags & SPP_HB_DEMAND) {
4471						/* on demand HB */
4472						if (sctp_send_hb(stcb, 1, net, SCTP_SO_LOCKED) < 0) {
4473							/* asoc destroyed */
4474							SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4475							error = EINVAL;
4476							break;
4477						}
4478					}
4479					if (paddrp->spp_flags & SPP_HB_DISABLE) {
4480						net->dest_state |= SCTP_ADDR_NOHB;
4481					}
4482					if (paddrp->spp_flags & SPP_HB_ENABLE) {
4483						net->dest_state &= ~SCTP_ADDR_NOHB;
4484					}
4485					if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
4486						if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4487							sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
4488							    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4489						}
4490						if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) {
4491							net->mtu = paddrp->spp_pathmtu + ovh;
4492							if (net->mtu < stcb->asoc.smallest_mtu) {
4493								sctp_pathmtu_adjustment(inp, stcb, net, net->mtu);
4494							}
4495						}
4496					}
4497					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
4498						if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4499							sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
4500						}
4501					}
4502					if (paddrp->spp_pathmaxrxt)
4503						net->failure_threshold = paddrp->spp_pathmaxrxt;
4504#ifdef INET
4505					if (paddrp->spp_flags & SPP_IPV4_TOS) {
4506						if (net->ro._l_addr.sin.sin_family == AF_INET) {
4507							net->tos_flowlabel = paddrp->spp_ipv4_tos & 0x000000fc;
4508						}
4509					}
4510#endif
4511#ifdef INET6
4512					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
4513						if (net->ro._l_addr.sin6.sin6_family == AF_INET6) {
4514							net->tos_flowlabel = paddrp->spp_ipv6_flowlabel;
4515						}
4516					}
4517#endif
4518				} else {
4519					/************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
4520					if (paddrp->spp_pathmaxrxt)
4521						stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
4522
4523					if (paddrp->spp_flags & SPP_HB_ENABLE) {
4524						/* Turn back on the timer */
4525						stcb->asoc.hb_is_disabled = 0;
4526						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
4527					}
4528					if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
4529						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4530							if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4531								sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
4532								    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4533							}
4534							if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) {
4535								net->mtu = paddrp->spp_pathmtu + ovh;
4536								if (net->mtu < stcb->asoc.smallest_mtu) {
4537									sctp_pathmtu_adjustment(inp, stcb, net, net->mtu);
4538								}
4539							}
4540						}
4541					}
4542					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
4543						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4544							if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4545								sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
4546							}
4547						}
4548					}
4549					if (paddrp->spp_flags & SPP_HB_DISABLE) {
4550						int cnt_of_unconf = 0;
4551						struct sctp_nets *lnet;
4552
4553						stcb->asoc.hb_is_disabled = 1;
4554						TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
4555							if (lnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
4556								cnt_of_unconf++;
4557							}
4558						}
4559						/*
4560						 * stop the timer ONLY if we
4561						 * have no unconfirmed
4562						 * addresses
4563						 */
4564						if (cnt_of_unconf == 0) {
4565							TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4566								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
4567								    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_11);
4568							}
4569						}
4570					}
4571					if (paddrp->spp_flags & SPP_HB_ENABLE) {
4572						/* start up the timer. */
4573						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4574							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
4575						}
4576					}
4577#ifdef INET
4578					if (paddrp->spp_flags & SPP_IPV4_TOS)
4579						stcb->asoc.default_tos = paddrp->spp_ipv4_tos & 0x000000fc;
4580#endif
4581#ifdef INET6
4582					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL)
4583						stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel;
4584#endif
4585
4586				}
4587				SCTP_TCB_UNLOCK(stcb);
4588			} else {
4589				/************************NO TCB, SET TO default stuff ******************/
4590				if (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC) {
4591					SCTP_INP_WLOCK(inp);
4592					/*
4593					 * For the TOS/FLOWLABEL stuff you
4594					 * set it with the options on the
4595					 * socket
4596					 */
4597					if (paddrp->spp_pathmaxrxt) {
4598						inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
4599					}
4600					if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
4601						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
4602					else if (paddrp->spp_hbinterval) {
4603						if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
4604							paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
4605						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
4606					}
4607					if (paddrp->spp_flags & SPP_HB_ENABLE) {
4608						sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
4609
4610					} else if (paddrp->spp_flags & SPP_HB_DISABLE) {
4611						sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
4612					}
4613					SCTP_INP_WUNLOCK(inp);
4614				} else {
4615					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4616					error = EINVAL;
4617				}
4618			}
4619			break;
4620		}
4621	case SCTP_RTOINFO:
4622		{
4623			struct sctp_rtoinfo *srto;
4624			uint32_t new_init, new_min, new_max;
4625
4626			SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
4627			SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
4628
4629			if (stcb) {
4630				if (srto->srto_initial)
4631					new_init = srto->srto_initial;
4632				else
4633					new_init = stcb->asoc.initial_rto;
4634				if (srto->srto_max)
4635					new_max = srto->srto_max;
4636				else
4637					new_max = stcb->asoc.maxrto;
4638				if (srto->srto_min)
4639					new_min = srto->srto_min;
4640				else
4641					new_min = stcb->asoc.minrto;
4642				if ((new_min <= new_init) && (new_init <= new_max)) {
4643					stcb->asoc.initial_rto = new_init;
4644					stcb->asoc.maxrto = new_max;
4645					stcb->asoc.minrto = new_min;
4646				} else {
4647					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4648					error = EINVAL;
4649				}
4650				SCTP_TCB_UNLOCK(stcb);
4651			} else {
4652				if (srto->srto_assoc_id == SCTP_FUTURE_ASSOC) {
4653					SCTP_INP_WLOCK(inp);
4654					if (srto->srto_initial)
4655						new_init = srto->srto_initial;
4656					else
4657						new_init = inp->sctp_ep.initial_rto;
4658					if (srto->srto_max)
4659						new_max = srto->srto_max;
4660					else
4661						new_max = inp->sctp_ep.sctp_maxrto;
4662					if (srto->srto_min)
4663						new_min = srto->srto_min;
4664					else
4665						new_min = inp->sctp_ep.sctp_minrto;
4666					if ((new_min <= new_init) && (new_init <= new_max)) {
4667						inp->sctp_ep.initial_rto = new_init;
4668						inp->sctp_ep.sctp_maxrto = new_max;
4669						inp->sctp_ep.sctp_minrto = new_min;
4670					} else {
4671						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4672						error = EINVAL;
4673					}
4674					SCTP_INP_WUNLOCK(inp);
4675				} else {
4676					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4677					error = EINVAL;
4678				}
4679			}
4680			break;
4681		}
4682	case SCTP_ASSOCINFO:
4683		{
4684			struct sctp_assocparams *sasoc;
4685
4686			SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
4687			SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
4688			if (sasoc->sasoc_cookie_life) {
4689				/* boundary check the cookie life */
4690				if (sasoc->sasoc_cookie_life < 1000)
4691					sasoc->sasoc_cookie_life = 1000;
4692				if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
4693					sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
4694				}
4695			}
4696			if (stcb) {
4697				if (sasoc->sasoc_asocmaxrxt)
4698					stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
4699				if (sasoc->sasoc_cookie_life) {
4700					stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
4701				}
4702				SCTP_TCB_UNLOCK(stcb);
4703			} else {
4704				if (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC) {
4705					SCTP_INP_WLOCK(inp);
4706					if (sasoc->sasoc_asocmaxrxt)
4707						inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
4708					if (sasoc->sasoc_cookie_life) {
4709						inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
4710					}
4711					SCTP_INP_WUNLOCK(inp);
4712				} else {
4713					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4714					error = EINVAL;
4715				}
4716			}
4717			break;
4718		}
4719	case SCTP_INITMSG:
4720		{
4721			struct sctp_initmsg *sinit;
4722
4723			SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
4724			SCTP_INP_WLOCK(inp);
4725			if (sinit->sinit_num_ostreams)
4726				inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
4727
4728			if (sinit->sinit_max_instreams)
4729				inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
4730
4731			if (sinit->sinit_max_attempts)
4732				inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
4733
4734			if (sinit->sinit_max_init_timeo)
4735				inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
4736			SCTP_INP_WUNLOCK(inp);
4737			break;
4738		}
4739	case SCTP_PRIMARY_ADDR:
4740		{
4741			struct sctp_setprim *spa;
4742			struct sctp_nets *net;
4743
4744			SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
4745			SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
4746
4747			net = NULL;
4748			if (stcb) {
4749				net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
4750			} else {
4751				/*
4752				 * We increment here since
4753				 * sctp_findassociation_ep_addr() wil do a
4754				 * decrement if it finds the stcb as long as
4755				 * the locked tcb (last argument) is NOT a
4756				 * TCB.. aka NULL.
4757				 */
4758				SCTP_INP_INCR_REF(inp);
4759				stcb = sctp_findassociation_ep_addr(&inp,
4760				    (struct sockaddr *)&spa->ssp_addr,
4761				    &net, NULL, NULL);
4762				if (stcb == NULL) {
4763					SCTP_INP_DECR_REF(inp);
4764				}
4765			}
4766
4767			if ((stcb) && (net)) {
4768				if ((net != stcb->asoc.primary_destination) &&
4769				    (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
4770					/* Ok we need to set it */
4771					if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
4772						if (net->dest_state & SCTP_ADDR_SWITCH_PRIMARY) {
4773							net->dest_state |= SCTP_ADDR_DOUBLE_SWITCH;
4774						}
4775						net->dest_state |= SCTP_ADDR_SWITCH_PRIMARY;
4776					}
4777				}
4778			} else {
4779				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4780				error = EINVAL;
4781			}
4782			if (stcb) {
4783				SCTP_TCB_UNLOCK(stcb);
4784			}
4785			break;
4786		}
4787	case SCTP_SET_DYNAMIC_PRIMARY:
4788		{
4789			union sctp_sockstore *ss;
4790
4791			error = priv_check(curthread,
4792			    PRIV_NETINET_RESERVEDPORT);
4793			if (error)
4794				break;
4795
4796			SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
4797			/* SUPER USER CHECK? */
4798			error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
4799			break;
4800		}
4801	case SCTP_SET_PEER_PRIMARY_ADDR:
4802		{
4803			struct sctp_setpeerprim *sspp;
4804
4805			SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
4806			SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
4807			if (stcb != NULL) {
4808				struct sctp_ifa *ifa;
4809
4810				ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
4811				    stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
4812				if (ifa == NULL) {
4813					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4814					error = EINVAL;
4815					goto out_of_it;
4816				}
4817				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
4818					/*
4819					 * Must validate the ifa found is in
4820					 * our ep
4821					 */
4822					struct sctp_laddr *laddr;
4823					int found = 0;
4824
4825					LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
4826						if (laddr->ifa == NULL) {
4827							SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
4828							    __FUNCTION__);
4829							continue;
4830						}
4831						if (laddr->ifa == ifa) {
4832							found = 1;
4833							break;
4834						}
4835					}
4836					if (!found) {
4837						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4838						error = EINVAL;
4839						goto out_of_it;
4840					}
4841				}
4842				if (sctp_set_primary_ip_address_sa(stcb,
4843				    (struct sockaddr *)&sspp->sspp_addr) != 0) {
4844					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4845					error = EINVAL;
4846				}
4847		out_of_it:
4848				SCTP_TCB_UNLOCK(stcb);
4849			} else {
4850				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4851				error = EINVAL;
4852			}
4853			break;
4854		}
4855	case SCTP_BINDX_ADD_ADDR:
4856		{
4857			struct sctp_getaddresses *addrs;
4858			size_t sz;
4859			struct thread *td;
4860
4861			td = (struct thread *)p;
4862			SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
4863			    optsize);
4864#ifdef INET
4865			if (addrs->addr->sa_family == AF_INET) {
4866				sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in);
4867				if (optsize < sz) {
4868					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4869					error = EINVAL;
4870					break;
4871				}
4872				if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
4873					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
4874					break;
4875				}
4876			} else
4877#endif
4878#ifdef INET6
4879			if (addrs->addr->sa_family == AF_INET6) {
4880				sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6);
4881				if (optsize < sz) {
4882					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4883					error = EINVAL;
4884					break;
4885				}
4886				if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
4887				    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
4888					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
4889					break;
4890				}
4891			} else
4892#endif
4893			{
4894				error = EAFNOSUPPORT;
4895				break;
4896			}
4897			sctp_bindx_add_address(so, inp, addrs->addr,
4898			    addrs->sget_assoc_id, vrf_id,
4899			    &error, p);
4900			break;
4901		}
4902	case SCTP_BINDX_REM_ADDR:
4903		{
4904			struct sctp_getaddresses *addrs;
4905			size_t sz;
4906			struct thread *td;
4907
4908			td = (struct thread *)p;
4909
4910			SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
4911#ifdef INET
4912			if (addrs->addr->sa_family == AF_INET) {
4913				sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in);
4914				if (optsize < sz) {
4915					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4916					error = EINVAL;
4917					break;
4918				}
4919				if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
4920					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
4921					break;
4922				}
4923			} else
4924#endif
4925#ifdef INET6
4926			if (addrs->addr->sa_family == AF_INET6) {
4927				sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6);
4928				if (optsize < sz) {
4929					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4930					error = EINVAL;
4931					break;
4932				}
4933				if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
4934				    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
4935					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
4936					break;
4937				}
4938			} else
4939#endif
4940			{
4941				error = EAFNOSUPPORT;
4942				break;
4943			}
4944			sctp_bindx_delete_address(so, inp, addrs->addr,
4945			    addrs->sget_assoc_id, vrf_id,
4946			    &error);
4947			break;
4948		}
4949	case SCTP_EVENT:
4950		{
4951			struct sctp_event *event;
4952			uint32_t event_type;
4953
4954			SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
4955			SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
4956			switch (event->se_type) {
4957			case SCTP_ASSOC_CHANGE:
4958				event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
4959				break;
4960			case SCTP_PEER_ADDR_CHANGE:
4961				event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
4962				break;
4963			case SCTP_REMOTE_ERROR:
4964				event_type = SCTP_PCB_FLAGS_RECVPEERERR;
4965				break;
4966			case SCTP_SEND_FAILED:
4967				event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
4968				break;
4969			case SCTP_SHUTDOWN_EVENT:
4970				event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
4971				break;
4972			case SCTP_ADAPTATION_INDICATION:
4973				event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
4974				break;
4975			case SCTP_PARTIAL_DELIVERY_EVENT:
4976				event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
4977				break;
4978			case SCTP_AUTHENTICATION_EVENT:
4979				event_type = SCTP_PCB_FLAGS_AUTHEVNT;
4980				break;
4981			case SCTP_STREAM_RESET_EVENT:
4982				event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
4983				break;
4984			case SCTP_SENDER_DRY_EVENT:
4985				event_type = SCTP_PCB_FLAGS_DRYEVNT;
4986				break;
4987			case SCTP_NOTIFICATIONS_STOPPED_EVENT:
4988				event_type = 0;
4989				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
4990				error = ENOTSUP;
4991				break;
4992			default:
4993				event_type = 0;
4994				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4995				error = EINVAL;
4996				break;
4997			}
4998			if (event_type > 0) {
4999				if (stcb) {
5000					if (event->se_on) {
5001						sctp_stcb_feature_on(inp, stcb, event_type);
5002						if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
5003							if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5004							    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5005							    (stcb->asoc.stream_queue_cnt == 0)) {
5006								sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
5007							}
5008						}
5009					} else {
5010						sctp_stcb_feature_off(inp, stcb, event_type);
5011					}
5012					SCTP_TCB_UNLOCK(stcb);
5013				} else {
5014					/*
5015					 * We don't want to send up a storm
5016					 * of events, so return an error for
5017					 * sender dry events
5018					 */
5019					if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
5020					    ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
5021					    (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
5022						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
5023						error = ENOTSUP;
5024						break;
5025					}
5026					if ((event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
5027					    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5028						SCTP_INP_WLOCK(inp);
5029						if (event->se_on) {
5030							sctp_feature_on(inp, event_type);
5031						} else {
5032							sctp_feature_off(inp, event_type);
5033						}
5034						SCTP_INP_WUNLOCK(inp);
5035					}
5036					if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
5037					    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5038						SCTP_INP_RLOCK(inp);
5039						LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5040							SCTP_TCB_LOCK(stcb);
5041							if (event->se_on) {
5042								sctp_stcb_feature_on(inp, stcb, event_type);
5043							} else {
5044								sctp_stcb_feature_off(inp, stcb, event_type);
5045							}
5046							SCTP_TCB_UNLOCK(stcb);
5047						}
5048						SCTP_INP_RUNLOCK(inp);
5049					}
5050				}
5051			}
5052			break;
5053		}
5054	case SCTP_RECVRCVINFO:
5055		{
5056			int *onoff;
5057
5058			SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5059			SCTP_INP_WLOCK(inp);
5060			if (*onoff != 0) {
5061				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5062			} else {
5063				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5064			}
5065			SCTP_INP_WUNLOCK(inp);
5066			break;
5067		}
5068	case SCTP_RECVNXTINFO:
5069		{
5070			int *onoff;
5071
5072			SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5073			SCTP_INP_WLOCK(inp);
5074			if (*onoff != 0) {
5075				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5076			} else {
5077				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5078			}
5079			SCTP_INP_WUNLOCK(inp);
5080			break;
5081		}
5082	case SCTP_DEFAULT_SNDINFO:
5083		{
5084			struct sctp_sndinfo *info;
5085			uint16_t policy;
5086
5087			SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
5088			SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
5089
5090			if (stcb) {
5091				if (info->snd_sid < stcb->asoc.streamoutcnt) {
5092					stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5093					policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5094					stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5095					stcb->asoc.def_send.sinfo_flags |= policy;
5096					stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5097					stcb->asoc.def_send.sinfo_context = info->snd_context;
5098				} else {
5099					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5100					error = EINVAL;
5101				}
5102				SCTP_TCB_UNLOCK(stcb);
5103			} else {
5104				if ((info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
5105				    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5106					SCTP_INP_WLOCK(inp);
5107					inp->def_send.sinfo_stream = info->snd_sid;
5108					policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
5109					inp->def_send.sinfo_flags = info->snd_flags;
5110					inp->def_send.sinfo_flags |= policy;
5111					inp->def_send.sinfo_ppid = info->snd_ppid;
5112					inp->def_send.sinfo_context = info->snd_context;
5113					SCTP_INP_WUNLOCK(inp);
5114				}
5115				if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
5116				    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5117					SCTP_INP_RLOCK(inp);
5118					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5119						SCTP_TCB_LOCK(stcb);
5120						if (info->snd_sid < stcb->asoc.streamoutcnt) {
5121							stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5122							policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5123							stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5124							stcb->asoc.def_send.sinfo_flags |= policy;
5125							stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5126							stcb->asoc.def_send.sinfo_context = info->snd_context;
5127						}
5128						SCTP_TCB_UNLOCK(stcb);
5129					}
5130					SCTP_INP_RUNLOCK(inp);
5131				}
5132			}
5133			break;
5134		}
5135	case SCTP_DEFAULT_PRINFO:
5136		{
5137			struct sctp_default_prinfo *info;
5138
5139			SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
5140			SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
5141
5142			if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
5143				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5144				error = EINVAL;
5145				break;
5146			}
5147			if (stcb) {
5148				stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5149				stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5150				SCTP_TCB_UNLOCK(stcb);
5151			} else {
5152				if ((info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
5153				    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5154					SCTP_INP_WLOCK(inp);
5155					inp->def_send.sinfo_flags &= 0xfff0;
5156					inp->def_send.sinfo_flags |= info->pr_policy;
5157					SCTP_INP_WUNLOCK(inp);
5158				}
5159				if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
5160				    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5161					SCTP_INP_RLOCK(inp);
5162					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5163						SCTP_TCB_LOCK(stcb);
5164						stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5165						stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5166						SCTP_TCB_UNLOCK(stcb);
5167					}
5168					SCTP_INP_RUNLOCK(inp);
5169				}
5170			}
5171			break;
5172		}
5173	default:
5174		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
5175		error = ENOPROTOOPT;
5176		break;
5177	}			/* end switch (opt) */
5178	return (error);
5179}
5180
5181int
5182sctp_ctloutput(struct socket *so, struct sockopt *sopt)
5183{
5184	void *optval = NULL;
5185	size_t optsize = 0;
5186	struct sctp_inpcb *inp;
5187	void *p;
5188	int error = 0;
5189
5190	inp = (struct sctp_inpcb *)so->so_pcb;
5191	if (inp == 0) {
5192		/* I made the same as TCP since we are not setup? */
5193		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5194		return (ECONNRESET);
5195	}
5196	if (sopt->sopt_level != IPPROTO_SCTP) {
5197		/* wrong proto level... send back up to IP */
5198#ifdef INET6
5199		if (INP_CHECK_SOCKAF(so, AF_INET6))
5200			error = ip6_ctloutput(so, sopt);
5201#endif				/* INET6 */
5202#if defined(INET) && defined (INET6)
5203		else
5204#endif
5205#ifdef INET
5206			error = ip_ctloutput(so, sopt);
5207#endif
5208		return (error);
5209	}
5210	optsize = sopt->sopt_valsize;
5211	if (optsize) {
5212		SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
5213		if (optval == NULL) {
5214			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
5215			return (ENOBUFS);
5216		}
5217		error = sooptcopyin(sopt, optval, optsize, optsize);
5218		if (error) {
5219			SCTP_FREE(optval, SCTP_M_SOCKOPT);
5220			goto out;
5221		}
5222	}
5223	p = (void *)sopt->sopt_td;
5224	if (sopt->sopt_dir == SOPT_SET) {
5225		error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
5226	} else if (sopt->sopt_dir == SOPT_GET) {
5227		error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
5228	} else {
5229		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5230		error = EINVAL;
5231	}
5232	if ((error == 0) && (optval != NULL)) {
5233		error = sooptcopyout(sopt, optval, optsize);
5234		SCTP_FREE(optval, SCTP_M_SOCKOPT);
5235	} else if (optval != NULL) {
5236		SCTP_FREE(optval, SCTP_M_SOCKOPT);
5237	}
5238out:
5239	return (error);
5240}
5241
5242#ifdef INET
5243static int
5244sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
5245{
5246	int error = 0;
5247	int create_lock_on = 0;
5248	uint32_t vrf_id;
5249	struct sctp_inpcb *inp;
5250	struct sctp_tcb *stcb = NULL;
5251
5252	inp = (struct sctp_inpcb *)so->so_pcb;
5253	if (inp == 0) {
5254		/* I made the same as TCP since we are not setup? */
5255		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5256		return (ECONNRESET);
5257	}
5258	if (addr == NULL) {
5259		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5260		return EINVAL;
5261	}
5262	switch (addr->sa_family) {
5263#ifdef INET6
5264	case AF_INET6:
5265		{
5266			struct sockaddr_in6 *sin6p;
5267
5268			if (addr->sa_len != sizeof(struct sockaddr_in6)) {
5269				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5270				return (EINVAL);
5271			}
5272			sin6p = (struct sockaddr_in6 *)addr;
5273			if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
5274				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5275				return (error);
5276			}
5277			break;
5278		}
5279#endif
5280#ifdef INET
5281	case AF_INET:
5282		{
5283			struct sockaddr_in *sinp;
5284
5285			if (addr->sa_len != sizeof(struct sockaddr_in)) {
5286				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5287				return (EINVAL);
5288			}
5289			sinp = (struct sockaddr_in *)addr;
5290			if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
5291				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5292				return (error);
5293			}
5294			break;
5295		}
5296#endif
5297	default:
5298		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
5299		return (EAFNOSUPPORT);
5300	}
5301	SCTP_INP_INCR_REF(inp);
5302	SCTP_ASOC_CREATE_LOCK(inp);
5303	create_lock_on = 1;
5304
5305
5306	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
5307	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
5308		/* Should I really unlock ? */
5309		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
5310		error = EFAULT;
5311		goto out_now;
5312	}
5313#ifdef INET6
5314	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
5315	    (addr->sa_family == AF_INET6)) {
5316		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5317		error = EINVAL;
5318		goto out_now;
5319	}
5320#endif				/* INET6 */
5321	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
5322	    SCTP_PCB_FLAGS_UNBOUND) {
5323		/* Bind a ephemeral port */
5324		error = sctp_inpcb_bind(so, NULL, NULL, p);
5325		if (error) {
5326			goto out_now;
5327		}
5328	}
5329	/* Now do we connect? */
5330	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
5331	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
5332		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5333		error = EINVAL;
5334		goto out_now;
5335	}
5336	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
5337	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
5338		/* We are already connected AND the TCP model */
5339		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
5340		error = EADDRINUSE;
5341		goto out_now;
5342	}
5343	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
5344		SCTP_INP_RLOCK(inp);
5345		stcb = LIST_FIRST(&inp->sctp_asoc_list);
5346		SCTP_INP_RUNLOCK(inp);
5347	} else {
5348		/*
5349		 * We increment here since sctp_findassociation_ep_addr()
5350		 * will do a decrement if it finds the stcb as long as the
5351		 * locked tcb (last argument) is NOT a TCB.. aka NULL.
5352		 */
5353		SCTP_INP_INCR_REF(inp);
5354		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
5355		if (stcb == NULL) {
5356			SCTP_INP_DECR_REF(inp);
5357		} else {
5358			SCTP_TCB_UNLOCK(stcb);
5359		}
5360	}
5361	if (stcb != NULL) {
5362		/* Already have or am bring up an association */
5363		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5364		error = EALREADY;
5365		goto out_now;
5366	}
5367	vrf_id = inp->def_vrf_id;
5368	/* We are GOOD to go */
5369	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
5370	if (stcb == NULL) {
5371		/* Gak! no memory */
5372		goto out_now;
5373	}
5374	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
5375		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
5376		/* Set the connected flag so we can queue data */
5377		SOCKBUF_LOCK(&so->so_rcv);
5378		so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
5379		SOCKBUF_UNLOCK(&so->so_rcv);
5380		SOCKBUF_LOCK(&so->so_snd);
5381		so->so_snd.sb_state &= ~SBS_CANTSENDMORE;
5382		SOCKBUF_UNLOCK(&so->so_snd);
5383		SOCK_LOCK(so);
5384		so->so_state &= ~SS_ISDISCONNECTING;
5385		SOCK_UNLOCK(so);
5386		soisconnecting(so);
5387	}
5388	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
5389	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
5390
5391	/* initialize authentication parameters for the assoc */
5392	sctp_initialize_auth_params(inp, stcb);
5393
5394	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
5395	SCTP_TCB_UNLOCK(stcb);
5396out_now:
5397	if (create_lock_on) {
5398		SCTP_ASOC_CREATE_UNLOCK(inp);
5399	}
5400	SCTP_INP_DECR_REF(inp);
5401	return error;
5402}
5403
5404#endif
5405
5406int
5407sctp_listen(struct socket *so, int backlog, struct thread *p)
5408{
5409	/*
5410	 * Note this module depends on the protocol processing being called
5411	 * AFTER any socket level flags and backlog are applied to the
5412	 * socket. The traditional way that the socket flags are applied is
5413	 * AFTER protocol processing. We have made a change to the
5414	 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
5415	 * place if the socket API for SCTP is to work properly.
5416	 */
5417
5418	int error = 0;
5419	struct sctp_inpcb *inp;
5420
5421	inp = (struct sctp_inpcb *)so->so_pcb;
5422	if (inp == 0) {
5423		/* I made the same as TCP since we are not setup? */
5424		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5425		return (ECONNRESET);
5426	}
5427	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
5428		/* See if we have a listener */
5429		struct sctp_inpcb *tinp;
5430		union sctp_sockstore store, *sp;
5431
5432		sp = &store;
5433		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
5434			/* not bound all */
5435			struct sctp_laddr *laddr;
5436
5437			LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
5438				memcpy(&store, &laddr->ifa->address, sizeof(store));
5439				switch (sp->sa.sa_family) {
5440#ifdef INET
5441				case AF_INET:
5442					sp->sin.sin_port = inp->sctp_lport;
5443					break;
5444#endif
5445#ifdef INET6
5446				case AF_INET6:
5447					sp->sin6.sin6_port = inp->sctp_lport;
5448					break;
5449#endif
5450				default:
5451					break;
5452				}
5453				tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
5454				if (tinp && (tinp != inp) &&
5455				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
5456				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
5457				    (tinp->sctp_socket->so_qlimit)) {
5458					/*
5459					 * we have a listener already and
5460					 * its not this inp.
5461					 */
5462					SCTP_INP_DECR_REF(tinp);
5463					return (EADDRINUSE);
5464				} else if (tinp) {
5465					SCTP_INP_DECR_REF(tinp);
5466				}
5467			}
5468		} else {
5469			/* Setup a local addr bound all */
5470			memset(&store, 0, sizeof(store));
5471			switch (sp->sa.sa_family) {
5472#ifdef INET
5473			case AF_INET:
5474				store.sin.sin_port = inp->sctp_lport;
5475				break;
5476#endif
5477#ifdef INET6
5478			case AF_INET6:
5479				sp->sin6.sin6_port = inp->sctp_lport;
5480				break;
5481#endif
5482			default:
5483				break;
5484			}
5485#ifdef INET6
5486			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5487				store.sa.sa_family = AF_INET6;
5488				store.sa.sa_len = sizeof(struct sockaddr_in6);
5489			}
5490#endif
5491#ifdef INET
5492			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
5493				store.sa.sa_family = AF_INET;
5494				store.sa.sa_len = sizeof(struct sockaddr_in);
5495			}
5496#endif
5497			tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
5498			if (tinp && (tinp != inp) &&
5499			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
5500			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
5501			    (tinp->sctp_socket->so_qlimit)) {
5502				/*
5503				 * we have a listener already and its not
5504				 * this inp.
5505				 */
5506				SCTP_INP_DECR_REF(tinp);
5507				return (EADDRINUSE);
5508			} else if (tinp) {
5509				SCTP_INP_DECR_REF(inp);
5510			}
5511		}
5512	}
5513	SCTP_INP_RLOCK(inp);
5514#ifdef SCTP_LOCK_LOGGING
5515	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
5516		sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
5517	}
5518#endif
5519	SOCK_LOCK(so);
5520	error = solisten_proto_check(so);
5521	if (error) {
5522		SOCK_UNLOCK(so);
5523		SCTP_INP_RUNLOCK(inp);
5524		return (error);
5525	}
5526	if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
5527	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
5528		/*
5529		 * The unlucky case - We are in the tcp pool with this guy.
5530		 * - Someone else is in the main inp slot. - We must move
5531		 * this guy (the listener) to the main slot - We must then
5532		 * move the guy that was listener to the TCP Pool.
5533		 */
5534		if (sctp_swap_inpcb_for_listen(inp)) {
5535			goto in_use;
5536		}
5537	}
5538	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
5539	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
5540		/* We are already connected AND the TCP model */
5541in_use:
5542		SCTP_INP_RUNLOCK(inp);
5543		SOCK_UNLOCK(so);
5544		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
5545		return (EADDRINUSE);
5546	}
5547	SCTP_INP_RUNLOCK(inp);
5548	if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
5549		/* We must do a bind. */
5550		SOCK_UNLOCK(so);
5551		if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
5552			/* bind error, probably perm */
5553			return (error);
5554		}
5555		SOCK_LOCK(so);
5556	}
5557	/* It appears for 7.0 and on, we must always call this. */
5558	solisten_proto(so, backlog);
5559	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
5560		/* remove the ACCEPTCONN flag for one-to-many sockets */
5561		so->so_options &= ~SO_ACCEPTCONN;
5562	}
5563	if (backlog == 0) {
5564		/* turning off listen */
5565		so->so_options &= ~SO_ACCEPTCONN;
5566	}
5567	SOCK_UNLOCK(so);
5568	return (error);
5569}
5570
5571static int sctp_defered_wakeup_cnt = 0;
5572
5573int
5574sctp_accept(struct socket *so, struct sockaddr **addr)
5575{
5576	struct sctp_tcb *stcb;
5577	struct sctp_inpcb *inp;
5578	union sctp_sockstore store;
5579
5580#ifdef INET6
5581	int error;
5582
5583#endif
5584	inp = (struct sctp_inpcb *)so->so_pcb;
5585
5586	if (inp == 0) {
5587		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5588		return (ECONNRESET);
5589	}
5590	SCTP_INP_RLOCK(inp);
5591	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
5592		SCTP_INP_RUNLOCK(inp);
5593		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5594		return (EOPNOTSUPP);
5595	}
5596	if (so->so_state & SS_ISDISCONNECTED) {
5597		SCTP_INP_RUNLOCK(inp);
5598		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
5599		return (ECONNABORTED);
5600	}
5601	stcb = LIST_FIRST(&inp->sctp_asoc_list);
5602	if (stcb == NULL) {
5603		SCTP_INP_RUNLOCK(inp);
5604		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5605		return (ECONNRESET);
5606	}
5607	SCTP_TCB_LOCK(stcb);
5608	SCTP_INP_RUNLOCK(inp);
5609	store = stcb->asoc.primary_destination->ro._l_addr;
5610	stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
5611	SCTP_TCB_UNLOCK(stcb);
5612	switch (store.sa.sa_family) {
5613#ifdef INET
5614	case AF_INET:
5615		{
5616			struct sockaddr_in *sin;
5617
5618			SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
5619			if (sin == NULL)
5620				return (ENOMEM);
5621			sin->sin_family = AF_INET;
5622			sin->sin_len = sizeof(*sin);
5623			sin->sin_port = ((struct sockaddr_in *)&store)->sin_port;
5624			sin->sin_addr = ((struct sockaddr_in *)&store)->sin_addr;
5625			*addr = (struct sockaddr *)sin;
5626			break;
5627		}
5628#endif
5629#ifdef INET6
5630	case AF_INET6:
5631		{
5632			struct sockaddr_in6 *sin6;
5633
5634			SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
5635			if (sin6 == NULL)
5636				return (ENOMEM);
5637			sin6->sin6_family = AF_INET6;
5638			sin6->sin6_len = sizeof(*sin6);
5639			sin6->sin6_port = ((struct sockaddr_in6 *)&store)->sin6_port;
5640
5641			sin6->sin6_addr = ((struct sockaddr_in6 *)&store)->sin6_addr;
5642			if ((error = sa6_recoverscope(sin6)) != 0) {
5643				SCTP_FREE_SONAME(sin6);
5644				return (error);
5645			}
5646			*addr = (struct sockaddr *)sin6;
5647			break;
5648		}
5649#endif
5650	default:
5651		/* TSNH */
5652		break;
5653	}
5654	/* Wake any delayed sleep action */
5655	if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
5656		SCTP_INP_WLOCK(inp);
5657		inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
5658		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
5659			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
5660			SCTP_INP_WUNLOCK(inp);
5661			SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
5662			if (sowriteable(inp->sctp_socket)) {
5663				sowwakeup_locked(inp->sctp_socket);
5664			} else {
5665				SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
5666			}
5667			SCTP_INP_WLOCK(inp);
5668		}
5669		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
5670			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
5671			SCTP_INP_WUNLOCK(inp);
5672			SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
5673			if (soreadable(inp->sctp_socket)) {
5674				sctp_defered_wakeup_cnt++;
5675				sorwakeup_locked(inp->sctp_socket);
5676			} else {
5677				SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
5678			}
5679			SCTP_INP_WLOCK(inp);
5680		}
5681		SCTP_INP_WUNLOCK(inp);
5682	}
5683	if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
5684		SCTP_TCB_LOCK(stcb);
5685		sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
5686	}
5687	return (0);
5688}
5689
5690#ifdef INET
5691int
5692sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
5693{
5694	struct sockaddr_in *sin;
5695	uint32_t vrf_id;
5696	struct sctp_inpcb *inp;
5697	struct sctp_ifa *sctp_ifa;
5698
5699	/*
5700	 * Do the malloc first in case it blocks.
5701	 */
5702	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
5703	if (sin == NULL)
5704		return (ENOMEM);
5705	sin->sin_family = AF_INET;
5706	sin->sin_len = sizeof(*sin);
5707	inp = (struct sctp_inpcb *)so->so_pcb;
5708	if (!inp) {
5709		SCTP_FREE_SONAME(sin);
5710		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5711		return ECONNRESET;
5712	}
5713	SCTP_INP_RLOCK(inp);
5714	sin->sin_port = inp->sctp_lport;
5715	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
5716		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
5717			struct sctp_tcb *stcb;
5718			struct sockaddr_in *sin_a;
5719			struct sctp_nets *net;
5720			int fnd;
5721
5722			stcb = LIST_FIRST(&inp->sctp_asoc_list);
5723			if (stcb == NULL) {
5724				goto notConn;
5725			}
5726			fnd = 0;
5727			sin_a = NULL;
5728			SCTP_TCB_LOCK(stcb);
5729			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5730				sin_a = (struct sockaddr_in *)&net->ro._l_addr;
5731				if (sin_a == NULL)
5732					/* this will make coverity happy */
5733					continue;
5734
5735				if (sin_a->sin_family == AF_INET) {
5736					fnd = 1;
5737					break;
5738				}
5739			}
5740			if ((!fnd) || (sin_a == NULL)) {
5741				/* punt */
5742				SCTP_TCB_UNLOCK(stcb);
5743				goto notConn;
5744			}
5745			vrf_id = inp->def_vrf_id;
5746			sctp_ifa = sctp_source_address_selection(inp,
5747			    stcb,
5748			    (sctp_route_t *) & net->ro,
5749			    net, 0, vrf_id);
5750			if (sctp_ifa) {
5751				sin->sin_addr = sctp_ifa->address.sin.sin_addr;
5752				sctp_free_ifa(sctp_ifa);
5753			}
5754			SCTP_TCB_UNLOCK(stcb);
5755		} else {
5756			/* For the bound all case you get back 0 */
5757	notConn:
5758			sin->sin_addr.s_addr = 0;
5759		}
5760
5761	} else {
5762		/* Take the first IPv4 address in the list */
5763		struct sctp_laddr *laddr;
5764		int fnd = 0;
5765
5766		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
5767			if (laddr->ifa->address.sa.sa_family == AF_INET) {
5768				struct sockaddr_in *sin_a;
5769
5770				sin_a = (struct sockaddr_in *)&laddr->ifa->address.sa;
5771				sin->sin_addr = sin_a->sin_addr;
5772				fnd = 1;
5773				break;
5774			}
5775		}
5776		if (!fnd) {
5777			SCTP_FREE_SONAME(sin);
5778			SCTP_INP_RUNLOCK(inp);
5779			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5780			return ENOENT;
5781		}
5782	}
5783	SCTP_INP_RUNLOCK(inp);
5784	(*addr) = (struct sockaddr *)sin;
5785	return (0);
5786}
5787
5788int
5789sctp_peeraddr(struct socket *so, struct sockaddr **addr)
5790{
5791	struct sockaddr_in *sin = (struct sockaddr_in *)*addr;
5792	int fnd;
5793	struct sockaddr_in *sin_a;
5794	struct sctp_inpcb *inp;
5795	struct sctp_tcb *stcb;
5796	struct sctp_nets *net;
5797
5798	/* Do the malloc first in case it blocks. */
5799	inp = (struct sctp_inpcb *)so->so_pcb;
5800	if ((inp == NULL) ||
5801	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
5802		/* UDP type and listeners will drop out here */
5803		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
5804		return (ENOTCONN);
5805	}
5806	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
5807	if (sin == NULL)
5808		return (ENOMEM);
5809	sin->sin_family = AF_INET;
5810	sin->sin_len = sizeof(*sin);
5811
5812	/* We must recapture incase we blocked */
5813	inp = (struct sctp_inpcb *)so->so_pcb;
5814	if (!inp) {
5815		SCTP_FREE_SONAME(sin);
5816		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5817		return ECONNRESET;
5818	}
5819	SCTP_INP_RLOCK(inp);
5820	stcb = LIST_FIRST(&inp->sctp_asoc_list);
5821	if (stcb) {
5822		SCTP_TCB_LOCK(stcb);
5823	}
5824	SCTP_INP_RUNLOCK(inp);
5825	if (stcb == NULL) {
5826		SCTP_FREE_SONAME(sin);
5827		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5828		return ECONNRESET;
5829	}
5830	fnd = 0;
5831	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5832		sin_a = (struct sockaddr_in *)&net->ro._l_addr;
5833		if (sin_a->sin_family == AF_INET) {
5834			fnd = 1;
5835			sin->sin_port = stcb->rport;
5836			sin->sin_addr = sin_a->sin_addr;
5837			break;
5838		}
5839	}
5840	SCTP_TCB_UNLOCK(stcb);
5841	if (!fnd) {
5842		/* No IPv4 address */
5843		SCTP_FREE_SONAME(sin);
5844		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5845		return ENOENT;
5846	}
5847	(*addr) = (struct sockaddr *)sin;
5848	return (0);
5849}
5850
5851#ifdef INET
5852struct pr_usrreqs sctp_usrreqs = {
5853	.pru_abort = sctp_abort,
5854	.pru_accept = sctp_accept,
5855	.pru_attach = sctp_attach,
5856	.pru_bind = sctp_bind,
5857	.pru_connect = sctp_connect,
5858	.pru_control = in_control,
5859	.pru_close = sctp_close,
5860	.pru_detach = sctp_close,
5861	.pru_sopoll = sopoll_generic,
5862	.pru_flush = sctp_flush,
5863	.pru_disconnect = sctp_disconnect,
5864	.pru_listen = sctp_listen,
5865	.pru_peeraddr = sctp_peeraddr,
5866	.pru_send = sctp_sendm,
5867	.pru_shutdown = sctp_shutdown,
5868	.pru_sockaddr = sctp_ingetaddr,
5869	.pru_sosend = sctp_sosend,
5870	.pru_soreceive = sctp_soreceive
5871};
5872
5873#endif
5874#endif
5875