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