The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/sctp_usrreq.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: f2617a5a0334281b08e5f8f94c988911


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.