LCOV - code coverage report
Current view: top level - netwerk/sctp/src/netinet - sctp_usrreq.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 3166 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 24 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13