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