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