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

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 1982, 1986, 1988, 1990, 1993
       3             :  *      The Regents of the University of California.
       4             :  * Copyright (c) 2004 The FreeBSD Foundation
       5             :  * Copyright (c) 2004-2008 Robert N. M. Watson
       6             :  * Copyright (c) 2009-2010 Brad Penoff
       7             :  * Copyright (c) 2009-2010 Humaira Kamal
       8             :  * Copyright (c) 2011-2012 Irene Ruengeler
       9             :  * Copyright (c) 2011-2012 Michael Tuexen
      10             :  * All rights reserved.
      11             :  *
      12             :  * Redistribution and use in source and binary forms, with or without
      13             :  * modification, are permitted provided that the following conditions
      14             :  * are met:
      15             :  * 1. Redistributions of source code must retain the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer.
      17             :  * 2. Redistributions in binary form must reproduce the above copyright
      18             :  *    notice, this list of conditions and the following disclaimer in the
      19             :  *    documentation and/or other materials provided with the distribution.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  *
      33             :  */
      34             : 
      35             : #include <netinet/sctp_os.h>
      36             : #include <netinet/sctp_pcb.h>
      37             : #include <netinet/sctputil.h>
      38             : #include <netinet/sctp_var.h>
      39             : #include <netinet/sctp_sysctl.h>
      40             : #include <netinet/sctp_input.h>
      41             : #include <netinet/sctp_peeloff.h>
      42             : #ifdef INET6
      43             : #include <netinet6/sctp6_var.h>
      44             : #endif
      45             : #if defined(__Userspace_os_Linux)
      46             : #define __FAVOR_BSD    /* (on Ubuntu at least) enables UDP header field names like BSD in RFC 768 */
      47             : #endif
      48             : #if !defined (__Userspace_os_Windows)
      49             : #if defined INET || defined INET6
      50             : #include <netinet/udp.h>
      51             : #endif
      52             : #include <arpa/inet.h>
      53             : #else
      54             : #include <user_socketvar.h>
      55             : #endif
      56             : userland_mutex_t accept_mtx;
      57             : userland_cond_t accept_cond;
      58             : #ifdef _WIN32
      59             : #include <time.h>
      60             : #include <sys/timeb.h>
      61             : #endif
      62             : 
      63             : MALLOC_DEFINE(M_PCB, "sctp_pcb", "sctp pcb");
      64             : MALLOC_DEFINE(M_SONAME, "sctp_soname", "sctp soname");
      65             : #define MAXLEN_MBUF_CHAIN  32
      66             : 
      67             : /* Prototypes */
      68             : extern int sctp_sosend(struct socket *so, struct sockaddr *addr, struct uio *uio,
      69             :                        struct mbuf *top, struct mbuf *control, int flags,
      70             :                      /* proc is a dummy in __Userspace__ and will not be passed to sctp_lower_sosend */                       struct proc *p);
      71             : 
      72             : extern int sctp_attach(struct socket *so, int proto, uint32_t vrf_id);
      73             : extern int sctpconn_attach(struct socket *so, int proto, uint32_t vrf_id);
      74             : 
      75             : void
      76           0 : usrsctp_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             : {
      80           0 :         sctp_init(port, conn_output, debug_printf);
      81           0 : }
      82             : 
      83             : 
      84             : /* Taken from  usr/src/sys/kern/uipc_sockbuf.c and modified for __Userspace__*/
      85             : /*
      86             :  * Socantsendmore indicates that no more data will be sent on the socket; it
      87             :  * would normally be applied to a socket when the user informs the system
      88             :  * that no more data is to be sent, by the protocol code (in case
      89             :  * PRU_SHUTDOWN).  Socantrcvmore indicates that no more data will be
      90             :  * received, and will normally be applied to the socket by a protocol when it
      91             :  * detects that the peer will send no more data.  Data queued for reading in
      92             :  * the socket may yet be read.
      93             :  */
      94             : 
      95           0 : void socantrcvmore_locked(struct socket *so)
      96             : {
      97             :         SOCKBUF_LOCK_ASSERT(&so->so_rcv);
      98           0 :         so->so_rcv.sb_state |= SBS_CANTRCVMORE;
      99           0 :         sorwakeup_locked(so);
     100           0 : }
     101             : 
     102           0 : void socantrcvmore(struct socket *so)
     103             : {
     104           0 :         SOCKBUF_LOCK(&so->so_rcv);
     105           0 :         socantrcvmore_locked(so);
     106           0 : }
     107             : 
     108             : void
     109           0 : socantsendmore_locked(struct socket *so)
     110             : {
     111             :         SOCKBUF_LOCK_ASSERT(&so->so_snd);
     112           0 :         so->so_snd.sb_state |= SBS_CANTSENDMORE;
     113           0 :         sowwakeup_locked(so);
     114           0 : }
     115             : 
     116             : void
     117           0 : socantsendmore(struct socket *so)
     118             : {
     119           0 :         SOCKBUF_LOCK(&so->so_snd);
     120           0 :         socantsendmore_locked(so);
     121           0 : }
     122             : 
     123             : 
     124             : 
     125             : /* Taken from  usr/src/sys/kern/uipc_sockbuf.c and called within sctp_lower_sosend.
     126             :  */
     127             : int
     128           0 : sbwait(struct sockbuf *sb)
     129             : {
     130             : #if defined(__Userspace__) /* __Userspace__ */
     131             : 
     132             :         SOCKBUF_LOCK_ASSERT(sb);
     133             : 
     134           0 :         sb->sb_flags |= SB_WAIT;
     135             : #if defined (__Userspace_os_Windows)
     136             :         if (SleepConditionVariableCS(&(sb->sb_cond), &(sb->sb_mtx), INFINITE))
     137             :                 return 0;
     138             :         else
     139             :                 return -1;
     140             : #else
     141           0 :         return (pthread_cond_wait(&(sb->sb_cond), &(sb->sb_mtx)));
     142             : #endif
     143             : 
     144             : #else
     145             :         SOCKBUF_LOCK_ASSERT(sb);
     146             : 
     147             :         sb->sb_flags |= SB_WAIT;
     148             :         return (msleep(&sb->sb_cc, &sb->sb_mtx,
     149             :             (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "sbwait",
     150             :             sb->sb_timeo));
     151             : #endif
     152             : }
     153             : 
     154             : 
     155             : 
     156             : 
     157             : /* Taken from  /src/sys/kern/uipc_socket.c
     158             :  * and modified for __Userspace__
     159             :  */
     160             : static struct socket *
     161           0 : soalloc(void)
     162             : {
     163             :         struct socket *so;
     164             : 
     165             :         /*
     166             :          * soalloc() sets of socket layer state for a socket,
     167             :          * called only by socreate() and sonewconn().
     168             :          *
     169             :          * sodealloc() tears down socket layer state for a socket,
     170             :          * called only by sofree() and sonewconn().
     171             :          * __Userspace__ TODO : Make sure so is properly deallocated
     172             :          * when tearing down the connection.
     173             :          */
     174             : 
     175           0 :         so = (struct socket *)malloc(sizeof(struct socket));
     176             : 
     177           0 :         if (so == NULL) {
     178           0 :                 return (NULL);
     179             :         }
     180           0 :         memset(so, 0, sizeof(struct socket));
     181             : 
     182             :         /* __Userspace__ Initializing the socket locks here */
     183           0 :         SOCKBUF_LOCK_INIT(&so->so_snd, "so_snd");
     184           0 :         SOCKBUF_LOCK_INIT(&so->so_rcv, "so_rcv");
     185           0 :         SOCKBUF_COND_INIT(&so->so_snd);
     186           0 :         SOCKBUF_COND_INIT(&so->so_rcv);
     187           0 :         SOCK_COND_INIT(so); /* timeo_cond */
     188             : 
     189             :         /* __Userspace__ Any ref counting required here? Will we have any use for aiojobq?
     190             :            What about gencnt and numopensockets?*/
     191           0 :         TAILQ_INIT(&so->so_aiojobq);
     192           0 :         return (so);
     193             : }
     194             : 
     195             : static void
     196           0 : sodealloc(struct socket *so)
     197             : {
     198             : 
     199             :         KASSERT(so->so_count == 0, ("sodealloc(): so_count %d", so->so_count));
     200             :         KASSERT(so->so_pcb == NULL, ("sodealloc(): so_pcb != NULL"));
     201             : 
     202           0 :         SOCKBUF_COND_DESTROY(&so->so_snd);
     203           0 :         SOCKBUF_COND_DESTROY(&so->so_rcv);
     204             : 
     205           0 :         SOCK_COND_DESTROY(so);
     206             : 
     207           0 :         SOCKBUF_LOCK_DESTROY(&so->so_snd);
     208           0 :         SOCKBUF_LOCK_DESTROY(&so->so_rcv);
     209             : 
     210           0 :         free(so);
     211           0 : }
     212             : 
     213             : /* Taken from  /src/sys/kern/uipc_socket.c
     214             :  * and modified for __Userspace__
     215             :  */
     216             : void
     217           0 : sofree(struct socket *so)
     218             : {
     219             :         struct socket *head;
     220             : 
     221             :         ACCEPT_LOCK_ASSERT();
     222             :         SOCK_LOCK_ASSERT(so);
     223             :         /* SS_NOFDREF unset in accept call.  this condition seems irrelevent
     224             :          *  for __Userspace__...
     225             :          */
     226           0 :         if (so->so_count != 0 ||
     227           0 :             (so->so_state & SS_PROTOREF) || (so->so_qstate & SQ_COMP)) {
     228           0 :                 SOCK_UNLOCK(so);
     229           0 :                 ACCEPT_UNLOCK();
     230           0 :                 return;
     231             :         }
     232           0 :         head = so->so_head;
     233           0 :         if (head != NULL) {
     234             :                 KASSERT((so->so_qstate & SQ_COMP) != 0 ||
     235             :                     (so->so_qstate & SQ_INCOMP) != 0,
     236             :                     ("sofree: so_head != NULL, but neither SQ_COMP nor "
     237             :                     "SQ_INCOMP"));
     238             :                 KASSERT((so->so_qstate & SQ_COMP) == 0 ||
     239             :                     (so->so_qstate & SQ_INCOMP) == 0,
     240             :                     ("sofree: so->so_qstate is SQ_COMP and also SQ_INCOMP"));
     241           0 :                 TAILQ_REMOVE(&head->so_incomp, so, so_list);
     242           0 :                 head->so_incqlen--;
     243           0 :                 so->so_qstate &= ~SQ_INCOMP;
     244           0 :                 so->so_head = NULL;
     245             :         }
     246             :         KASSERT((so->so_qstate & SQ_COMP) == 0 &&
     247             :             (so->so_qstate & SQ_INCOMP) == 0,
     248             :             ("sofree: so_head == NULL, but still SQ_COMP(%d) or SQ_INCOMP(%d)",
     249             :             so->so_qstate & SQ_COMP, so->so_qstate & SQ_INCOMP));
     250           0 :         if (so->so_options & SCTP_SO_ACCEPTCONN) {
     251             :                 KASSERT((TAILQ_EMPTY(&so->so_comp)), ("sofree: so_comp populated"));
     252             :                 KASSERT((TAILQ_EMPTY(&so->so_incomp)), ("sofree: so_comp populated"));
     253             :         }
     254           0 :         SOCK_UNLOCK(so);
     255           0 :         ACCEPT_UNLOCK();
     256           0 :         sctp_close(so); /* was...    sctp_detach(so); */
     257             :         /*
     258             :          * From this point on, we assume that no other references to this
     259             :          * socket exist anywhere else in the stack.  Therefore, no locks need
     260             :          * to be acquired or held.
     261             :          *
     262             :          * We used to do a lot of socket buffer and socket locking here, as
     263             :          * well as invoke sorflush() and perform wakeups.  The direct call to
     264             :          * dom_dispose() and sbrelease_internal() are an inlining of what was
     265             :          * necessary from sorflush().
     266             :          *
     267             :          * Notice that the socket buffer and kqueue state are torn down
     268             :          * before calling pru_detach.  This means that protocols shold not
     269             :          * assume they can perform socket wakeups, etc, in their detach code.
     270             :          */
     271           0 :         sodealloc(so);
     272             : }
     273             : 
     274             : 
     275             : 
     276             : /* Taken from  /src/sys/kern/uipc_socket.c */
     277             : int
     278           0 : soabort(so)
     279             :         struct socket *so;
     280             : {
     281             :         int error;
     282             : #if defined(INET6)
     283             :         struct sctp_inpcb *inp;
     284             : #endif
     285             : 
     286             : #if defined(INET6)
     287             :         inp = (struct sctp_inpcb *)so->so_pcb;
     288             :         if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
     289             :                 error = sctp6_abort(so);
     290             :         } else {
     291             : #if defined(INET)
     292             :                 error = sctp_abort(so);
     293             : #else
     294             :                 error = EAFNOSUPPORT;
     295             : #endif
     296             :         }
     297             : #elif defined(INET)
     298             :         error = sctp_abort(so);
     299             : #else
     300           0 :         error = EAFNOSUPPORT;
     301             : #endif
     302           0 :         if (error) {
     303           0 :                 sofree(so);
     304           0 :                 return error;
     305             :         }
     306           0 :         return (0);
     307             : }
     308             : 
     309             : 
     310             : /* Taken from  usr/src/sys/kern/uipc_socket.c and called within sctp_connect (sctp_usrreq.c).
     311             :  *  We use sctp_connect for send_one_init_real in ms1.
     312             :  */
     313             : void
     314           0 : soisconnecting(struct socket *so)
     315             : {
     316             : 
     317           0 :         SOCK_LOCK(so);
     318           0 :         so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
     319           0 :         so->so_state |= SS_ISCONNECTING;
     320           0 :         SOCK_UNLOCK(so);
     321           0 : }
     322             : 
     323             : /* Taken from  usr/src/sys/kern/uipc_socket.c and called within sctp_disconnect (sctp_usrreq.c).
     324             :  *  TODO Do we use sctp_disconnect?
     325             :  */
     326             : void
     327           0 : soisdisconnecting(struct socket *so)
     328             : {
     329             : 
     330             :         /*
     331             :          * Note: This code assumes that SOCK_LOCK(so) and
     332             :          * SOCKBUF_LOCK(&so->so_rcv) are the same.
     333             :          */
     334           0 :         SOCKBUF_LOCK(&so->so_rcv);
     335           0 :         so->so_state &= ~SS_ISCONNECTING;
     336           0 :         so->so_state |= SS_ISDISCONNECTING;
     337           0 :         so->so_rcv.sb_state |= SBS_CANTRCVMORE;
     338           0 :         sorwakeup_locked(so);
     339           0 :         SOCKBUF_LOCK(&so->so_snd);
     340           0 :         so->so_snd.sb_state |= SBS_CANTSENDMORE;
     341           0 :         sowwakeup_locked(so);
     342           0 :         wakeup("dummy",so);
     343             :         /* requires 2 args but this was in orig */
     344             :         /* wakeup(&so->so_timeo); */
     345           0 : }
     346             : 
     347             : 
     348             : /* Taken from sys/kern/kern_synch.c and
     349             :    modified for __Userspace__
     350             : */
     351             : 
     352             : /*
     353             :  * Make all threads sleeping on the specified identifier runnable.
     354             :  * Associating wakeup with so_timeo identifier and timeo_cond
     355             :  * condition variable. TODO. If we use iterator thread then we need to
     356             :  * modify wakeup so it can distinguish between iterator identifier and
     357             :  * timeo identifier.
     358             :  */
     359             : void
     360           0 : wakeup(ident, so)
     361             :         void *ident;
     362             :         struct socket *so;
     363             : {
     364           0 :         SOCK_LOCK(so);
     365             : #if defined (__Userspace_os_Windows)
     366             :         WakeAllConditionVariable(&(so)->timeo_cond);
     367             : #else
     368           0 :         pthread_cond_broadcast(&(so)->timeo_cond);
     369             : #endif
     370           0 :         SOCK_UNLOCK(so);
     371           0 : }
     372             : 
     373             : 
     374             : /*
     375             :  * Make a thread sleeping on the specified identifier runnable.
     376             :  * May wake more than one thread if a target thread is currently
     377             :  * swapped out.
     378             :  */
     379             : void
     380           0 : wakeup_one(ident)
     381             :         void *ident;
     382             : {
     383             :         /* __Userspace__ Check: We are using accept_cond for wakeup_one.
     384             :           It seems that wakeup_one is only called within
     385             :           soisconnected() and sonewconn() with ident &head->so_timeo
     386             :           head is so->so_head, which is back pointer to listen socket
     387             :           This seems to indicate that the use of accept_cond is correct
     388             :           since socket where accepts occur is so_head in all
     389             :           subsidiary sockets.
     390             :          */
     391           0 :         ACCEPT_LOCK();
     392             : #if defined (__Userspace_os_Windows)
     393             :         WakeAllConditionVariable(&accept_cond);
     394             : #else
     395           0 :         pthread_cond_broadcast(&accept_cond);
     396             : #endif
     397           0 :         ACCEPT_UNLOCK();
     398           0 : }
     399             : 
     400             : 
     401             : /* Called within sctp_process_cookie_[existing/new] */
     402             : void
     403           0 : soisconnected(struct socket *so)
     404             : {
     405             :         struct socket *head;
     406             : 
     407           0 :         ACCEPT_LOCK();
     408           0 :         SOCK_LOCK(so);
     409           0 :         so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
     410           0 :         so->so_state |= SS_ISCONNECTED;
     411           0 :         head = so->so_head;
     412           0 :         if (head != NULL && (so->so_qstate & SQ_INCOMP)) {
     413           0 :                 SOCK_UNLOCK(so);
     414           0 :                 TAILQ_REMOVE(&head->so_incomp, so, so_list);
     415           0 :                 head->so_incqlen--;
     416           0 :                 so->so_qstate &= ~SQ_INCOMP;
     417           0 :                 TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
     418           0 :                 head->so_qlen++;
     419           0 :                 so->so_qstate |= SQ_COMP;
     420           0 :                 ACCEPT_UNLOCK();
     421           0 :                 sorwakeup(head);
     422           0 :                 wakeup_one(&head->so_timeo);
     423           0 :                 return;
     424             :         }
     425           0 :         SOCK_UNLOCK(so);
     426           0 :         ACCEPT_UNLOCK();
     427           0 :         wakeup(&so->so_timeo, so);
     428           0 :         sorwakeup(so);
     429           0 :         sowwakeup(so);
     430             : 
     431             : }
     432             : 
     433             : /* called within sctp_handle_cookie_echo */
     434             : 
     435             : struct socket *
     436           0 : sonewconn(struct socket *head, int connstatus)
     437             : {
     438             :         struct socket *so;
     439             :         int over;
     440             : 
     441           0 :         ACCEPT_LOCK();
     442           0 :         over = (head->so_qlen > 3 * head->so_qlimit / 2);
     443           0 :         ACCEPT_UNLOCK();
     444             : #ifdef REGRESSION
     445             :         if (regression_sonewconn_earlytest && over)
     446             : #else
     447           0 :         if (over)
     448             : #endif
     449           0 :                 return (NULL);
     450           0 :         so = soalloc();
     451           0 :         if (so == NULL)
     452           0 :                 return (NULL);
     453           0 :         so->so_head = head;
     454           0 :         so->so_type = head->so_type;
     455           0 :         so->so_options = head->so_options &~ SCTP_SO_ACCEPTCONN;
     456           0 :         so->so_linger = head->so_linger;
     457           0 :         so->so_state = head->so_state | SS_NOFDREF;
     458           0 :         so->so_dom = head->so_dom;
     459             : #ifdef MAC
     460             :         SOCK_LOCK(head);
     461             :         mac_create_socket_from_socket(head, so);
     462             :         SOCK_UNLOCK(head);
     463             : #endif
     464           0 :         if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat)) {
     465           0 :                 sodealloc(so);
     466           0 :                 return (NULL);
     467             :         }
     468           0 :         switch (head->so_dom) {
     469             : #ifdef INET
     470             :         case AF_INET:
     471             :                 if (sctp_attach(so, IPPROTO_SCTP, SCTP_DEFAULT_VRFID)) {
     472             :                         sodealloc(so);
     473             :                         return (NULL);
     474             :                 }
     475             :                 break;
     476             : #endif
     477             : #ifdef INET6
     478             :         case AF_INET6:
     479             :                 if (sctp6_attach(so, IPPROTO_SCTP, SCTP_DEFAULT_VRFID)) {
     480             :                         sodealloc(so);
     481             :                         return (NULL);
     482             :                 }
     483             :                 break;
     484             : #endif
     485             :         case AF_CONN:
     486           0 :                 if (sctpconn_attach(so, IPPROTO_SCTP, SCTP_DEFAULT_VRFID)) {
     487           0 :                         sodealloc(so);
     488           0 :                         return (NULL);
     489             :                 }
     490           0 :                 break;
     491             :         default:
     492           0 :                 sodealloc(so);
     493           0 :                 return (NULL);
     494             :                 break;
     495             :         }
     496           0 :         so->so_rcv.sb_lowat = head->so_rcv.sb_lowat;
     497           0 :         so->so_snd.sb_lowat = head->so_snd.sb_lowat;
     498           0 :         so->so_rcv.sb_timeo = head->so_rcv.sb_timeo;
     499           0 :         so->so_snd.sb_timeo = head->so_snd.sb_timeo;
     500           0 :         so->so_rcv.sb_flags |= head->so_rcv.sb_flags & SB_AUTOSIZE;
     501           0 :         so->so_snd.sb_flags |= head->so_snd.sb_flags & SB_AUTOSIZE;
     502           0 :         so->so_state |= connstatus;
     503           0 :         ACCEPT_LOCK();
     504           0 :         if (connstatus) {
     505           0 :                 TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
     506           0 :                 so->so_qstate |= SQ_COMP;
     507           0 :                 head->so_qlen++;
     508             :         } else {
     509             :                 /*
     510             :                  * Keep removing sockets from the head until there's room for
     511             :                  * us to insert on the tail.  In pre-locking revisions, this
     512             :                  * was a simple if(), but as we could be racing with other
     513             :                  * threads and soabort() requires dropping locks, we must
     514             :                  * loop waiting for the condition to be true.
     515             :                  */
     516           0 :                 while (head->so_incqlen > head->so_qlimit) {
     517             :                         struct socket *sp;
     518           0 :                         sp = TAILQ_FIRST(&head->so_incomp);
     519           0 :                         TAILQ_REMOVE(&head->so_incomp, sp, so_list);
     520           0 :                         head->so_incqlen--;
     521           0 :                         sp->so_qstate &= ~SQ_INCOMP;
     522           0 :                         sp->so_head = NULL;
     523           0 :                         ACCEPT_UNLOCK();
     524           0 :                         soabort(sp);
     525           0 :                         ACCEPT_LOCK();
     526             :                 }
     527           0 :                 TAILQ_INSERT_TAIL(&head->so_incomp, so, so_list);
     528           0 :                 so->so_qstate |= SQ_INCOMP;
     529           0 :                 head->so_incqlen++;
     530             :         }
     531           0 :         ACCEPT_UNLOCK();
     532           0 :         if (connstatus) {
     533           0 :                 sorwakeup(head);
     534           0 :                 wakeup_one(&head->so_timeo);
     535             :         }
     536           0 :         return (so);
     537             : 
     538             : }
     539             : 
     540             : /* From /src/sys/sys/sysproto.h */
     541             : struct sctp_generic_sendmsg_args {
     542             :         int sd;
     543             :         caddr_t msg;
     544             :         int mlen;
     545             :         caddr_t to;
     546             :         socklen_t tolen;  /* was __socklen_t */
     547             :         struct sctp_sndrcvinfo * sinfo;
     548             :         int flags;
     549             : };
     550             : 
     551             : struct sctp_generic_recvmsg_args {
     552             :         int sd;
     553             :         struct iovec *iov;
     554             :         int iovlen;
     555             :         struct sockaddr *from;
     556             :         socklen_t *fromlenaddr; /* was __socklen_t */
     557             :         struct sctp_sndrcvinfo *sinfo;
     558             :         int *msg_flags;
     559             : };
     560             : 
     561             : 
     562             :  /*
     563             :    Source: /src/sys/gnu/fs/xfs/FreeBSD/xfs_ioctl.c
     564             :  */
     565             : static __inline__ int
     566           0 : copy_to_user(void *dst, void *src, int len) {
     567           0 :         memcpy(dst, src, len);
     568           0 :         return 0;
     569             : }
     570             : 
     571             : static __inline__ int
     572           0 : copy_from_user(void *dst, void *src, int len) {
     573           0 :         memcpy(dst, src, len);
     574           0 :         return 0;
     575             : }
     576             : 
     577             : /*
     578             :  References:
     579             :  src/sys/dev/lmc/if_lmc.h:
     580             :  src/sys/powerpc/powerpc/copyinout.c
     581             :  src/sys/sys/systm.h
     582             : */
     583             : # define copyin(u, k, len)      copy_from_user(k, u, len)
     584             : 
     585             : /* References:
     586             :    src/sys/powerpc/powerpc/copyinout.c
     587             :    src/sys/sys/systm.h
     588             : */
     589             : # define copyout(k, u, len)     copy_to_user(u, k, len)
     590             : 
     591             : 
     592             : /* copyiniov definition copied/modified from src/sys/kern/kern_subr.c */
     593             : int
     594           0 : copyiniov(struct iovec *iovp, u_int iovcnt, struct iovec **iov, int error)
     595             : {
     596             :         u_int iovlen;
     597             : 
     598           0 :         *iov = NULL;
     599           0 :         if (iovcnt > UIO_MAXIOV)
     600           0 :                 return (error);
     601           0 :         iovlen = iovcnt * sizeof (struct iovec);
     602           0 :         *iov = malloc(iovlen); /*, M_IOV, M_WAITOK); */
     603           0 :         error = copyin(iovp, *iov, iovlen);
     604           0 :         if (error) {
     605           0 :                 free(*iov); /*, M_IOV); */
     606           0 :                 *iov = NULL;
     607             :         }
     608           0 :         return (error);
     609             : }
     610             : 
     611             : /* (__Userspace__) version of uiomove */
     612             : int
     613           0 : uiomove(void *cp, int n, struct uio *uio)
     614             : {
     615             :         struct iovec *iov;
     616             :         int cnt;
     617           0 :         int error = 0;
     618             : 
     619           0 :         if ((uio->uio_rw != UIO_READ) &&
     620           0 :             (uio->uio_rw != UIO_WRITE)) {
     621           0 :                 return (EINVAL);
     622             :         }
     623             : 
     624           0 :         while (n > 0 && uio->uio_resid) {
     625           0 :                 iov = uio->uio_iov;
     626           0 :                 cnt = iov->iov_len;
     627           0 :                 if (cnt == 0) {
     628           0 :                         uio->uio_iov++;
     629           0 :                         uio->uio_iovcnt--;
     630           0 :                         continue;
     631             :                 }
     632           0 :                 if (cnt > n)
     633           0 :                         cnt = n;
     634             : 
     635           0 :                 switch (uio->uio_segflg) {
     636             : 
     637             :                 case UIO_USERSPACE:
     638           0 :                         if (uio->uio_rw == UIO_READ)
     639           0 :                                 error = copyout(cp, iov->iov_base, cnt);
     640             :                         else
     641           0 :                                 error = copyin(iov->iov_base, cp, cnt);
     642           0 :                         if (error)
     643           0 :                                 goto out;
     644           0 :                         break;
     645             : 
     646             :                 case UIO_SYSSPACE:
     647           0 :                         if (uio->uio_rw == UIO_READ)
     648           0 :                                 bcopy(cp, iov->iov_base, cnt);
     649             :                         else
     650           0 :                                 bcopy(iov->iov_base, cp, cnt);
     651           0 :                         break;
     652             :                 }
     653           0 :                 iov->iov_base = (char *)iov->iov_base + cnt;
     654           0 :                 iov->iov_len -= cnt;
     655           0 :                 uio->uio_resid -= cnt;
     656           0 :                 uio->uio_offset += cnt;
     657           0 :                 cp = (char *)cp + cnt;
     658           0 :                 n -= cnt;
     659             :         }
     660             : out:
     661           0 :         return (error);
     662             : }
     663             : 
     664             : 
     665             : /* Source: src/sys/kern/uipc_syscalls.c */
     666             : int
     667           0 : getsockaddr(namp, uaddr, len)
     668             :         struct sockaddr **namp;
     669             :         caddr_t uaddr;
     670             :         size_t len;
     671             : {
     672             :         struct sockaddr *sa;
     673             :         int error;
     674             : 
     675           0 :         if (len > SOCK_MAXADDRLEN)
     676           0 :                 return (ENAMETOOLONG);
     677           0 :         if (len < offsetof(struct sockaddr, sa_data))
     678           0 :                 return (EINVAL);
     679           0 :         MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
     680           0 :         error = copyin(uaddr, sa, len);
     681           0 :         if (error) {
     682           0 :                 FREE(sa, M_SONAME);
     683             :         } else {
     684             : #ifdef HAVE_SA_LEN
     685             :                 sa->sa_len = len;
     686             : #endif
     687           0 :                 *namp = sa;
     688             :         }
     689           0 :         return (error);
     690             : }
     691             : 
     692             : 
     693             : /* Taken from  /src/lib/libc/net/sctp_sys_calls.c
     694             :  * and modified for __Userspace__
     695             :  * calling sctp_generic_sendmsg from this function
     696             :  */
     697             : ssize_t
     698           0 : userspace_sctp_sendmsg(struct socket *so,
     699             :                        const void *data,
     700             :                        size_t len,
     701             :                        struct sockaddr *to,
     702             :                        socklen_t tolen,
     703             :                        u_int32_t ppid,
     704             :                        u_int32_t flags,
     705             :                        u_int16_t stream_no,
     706             :                        u_int32_t timetolive,
     707             :                        u_int32_t context)
     708             : {
     709           0 :         struct sctp_sndrcvinfo sndrcvinfo, *sinfo = &sndrcvinfo;
     710             :         struct uio auio;
     711             :         struct iovec iov[1];
     712             : 
     713           0 :         memset(sinfo, 0, sizeof(struct sctp_sndrcvinfo));
     714           0 :         sinfo->sinfo_ppid = ppid;
     715           0 :         sinfo->sinfo_flags = flags;
     716           0 :         sinfo->sinfo_stream = stream_no;
     717           0 :         sinfo->sinfo_timetolive = timetolive;
     718           0 :         sinfo->sinfo_context = context;
     719           0 :         sinfo->sinfo_assoc_id = 0;
     720             : 
     721             : 
     722             :         /* Perform error checks on destination (to) */
     723           0 :         if (tolen > SOCK_MAXADDRLEN){
     724           0 :                 errno = ENAMETOOLONG;
     725           0 :                 return (-1);
     726             :         }
     727           0 :         if ((tolen > 0) &&
     728           0 :             ((to == NULL) || (tolen < (socklen_t)sizeof(struct sockaddr)))) {
     729           0 :                 errno = EINVAL;
     730           0 :                 return (-1);
     731             :         }
     732             :         /* Adding the following as part of defensive programming, in case the application
     733             :            does not do it when preparing the destination address.*/
     734             : #ifdef HAVE_SA_LEN
     735             :         if (to != NULL) {
     736             :                 to->sa_len = tolen;
     737             :         }
     738             : #endif
     739             : 
     740           0 :         iov[0].iov_base = (caddr_t)data;
     741           0 :         iov[0].iov_len = len;
     742             : 
     743           0 :         auio.uio_iov =  iov;
     744           0 :         auio.uio_iovcnt = 1;
     745           0 :         auio.uio_segflg = UIO_USERSPACE;
     746           0 :         auio.uio_rw = UIO_WRITE;
     747           0 :         auio.uio_offset = 0;                    /* XXX */
     748           0 :         auio.uio_resid = len;
     749           0 :         errno = sctp_lower_sosend(so, to, &auio, NULL, NULL, 0, sinfo);
     750           0 :         if (errno == 0) {
     751           0 :                 return (len - auio.uio_resid);
     752             :         } else {
     753           0 :                 return (-1);
     754             :         }
     755             : }
     756             : 
     757             : 
     758             : ssize_t
     759           0 : usrsctp_sendv(struct socket *so,
     760             :               const void *data,
     761             :               size_t len,
     762             :               struct sockaddr *to,
     763             :               int addrcnt,
     764             :               void *info,
     765             :               socklen_t infolen,
     766             :               unsigned int infotype,
     767             :               int flags)
     768             : {
     769             :         struct sctp_sndrcvinfo sinfo;
     770             :         struct uio auio;
     771             :         struct iovec iov[1];
     772             :         int use_sinfo;
     773             : 
     774           0 :         if (so == NULL) {
     775           0 :                 errno = EBADF;
     776           0 :                 return (-1);
     777             :         }
     778           0 :         memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
     779           0 :         use_sinfo = 0;
     780           0 :         switch (infotype) {
     781             :         case SCTP_SENDV_NOINFO:
     782           0 :                 if ((infolen != 0) || (info != NULL)) {
     783           0 :                         errno = EINVAL;
     784           0 :                         return (-1);
     785             :                 }
     786           0 :                 break;
     787             :         case SCTP_SENDV_SNDINFO:
     788           0 :                 if ((info == NULL) || (infolen != sizeof(struct sctp_sndinfo))) {
     789           0 :                         errno = EINVAL;
     790           0 :                         return (-1);
     791             :                 }
     792           0 :                 sinfo.sinfo_stream = ((struct sctp_sndinfo *)info)->snd_sid;
     793           0 :                 sinfo.sinfo_flags = ((struct sctp_sndinfo *)info)->snd_flags;
     794           0 :                 sinfo.sinfo_ppid = ((struct sctp_sndinfo *)info)->snd_ppid;
     795           0 :                 sinfo.sinfo_context = ((struct sctp_sndinfo *)info)->snd_context;
     796           0 :                 sinfo.sinfo_assoc_id = ((struct sctp_sndinfo *)info)->snd_assoc_id;
     797           0 :                 use_sinfo = 1;
     798           0 :                 break;
     799             :         case SCTP_SENDV_PRINFO:
     800           0 :                 if ((info == NULL) || (infolen != sizeof(struct sctp_prinfo))) {
     801           0 :                         errno = EINVAL;
     802           0 :                         return (-1);
     803             :                 }
     804           0 :                 sinfo.sinfo_stream = 0;
     805           0 :                 sinfo.sinfo_flags = PR_SCTP_POLICY(((struct sctp_prinfo *)info)->pr_policy);
     806           0 :                 sinfo.sinfo_timetolive = ((struct sctp_prinfo *)info)->pr_value;
     807           0 :                 use_sinfo = 1;
     808           0 :                 break;
     809             :         case SCTP_SENDV_AUTHINFO:
     810           0 :                 errno = EINVAL;
     811           0 :                 return (-1);
     812             :         case SCTP_SENDV_SPA:
     813           0 :                 if ((info == NULL) || (infolen != sizeof(struct sctp_sendv_spa))) {
     814           0 :                         errno = EINVAL;
     815           0 :                         return (-1);
     816             :                 }
     817           0 :                 if (((struct sctp_sendv_spa *)info)->sendv_flags & SCTP_SEND_SNDINFO_VALID) {
     818           0 :                         sinfo.sinfo_stream = ((struct sctp_sendv_spa *)info)->sendv_sndinfo.snd_sid;
     819           0 :                         sinfo.sinfo_flags = ((struct sctp_sendv_spa *)info)->sendv_sndinfo.snd_flags;
     820           0 :                         sinfo.sinfo_ppid = ((struct sctp_sendv_spa *)info)->sendv_sndinfo.snd_ppid;
     821           0 :                         sinfo.sinfo_context = ((struct sctp_sendv_spa *)info)->sendv_sndinfo.snd_context;
     822           0 :                         sinfo.sinfo_assoc_id = ((struct sctp_sendv_spa *)info)->sendv_sndinfo.snd_assoc_id;
     823             :                 } else {
     824           0 :                         sinfo.sinfo_flags = 0;
     825           0 :                         sinfo.sinfo_stream = 0;
     826             :                 }
     827           0 :                 if (((struct sctp_sendv_spa *)info)->sendv_flags & SCTP_SEND_PRINFO_VALID) {
     828           0 :                         sinfo.sinfo_flags |= PR_SCTP_POLICY(((struct sctp_sendv_spa *)info)->sendv_prinfo.pr_policy);
     829           0 :                         sinfo.sinfo_timetolive = ((struct sctp_sendv_spa *)info)->sendv_prinfo.pr_value;
     830             :                 }
     831           0 :                 if (((struct sctp_sendv_spa *)info)->sendv_flags & SCTP_SEND_AUTHINFO_VALID) {
     832           0 :                         errno = EINVAL;
     833           0 :                         return (-1);
     834             :                 }
     835           0 :                 use_sinfo = 1;
     836           0 :                 break;
     837             :         default:
     838           0 :                 errno = EINVAL;
     839           0 :                 return (-1);
     840             :         }
     841             : 
     842             :         /* Perform error checks on destination (to) */
     843           0 :         if (addrcnt > 1) {
     844           0 :                 errno = EINVAL;
     845           0 :                 return (-1);
     846             :         }
     847             : 
     848           0 :         iov[0].iov_base = (caddr_t)data;
     849           0 :         iov[0].iov_len = len;
     850             : 
     851           0 :         auio.uio_iov =  iov;
     852           0 :         auio.uio_iovcnt = 1;
     853           0 :         auio.uio_segflg = UIO_USERSPACE;
     854           0 :         auio.uio_rw = UIO_WRITE;
     855           0 :         auio.uio_offset = 0;                    /* XXX */
     856           0 :         auio.uio_resid = len;
     857           0 :         errno = sctp_lower_sosend(so, to, &auio, NULL, NULL, flags, use_sinfo ? &sinfo : NULL);
     858           0 :         if (errno == 0) {
     859           0 :                 return (len - auio.uio_resid);
     860             :         } else {
     861           0 :                 return (-1);
     862             :         }
     863             : }
     864             : 
     865             : 
     866             : ssize_t
     867           0 : userspace_sctp_sendmbuf(struct socket *so,
     868             :     struct mbuf* mbufdata,
     869             :     size_t len,
     870             :     struct sockaddr *to,
     871             :     socklen_t tolen,
     872             :     u_int32_t ppid,
     873             :     u_int32_t flags,
     874             :     u_int16_t stream_no,
     875             :     u_int32_t timetolive,
     876             :     u_int32_t context)
     877             : {
     878             : 
     879           0 :     struct sctp_sndrcvinfo sndrcvinfo, *sinfo = &sndrcvinfo;
     880             :     /*    struct uio auio;
     881             :           struct iovec iov[1]; */
     882           0 :     int error = 0;
     883           0 :     int uflags = 0;
     884             :     int retvalsendmsg;
     885             : 
     886           0 :     sinfo->sinfo_ppid = ppid;
     887           0 :     sinfo->sinfo_flags = flags;
     888           0 :     sinfo->sinfo_stream = stream_no;
     889           0 :     sinfo->sinfo_timetolive = timetolive;
     890           0 :     sinfo->sinfo_context = context;
     891           0 :     sinfo->sinfo_assoc_id = 0;
     892             : 
     893             :     /* Perform error checks on destination (to) */
     894           0 :     if (tolen > SOCK_MAXADDRLEN){
     895           0 :         error = (ENAMETOOLONG);
     896           0 :         goto sendmsg_return;
     897             :     }
     898           0 :     if (tolen < (socklen_t)offsetof(struct sockaddr, sa_data)){
     899           0 :         error = (EINVAL);
     900           0 :         goto sendmsg_return;
     901             :     }
     902             :     /* Adding the following as part of defensive programming, in case the application
     903             :        does not do it when preparing the destination address.*/
     904             : #ifdef HAVE_SA_LEN
     905             :     to->sa_len = tolen;
     906             : #endif
     907             : 
     908           0 :     error = sctp_lower_sosend(so, to, NULL/*uio*/,
     909             :                               (struct mbuf *)mbufdata, (struct mbuf *)NULL,
     910             :                               uflags, sinfo);
     911             : sendmsg_return:
     912             :     /* TODO: Needs a condition for non-blocking when error is EWOULDBLOCK */
     913           0 :     if (0 == error)
     914           0 :         retvalsendmsg = len;
     915           0 :     else if(error == EWOULDBLOCK) {
     916           0 :         errno = EWOULDBLOCK;
     917           0 :         retvalsendmsg = (-1);
     918             :     } else {
     919           0 :         SCTP_PRINTF("%s: error = %d\n", __func__, error);
     920           0 :         errno = error;
     921           0 :         retvalsendmsg = (-1);
     922             :     }
     923           0 :     return retvalsendmsg;
     924             : 
     925             : }
     926             : 
     927             : 
     928             : /* taken from usr.lib/sctp_sys_calls.c and needed here */
     929             : #define        SCTP_SMALL_IOVEC_SIZE 2
     930             : 
     931             : /* Taken from  /src/lib/libc/net/sctp_sys_calls.c
     932             :  * and modified for __Userspace__
     933             :  * calling sctp_generic_recvmsg from this function
     934             :  */
     935             : ssize_t
     936           0 : userspace_sctp_recvmsg(struct socket *so,
     937             :     void *dbuf,
     938             :     size_t len,
     939             :     struct sockaddr *from,
     940             :     socklen_t *fromlenp,
     941             :     struct sctp_sndrcvinfo *sinfo,
     942             :     int *msg_flags)
     943             : {
     944             :         struct uio auio;
     945             :         struct iovec iov[SCTP_SMALL_IOVEC_SIZE];
     946             :         struct iovec *tiov;
     947           0 :         int iovlen = 1;
     948           0 :         int error = 0;
     949             :         int ulen, i, retval;
     950             :         socklen_t fromlen;
     951             : 
     952           0 :         iov[0].iov_base = dbuf;
     953           0 :         iov[0].iov_len = len;
     954             : 
     955           0 :         auio.uio_iov = iov;
     956           0 :         auio.uio_iovcnt = iovlen;
     957           0 :         auio.uio_segflg = UIO_USERSPACE;
     958           0 :         auio.uio_rw = UIO_READ;
     959           0 :         auio.uio_offset = 0;                    /* XXX */
     960           0 :         auio.uio_resid = 0;
     961           0 :         tiov = iov;
     962           0 :         for (i = 0; i <iovlen; i++, tiov++) {
     963           0 :                 if ((auio.uio_resid += tiov->iov_len) < 0) {
     964           0 :                         error = EINVAL;
     965           0 :                         SCTP_PRINTF("%s: error = %d\n", __func__, error);
     966           0 :                         return (-1);
     967             :                 }
     968             :         }
     969           0 :         ulen = auio.uio_resid;
     970           0 :         if (fromlenp != NULL) {
     971           0 :                 fromlen = *fromlenp;
     972             :         } else {
     973           0 :                 fromlen = 0;
     974             :         }
     975           0 :         error = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL,
     976             :                     from, fromlen, msg_flags,
     977             :                     (struct sctp_sndrcvinfo *)sinfo, 1);
     978             : 
     979           0 :         if (error) {
     980           0 :                 if (auio.uio_resid != (int)ulen &&
     981           0 :                     (error == EINTR ||
     982             : #if !defined(__Userspace_os_NetBSD)
     983           0 :                      error == ERESTART ||
     984             : #endif
     985             :                      error == EWOULDBLOCK)) {
     986           0 :                         error = 0;
     987             :                 }
     988             :         }
     989           0 :         if ((fromlenp != NULL) && (fromlen > 0) && (from != NULL)) {
     990           0 :                 switch (from->sa_family) {
     991             : #if defined(INET)
     992             :                 case AF_INET:
     993             :                         *fromlenp = sizeof(struct sockaddr_in);
     994             :                         break;
     995             : #endif
     996             : #if defined(INET6)
     997             :                 case AF_INET6:
     998             :                         *fromlenp = sizeof(struct sockaddr_in6);
     999             :                         break;
    1000             : #endif
    1001             :                 case AF_CONN:
    1002           0 :                         *fromlenp = sizeof(struct sockaddr_conn);
    1003           0 :                         break;
    1004             :                 default:
    1005           0 :                         *fromlenp = 0;
    1006           0 :                         break;
    1007             :                 }
    1008           0 :                 if (*fromlenp > fromlen) {
    1009           0 :                         *fromlenp = fromlen;
    1010             :                 }
    1011             :         }
    1012           0 :         if (error == 0){
    1013             :                 /* ready return value */
    1014           0 :                 retval = (int)ulen - auio.uio_resid;
    1015           0 :                 return (retval);
    1016             :         } else {
    1017           0 :                 SCTP_PRINTF("%s: error = %d\n", __func__, error);
    1018           0 :                 return (-1);
    1019             :         }
    1020             : }
    1021             : 
    1022             : ssize_t
    1023           0 : usrsctp_recvv(struct socket *so,
    1024             :     void *dbuf,
    1025             :     size_t len,
    1026             :     struct sockaddr *from,
    1027             :     socklen_t *fromlenp,
    1028             :     void *info,
    1029             :     socklen_t *infolen,
    1030             :     unsigned int *infotype,
    1031             :     int *msg_flags)
    1032             : {
    1033             :         struct uio auio;
    1034             :         struct iovec iov[SCTP_SMALL_IOVEC_SIZE];
    1035             :         struct iovec *tiov;
    1036           0 :         int iovlen = 1;
    1037             :         int ulen, i;
    1038             :         socklen_t fromlen;
    1039             :         struct sctp_rcvinfo *rcv;
    1040             :         struct sctp_recvv_rn *rn;
    1041             :         struct sctp_extrcvinfo seinfo;
    1042             : 
    1043           0 :         if (so == NULL) {
    1044           0 :                 errno = EBADF;
    1045           0 :                 return (-1);
    1046             :         }
    1047           0 :         iov[0].iov_base = dbuf;
    1048           0 :         iov[0].iov_len = len;
    1049             : 
    1050           0 :         auio.uio_iov = iov;
    1051           0 :         auio.uio_iovcnt = iovlen;
    1052           0 :         auio.uio_segflg = UIO_USERSPACE;
    1053           0 :         auio.uio_rw = UIO_READ;
    1054           0 :         auio.uio_offset = 0;                    /* XXX */
    1055           0 :         auio.uio_resid = 0;
    1056           0 :         tiov = iov;
    1057           0 :         for (i = 0; i <iovlen; i++, tiov++) {
    1058           0 :                 if ((auio.uio_resid += tiov->iov_len) < 0) {
    1059           0 :                         errno = EINVAL;
    1060           0 :                         return (-1);
    1061             :                 }
    1062             :         }
    1063           0 :         ulen = auio.uio_resid;
    1064           0 :         if (fromlenp != NULL) {
    1065           0 :                 fromlen = *fromlenp;
    1066             :         } else {
    1067           0 :                 fromlen = 0;
    1068             :         }
    1069           0 :         errno = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL,
    1070             :                     from, fromlen, msg_flags,
    1071             :                     (struct sctp_sndrcvinfo *)&seinfo, 1);
    1072           0 :         if (errno) {
    1073           0 :                 if (auio.uio_resid != (int)ulen &&
    1074           0 :                     (errno == EINTR ||
    1075             : #if !defined(__Userspace_os_NetBSD)
    1076           0 :                      errno == ERESTART ||
    1077             : #endif
    1078           0 :                      errno == EWOULDBLOCK)) {
    1079           0 :                         errno = 0;
    1080             :                 }
    1081             :         }
    1082           0 :         if ((*msg_flags & MSG_NOTIFICATION) == 0) {
    1083             :                 struct sctp_inpcb *inp;
    1084             : 
    1085           0 :                 inp = (struct sctp_inpcb *)so->so_pcb;
    1086           0 :                 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO) &&
    1087           0 :                     sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO) &&
    1088           0 :                     *infolen >= (socklen_t)sizeof(struct sctp_recvv_rn) &&
    1089           0 :                     seinfo.sreinfo_next_flags & SCTP_NEXT_MSG_AVAIL) {
    1090           0 :                         rn = (struct sctp_recvv_rn *)info;
    1091           0 :                         rn->recvv_rcvinfo.rcv_sid = seinfo.sinfo_stream;
    1092           0 :                         rn->recvv_rcvinfo.rcv_ssn = seinfo.sinfo_ssn;
    1093           0 :                         rn->recvv_rcvinfo.rcv_flags = seinfo.sinfo_flags;
    1094           0 :                         rn->recvv_rcvinfo.rcv_ppid = seinfo.sinfo_ppid;
    1095           0 :                         rn->recvv_rcvinfo.rcv_context = seinfo.sinfo_context;
    1096           0 :                         rn->recvv_rcvinfo.rcv_tsn = seinfo.sinfo_tsn;
    1097           0 :                         rn->recvv_rcvinfo.rcv_cumtsn = seinfo.sinfo_cumtsn;
    1098           0 :                         rn->recvv_rcvinfo.rcv_assoc_id = seinfo.sinfo_assoc_id;
    1099           0 :                         rn->recvv_nxtinfo.nxt_sid = seinfo.sreinfo_next_stream;
    1100           0 :                         rn->recvv_nxtinfo.nxt_flags = 0;
    1101           0 :                         if (seinfo.sreinfo_next_flags & SCTP_NEXT_MSG_IS_UNORDERED) {
    1102           0 :                                 rn->recvv_nxtinfo.nxt_flags |= SCTP_UNORDERED;
    1103             :                         }
    1104           0 :                         if (seinfo.sreinfo_next_flags & SCTP_NEXT_MSG_IS_NOTIFICATION) {
    1105           0 :                                 rn->recvv_nxtinfo.nxt_flags |= SCTP_NOTIFICATION;
    1106             :                         }
    1107           0 :                         if (seinfo.sreinfo_next_flags & SCTP_NEXT_MSG_ISCOMPLETE) {
    1108           0 :                                 rn->recvv_nxtinfo.nxt_flags |= SCTP_COMPLETE;
    1109             :                         }
    1110           0 :                         rn->recvv_nxtinfo.nxt_ppid = seinfo.sreinfo_next_ppid;
    1111           0 :                         rn->recvv_nxtinfo.nxt_length = seinfo.sreinfo_next_length;
    1112           0 :                         rn->recvv_nxtinfo.nxt_assoc_id = seinfo.sreinfo_next_aid;
    1113           0 :                         *infolen = (socklen_t)sizeof(struct sctp_recvv_rn);
    1114           0 :                         *infotype = SCTP_RECVV_RN;
    1115           0 :                 } else if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO) &&
    1116           0 :                            *infolen >= (socklen_t)sizeof(struct sctp_rcvinfo)) {
    1117           0 :                         rcv = (struct sctp_rcvinfo *)info;
    1118           0 :                         rcv->rcv_sid = seinfo.sinfo_stream;
    1119           0 :                         rcv->rcv_ssn = seinfo.sinfo_ssn;
    1120           0 :                         rcv->rcv_flags = seinfo.sinfo_flags;
    1121           0 :                         rcv->rcv_ppid = seinfo.sinfo_ppid;
    1122           0 :                         rcv->rcv_context = seinfo.sinfo_context;
    1123           0 :                         rcv->rcv_tsn = seinfo.sinfo_tsn;
    1124           0 :                         rcv->rcv_cumtsn = seinfo.sinfo_cumtsn;
    1125           0 :                         rcv->rcv_assoc_id = seinfo.sinfo_assoc_id;
    1126           0 :                         *infolen = (socklen_t)sizeof(struct sctp_rcvinfo);
    1127           0 :                         *infotype = SCTP_RECVV_RCVINFO;
    1128             :                 } else {
    1129           0 :                         *infotype = SCTP_RECVV_NOINFO;
    1130           0 :                         *infolen = 0;
    1131             :                 }
    1132             :         }
    1133           0 :         if ((fromlenp != NULL) && (fromlen > 0) && (from != NULL)) {
    1134           0 :                 switch (from->sa_family) {
    1135             : #if defined(INET)
    1136             :                 case AF_INET:
    1137             :                         *fromlenp = sizeof(struct sockaddr_in);
    1138             :                         break;
    1139             : #endif
    1140             : #if defined(INET6)
    1141             :                 case AF_INET6:
    1142             :                         *fromlenp = sizeof(struct sockaddr_in6);
    1143             :                         break;
    1144             : #endif
    1145             :                 case AF_CONN:
    1146           0 :                         *fromlenp = sizeof(struct sockaddr_conn);
    1147           0 :                         break;
    1148             :                 default:
    1149           0 :                         *fromlenp = 0;
    1150           0 :                         break;
    1151             :                 }
    1152           0 :                 if (*fromlenp > fromlen) {
    1153           0 :                         *fromlenp = fromlen;
    1154             :                 }
    1155             :         }
    1156           0 :         if (errno == 0) {
    1157             :                 /* ready return value */
    1158           0 :                 return ((int)ulen - auio.uio_resid);
    1159             :         } else {
    1160           0 :                 return (-1);
    1161             :         }
    1162             : }
    1163             : 
    1164             : 
    1165             : 
    1166             : 
    1167             : #if defined(__Userspace__)
    1168             : /* Taken from  /src/sys/kern/uipc_socket.c
    1169             :  * and modified for __Userspace__
    1170             :  * socreate returns a socket.  The socket should be
    1171             :  * closed with soclose().
    1172             :  */
    1173             : int
    1174           0 : socreate(int dom, struct socket **aso, int type, int proto)
    1175             : {
    1176             :         struct socket *so;
    1177             :         int error;
    1178             : 
    1179           0 :         if ((dom != AF_CONN) && (dom != AF_INET) && (dom != AF_INET6)) {
    1180           0 :                 return (EINVAL);
    1181             :         }
    1182           0 :         if ((type != SOCK_STREAM) && (type != SOCK_SEQPACKET)) {
    1183           0 :                 return (EINVAL);
    1184             :         }
    1185           0 :         if (proto != IPPROTO_SCTP) {
    1186           0 :                 return (EINVAL);
    1187             :         }
    1188             : 
    1189           0 :         so = soalloc();
    1190           0 :         if (so == NULL) {
    1191           0 :                 return (ENOBUFS);
    1192             :         }
    1193             : 
    1194             :         /*
    1195             :          * so_incomp represents a queue of connections that
    1196             :          * must be completed at protocol level before being
    1197             :          * returned. so_comp field heads a list of sockets
    1198             :          * that are ready to be returned to the listening process
    1199             :          *__Userspace__ These queues are being used at a number of places like accept etc.
    1200             :          */
    1201           0 :         TAILQ_INIT(&so->so_incomp);
    1202           0 :         TAILQ_INIT(&so->so_comp);
    1203           0 :         so->so_type = type;
    1204           0 :         so->so_count = 1;
    1205           0 :         so->so_dom = dom;
    1206             :         /*
    1207             :          * Auto-sizing of socket buffers is managed by the protocols and
    1208             :          * the appropriate flags must be set in the pru_attach function.
    1209             :          * For __Userspace__ The pru_attach function in this case is sctp_attach.
    1210             :          */
    1211           0 :         switch (dom) {
    1212             : #if defined(INET)
    1213             :         case AF_INET:
    1214             :                 error = sctp_attach(so, proto, SCTP_DEFAULT_VRFID);
    1215             :                 break;
    1216             : #endif
    1217             : #if defined(INET6)
    1218             :         case AF_INET6:
    1219             :                 error = sctp6_attach(so, proto, SCTP_DEFAULT_VRFID);
    1220             :                 break;
    1221             : #endif
    1222             :         case AF_CONN:
    1223           0 :                 error = sctpconn_attach(so, proto, SCTP_DEFAULT_VRFID);
    1224           0 :                 break;
    1225             :         default:
    1226           0 :                 error = EAFNOSUPPORT;
    1227           0 :                 break;
    1228             :         }
    1229           0 :         if (error) {
    1230             :                 KASSERT(so->so_count == 1, ("socreate: so_count %d", so->so_count));
    1231           0 :                 so->so_count = 0;
    1232           0 :                 sodealloc(so);
    1233           0 :                 return (error);
    1234             :         }
    1235           0 :         *aso = so;
    1236           0 :         return (0);
    1237             : }
    1238             : #else
    1239             : /* The kernel version for reference is below. The #else
    1240             :    should be removed once the __Userspace__
    1241             :    version is tested.
    1242             :  * socreate returns a socket with a ref count of 1.  The socket should be
    1243             :  * closed with soclose().
    1244             :  */
    1245             : int
    1246             : socreate(int dom, struct socket **aso, int type, int proto,
    1247             :     struct ucred *cred, struct thread *td)
    1248             : {
    1249             :         struct protosw *prp;
    1250             :         struct socket *so;
    1251             :         int error;
    1252             : 
    1253             :         if (proto)
    1254             :                 prp = pffindproto(dom, proto, type);
    1255             :         else
    1256             :                 prp = pffindtype(dom, type);
    1257             : 
    1258             :         if (prp == NULL || prp->pr_usrreqs->pru_attach == NULL ||
    1259             :             prp->pr_usrreqs->pru_attach == pru_attach_notsupp)
    1260             :                 return (EPROTONOSUPPORT);
    1261             : 
    1262             :         if (jailed(cred) && jail_socket_unixiproute_only &&
    1263             :             prp->pr_domain->dom_family != PF_LOCAL &&
    1264             :             prp->pr_domain->dom_family != PF_INET &&
    1265             :             prp->pr_domain->dom_family != PF_ROUTE) {
    1266             :                 return (EPROTONOSUPPORT);
    1267             :         }
    1268             : 
    1269             :         if (prp->pr_type != type)
    1270             :                 return (EPROTOTYPE);
    1271             :         so = soalloc();
    1272             :         if (so == NULL)
    1273             :                 return (ENOBUFS);
    1274             : 
    1275             :         TAILQ_INIT(&so->so_incomp);
    1276             :         TAILQ_INIT(&so->so_comp);
    1277             :         so->so_type = type;
    1278             :         so->so_cred = crhold(cred);
    1279             :         so->so_proto = prp;
    1280             : #ifdef MAC
    1281             :         mac_create_socket(cred, so);
    1282             : #endif
    1283             :         knlist_init(&so->so_rcv.sb_sel.si_note, SOCKBUF_MTX(&so->so_rcv),
    1284             :             NULL, NULL, NULL);
    1285             :         knlist_init(&so->so_snd.sb_sel.si_note, SOCKBUF_MTX(&so->so_snd),
    1286             :             NULL, NULL, NULL);
    1287             :         so->so_count = 1;
    1288             :         /*
    1289             :          * Auto-sizing of socket buffers is managed by the protocols and
    1290             :          * the appropriate flags must be set in the pru_attach function.
    1291             :          */
    1292             :         error = (*prp->pr_usrreqs->pru_attach)(so, proto, td);
    1293             :         if (error) {
    1294             :                 KASSERT(so->so_count == 1, ("socreate: so_count %d",
    1295             :                     so->so_count));
    1296             :                 so->so_count = 0;
    1297             :                 sodealloc(so);
    1298             :                 return (error);
    1299             :         }
    1300             :         *aso = so;
    1301             :         return (0);
    1302             : }
    1303             : #endif
    1304             : 
    1305             : 
    1306             : 
    1307             : 
    1308             : /* Taken from  /src/sys/kern/uipc_syscalls.c
    1309             :  * and modified for __Userspace__
    1310             :  * Removing struct thread td.
    1311             :  */
    1312             : struct socket *
    1313           0 : userspace_socket(int domain, int type, int protocol)
    1314             : {
    1315           0 :         struct socket *so = NULL;
    1316             : 
    1317           0 :         errno = socreate(domain, &so, type, protocol);
    1318           0 :         if (errno) {
    1319           0 :                 return (NULL);
    1320             :         }
    1321             :         /*
    1322             :          * The original socket call returns the file descriptor fd.
    1323             :          * td->td_retval[0] = fd.
    1324             :          * We are returning struct socket *so.
    1325             :          */
    1326           0 :         return (so);
    1327             : }
    1328             : 
    1329             : struct socket *
    1330           0 : usrsctp_socket(int domain, int type, int protocol,
    1331             :                int (*receive_cb)(struct socket *sock, union sctp_sockstore addr, void *data,
    1332             :                                  size_t datalen, struct sctp_rcvinfo, int flags, void *ulp_info),
    1333             :                int (*send_cb)(struct socket *sock, uint32_t sb_free),
    1334             :                uint32_t sb_threshold,
    1335             :                void *ulp_info)
    1336             : {
    1337             :         struct socket *so;
    1338             : 
    1339           0 :         if ((protocol = IPPROTO_SCTP) && (SCTP_BASE_VAR(sctp_pcb_initialized) == 0)) {
    1340           0 :                 errno = EPROTONOSUPPORT;
    1341           0 :                 return (NULL);
    1342             :         }
    1343           0 :         if ((receive_cb == NULL) &&
    1344           0 :             ((send_cb != NULL) || (sb_threshold != 0) || (ulp_info != NULL))) {
    1345           0 :                 errno = EINVAL;
    1346           0 :                 return (NULL);
    1347             :         }
    1348           0 :         if ((domain == AF_CONN) && (SCTP_BASE_VAR(conn_output) == NULL)) {
    1349           0 :                 errno = EAFNOSUPPORT;
    1350           0 :                 return (NULL);
    1351             :         }
    1352           0 :         errno = socreate(domain, &so, type, protocol);
    1353           0 :         if (errno) {
    1354           0 :                 return (NULL);
    1355             :         }
    1356             :         /*
    1357             :          * The original socket call returns the file descriptor fd.
    1358             :          * td->td_retval[0] = fd.
    1359             :          * We are returning struct socket *so.
    1360             :          */
    1361           0 :         register_recv_cb(so, receive_cb);
    1362           0 :         register_send_cb(so, sb_threshold, send_cb);
    1363           0 :         register_ulp_info(so, ulp_info);
    1364           0 :         return (so);
    1365             : }
    1366             : 
    1367             : 
    1368             : u_long  sb_max = SB_MAX;
    1369             : u_long sb_max_adj =
    1370             :        SB_MAX * MCLBYTES / (MSIZE + MCLBYTES); /* adjusted sb_max */
    1371             : 
    1372             : static  u_long sb_efficiency = 8;       /* parameter for sbreserve() */
    1373             : 
    1374             : /*
    1375             :  * Allot mbufs to a sockbuf.  Attempt to scale mbmax so that mbcnt doesn't
    1376             :  * become limiting if buffering efficiency is near the normal case.
    1377             :  */
    1378             : int
    1379           0 : sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so)
    1380             : {
    1381             :         SOCKBUF_LOCK_ASSERT(sb);
    1382           0 :         sb->sb_mbmax = (u_int)min(cc * sb_efficiency, sb_max);
    1383           0 :         sb->sb_hiwat = (u_int)cc;
    1384           0 :         if (sb->sb_lowat > (int)sb->sb_hiwat)
    1385           0 :                 sb->sb_lowat = (int)sb->sb_hiwat;
    1386           0 :         return (1);
    1387             : }
    1388             : 
    1389             : static int
    1390           0 : sbreserve(struct sockbuf *sb, u_long cc, struct socket *so)
    1391             : {
    1392             :         int error;
    1393             : 
    1394           0 :         SOCKBUF_LOCK(sb);
    1395           0 :         error = sbreserve_locked(sb, cc, so);
    1396           0 :         SOCKBUF_UNLOCK(sb);
    1397           0 :         return (error);
    1398             : }
    1399             : 
    1400             : #if defined(__Userspace__)
    1401             : int
    1402           0 : soreserve(struct socket *so, u_long sndcc, u_long rcvcc)
    1403             : {
    1404           0 :         SOCKBUF_LOCK(&so->so_snd);
    1405           0 :         SOCKBUF_LOCK(&so->so_rcv);
    1406           0 :         so->so_snd.sb_hiwat = (uint32_t)sndcc;
    1407           0 :         so->so_rcv.sb_hiwat = (uint32_t)rcvcc;
    1408             : 
    1409           0 :         if (sbreserve_locked(&so->so_snd, sndcc, so) == 0) {
    1410           0 :                 goto bad;
    1411             :         }
    1412           0 :         if (sbreserve_locked(&so->so_rcv, rcvcc, so) == 0) {
    1413           0 :                 goto bad;
    1414             :         }
    1415           0 :         if (so->so_rcv.sb_lowat == 0)
    1416           0 :                 so->so_rcv.sb_lowat = 1;
    1417           0 :         if (so->so_snd.sb_lowat == 0)
    1418           0 :                 so->so_snd.sb_lowat = MCLBYTES;
    1419           0 :         if (so->so_snd.sb_lowat > (int)so->so_snd.sb_hiwat)
    1420           0 :                 so->so_snd.sb_lowat = (int)so->so_snd.sb_hiwat;
    1421           0 :         SOCKBUF_UNLOCK(&so->so_rcv);
    1422           0 :         SOCKBUF_UNLOCK(&so->so_snd);
    1423           0 :         return (0);
    1424             : 
    1425             :  bad:
    1426           0 :         SOCKBUF_UNLOCK(&so->so_rcv);
    1427           0 :         SOCKBUF_UNLOCK(&so->so_snd);
    1428           0 :         return (ENOBUFS);
    1429             : }
    1430             : #else /* kernel version for reference */
    1431             : int
    1432             : soreserve(struct socket *so, u_long sndcc, u_long rcvcc)
    1433             : {
    1434             :         struct thread *td = curthread;
    1435             : 
    1436             :         SOCKBUF_LOCK(&so->so_snd);
    1437             :         SOCKBUF_LOCK(&so->so_rcv);
    1438             :         if (sbreserve_locked(&so->so_snd, sndcc, so, td) == 0)
    1439             :                 goto bad;
    1440             :         if (sbreserve_locked(&so->so_rcv, rcvcc, so, td) == 0)
    1441             :                 goto bad2;
    1442             :         if (so->so_rcv.sb_lowat == 0)
    1443             :                 so->so_rcv.sb_lowat = 1;
    1444             :         if (so->so_snd.sb_lowat == 0)
    1445             :                 so->so_snd.sb_lowat = MCLBYTES;
    1446             :         if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat)
    1447             :                 so->so_snd.sb_lowat = so->so_snd.sb_hiwat;
    1448             :         SOCKBUF_UNLOCK(&so->so_rcv);
    1449             :         SOCKBUF_UNLOCK(&so->so_snd);
    1450             :         return (0);
    1451             : bad2:
    1452             :         sbrelease_locked(&so->so_snd, so);
    1453             : bad:
    1454             :         SOCKBUF_UNLOCK(&so->so_rcv);
    1455             :         SOCKBUF_UNLOCK(&so->so_snd);
    1456             :         return (ENOBUFS);
    1457             : }
    1458             : #endif
    1459             : 
    1460             : 
    1461             : 
    1462             : 
    1463             : 
    1464             : /* Taken from  /src/sys/kern/uipc_sockbuf.c
    1465             :  * and modified for __Userspace__
    1466             :  */
    1467             : 
    1468             : #if defined(__Userspace__)
    1469             : void
    1470           0 : sowakeup(struct socket *so, struct sockbuf *sb)
    1471             : {
    1472             : 
    1473             :         SOCKBUF_LOCK_ASSERT(sb);
    1474             : 
    1475           0 :         sb->sb_flags &= ~SB_SEL;
    1476           0 :         if (sb->sb_flags & SB_WAIT) {
    1477           0 :                 sb->sb_flags &= ~SB_WAIT;
    1478             : #if defined (__Userspace_os_Windows)
    1479             :                 WakeAllConditionVariable(&(sb)->sb_cond);
    1480             : #else
    1481           0 :                 pthread_cond_broadcast(&(sb)->sb_cond);
    1482             : #endif
    1483             :         }
    1484           0 :         SOCKBUF_UNLOCK(sb);
    1485             :         /*__Userspace__ what todo about so_upcall?*/
    1486             : 
    1487           0 : }
    1488             : #else /* kernel version for reference */
    1489             : /*
    1490             :  * Wakeup processes waiting on a socket buffer.  Do asynchronous notification
    1491             :  * via SIGIO if the socket has the SS_ASYNC flag set.
    1492             :  *
    1493             :  * Called with the socket buffer lock held; will release the lock by the end
    1494             :  * of the function.  This allows the caller to acquire the socket buffer lock
    1495             :  * while testing for the need for various sorts of wakeup and hold it through
    1496             :  * to the point where it's no longer required.  We currently hold the lock
    1497             :  * through calls out to other subsystems (with the exception of kqueue), and
    1498             :  * then release it to avoid lock order issues.  It's not clear that's
    1499             :  * correct.
    1500             :  */
    1501             : void
    1502             : sowakeup(struct socket *so, struct sockbuf *sb)
    1503             : {
    1504             : 
    1505             :         SOCKBUF_LOCK_ASSERT(sb);
    1506             : 
    1507             :         selwakeuppri(&sb->sb_sel, PSOCK);
    1508             :         sb->sb_flags &= ~SB_SEL;
    1509             :         if (sb->sb_flags & SB_WAIT) {
    1510             :                 sb->sb_flags &= ~SB_WAIT;
    1511             :                 wakeup(&sb->sb_cc);
    1512             :         }
    1513             :         KNOTE_LOCKED(&sb->sb_sel.si_note, 0);
    1514             :         SOCKBUF_UNLOCK(sb);
    1515             :         if ((so->so_state & SS_ASYNC) && so->so_sigio != NULL)
    1516             :                 pgsigio(&so->so_sigio, SIGIO, 0);
    1517             :         if (sb->sb_flags & SB_UPCALL)
    1518             :                 (*so->so_upcall)(so, so->so_upcallarg, M_NOWAIT);
    1519             :         if (sb->sb_flags & SB_AIO)
    1520             :                 aio_swake(so, sb);
    1521             :         mtx_assert(SOCKBUF_MTX(sb), MA_NOTOWNED);
    1522             : }
    1523             : #endif
    1524             : 
    1525             : 
    1526             : 
    1527             : /* Taken from  /src/sys/kern/uipc_socket.c
    1528             :  * and modified for __Userspace__
    1529             :  */
    1530             : 
    1531             : int
    1532           0 : sobind(struct socket *so, struct sockaddr *nam)
    1533             : {
    1534           0 :         switch (nam->sa_family) {
    1535             : #if defined(INET)
    1536             :         case AF_INET:
    1537             :                 return (sctp_bind(so, nam));
    1538             : #endif
    1539             : #if defined(INET6)
    1540             :         case AF_INET6:
    1541             :                 return (sctp6_bind(so, nam, NULL));
    1542             : #endif
    1543             :         case AF_CONN:
    1544           0 :                 return (sctpconn_bind(so, nam));
    1545             :         default:
    1546           0 :                 return EAFNOSUPPORT;
    1547             :         }
    1548             : }
    1549             : 
    1550             : /* Taken from  /src/sys/kern/uipc_syscalls.c
    1551             :  * and modified for __Userspace__
    1552             :  */
    1553             : 
    1554             : int
    1555           0 : usrsctp_bind(struct socket *so, struct sockaddr *name, int namelen)
    1556             : {
    1557             :         struct sockaddr *sa;
    1558             : 
    1559           0 :         if (so == NULL) {
    1560           0 :                 errno = EBADF;
    1561           0 :                 return (-1);
    1562             :         }
    1563           0 :         if ((errno = getsockaddr(&sa, (caddr_t)name, namelen)) != 0)
    1564           0 :                 return (-1);
    1565             : 
    1566           0 :         errno = sobind(so, sa);
    1567           0 :         FREE(sa, M_SONAME);
    1568           0 :         if (errno) {
    1569           0 :                 return (-1);
    1570             :         } else {
    1571           0 :                 return (0);
    1572             :         }
    1573             : }
    1574             : 
    1575             : int
    1576           0 : userspace_bind(struct socket *so, struct sockaddr *name, int namelen)
    1577             : {
    1578           0 :         return (usrsctp_bind(so, name, namelen));
    1579             : }
    1580             : 
    1581             : /* Taken from  /src/sys/kern/uipc_socket.c
    1582             :  * and modified for __Userspace__
    1583             :  */
    1584             : 
    1585             : int
    1586           0 : solisten(struct socket *so, int backlog)
    1587             : {
    1588           0 :         if (so == NULL) {
    1589           0 :                 return (EBADF);
    1590             :         } else {
    1591           0 :                 return (sctp_listen(so, backlog, NULL));
    1592             :         }
    1593             : }
    1594             : 
    1595             : 
    1596             : int
    1597           0 : solisten_proto_check(struct socket *so)
    1598             : {
    1599             : 
    1600             :         SOCK_LOCK_ASSERT(so);
    1601             : 
    1602           0 :         if (so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING |
    1603             :             SS_ISDISCONNECTING))
    1604           0 :                 return (EINVAL);
    1605           0 :         return (0);
    1606             : }
    1607             : 
    1608             : static int somaxconn = SOMAXCONN;
    1609             : 
    1610             : void
    1611           0 : solisten_proto(struct socket *so, int backlog)
    1612             : {
    1613             : 
    1614             :         SOCK_LOCK_ASSERT(so);
    1615             : 
    1616           0 :         if (backlog < 0 || backlog > somaxconn)
    1617           0 :                 backlog = somaxconn;
    1618           0 :         so->so_qlimit = backlog;
    1619           0 :         so->so_options |= SCTP_SO_ACCEPTCONN;
    1620           0 : }
    1621             : 
    1622             : 
    1623             : 
    1624             : 
    1625             : /* Taken from  /src/sys/kern/uipc_syscalls.c
    1626             :  * and modified for __Userspace__
    1627             :  */
    1628             : 
    1629             : int
    1630           0 : usrsctp_listen(struct socket *so, int backlog)
    1631             : {
    1632           0 :         errno = solisten(so, backlog);
    1633           0 :         if (errno) {
    1634           0 :                 return (-1);
    1635             :         } else {
    1636           0 :                 return (0);
    1637             :         }
    1638             : }
    1639             : 
    1640             : int
    1641           0 : userspace_listen(struct socket *so, int backlog)
    1642             : {
    1643           0 :         return (usrsctp_listen(so, backlog));
    1644             : }
    1645             : 
    1646             : /* Taken from  /src/sys/kern/uipc_socket.c
    1647             :  * and modified for __Userspace__
    1648             :  */
    1649             : 
    1650             : int
    1651           0 : soaccept(struct socket *so, struct sockaddr **nam)
    1652             : {
    1653             :         int error;
    1654             : 
    1655           0 :         SOCK_LOCK(so);
    1656             :         KASSERT((so->so_state & SS_NOFDREF) != 0, ("soaccept: !NOFDREF"));
    1657           0 :         so->so_state &= ~SS_NOFDREF;
    1658           0 :         SOCK_UNLOCK(so);
    1659           0 :         error = sctp_accept(so, nam);
    1660           0 :         return (error);
    1661             : }
    1662             : 
    1663             : 
    1664             : 
    1665             : /* Taken from  /src/sys/kern/uipc_syscalls.c
    1666             :  * kern_accept modified for __Userspace__
    1667             :  */
    1668             : int
    1669           0 : user_accept(struct socket *head,  struct sockaddr **name, socklen_t *namelen, struct socket **ptr_accept_ret_sock)
    1670             : {
    1671           0 :         struct sockaddr *sa = NULL;
    1672             :         int error;
    1673           0 :         struct socket *so = NULL;
    1674             : 
    1675             : 
    1676           0 :         if (name) {
    1677           0 :                 *name = NULL;
    1678             :         }
    1679             : 
    1680           0 :         if ((head->so_options & SCTP_SO_ACCEPTCONN) == 0) {
    1681           0 :                 error = EINVAL;
    1682           0 :                 goto done;
    1683             :         }
    1684             : 
    1685           0 :         ACCEPT_LOCK();
    1686           0 :         if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) {
    1687           0 :                 ACCEPT_UNLOCK();
    1688           0 :                 error = EWOULDBLOCK;
    1689           0 :                 goto noconnection;
    1690             :         }
    1691           0 :         while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) {
    1692           0 :                 if (head->so_rcv.sb_state & SBS_CANTRCVMORE) {
    1693           0 :                         head->so_error = ECONNABORTED;
    1694           0 :                         break;
    1695             :                 }
    1696             : #if defined (__Userspace_os_Windows)
    1697             :                 if (SleepConditionVariableCS(&accept_cond, &accept_mtx, INFINITE))
    1698             :                         error = 0;
    1699             :                 else
    1700             :                         error = GetLastError();
    1701             : #else
    1702           0 :                 error = pthread_cond_wait(&accept_cond, &accept_mtx);
    1703             : #endif
    1704           0 :                 if (error) {
    1705           0 :                         ACCEPT_UNLOCK();
    1706           0 :                         goto noconnection;
    1707             :                 }
    1708             :         }
    1709           0 :         if (head->so_error) {
    1710           0 :                 error = head->so_error;
    1711           0 :                 head->so_error = 0;
    1712           0 :                 ACCEPT_UNLOCK();
    1713           0 :                 goto noconnection;
    1714             :         }
    1715           0 :         so = TAILQ_FIRST(&head->so_comp);
    1716             :         KASSERT(!(so->so_qstate & SQ_INCOMP), ("accept1: so SQ_INCOMP"));
    1717             :         KASSERT(so->so_qstate & SQ_COMP, ("accept1: so not SQ_COMP"));
    1718             : 
    1719             :         /*
    1720             :          * Before changing the flags on the socket, we have to bump the
    1721             :          * reference count.  Otherwise, if the protocol calls sofree(),
    1722             :          * the socket will be released due to a zero refcount.
    1723             :          */
    1724           0 :         SOCK_LOCK(so);                  /* soref() and so_state update */
    1725           0 :         soref(so);                      /* file descriptor reference */
    1726             : 
    1727           0 :         TAILQ_REMOVE(&head->so_comp, so, so_list);
    1728           0 :         head->so_qlen--;
    1729           0 :         so->so_state |= (head->so_state & SS_NBIO);
    1730           0 :         so->so_qstate &= ~SQ_COMP;
    1731           0 :         so->so_head = NULL;
    1732           0 :         SOCK_UNLOCK(so);
    1733           0 :         ACCEPT_UNLOCK();
    1734             : 
    1735             : 
    1736             :         /*
    1737             :          * The original accept returns fd value via td->td_retval[0] = fd;
    1738             :          * we will return the socket for accepted connection.
    1739             :          */
    1740             : 
    1741           0 :         error = soaccept(so, &sa);
    1742           0 :         if (error) {
    1743             :                 /*
    1744             :                  * return a namelen of zero for older code which might
    1745             :                  * ignore the return value from accept.
    1746             :                  */
    1747           0 :                 if (name)
    1748           0 :                         *namelen = 0;
    1749           0 :                 goto noconnection;
    1750             :         }
    1751           0 :         if (sa == NULL) {
    1752           0 :                 if (name)
    1753           0 :                         *namelen = 0;
    1754           0 :                 goto done;
    1755             :         }
    1756           0 :         if (name) {
    1757             : #ifdef HAVE_SA_LEN
    1758             :                 /* check sa_len before it is destroyed */
    1759             :                 if (*namelen > sa->sa_len) {
    1760             :                         *namelen = sa->sa_len;
    1761             :                 }
    1762             : #else
    1763             :                 socklen_t sa_len;
    1764             : 
    1765           0 :                 switch (sa->sa_family) {
    1766             : #ifdef INET
    1767             :                 case AF_INET:
    1768             :                         sa_len = sizeof(struct sockaddr_in);
    1769             :                         break;
    1770             : #endif
    1771             : #ifdef INET6
    1772             :                 case AF_INET6:
    1773             :                         sa_len = sizeof(struct sockaddr_in6);
    1774             :                         break;
    1775             : #endif
    1776             :                 case AF_CONN:
    1777           0 :                         sa_len = sizeof(struct sockaddr_conn);
    1778           0 :                         break;
    1779             :                 default:
    1780           0 :                         sa_len = 0;
    1781           0 :                         break;
    1782             :                 }
    1783           0 :                 if (*namelen > sa_len) {
    1784           0 :                         *namelen = sa_len;
    1785             :                 }
    1786             : #endif
    1787           0 :                 *name = sa;
    1788           0 :                 sa = NULL;
    1789             :         }
    1790             : noconnection:
    1791           0 :         if (sa) {
    1792           0 :                 FREE(sa, M_SONAME);
    1793             :         }
    1794             : 
    1795             : done:
    1796           0 :         *ptr_accept_ret_sock = so;
    1797           0 :         return (error);
    1798             : }
    1799             : 
    1800             : 
    1801             : 
    1802             : /* Taken from  /src/sys/kern/uipc_syscalls.c
    1803             :  * and modified for __Userspace__
    1804             :  */
    1805             : /*
    1806             :  * accept1()
    1807             :  */
    1808             : static int
    1809           0 : accept1(struct socket *so, struct sockaddr *aname, socklen_t *anamelen, struct socket **ptr_accept_ret_sock)
    1810             : {
    1811             :         struct sockaddr *name;
    1812             :         socklen_t namelen;
    1813             :         int error;
    1814             : 
    1815           0 :         if (so == NULL) {
    1816           0 :                 return (EBADF);
    1817             :         }
    1818           0 :         if (aname == NULL) {
    1819           0 :                 return (user_accept(so, NULL, NULL, ptr_accept_ret_sock));
    1820             :         }
    1821             : 
    1822           0 :         error = copyin(anamelen, &namelen, sizeof (namelen));
    1823           0 :         if (error)
    1824           0 :                 return (error);
    1825             : 
    1826           0 :         error = user_accept(so, &name, &namelen, ptr_accept_ret_sock);
    1827             : 
    1828             :         /*
    1829             :          * return a namelen of zero for older code which might
    1830             :          * ignore the return value from accept.
    1831             :          */
    1832           0 :         if (error) {
    1833           0 :                 (void) copyout(&namelen,
    1834             :                     anamelen, sizeof(*anamelen));
    1835           0 :                 return (error);
    1836             :         }
    1837             : 
    1838           0 :         if (error == 0 && name != NULL) {
    1839           0 :                 error = copyout(name, aname, namelen);
    1840             :         }
    1841           0 :         if (error == 0) {
    1842           0 :                 error = copyout(&namelen, anamelen, sizeof(namelen));
    1843             :         }
    1844             : 
    1845           0 :         if (name) {
    1846           0 :                 FREE(name, M_SONAME);
    1847             :         }
    1848           0 :         return (error);
    1849             : }
    1850             : 
    1851             : struct socket *
    1852           0 : usrsctp_accept(struct socket *so, struct sockaddr *aname, socklen_t *anamelen)
    1853             : {
    1854             :         struct socket *accept_return_sock;
    1855             : 
    1856           0 :         errno = accept1(so, aname, anamelen, &accept_return_sock);
    1857           0 :         if (errno) {
    1858           0 :                 return (NULL);
    1859             :         } else {
    1860           0 :                 return (accept_return_sock);
    1861             :         }
    1862             : }
    1863             : 
    1864             : struct socket *
    1865           0 : userspace_accept(struct socket *so, struct sockaddr *aname, socklen_t *anamelen)
    1866             : {
    1867           0 :         return (usrsctp_accept(so, aname, anamelen));
    1868             : }
    1869             : 
    1870             : struct socket *
    1871           0 : usrsctp_peeloff(struct socket *head, sctp_assoc_t id)
    1872             : {
    1873             :         struct socket *so;
    1874             : 
    1875           0 :         if ((errno = sctp_can_peel_off(head, id)) != 0) {
    1876           0 :                 return (NULL);
    1877             :         }
    1878           0 :         if ((so = sonewconn(head, SS_ISCONNECTED)) == NULL) {
    1879           0 :                 return (NULL);
    1880             :         }
    1881           0 :         ACCEPT_LOCK();
    1882           0 :         SOCK_LOCK(so);
    1883           0 :         soref(so);
    1884           0 :         TAILQ_REMOVE(&head->so_comp, so, so_list);
    1885           0 :         head->so_qlen--;
    1886           0 :         so->so_state |= (head->so_state & SS_NBIO);
    1887           0 :         so->so_qstate &= ~SQ_COMP;
    1888           0 :         so->so_head = NULL;
    1889           0 :         SOCK_UNLOCK(so);
    1890           0 :         ACCEPT_UNLOCK();
    1891           0 :         if ((errno = sctp_do_peeloff(head, so, id)) != 0) {
    1892           0 :                 so->so_count = 0;
    1893           0 :                 sodealloc(so);
    1894           0 :                 return (NULL);
    1895             :         }
    1896           0 :         return (so);
    1897             : }
    1898             : 
    1899             : int
    1900           0 : sodisconnect(struct socket *so)
    1901             : {
    1902             :         int error;
    1903             : 
    1904           0 :         if ((so->so_state & SS_ISCONNECTED) == 0)
    1905           0 :                 return (ENOTCONN);
    1906           0 :         if (so->so_state & SS_ISDISCONNECTING)
    1907           0 :                 return (EALREADY);
    1908           0 :         error = sctp_disconnect(so);
    1909           0 :         return (error);
    1910             : }
    1911             : 
    1912             : int
    1913           0 : usrsctp_set_non_blocking(struct socket *so, int onoff)
    1914             : {
    1915           0 :         if (so == NULL) {
    1916           0 :                 errno = EBADF;
    1917           0 :                 return (-1);
    1918             :         }
    1919           0 :         SOCK_LOCK(so);
    1920           0 :         if (onoff != 0) {
    1921           0 :                 so->so_state |= SS_NBIO;
    1922             :         } else {
    1923           0 :                 so->so_state &= ~SS_NBIO;
    1924             :         }
    1925           0 :         SOCK_UNLOCK(so);
    1926           0 :         return (0);
    1927             : }
    1928             : 
    1929             : int
    1930           0 : usrsctp_get_non_blocking(struct socket *so)
    1931             : {
    1932             :         int result;
    1933             : 
    1934           0 :         if (so == NULL) {
    1935           0 :                 errno = EBADF;
    1936           0 :                 return (-1);
    1937             :         }
    1938           0 :         SOCK_LOCK(so);
    1939           0 :         if (so->so_state & SS_NBIO) {
    1940           0 :                 result = 1;
    1941             :         } else {
    1942           0 :                 result = 0;
    1943             :         }
    1944           0 :         SOCK_UNLOCK(so);
    1945           0 :         return (result);
    1946             : }
    1947             : 
    1948             : int
    1949           0 : soconnect(struct socket *so, struct sockaddr *nam)
    1950             : {
    1951             :         int error;
    1952             : 
    1953           0 :         if (so->so_options & SCTP_SO_ACCEPTCONN)
    1954           0 :                 return (EOPNOTSUPP);
    1955             :         /*
    1956             :          * If protocol is connection-based, can only connect once.
    1957             :          * Otherwise, if connected, try to disconnect first.  This allows
    1958             :          * user to disconnect by connecting to, e.g., a null address.
    1959             :          */
    1960           0 :         if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && (error = sodisconnect(so))) {
    1961           0 :                 error = EISCONN;
    1962             :         } else {
    1963             :                 /*
    1964             :                  * Prevent accumulated error from previous connection from
    1965             :                  * biting us.
    1966             :                  */
    1967           0 :                 so->so_error = 0;
    1968           0 :                 switch (nam->sa_family) {
    1969             : #if defined(INET)
    1970             :                 case AF_INET:
    1971             :                         error = sctp_connect(so, nam);
    1972             :                         break;
    1973             : #endif
    1974             : #if defined(INET6)
    1975             :                 case AF_INET6:
    1976             :                         error = sctp6_connect(so, nam);
    1977             :                         break;
    1978             : #endif
    1979             :                 case AF_CONN:
    1980           0 :                         error = sctpconn_connect(so, nam);
    1981           0 :                         break;
    1982             :                 default:
    1983           0 :                         error = EAFNOSUPPORT;
    1984             :                 }
    1985             :         }
    1986             : 
    1987           0 :         return (error);
    1988             : }
    1989             : 
    1990             : 
    1991             : 
    1992           0 : int user_connect(struct socket *so, struct sockaddr *sa)
    1993             : {
    1994             :         int error;
    1995           0 :         int interrupted = 0;
    1996             : 
    1997           0 :         if (so == NULL) {
    1998           0 :                 error = EBADF;
    1999           0 :                 goto done1;
    2000             :         }
    2001           0 :         if (so->so_state & SS_ISCONNECTING) {
    2002           0 :                 error = EALREADY;
    2003           0 :                 goto done1;
    2004             :         }
    2005             : 
    2006           0 :         error = soconnect(so, sa);
    2007           0 :         if (error) {
    2008           0 :                 goto bad;
    2009             :         }
    2010           0 :         if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
    2011           0 :                 error = EINPROGRESS;
    2012           0 :                 goto done1;
    2013             :         }
    2014             : 
    2015           0 :         SOCK_LOCK(so);
    2016           0 :         while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
    2017             : #if defined (__Userspace_os_Windows)
    2018             :                 if (SleepConditionVariableCS(SOCK_COND(so), SOCK_MTX(so), INFINITE))
    2019             :                         error = 0;
    2020             :                 else
    2021             :                         error = -1;
    2022             : #else
    2023           0 :                 error = pthread_cond_wait(SOCK_COND(so), SOCK_MTX(so));
    2024             : #endif
    2025           0 :                 if (error) {
    2026             : #if defined(__Userspace_os_NetBSD)
    2027             :                         if (error == EINTR) {
    2028             : #else
    2029           0 :                         if (error == EINTR || error == ERESTART) {
    2030             : #endif
    2031           0 :                                 interrupted = 1;
    2032             :                         }
    2033           0 :                         break;
    2034             :                 }
    2035             :         }
    2036           0 :         if (error == 0) {
    2037           0 :                 error = so->so_error;
    2038           0 :                 so->so_error = 0;
    2039             :         }
    2040           0 :         SOCK_UNLOCK(so);
    2041             : 
    2042             : bad:
    2043           0 :         if (!interrupted) {
    2044           0 :                 so->so_state &= ~SS_ISCONNECTING;
    2045             :         }
    2046             : #if !defined(__Userspace_os_NetBSD)
    2047           0 :         if (error == ERESTART) {
    2048           0 :                 error = EINTR;
    2049             :         }
    2050             : #endif
    2051             : done1:
    2052           0 :         return (error);
    2053             : }
    2054             : 
    2055           0 : int usrsctp_connect(struct socket *so, struct sockaddr *name, int namelen)
    2056             : {
    2057             :         struct sockaddr *sa;
    2058             : 
    2059           0 :         errno = getsockaddr(&sa, (caddr_t)name, namelen);
    2060           0 :         if (errno)
    2061           0 :                 return (-1);
    2062             : 
    2063           0 :         errno = user_connect(so, sa);
    2064           0 :         FREE(sa, M_SONAME);
    2065           0 :         if (errno) {
    2066           0 :                 return (-1);
    2067             :         } else {
    2068           0 :                 return (0);
    2069             :         }
    2070             : }
    2071             : 
    2072           0 : int userspace_connect(struct socket *so, struct sockaddr *name, int namelen)
    2073             : {
    2074           0 :         return (usrsctp_connect(so, name, namelen));
    2075             : }
    2076             : 
    2077             : #define SCTP_STACK_BUF_SIZE         2048
    2078             : 
    2079             : void
    2080           0 : usrsctp_close(struct socket *so) {
    2081           0 :         if (so != NULL) {
    2082           0 :                 if (so->so_options & SCTP_SO_ACCEPTCONN) {
    2083             :                         struct socket *sp;
    2084             : 
    2085           0 :                         ACCEPT_LOCK();
    2086           0 :                         while ((sp = TAILQ_FIRST(&so->so_comp)) != NULL) {
    2087           0 :                                 TAILQ_REMOVE(&so->so_comp, sp, so_list);
    2088           0 :                                 so->so_qlen--;
    2089           0 :                                 sp->so_qstate &= ~SQ_COMP;
    2090           0 :                                 sp->so_head = NULL;
    2091           0 :                                 ACCEPT_UNLOCK();
    2092           0 :                                 soabort(sp);
    2093           0 :                                 ACCEPT_LOCK();
    2094             :                         }
    2095           0 :                         ACCEPT_UNLOCK();
    2096             :                 }
    2097           0 :                 ACCEPT_LOCK();
    2098           0 :                 SOCK_LOCK(so);
    2099           0 :                 sorele(so);
    2100             :         }
    2101           0 : }
    2102             : 
    2103             : void
    2104           0 : userspace_close(struct socket *so)
    2105             : {
    2106           0 :         usrsctp_close(so);
    2107           0 : }
    2108             : 
    2109             : int
    2110           0 : usrsctp_shutdown(struct socket *so, int how)
    2111             : {
    2112           0 :         if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR)) {
    2113           0 :                 errno = EINVAL;
    2114           0 :                 return (-1);
    2115             :         }
    2116           0 :         if (so == NULL) {
    2117           0 :                 errno = EBADF;
    2118           0 :                 return (-1);
    2119             :         }
    2120           0 :         sctp_flush(so, how);
    2121           0 :         if (how != SHUT_WR)
    2122           0 :                  socantrcvmore(so);
    2123           0 :         if (how != SHUT_RD) {
    2124           0 :                 errno = sctp_shutdown(so);
    2125           0 :                 if (errno) {
    2126           0 :                         return (-1);
    2127             :                 } else {
    2128           0 :                         return (0);
    2129             :                 }
    2130             :         }
    2131           0 :         return (0);
    2132             : }
    2133             : 
    2134             : int
    2135           0 : userspace_shutdown(struct socket *so, int how)
    2136             : {
    2137           0 :         return (usrsctp_shutdown(so, how));
    2138             : }
    2139             : 
    2140             : int
    2141           0 : usrsctp_finish(void)
    2142             : {
    2143           0 :         if (SCTP_BASE_VAR(sctp_pcb_initialized) == 0) {
    2144           0 :                 return (0);
    2145             :         }
    2146           0 :         if (SCTP_INP_INFO_TRYLOCK()) {
    2147           0 :                 if (!LIST_EMPTY(&SCTP_BASE_INFO(listhead))) {
    2148           0 :                         SCTP_INP_INFO_RUNLOCK();
    2149           0 :                         return (-1);
    2150             :                 }
    2151           0 :                 SCTP_INP_INFO_RUNLOCK();
    2152             :         } else {
    2153           0 :                 return (-1);
    2154             :         }
    2155           0 :         sctp_finish();
    2156           0 :         return (0);
    2157             : }
    2158             : 
    2159             : int
    2160           0 : userspace_finish(void)
    2161             : {
    2162           0 :         return (usrsctp_finish());
    2163             : }
    2164             : 
    2165             : /* needed from sctp_usrreq.c */
    2166             : int
    2167             : sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, void *p);
    2168             : 
    2169             : int
    2170           0 : usrsctp_setsockopt(struct socket *so, int level, int option_name,
    2171             :                    const void *option_value, socklen_t option_len)
    2172             : {
    2173           0 :         if (so == NULL) {
    2174           0 :                 errno = EBADF;
    2175           0 :                 return (-1);
    2176             :         }
    2177           0 :         switch (level) {
    2178             :         case SOL_SOCKET:
    2179             :         {
    2180           0 :                 switch (option_name) {
    2181             :                 case SO_RCVBUF:
    2182           0 :                         if (option_len < (socklen_t)sizeof(int)) {
    2183           0 :                                 errno = EINVAL;
    2184           0 :                                 return (-1);
    2185             :                         } else {
    2186             :                                 int *buf_size;
    2187             : 
    2188           0 :                                 buf_size = (int *)option_value;
    2189           0 :                                 if (*buf_size < 1) {
    2190           0 :                                         errno = EINVAL;
    2191           0 :                                         return (-1);
    2192             :                                 }
    2193           0 :                                 sbreserve(&so->so_rcv, (u_long)*buf_size, so);
    2194           0 :                                 return (0);
    2195             :                         }
    2196             :                         break;
    2197             :                 case SO_SNDBUF:
    2198           0 :                         if (option_len < (socklen_t)sizeof(int)) {
    2199           0 :                                 errno = EINVAL;
    2200           0 :                                 return (-1);
    2201             :                         } else {
    2202             :                                 int *buf_size;
    2203             : 
    2204           0 :                                 buf_size = (int *)option_value;
    2205           0 :                                 if (*buf_size < 1) {
    2206           0 :                                         errno = EINVAL;
    2207           0 :                                         return (-1);
    2208             :                                 }
    2209           0 :                                 sbreserve(&so->so_snd, (u_long)*buf_size, so);
    2210           0 :                                 return (0);
    2211             :                         }
    2212             :                         break;
    2213             :                 case SO_LINGER:
    2214           0 :                         if (option_len < (socklen_t)sizeof(struct linger)) {
    2215           0 :                                 errno = EINVAL;
    2216           0 :                                 return (-1);
    2217             :                         } else {
    2218             :                                 struct linger *l;
    2219             : 
    2220           0 :                                 l = (struct linger *)option_value;
    2221           0 :                                 so->so_linger = l->l_linger;
    2222           0 :                                 if (l->l_onoff) {
    2223           0 :                                         so->so_options |= SCTP_SO_LINGER;
    2224             :                                 } else {
    2225           0 :                                         so->so_options &= ~SCTP_SO_LINGER;
    2226             :                                 }
    2227           0 :                                 return (0);
    2228             :                         }
    2229             :                 default:
    2230           0 :                         errno = EINVAL;
    2231           0 :                         return (-1);
    2232             :                 }
    2233             :         }
    2234             :         case IPPROTO_SCTP:
    2235           0 :                 errno = sctp_setopt(so, option_name, (void *) option_value, (size_t)option_len, NULL);
    2236           0 :                 if (errno) {
    2237           0 :                         return (-1);
    2238             :                 } else {
    2239           0 :                         return (0);
    2240             :                 }
    2241             :         default:
    2242           0 :                 errno = ENOPROTOOPT;
    2243           0 :                 return (-1);
    2244             :         }
    2245             : }
    2246             : 
    2247             : int
    2248           0 : userspace_setsockopt(struct socket *so, int level, int option_name,
    2249             :                      const void *option_value, socklen_t option_len)
    2250             : {
    2251           0 :         return (usrsctp_setsockopt(so, level, option_name, option_value, option_len));
    2252             : }
    2253             : 
    2254             : /* needed from sctp_usrreq.c */
    2255             : int
    2256             : sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
    2257             :             void *p);
    2258             : 
    2259             : int
    2260           0 : usrsctp_getsockopt(struct socket *so, int level, int option_name,
    2261             :                    void *option_value, socklen_t *option_len)
    2262             : {
    2263           0 :         if (so == NULL) {
    2264           0 :                 errno = EBADF;
    2265           0 :                 return (-1);
    2266             :         }
    2267           0 :         if (option_len == NULL) {
    2268           0 :                 errno = EFAULT;
    2269           0 :                 return (-1);
    2270             :         }
    2271           0 :         switch (level) {
    2272             :         case SOL_SOCKET:
    2273           0 :                 switch (option_name) {
    2274             :                 case SO_RCVBUF:
    2275           0 :                         if (*option_len < (socklen_t)sizeof(int)) {
    2276           0 :                                 errno = EINVAL;
    2277           0 :                                 return (-1);
    2278             :                         } else {
    2279             :                                 int *buf_size;
    2280             : 
    2281           0 :                                 buf_size = (int *)option_value;
    2282           0 :                                 *buf_size = so->so_rcv.sb_hiwat;;
    2283           0 :                                 *option_len = (socklen_t)sizeof(int);
    2284           0 :                                 return (0);
    2285             :                         }
    2286             :                         break;
    2287             :                 case SO_SNDBUF:
    2288           0 :                         if (*option_len < (socklen_t)sizeof(int)) {
    2289           0 :                                 errno = EINVAL;
    2290           0 :                                 return (-1);
    2291             :                         } else {
    2292             :                                 int *buf_size;
    2293             : 
    2294           0 :                                 buf_size = (int *)option_value;
    2295           0 :                                 *buf_size = so->so_snd.sb_hiwat;
    2296           0 :                                 *option_len = (socklen_t)sizeof(int);
    2297           0 :                                 return (0);
    2298             :                         }
    2299             :                         break;
    2300             :                 case SO_LINGER:
    2301           0 :                         if (*option_len < (socklen_t)sizeof(struct linger)) {
    2302           0 :                                 errno = EINVAL;
    2303           0 :                                 return (-1);
    2304             :                         } else {
    2305             :                                 struct linger *l;
    2306             : 
    2307           0 :                                 l = (struct linger *)option_value;
    2308           0 :                                 l->l_linger = so->so_linger;
    2309           0 :                                 if (so->so_options & SCTP_SO_LINGER) {
    2310           0 :                                         l->l_onoff = 1;
    2311             :                                 } else {
    2312           0 :                                         l->l_onoff = 0;
    2313             :                                 }
    2314           0 :                                 *option_len = (socklen_t)sizeof(struct linger);
    2315           0 :                                 return (0);
    2316             :                         }
    2317             :                 default:
    2318           0 :                         errno = EINVAL;
    2319           0 :                         return (-1);
    2320             :                 }
    2321             :         case IPPROTO_SCTP:
    2322             :         {
    2323             :                 size_t len;
    2324             : 
    2325           0 :                 len = (size_t)*option_len;
    2326           0 :                 errno = sctp_getopt(so, option_name, option_value, &len, NULL);
    2327           0 :                 *option_len = (socklen_t)len;
    2328           0 :                 if (errno) {
    2329           0 :                         return (-1);
    2330             :                 } else {
    2331           0 :                         return (0);
    2332             :                 }
    2333             :         }
    2334             :         default:
    2335           0 :                 errno = ENOPROTOOPT;
    2336           0 :                 return (-1);
    2337             :         }
    2338             : }
    2339             : 
    2340             : int
    2341           0 : userspace_getsockopt(struct socket *so, int level, int option_name,
    2342             :                      void *option_value, socklen_t *option_len)
    2343             : {
    2344           0 :         return (usrsctp_getsockopt(so, level, option_name, option_value, option_len));
    2345             : }
    2346             : 
    2347             : int
    2348           0 : usrsctp_set_ulpinfo(struct socket *so, void *ulp_info)
    2349             : {
    2350           0 :         return (register_ulp_info(so, ulp_info));
    2351             : }
    2352             : 
    2353             : int
    2354           0 : usrsctp_bindx(struct socket *so, struct sockaddr *addrs, int addrcnt, int flags)
    2355             : {
    2356             :         struct sctp_getaddresses *gaddrs;
    2357             :         struct sockaddr *sa;
    2358             : #ifdef INET
    2359             :         struct sockaddr_in *sin;
    2360             : #endif
    2361             : #ifdef INET6
    2362             :         struct sockaddr_in6 *sin6;
    2363             : #endif
    2364             :         int i;
    2365             :         size_t argsz;
    2366             : #if defined(INET) || defined(INET6)
    2367             :         uint16_t sport = 0;
    2368             : #endif
    2369             : 
    2370             :         /* validate the flags */
    2371           0 :         if ((flags != SCTP_BINDX_ADD_ADDR) &&
    2372             :             (flags != SCTP_BINDX_REM_ADDR)) {
    2373           0 :                 errno = EFAULT;
    2374           0 :                 return (-1);
    2375             :         }
    2376             :         /* validate the address count and list */
    2377           0 :         if ((addrcnt <= 0) || (addrs == NULL)) {
    2378           0 :                 errno = EINVAL;
    2379           0 :                 return (-1);
    2380             :         }
    2381             :         /* First pre-screen the addresses */
    2382           0 :         sa = addrs;
    2383           0 :         for (i = 0; i < addrcnt; i++) {
    2384           0 :                 switch (sa->sa_family) {
    2385             : #ifdef INET
    2386             :                 case AF_INET:
    2387             : #ifdef HAVE_SA_LEN
    2388             :                         if (sa->sa_len != sizeof(struct sockaddr_in)) {
    2389             :                                 errno = EINVAL;
    2390             :                                 return (-1);
    2391             :                         }
    2392             : #endif
    2393             :                         sin = (struct sockaddr_in *)sa;
    2394             :                         if (sin->sin_port) {
    2395             :                                 /* non-zero port, check or save */
    2396             :                                 if (sport) {
    2397             :                                         /* Check against our port */
    2398             :                                         if (sport != sin->sin_port) {
    2399             :                                                 errno = EINVAL;
    2400             :                                                 return (-1);
    2401             :                                         }
    2402             :                                 } else {
    2403             :                                         /* save off the port */
    2404             :                                         sport = sin->sin_port;
    2405             :                                 }
    2406             :                         }
    2407             : #ifndef HAVE_SA_LEN
    2408             :                         sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
    2409             : #endif
    2410             :                         break;
    2411             : #endif
    2412             : #ifdef INET6
    2413             :                 case AF_INET6:
    2414             : #ifdef HAVE_SA_LEN
    2415             :                         if (sa->sa_len != sizeof(struct sockaddr_in6)) {
    2416             :                                 errno = EINVAL;
    2417             :                                 return (-1);
    2418             :                         }
    2419             : #endif
    2420             :                         sin6 = (struct sockaddr_in6 *)sa;
    2421             :                         if (sin6->sin6_port) {
    2422             :                                 /* non-zero port, check or save */
    2423             :                                 if (sport) {
    2424             :                                         /* Check against our port */
    2425             :                                         if (sport != sin6->sin6_port) {
    2426             :                                                 errno = EINVAL;
    2427             :                                                 return (-1);
    2428             :                                         }
    2429             :                                 } else {
    2430             :                                         /* save off the port */
    2431             :                                         sport = sin6->sin6_port;
    2432             :                                 }
    2433             :                         }
    2434             : #ifndef HAVE_SA_LEN
    2435             :                         sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
    2436             : #endif
    2437             :                         break;
    2438             : #endif
    2439             :                 default:
    2440             :                         /* Invalid address family specified. */
    2441           0 :                         errno = EAFNOSUPPORT;
    2442           0 :                         return (-1);
    2443             :                 }
    2444             : #ifdef HAVE_SA_LEN
    2445             :                 sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
    2446             : #endif
    2447             :         }
    2448           0 :         argsz = sizeof(struct sctp_getaddresses) +
    2449             :                 sizeof(struct sockaddr_storage);
    2450           0 :         if ((gaddrs = (struct sctp_getaddresses *)malloc(argsz)) == NULL) {
    2451           0 :                 errno = ENOMEM;
    2452           0 :                 return (-1);
    2453             :         }
    2454           0 :         sa = addrs;
    2455           0 :         for (i = 0; i < addrcnt; i++) {
    2456             : #ifndef HAVE_SA_LEN
    2457             :                 size_t sa_len;
    2458             : #endif
    2459           0 :                 memset(gaddrs, 0, argsz);
    2460           0 :                 gaddrs->sget_assoc_id = 0;
    2461             : #ifdef HAVE_SA_LEN
    2462             :                 memcpy(gaddrs->addr, sa, sa->sa_len);
    2463             :                 if (usrsctp_setsockopt(so, IPPROTO_SCTP, flags, gaddrs, (socklen_t)argsz) != 0) {
    2464             :                         free(gaddrs);
    2465             :                         return (-1);
    2466             :                 }
    2467             :                 sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
    2468             : #else
    2469           0 :                 switch (sa->sa_family) {
    2470             : #ifdef INET
    2471             :                 case AF_INET:
    2472             :                         sa_len = sizeof(struct sockaddr_in);
    2473             :                         break;
    2474             : #endif
    2475             : #ifdef INET6
    2476             :                 case AF_INET6:
    2477             :                         sa_len = sizeof(struct sockaddr_in6);
    2478             :                         break;
    2479             : #endif
    2480             :                 default:
    2481           0 :                         sa_len = 0;
    2482           0 :                         break;
    2483             :                 }
    2484           0 :                 memcpy(gaddrs->addr, sa, sa_len);
    2485             :                 /*
    2486             :                  * Now, if there was a port mentioned, assure that the
    2487             :                  * first address has that port to make sure it fails or
    2488             :                  * succeeds correctly.
    2489             :                  */
    2490             : #if defined(INET) || defined(INET6)
    2491             :                 if ((i == 0) && (sport != 0)) {
    2492             :                         switch (gaddrs->addr->sa_family) {
    2493             : #ifdef INET
    2494             :                         case AF_INET:
    2495             :                                 sin = (struct sockaddr_in *)gaddrs->addr;
    2496             :                                 sin->sin_port = sport;
    2497             :                                 break;
    2498             : #endif
    2499             : #ifdef INET6
    2500             :                         case AF_INET6:
    2501             :                                 sin6 = (struct sockaddr_in6 *)gaddrs->addr;
    2502             :                                 sin6->sin6_port = sport;
    2503             :                                 break;
    2504             : #endif
    2505             :                         }
    2506             :                 }
    2507             : #endif
    2508           0 :                 if (usrsctp_setsockopt(so, IPPROTO_SCTP, flags, gaddrs, (socklen_t)argsz) != 0) {
    2509           0 :                         free(gaddrs);
    2510           0 :                         return (-1);
    2511             :                 }
    2512           0 :                 sa = (struct sockaddr *)((caddr_t)sa + sa_len);
    2513             : #endif
    2514             :         }
    2515           0 :         free(gaddrs);
    2516           0 :         return (0);
    2517             : }
    2518             : 
    2519             : int
    2520           0 : usrsctp_connectx(struct socket *so,
    2521             :                  const struct sockaddr *addrs, int addrcnt,
    2522             :                  sctp_assoc_t *id)
    2523             : {
    2524             : #if defined(INET) || defined(INET6)
    2525             :         char buf[SCTP_STACK_BUF_SIZE];
    2526             :         int i, ret, cnt, *aa;
    2527             :         char *cpto;
    2528             :         const struct sockaddr *at;
    2529             :         sctp_assoc_t *p_id;
    2530             :         size_t len = sizeof(int);
    2531             : 
    2532             :         /* validate the address count and list */
    2533             :         if ((addrs == NULL) || (addrcnt <= 0)) {
    2534             :                 errno = EINVAL;
    2535             :                 return (-1);
    2536             :         }
    2537             :         at = addrs;
    2538             :         cnt = 0;
    2539             :         cpto = ((caddr_t)buf + sizeof(int));
    2540             :         /* validate all the addresses and get the size */
    2541             :         for (i = 0; i < addrcnt; i++) {
    2542             :                 switch (at->sa_family) {
    2543             : #ifdef INET
    2544             :                 case AF_INET:
    2545             : #ifdef HAVE_SA_LEN
    2546             :                         if (at->sa_len != sizeof(struct sockaddr_in)) {
    2547             :                                 errno = EINVAL;
    2548             :                                 return (-1);
    2549             :                         }
    2550             : #endif
    2551             :                         memcpy(cpto, at, sizeof(struct sockaddr_in));
    2552             :                         cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in));
    2553             :                         len += sizeof(struct sockaddr_in);
    2554             :                         at = (struct sockaddr *)((caddr_t)at + sizeof(struct sockaddr_in));
    2555             :                         break;
    2556             : #endif
    2557             : #ifdef INET6
    2558             :                 case AF_INET6:
    2559             : #ifdef HAVE_SA_LEN
    2560             :                         if (at->sa_len != sizeof(struct sockaddr_in6)) {
    2561             :                                 errno = EINVAL;
    2562             :                                 return (-1);
    2563             :                         }
    2564             : #endif
    2565             : #ifdef INET
    2566             :                         if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)at)->sin6_addr)) {
    2567             :                                 in6_sin6_2_sin((struct sockaddr_in *)cpto, (struct sockaddr_in6 *)at);
    2568             :                                 cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in));
    2569             :                                 len += sizeof(struct sockaddr_in);
    2570             :                         } else {
    2571             :                                 memcpy(cpto, at, sizeof(struct sockaddr_in6));
    2572             :                                 cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in6));
    2573             :                                 len += sizeof(struct sockaddr_in6);
    2574             :                         }
    2575             : #else
    2576             :                         memcpy(cpto, at, sizeof(struct sockaddr_in6));
    2577             :                         cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in6));
    2578             :                         len += sizeof(struct sockaddr_in6);
    2579             : #endif
    2580             :                         at = (struct sockaddr *)((caddr_t)at + sizeof(struct sockaddr_in6));
    2581             :                         break;
    2582             : #endif
    2583             :                 default:
    2584             :                         errno = EINVAL;
    2585             :                         return (-1);
    2586             :                 }
    2587             :                 if (len > (sizeof(buf) - sizeof(int))) {
    2588             :                         /* Never enough memory */
    2589             :                         errno = E2BIG;
    2590             :                         return (-1);
    2591             :                 }
    2592             :                 cnt++;
    2593             :         }
    2594             :         /* do we have any? */
    2595             :         if (cnt == 0) {
    2596             :                 errno = EINVAL;
    2597             :                 return (-1);
    2598             :         }
    2599             :         aa = (int *)buf;
    2600             :         *aa = cnt;
    2601             :         ret = usrsctp_setsockopt(so, IPPROTO_SCTP, SCTP_CONNECT_X, (void *)buf, (socklen_t)len);
    2602             :         if ((ret == 0) && id) {
    2603             :                 p_id = (sctp_assoc_t *)buf;
    2604             :                 *id = *p_id;
    2605             :         }
    2606             :         return (ret);
    2607             : #else
    2608           0 :         errno = EINVAL;
    2609           0 :         return (-1);
    2610             : #endif
    2611             : }
    2612             : 
    2613             : int
    2614           0 : usrsctp_getpaddrs(struct socket *so, sctp_assoc_t id, struct sockaddr **raddrs)
    2615             : {
    2616             :         struct sctp_getaddresses *addrs;
    2617             :         struct sockaddr *sa;
    2618             :         sctp_assoc_t asoc;
    2619             :         caddr_t lim;
    2620             :         socklen_t opt_len;
    2621             :         int cnt;
    2622             : 
    2623           0 :         if (raddrs == NULL) {
    2624           0 :                 errno = EFAULT;
    2625           0 :                 return (-1);
    2626             :         }
    2627           0 :         asoc = id;
    2628           0 :         opt_len = (socklen_t)sizeof(sctp_assoc_t);
    2629           0 :         if (usrsctp_getsockopt(so, IPPROTO_SCTP, SCTP_GET_REMOTE_ADDR_SIZE, &asoc, &opt_len) != 0) {
    2630           0 :                 return (-1);
    2631             :         }
    2632             :         /* size required is returned in 'asoc' */
    2633           0 :         opt_len = (socklen_t)((size_t)asoc + sizeof(struct sctp_getaddresses));
    2634           0 :         addrs = calloc(1, (size_t)opt_len);
    2635           0 :         if (addrs == NULL) {
    2636           0 :                 errno = ENOMEM;
    2637           0 :                 return (-1);
    2638             :         }
    2639           0 :         addrs->sget_assoc_id = id;
    2640             :         /* Now lets get the array of addresses */
    2641           0 :         if (usrsctp_getsockopt(so, IPPROTO_SCTP, SCTP_GET_PEER_ADDRESSES, addrs, &opt_len) != 0) {
    2642           0 :                 free(addrs);
    2643           0 :                 return (-1);
    2644             :         }
    2645           0 :         *raddrs = (struct sockaddr *)&addrs->addr[0];
    2646           0 :         cnt = 0;
    2647           0 :         sa = (struct sockaddr *)&addrs->addr[0];
    2648           0 :         lim = (caddr_t)addrs + opt_len;
    2649             : #ifdef HAVE_SA_LEN
    2650             :         while (((caddr_t)sa < lim) && (sa->sa_len > 0)) {
    2651             :                 sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
    2652             : #else
    2653           0 :         while ((caddr_t)sa < lim) {
    2654           0 :                 switch (sa->sa_family) {
    2655             : #ifdef INET
    2656             :                 case AF_INET:
    2657             :                         sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
    2658             :                         break;
    2659             : #endif
    2660             : #ifdef INET6
    2661             :                 case AF_INET6:
    2662             :                         sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
    2663             :                         break;
    2664             : #endif
    2665             :                 case AF_CONN:
    2666           0 :                         sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_conn));
    2667           0 :                         break;
    2668             :                 default:
    2669           0 :                         return (cnt);
    2670             :                         break;
    2671             :                 }
    2672             : #endif
    2673           0 :                 cnt++;
    2674             :         }
    2675           0 :         return (cnt);
    2676             : }
    2677             : 
    2678             : void
    2679           0 : usrsctp_freepaddrs(struct sockaddr *addrs)
    2680             : {
    2681             :         /* Take away the hidden association id */
    2682             :         void *fr_addr;
    2683             : 
    2684           0 :         fr_addr = (void *)((caddr_t)addrs - sizeof(sctp_assoc_t));
    2685             :         /* Now free it */
    2686           0 :         free(fr_addr);
    2687           0 : }
    2688             : 
    2689             : int
    2690           0 : usrsctp_getladdrs(struct socket *so, sctp_assoc_t id, struct sockaddr **raddrs)
    2691             : {
    2692             :         struct sctp_getaddresses *addrs;
    2693             :         caddr_t lim;
    2694             :         struct sockaddr *sa;
    2695             :         size_t size_of_addresses;
    2696             :         socklen_t opt_len;
    2697             :         int cnt;
    2698             : 
    2699           0 :         if (raddrs == NULL) {
    2700           0 :                 errno = EFAULT;
    2701           0 :                 return (-1);
    2702             :         }
    2703           0 :         size_of_addresses = 0;
    2704           0 :         opt_len = (socklen_t)sizeof(int);
    2705           0 :         if (usrsctp_getsockopt(so, IPPROTO_SCTP, SCTP_GET_LOCAL_ADDR_SIZE, &size_of_addresses, &opt_len) != 0) {
    2706           0 :                 errno = ENOMEM;
    2707           0 :                 return (-1);
    2708             :         }
    2709           0 :         if (size_of_addresses == 0) {
    2710           0 :                 errno = ENOTCONN;
    2711           0 :                 return (-1);
    2712             :         }
    2713           0 :         opt_len = (socklen_t)(size_of_addresses +
    2714             :                               sizeof(struct sockaddr_storage) +
    2715             :                               sizeof(struct sctp_getaddresses));
    2716           0 :         addrs = calloc(1, (size_t)opt_len);
    2717           0 :         if (addrs == NULL) {
    2718           0 :                 errno = ENOMEM;
    2719           0 :                 return (-1);
    2720             :         }
    2721           0 :         addrs->sget_assoc_id = id;
    2722             :         /* Now lets get the array of addresses */
    2723           0 :         if (usrsctp_getsockopt(so, IPPROTO_SCTP, SCTP_GET_LOCAL_ADDRESSES, addrs, &opt_len) != 0) {
    2724           0 :                 free(addrs);
    2725           0 :                 errno = ENOMEM;
    2726           0 :                 return (-1);
    2727             :         }
    2728           0 :         *raddrs = (struct sockaddr *)&addrs->addr[0];
    2729           0 :         cnt = 0;
    2730           0 :         sa = (struct sockaddr *)&addrs->addr[0];
    2731           0 :         lim = (caddr_t)addrs + opt_len;
    2732             : #ifdef HAVE_SA_LEN
    2733             :         while (((caddr_t)sa < lim) && (sa->sa_len > 0)) {
    2734             :                 sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
    2735             : #else
    2736           0 :         while ((caddr_t)sa < lim) {
    2737           0 :                 switch (sa->sa_family) {
    2738             : #ifdef INET
    2739             :                 case AF_INET:
    2740             :                         sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
    2741             :                         break;
    2742             : #endif
    2743             : #ifdef INET6
    2744             :                 case AF_INET6:
    2745             :                         sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
    2746             :                         break;
    2747             : #endif
    2748             :                 case AF_CONN:
    2749           0 :                         sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_conn));
    2750           0 :                         break;
    2751             :                 default:
    2752           0 :                         return (cnt);
    2753             :                         break;
    2754             :                 }
    2755             : #endif
    2756           0 :                 cnt++;
    2757             :         }
    2758           0 :         return (cnt);
    2759             : }
    2760             : 
    2761             : void
    2762           0 : usrsctp_freeladdrs(struct sockaddr *addrs)
    2763             : {
    2764             :         /* Take away the hidden association id */
    2765             :         void *fr_addr;
    2766             : 
    2767           0 :         fr_addr = (void *)((caddr_t)addrs - sizeof(sctp_assoc_t));
    2768             :         /* Now free it */
    2769           0 :         free(fr_addr);
    2770           0 : }
    2771             : 
    2772             : #ifdef INET
    2773             : void
    2774             : sctp_userspace_ip_output(int *result, struct mbuf *o_pak,
    2775             :                          sctp_route_t *ro, void *stcb,
    2776             :                          uint32_t vrf_id)
    2777             : {
    2778             :         struct mbuf *m;
    2779             :         struct mbuf *m_orig;
    2780             :         int iovcnt;
    2781             :         int send_len;
    2782             :         int len;
    2783             :         int send_count;
    2784             :         struct ip *ip;
    2785             :         struct udphdr *udp;
    2786             : #if !defined (__Userspace_os_Windows)
    2787             :         int res;
    2788             : #endif
    2789             :         struct sockaddr_in dst;
    2790             : #if defined (__Userspace_os_Windows)
    2791             :         WSAMSG win_msg_hdr;
    2792             :         int win_sent_len;
    2793             :         WSABUF send_iovec[MAXLEN_MBUF_CHAIN];
    2794             :         WSABUF winbuf;
    2795             : #else
    2796             :         struct iovec send_iovec[MAXLEN_MBUF_CHAIN];
    2797             :         struct msghdr msg_hdr;
    2798             : #endif
    2799             :         int use_udp_tunneling;
    2800             : 
    2801             :         *result = 0;
    2802             : 
    2803             :         m = SCTP_HEADER_TO_CHAIN(o_pak);
    2804             :         m_orig = m;
    2805             : 
    2806             :         len = sizeof(struct ip);
    2807             :         if (SCTP_BUF_LEN(m) < len) {
    2808             :                 if ((m = m_pullup(m, len)) == 0) {
    2809             :                         SCTP_PRINTF("Can not get the IP header in the first mbuf.\n");
    2810             :                         return;
    2811             :                 }
    2812             :         }
    2813             :         ip = mtod(m, struct ip *);
    2814             :         use_udp_tunneling = (ip->ip_p == IPPROTO_UDP);
    2815             : 
    2816             :         if (use_udp_tunneling) {
    2817             :                 len = sizeof(struct ip) + sizeof(struct udphdr);
    2818             :                 if (SCTP_BUF_LEN(m) < len) {
    2819             :                         if ((m = m_pullup(m, len)) == 0) {
    2820             :                                 SCTP_PRINTF("Can not get the UDP/IP header in the first mbuf.\n");
    2821             :                                 return;
    2822             :                         }
    2823             :                         ip = mtod(m, struct ip *);
    2824             :                 }
    2825             :                 udp = (struct udphdr *)(ip + 1);
    2826             :         } else {
    2827             :                 udp = NULL;
    2828             :         }
    2829             : 
    2830             :         if (!use_udp_tunneling) {
    2831             :                 if (ip->ip_src.s_addr == INADDR_ANY) {
    2832             :                         /* TODO get addr of outgoing interface */
    2833             :                         SCTP_PRINTF("Why did the SCTP implementation did not choose a source address?\n");
    2834             :                 }
    2835             :                 /* TODO need to worry about ro->ro_dst as in ip_output? */
    2836             : #if defined(__Userspace_os_Linux) || defined (__Userspace_os_Windows)
    2837             :                 /* need to put certain fields into network order for Linux */
    2838             :                 ip->ip_len = htons(ip->ip_len);
    2839             :                 ip->ip_off = 0;
    2840             : #endif
    2841             :         }
    2842             : 
    2843             :         memset((void *)&dst, 0, sizeof(struct sockaddr_in));
    2844             :         dst.sin_family = AF_INET;
    2845             :         dst.sin_addr.s_addr = ip->ip_dst.s_addr;
    2846             : #ifdef HAVE_SIN_LEN
    2847             :         dst.sin_len = sizeof(struct sockaddr_in);
    2848             : #endif
    2849             :         if (use_udp_tunneling) {
    2850             :                 dst.sin_port = udp->uh_dport;
    2851             :         } else {
    2852             :                 dst.sin_port = 0;
    2853             :         }
    2854             : 
    2855             :         /* tweak the mbuf chain */
    2856             :         if (use_udp_tunneling) {
    2857             :                 m_adj(m, sizeof(struct ip) + sizeof(struct udphdr));
    2858             :         }
    2859             : 
    2860             :         send_len = SCTP_HEADER_LEN(m); /* length of entire packet */
    2861             :         send_count = 0;
    2862             :         for (iovcnt = 0; m != NULL && iovcnt < MAXLEN_MBUF_CHAIN; m = m->m_next, iovcnt++) {
    2863             : #if !defined (__Userspace_os_Windows)
    2864             :                 send_iovec[iovcnt].iov_base = (caddr_t)m->m_data;
    2865             :                 send_iovec[iovcnt].iov_len = SCTP_BUF_LEN(m);
    2866             :                 send_count += send_iovec[iovcnt].iov_len;
    2867             : #else
    2868             :                 send_iovec[iovcnt].buf = (caddr_t)m->m_data;
    2869             :                 send_iovec[iovcnt].len = SCTP_BUF_LEN(m);
    2870             :                 send_count += send_iovec[iovcnt].len;
    2871             : #endif
    2872             :         }
    2873             : 
    2874             :         if (m != NULL) {
    2875             :                 SCTP_PRINTF("mbuf chain couldn't be copied completely\n");
    2876             :                 goto free_mbuf;
    2877             :         }
    2878             : 
    2879             : #if !defined (__Userspace_os_Windows)
    2880             :         msg_hdr.msg_name = (struct sockaddr *) &dst;
    2881             :         msg_hdr.msg_namelen = sizeof(struct sockaddr_in);
    2882             :         msg_hdr.msg_iov = send_iovec;
    2883             :         msg_hdr.msg_iovlen = iovcnt;
    2884             :         msg_hdr.msg_control = NULL;
    2885             :         msg_hdr.msg_controllen = 0;
    2886             :         msg_hdr.msg_flags = 0;
    2887             : 
    2888             :         if ((!use_udp_tunneling) && (SCTP_BASE_VAR(userspace_rawsctp) > -1)) {
    2889             :                 if ((res = sendmsg(SCTP_BASE_VAR(userspace_rawsctp), &msg_hdr, MSG_DONTWAIT)) != send_len) {
    2890             :                         *result = errno;
    2891             :                 }
    2892             :         }
    2893             :         if ((use_udp_tunneling) && (SCTP_BASE_VAR(userspace_udpsctp) > -1)) {
    2894             :                 if ((res = sendmsg(SCTP_BASE_VAR(userspace_udpsctp), &msg_hdr, MSG_DONTWAIT)) != send_len) {
    2895             :                         *result = errno;
    2896             :                 }
    2897             :         }
    2898             : #else
    2899             :         win_msg_hdr.name = (struct sockaddr *) &dst;
    2900             :         win_msg_hdr.namelen = sizeof(struct sockaddr_in);
    2901             :         win_msg_hdr.lpBuffers = (LPWSABUF)send_iovec;
    2902             :         win_msg_hdr.dwBufferCount = iovcnt;
    2903             :         winbuf.len = 0;
    2904             :         winbuf.buf = NULL;
    2905             :         win_msg_hdr.Control = winbuf;
    2906             :         win_msg_hdr.dwFlags = 0;
    2907             : 
    2908             :         if ((!use_udp_tunneling) && (SCTP_BASE_VAR(userspace_rawsctp) > -1)) {
    2909             :                 if (WSASendTo(SCTP_BASE_VAR(userspace_rawsctp), (LPWSABUF) send_iovec, iovcnt, &win_sent_len, win_msg_hdr.dwFlags, win_msg_hdr.name, (int) win_msg_hdr.namelen, NULL, NULL) != 0) {
    2910             :                         *result = WSAGetLastError();
    2911             :                 } else if (win_sent_len != send_len) {
    2912             :                         *result = WSAGetLastError();
    2913             :                 }
    2914             :         }
    2915             :         if ((use_udp_tunneling) && (SCTP_BASE_VAR(userspace_udpsctp) > -1)) {
    2916             :                 if (WSASendTo(SCTP_BASE_VAR(userspace_udpsctp), (LPWSABUF) send_iovec, iovcnt, &win_sent_len, win_msg_hdr.dwFlags, win_msg_hdr.name, (int) win_msg_hdr.namelen, NULL, NULL) != 0) {
    2917             :                         *result = WSAGetLastError();
    2918             :                 } else if (win_sent_len != send_len) {
    2919             :                         *result = WSAGetLastError();
    2920             :                 }
    2921             :         }
    2922             : #endif
    2923             : free_mbuf:
    2924             :         sctp_m_freem(m_orig);
    2925             : }
    2926             : #endif
    2927             : 
    2928             : #if defined (INET6)
    2929             : void sctp_userspace_ip6_output(int *result, struct mbuf *o_pak,
    2930             :                                             struct route_in6 *ro, void *stcb,
    2931             :                                             uint32_t vrf_id)
    2932             : {
    2933             :         struct mbuf *m;
    2934             :         struct mbuf *m_orig;
    2935             :         int iovcnt;
    2936             :         int send_len;
    2937             :         int len;
    2938             :         int send_count;
    2939             :         struct ip6_hdr *ip6;
    2940             :         struct udphdr *udp;
    2941             : #if !defined (__Userspace_os_Windows)
    2942             :         int res;
    2943             : #endif
    2944             :         struct sockaddr_in6 dst;
    2945             : #if defined (__Userspace_os_Windows)
    2946             :         WSAMSG win_msg_hdr;
    2947             :         int win_sent_len;
    2948             :         WSABUF send_iovec[MAXLEN_MBUF_CHAIN];
    2949             :         WSABUF winbuf;
    2950             : #else
    2951             :         struct iovec send_iovec[MAXLEN_MBUF_CHAIN];
    2952             :         struct msghdr msg_hdr;
    2953             : #endif
    2954             :         int use_udp_tunneling;
    2955             : 
    2956             :         *result = 0;
    2957             : 
    2958             :         m = SCTP_HEADER_TO_CHAIN(o_pak);
    2959             :         m_orig = m;
    2960             : 
    2961             :         len = sizeof(struct ip6_hdr);
    2962             : 
    2963             :         if (SCTP_BUF_LEN(m) < len) {
    2964             :                 if ((m = m_pullup(m, len)) == 0) {
    2965             :                         SCTP_PRINTF("Can not get the IP header in the first mbuf.\n");
    2966             :                         return;
    2967             :                 }
    2968             :         }
    2969             : 
    2970             :         ip6 = mtod(m, struct ip6_hdr *);
    2971             :         use_udp_tunneling = (ip6->ip6_nxt == IPPROTO_UDP);
    2972             : 
    2973             :         if (use_udp_tunneling) {
    2974             :                 len = sizeof(struct ip6_hdr) + sizeof(struct udphdr);
    2975             :                 if (SCTP_BUF_LEN(m) < len) {
    2976             :                         if ((m = m_pullup(m, len)) == 0) {
    2977             :                                 SCTP_PRINTF("Can not get the UDP/IP header in the first mbuf.\n");
    2978             :                                 return;
    2979             :                         }
    2980             :                         ip6 = mtod(m, struct ip6_hdr *);
    2981             :                 }
    2982             :                 udp = (struct udphdr *)(ip6 + 1);
    2983             :         } else {
    2984             :                 udp = NULL;
    2985             :         }
    2986             : 
    2987             :         if (!use_udp_tunneling) {
    2988             :                 if (ip6->ip6_src.s6_addr == in6addr_any.s6_addr) {
    2989             :                         /* TODO get addr of outgoing interface */
    2990             :                         SCTP_PRINTF("Why did the SCTP implementation did not choose a source address?\n");
    2991             :                 }
    2992             :                 /* TODO need to worry about ro->ro_dst as in ip_output? */
    2993             : #if defined(__Userspace_os_Linux) || defined (__Userspace_os_Windows)
    2994             :                 /* need to put certain fields into network order for Linux */
    2995             :                 ip6->ip6_plen = htons(ip6->ip6_plen);
    2996             : #endif
    2997             :         }
    2998             : 
    2999             :         memset((void *)&dst, 0, sizeof(struct sockaddr_in6));
    3000             :         dst.sin6_family = AF_INET6;
    3001             :         dst.sin6_addr = ip6->ip6_dst;
    3002             : #ifdef HAVE_SIN6_LEN
    3003             :         dst.sin6_len = sizeof(struct sockaddr_in6);
    3004             : #endif
    3005             : 
    3006             :         if (use_udp_tunneling) {
    3007             :                 dst.sin6_port = udp->uh_dport;
    3008             :         } else {
    3009             :                 dst.sin6_port = 0;
    3010             :         }
    3011             : 
    3012             :         /* tweak the mbuf chain */
    3013             :         if (use_udp_tunneling) {
    3014             :                 m_adj(m, sizeof(struct ip6_hdr) + sizeof(struct udphdr));
    3015             :         } else {
    3016             :           m_adj(m, sizeof(struct ip6_hdr));
    3017             :         }
    3018             : 
    3019             :         send_len = SCTP_HEADER_LEN(m); /* length of entire packet */
    3020             :         send_count = 0;
    3021             :         for (iovcnt = 0; m != NULL && iovcnt < MAXLEN_MBUF_CHAIN; m = m->m_next, iovcnt++) {
    3022             : #if !defined (__Userspace_os_Windows)
    3023             :                 send_iovec[iovcnt].iov_base = (caddr_t)m->m_data;
    3024             :                 send_iovec[iovcnt].iov_len = SCTP_BUF_LEN(m);
    3025             :                 send_count += send_iovec[iovcnt].iov_len;
    3026             : #else
    3027             :                 send_iovec[iovcnt].buf = (caddr_t)m->m_data;
    3028             :                 send_iovec[iovcnt].len = SCTP_BUF_LEN(m);
    3029             :                 send_count += send_iovec[iovcnt].len;
    3030             : #endif
    3031             :         }
    3032             :         if (m != NULL) {
    3033             :                 SCTP_PRINTF("mbuf chain couldn't be copied completely\n");
    3034             :                 goto free_mbuf;
    3035             :         }
    3036             : 
    3037             : #if !defined (__Userspace_os_Windows)
    3038             :         msg_hdr.msg_name = (struct sockaddr *) &dst;
    3039             :         msg_hdr.msg_namelen = sizeof(struct sockaddr_in6);
    3040             :         msg_hdr.msg_iov = send_iovec;
    3041             :         msg_hdr.msg_iovlen = iovcnt;
    3042             :         msg_hdr.msg_control = NULL;
    3043             :         msg_hdr.msg_controllen = 0;
    3044             :         msg_hdr.msg_flags = 0;
    3045             : 
    3046             :         if ((!use_udp_tunneling) && (SCTP_BASE_VAR(userspace_rawsctp6) > -1)) {
    3047             :                 if ((res = sendmsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg_hdr, MSG_DONTWAIT)) != send_len) {
    3048             :                         *result = errno;
    3049             :                 }
    3050             :         }
    3051             :         if ((use_udp_tunneling) && (SCTP_BASE_VAR(userspace_udpsctp6) > -1)) {
    3052             :                 if ((res = sendmsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg_hdr, MSG_DONTWAIT)) != send_len) {
    3053             :                         *result = errno;
    3054             :                 }
    3055             :         }
    3056             : #else
    3057             :         win_msg_hdr.name = (struct sockaddr *) &dst;
    3058             :         win_msg_hdr.namelen = sizeof(struct sockaddr_in6);
    3059             :         win_msg_hdr.lpBuffers = (LPWSABUF)send_iovec;
    3060             :         win_msg_hdr.dwBufferCount = iovcnt;
    3061             :         winbuf.len = 0;
    3062             :         winbuf.buf = NULL;
    3063             :         win_msg_hdr.Control = winbuf;
    3064             :         win_msg_hdr.dwFlags = 0;
    3065             : 
    3066             :         if ((!use_udp_tunneling) && (SCTP_BASE_VAR(userspace_rawsctp6) > -1)) {
    3067             :                 if (WSASendTo(SCTP_BASE_VAR(userspace_rawsctp6), (LPWSABUF) send_iovec, iovcnt, &win_sent_len, win_msg_hdr.dwFlags, win_msg_hdr.name, (int) win_msg_hdr.namelen, NULL, NULL) != 0) {
    3068             :                         *result = WSAGetLastError();
    3069             :                 } else if (win_sent_len != send_len) {
    3070             :                         *result = WSAGetLastError();
    3071             :                 }
    3072             :         }
    3073             :         if ((use_udp_tunneling) && (SCTP_BASE_VAR(userspace_udpsctp6) > -1)) {
    3074             :                 if (WSASendTo(SCTP_BASE_VAR(userspace_udpsctp6), (LPWSABUF) send_iovec, iovcnt, &win_sent_len, win_msg_hdr.dwFlags, win_msg_hdr.name, (int) win_msg_hdr.namelen, NULL, NULL) != 0) {
    3075             :                         *result = WSAGetLastError();
    3076             :                 } else if (win_sent_len != send_len) {
    3077             :                         *result = WSAGetLastError();
    3078             :                 }
    3079             :         }
    3080             : #endif
    3081             : free_mbuf:
    3082             :         sctp_m_freem(m_orig);
    3083             : }
    3084             : #endif
    3085             : 
    3086             : void
    3087           0 : usrsctp_register_address(void *addr)
    3088             : {
    3089             :         struct sockaddr_conn sconn;
    3090             : 
    3091           0 :         memset(&sconn, 0, sizeof(struct sockaddr_conn));
    3092           0 :         sconn.sconn_family = AF_CONN;
    3093             : #ifdef HAVE_SCONN_LEN
    3094             :         sconn.sconn_len = sizeof(struct sockaddr_conn);
    3095             : #endif
    3096           0 :         sconn.sconn_port = 0;
    3097           0 :         sconn.sconn_addr = addr;
    3098           0 :         sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID,
    3099             :                              NULL,
    3100             :                              0xffffffff,
    3101             :                              0,
    3102             :                              "conn",
    3103             :                              NULL,
    3104             :                              (struct sockaddr *)&sconn,
    3105             :                              0,
    3106             :                              0);
    3107           0 : }
    3108             : 
    3109             : void
    3110           0 : usrsctp_deregister_address(void *addr)
    3111             : {
    3112             :         struct sockaddr_conn sconn;
    3113             : 
    3114           0 :         memset(&sconn, 0, sizeof(struct sockaddr_conn));
    3115           0 :         sconn.sconn_family = AF_CONN;
    3116             : #ifdef HAVE_SCONN_LEN
    3117             :         sconn.sconn_len = sizeof(struct sockaddr_conn);
    3118             : #endif
    3119           0 :         sconn.sconn_port = 0;
    3120           0 :         sconn.sconn_addr = addr;
    3121           0 :         sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID,
    3122             :                                (struct sockaddr *)&sconn,
    3123             :                                0xffffffff,
    3124             :                                "conn");
    3125           0 : }
    3126             : 
    3127             : #define PREAMBLE_FORMAT "\n%c %02d:%02d:%02d.%06ld "
    3128             : #define PREAMBLE_LENGTH 19
    3129             : #define HEADER "0000 "
    3130             : #define TRAILER "# SCTP_PACKET\n"
    3131             : 
    3132             : char *
    3133           0 : usrsctp_dumppacket(void *buf, size_t len, int outbound)
    3134             : {
    3135             :         size_t i, pos;
    3136             :         char *dump_buf, *packet;
    3137             : #ifdef _WIN32
    3138             :         struct timeb tb;
    3139             :         struct tm t;
    3140             : #else
    3141             :         struct timeval tv;
    3142             :         struct tm *t;
    3143             :         time_t sec;
    3144             : #endif
    3145             : 
    3146           0 :         if ((len == 0) || (buf == NULL)) {
    3147           0 :                 return (NULL);
    3148             :         }
    3149           0 :         if ((dump_buf = malloc(PREAMBLE_LENGTH + strlen(HEADER) + 3 * len + strlen(TRAILER) + 1)) == NULL) {
    3150           0 :                 return (NULL);
    3151             :         }
    3152           0 :         pos = 0;
    3153             : #ifdef _WIN32
    3154             :         ftime(&tb);
    3155             :         localtime_s(&t, &tb.time);
    3156             :         _snprintf_s(dump_buf, PREAMBLE_LENGTH + 1, PREAMBLE_LENGTH, PREAMBLE_FORMAT,
    3157             :                     outbound ? 'O' : 'I',
    3158             :                     t.tm_hour, t.tm_min, t.tm_sec, (long)(1000 * tb.millitm));
    3159             : #else
    3160           0 :         gettimeofday(&tv, NULL);
    3161           0 :         sec = (time_t)tv.tv_sec;
    3162           0 :         t = localtime((const time_t *)&sec);
    3163           0 :         snprintf(dump_buf, PREAMBLE_LENGTH + 1, PREAMBLE_FORMAT,
    3164             :                  outbound ? 'O' : 'I',
    3165           0 :                  t->tm_hour, t->tm_min, t->tm_sec, (long)tv.tv_usec);
    3166             : #endif
    3167           0 :         pos += PREAMBLE_LENGTH;
    3168             : #ifdef _WIN32
    3169             :         strncpy_s(dump_buf + pos, strlen(HEADER) + 1, HEADER, strlen(HEADER));
    3170             : #else
    3171           0 :         strcpy(dump_buf + pos, HEADER);
    3172             : #endif
    3173           0 :         pos += strlen(HEADER);
    3174           0 :         packet = (char *)buf;
    3175           0 :         for (i = 0; i < len; i++) {
    3176             :                 uint8_t byte, low, high;
    3177             : 
    3178           0 :                 byte = (uint8_t)packet[i];
    3179           0 :                 high = byte / 16;
    3180           0 :                 low = byte % 16;
    3181           0 :                 dump_buf[pos++] = high < 10 ? '0' + high : 'a' + (high - 10);
    3182           0 :                 dump_buf[pos++] = low < 10 ? '0' + low : 'a' + (low - 10);
    3183           0 :                 dump_buf[pos++] = ' ';
    3184             :         }
    3185             : #ifdef _WIN32
    3186             :         strncpy_s(dump_buf + pos, strlen(TRAILER) + 1, TRAILER, strlen(TRAILER));
    3187             : #else
    3188           0 :         strcpy(dump_buf + pos, TRAILER);
    3189             : #endif
    3190           0 :         pos += strlen(TRAILER);
    3191           0 :         dump_buf[pos++] = '\0';
    3192           0 :         return (dump_buf);
    3193             : }
    3194             : 
    3195             : void
    3196           0 : usrsctp_freedumpbuffer(char *buf)
    3197             : {
    3198           0 :         free(buf);
    3199           0 : }
    3200             : 
    3201             : void
    3202           0 : usrsctp_conninput(void *addr, const void *buffer, size_t length, uint8_t ecn_bits)
    3203             : {
    3204             :         struct sockaddr_conn src, dst;
    3205             :         struct mbuf *m;
    3206             :         struct sctphdr *sh;
    3207             :         struct sctp_chunkhdr *ch;
    3208             : 
    3209           0 :         SCTP_STAT_INCR(sctps_recvpackets);
    3210           0 :         SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
    3211           0 :         memset(&src, 0, sizeof(struct sockaddr_conn));
    3212           0 :         src.sconn_family = AF_CONN;
    3213             : #ifdef HAVE_SCONN_LEN
    3214             :         src.sconn_len = sizeof(struct sockaddr_conn);
    3215             : #endif
    3216           0 :         src.sconn_addr = addr;
    3217           0 :         memset(&dst, 0, sizeof(struct sockaddr_conn));
    3218           0 :         dst.sconn_family = AF_CONN;
    3219             : #ifdef HAVE_SCONN_LEN
    3220             :         dst.sconn_len = sizeof(struct sockaddr_conn);
    3221             : #endif
    3222           0 :         dst.sconn_addr = addr;
    3223           0 :         if ((m = sctp_get_mbuf_for_msg(length, 1, M_NOWAIT, 0, MT_DATA)) == NULL) {
    3224           0 :                 return;
    3225             :         }
    3226           0 :         m_copyback(m, 0, length, (caddr_t)buffer);
    3227           0 :         if (SCTP_BUF_LEN(m) < (int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr))) {
    3228           0 :                 if ((m = m_pullup(m, sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr))) == NULL) {
    3229           0 :                         SCTP_STAT_INCR(sctps_hdrops);
    3230           0 :                         return;
    3231             :                 }
    3232             :         }
    3233           0 :         sh = mtod(m, struct sctphdr *);;
    3234           0 :         ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
    3235           0 :         src.sconn_port = sh->src_port;
    3236           0 :         dst.sconn_port = sh->dest_port;
    3237           0 :         sctp_common_input_processing(&m, 0, sizeof(struct sctphdr), length,
    3238             :                                      (struct sockaddr *)&src,
    3239             :                                      (struct sockaddr *)&dst,
    3240             :                                      sh, ch,
    3241             : #if !defined(SCTP_WITH_NO_CSUM)
    3242             :                                      1,
    3243             : #endif
    3244             :                                      ecn_bits,
    3245             :                                      SCTP_DEFAULT_VRFID, 0);
    3246           0 :         if (m) {
    3247           0 :                 sctp_m_freem(m);
    3248             :         }
    3249           0 :         return;
    3250             : }
    3251             : 
    3252             : 
    3253             : #define USRSCTP_SYSCTL_SET_DEF(__field) \
    3254             : void usrsctp_sysctl_set_ ## __field(uint32_t value) { \
    3255             :         SCTP_BASE_SYSCTL(__field) = value; \
    3256             : }
    3257             : 
    3258           0 : USRSCTP_SYSCTL_SET_DEF(sctp_sendspace)
    3259           0 : USRSCTP_SYSCTL_SET_DEF(sctp_recvspace)
    3260           0 : USRSCTP_SYSCTL_SET_DEF(sctp_auto_asconf)
    3261           0 : USRSCTP_SYSCTL_SET_DEF(sctp_multiple_asconfs)
    3262           0 : USRSCTP_SYSCTL_SET_DEF(sctp_ecn_enable)
    3263           0 : USRSCTP_SYSCTL_SET_DEF(sctp_pr_enable)
    3264           0 : USRSCTP_SYSCTL_SET_DEF(sctp_auth_enable)
    3265           0 : USRSCTP_SYSCTL_SET_DEF(sctp_asconf_enable)
    3266           0 : USRSCTP_SYSCTL_SET_DEF(sctp_reconfig_enable)
    3267           0 : USRSCTP_SYSCTL_SET_DEF(sctp_nrsack_enable)
    3268           0 : USRSCTP_SYSCTL_SET_DEF(sctp_pktdrop_enable)
    3269           0 : USRSCTP_SYSCTL_SET_DEF(sctp_strict_sacks)
    3270             : #if !defined(SCTP_WITH_NO_CSUM)
    3271           0 : USRSCTP_SYSCTL_SET_DEF(sctp_no_csum_on_loopback)
    3272             : #endif
    3273           0 : USRSCTP_SYSCTL_SET_DEF(sctp_peer_chunk_oh)
    3274           0 : USRSCTP_SYSCTL_SET_DEF(sctp_max_burst_default)
    3275           0 : USRSCTP_SYSCTL_SET_DEF(sctp_max_chunks_on_queue)
    3276           0 : USRSCTP_SYSCTL_SET_DEF(sctp_hashtblsize)
    3277           0 : USRSCTP_SYSCTL_SET_DEF(sctp_pcbtblsize)
    3278           0 : USRSCTP_SYSCTL_SET_DEF(sctp_min_split_point)
    3279           0 : USRSCTP_SYSCTL_SET_DEF(sctp_chunkscale)
    3280           0 : USRSCTP_SYSCTL_SET_DEF(sctp_delayed_sack_time_default)
    3281           0 : USRSCTP_SYSCTL_SET_DEF(sctp_sack_freq_default)
    3282           0 : USRSCTP_SYSCTL_SET_DEF(sctp_system_free_resc_limit)
    3283           0 : USRSCTP_SYSCTL_SET_DEF(sctp_asoc_free_resc_limit)
    3284           0 : USRSCTP_SYSCTL_SET_DEF(sctp_heartbeat_interval_default)
    3285           0 : USRSCTP_SYSCTL_SET_DEF(sctp_pmtu_raise_time_default)
    3286           0 : USRSCTP_SYSCTL_SET_DEF(sctp_shutdown_guard_time_default)
    3287           0 : USRSCTP_SYSCTL_SET_DEF(sctp_secret_lifetime_default)
    3288           0 : USRSCTP_SYSCTL_SET_DEF(sctp_rto_max_default)
    3289           0 : USRSCTP_SYSCTL_SET_DEF(sctp_rto_min_default)
    3290           0 : USRSCTP_SYSCTL_SET_DEF(sctp_rto_initial_default)
    3291           0 : USRSCTP_SYSCTL_SET_DEF(sctp_init_rto_max_default)
    3292           0 : USRSCTP_SYSCTL_SET_DEF(sctp_valid_cookie_life_default)
    3293           0 : USRSCTP_SYSCTL_SET_DEF(sctp_init_rtx_max_default)
    3294           0 : USRSCTP_SYSCTL_SET_DEF(sctp_assoc_rtx_max_default)
    3295           0 : USRSCTP_SYSCTL_SET_DEF(sctp_path_rtx_max_default)
    3296           0 : USRSCTP_SYSCTL_SET_DEF(sctp_add_more_threshold)
    3297           0 : USRSCTP_SYSCTL_SET_DEF(sctp_nr_outgoing_streams_default)
    3298           0 : USRSCTP_SYSCTL_SET_DEF(sctp_cmt_on_off)
    3299           0 : USRSCTP_SYSCTL_SET_DEF(sctp_cmt_use_dac)
    3300           0 : USRSCTP_SYSCTL_SET_DEF(sctp_use_cwnd_based_maxburst)
    3301           0 : USRSCTP_SYSCTL_SET_DEF(sctp_nat_friendly)
    3302           0 : USRSCTP_SYSCTL_SET_DEF(sctp_L2_abc_variable)
    3303           0 : USRSCTP_SYSCTL_SET_DEF(sctp_mbuf_threshold_count)
    3304           0 : USRSCTP_SYSCTL_SET_DEF(sctp_do_drain)
    3305           0 : USRSCTP_SYSCTL_SET_DEF(sctp_hb_maxburst)
    3306           0 : USRSCTP_SYSCTL_SET_DEF(sctp_abort_if_one_2_one_hits_limit)
    3307           0 : USRSCTP_SYSCTL_SET_DEF(sctp_strict_data_order)
    3308           0 : USRSCTP_SYSCTL_SET_DEF(sctp_min_residual)
    3309           0 : USRSCTP_SYSCTL_SET_DEF(sctp_max_retran_chunk)
    3310           0 : USRSCTP_SYSCTL_SET_DEF(sctp_logging_level)
    3311           0 : USRSCTP_SYSCTL_SET_DEF(sctp_default_cc_module)
    3312           0 : USRSCTP_SYSCTL_SET_DEF(sctp_default_frag_interleave)
    3313           0 : USRSCTP_SYSCTL_SET_DEF(sctp_mobility_base)
    3314           0 : USRSCTP_SYSCTL_SET_DEF(sctp_mobility_fasthandoff)
    3315           0 : USRSCTP_SYSCTL_SET_DEF(sctp_inits_include_nat_friendly)
    3316           0 : USRSCTP_SYSCTL_SET_DEF(sctp_udp_tunneling_port)
    3317           0 : USRSCTP_SYSCTL_SET_DEF(sctp_enable_sack_immediately)
    3318           0 : USRSCTP_SYSCTL_SET_DEF(sctp_vtag_time_wait)
    3319           0 : USRSCTP_SYSCTL_SET_DEF(sctp_blackhole)
    3320           0 : USRSCTP_SYSCTL_SET_DEF(sctp_diag_info_code)
    3321           0 : USRSCTP_SYSCTL_SET_DEF(sctp_fr_max_burst_default)
    3322           0 : USRSCTP_SYSCTL_SET_DEF(sctp_path_pf_threshold)
    3323           0 : USRSCTP_SYSCTL_SET_DEF(sctp_default_ss_module)
    3324           0 : USRSCTP_SYSCTL_SET_DEF(sctp_rttvar_bw)
    3325           0 : USRSCTP_SYSCTL_SET_DEF(sctp_rttvar_rtt)
    3326           0 : USRSCTP_SYSCTL_SET_DEF(sctp_rttvar_eqret)
    3327           0 : USRSCTP_SYSCTL_SET_DEF(sctp_steady_step)
    3328           0 : USRSCTP_SYSCTL_SET_DEF(sctp_use_dccc_ecn)
    3329           0 : USRSCTP_SYSCTL_SET_DEF(sctp_buffer_splitting)
    3330           0 : USRSCTP_SYSCTL_SET_DEF(sctp_initial_cwnd)
    3331             : #ifdef SCTP_DEBUG
    3332           0 : USRSCTP_SYSCTL_SET_DEF(sctp_debug_on)
    3333             : #endif
    3334             : 
    3335             : #define USRSCTP_SYSCTL_GET_DEF(__field) \
    3336             : uint32_t usrsctp_sysctl_get_ ## __field(void) { \
    3337             :         return SCTP_BASE_SYSCTL(__field); \
    3338             : }
    3339             : 
    3340           0 : USRSCTP_SYSCTL_GET_DEF(sctp_sendspace)
    3341           0 : USRSCTP_SYSCTL_GET_DEF(sctp_recvspace)
    3342           0 : USRSCTP_SYSCTL_GET_DEF(sctp_auto_asconf)
    3343           0 : USRSCTP_SYSCTL_GET_DEF(sctp_multiple_asconfs)
    3344           0 : USRSCTP_SYSCTL_GET_DEF(sctp_ecn_enable)
    3345           0 : USRSCTP_SYSCTL_GET_DEF(sctp_pr_enable)
    3346           0 : USRSCTP_SYSCTL_GET_DEF(sctp_auth_enable)
    3347           0 : USRSCTP_SYSCTL_GET_DEF(sctp_asconf_enable)
    3348           0 : USRSCTP_SYSCTL_GET_DEF(sctp_reconfig_enable)
    3349           0 : USRSCTP_SYSCTL_GET_DEF(sctp_nrsack_enable)
    3350           0 : USRSCTP_SYSCTL_GET_DEF(sctp_pktdrop_enable)
    3351           0 : USRSCTP_SYSCTL_GET_DEF(sctp_strict_sacks)
    3352             : #if !defined(SCTP_WITH_NO_CSUM)
    3353           0 : USRSCTP_SYSCTL_GET_DEF(sctp_no_csum_on_loopback)
    3354             : #endif
    3355           0 : USRSCTP_SYSCTL_GET_DEF(sctp_peer_chunk_oh)
    3356           0 : USRSCTP_SYSCTL_GET_DEF(sctp_max_burst_default)
    3357           0 : USRSCTP_SYSCTL_GET_DEF(sctp_max_chunks_on_queue)
    3358           0 : USRSCTP_SYSCTL_GET_DEF(sctp_hashtblsize)
    3359           0 : USRSCTP_SYSCTL_GET_DEF(sctp_pcbtblsize)
    3360           0 : USRSCTP_SYSCTL_GET_DEF(sctp_min_split_point)
    3361           0 : USRSCTP_SYSCTL_GET_DEF(sctp_chunkscale)
    3362           0 : USRSCTP_SYSCTL_GET_DEF(sctp_delayed_sack_time_default)
    3363           0 : USRSCTP_SYSCTL_GET_DEF(sctp_sack_freq_default)
    3364           0 : USRSCTP_SYSCTL_GET_DEF(sctp_system_free_resc_limit)
    3365           0 : USRSCTP_SYSCTL_GET_DEF(sctp_asoc_free_resc_limit)
    3366           0 : USRSCTP_SYSCTL_GET_DEF(sctp_heartbeat_interval_default)
    3367           0 : USRSCTP_SYSCTL_GET_DEF(sctp_pmtu_raise_time_default)
    3368           0 : USRSCTP_SYSCTL_GET_DEF(sctp_shutdown_guard_time_default)
    3369           0 : USRSCTP_SYSCTL_GET_DEF(sctp_secret_lifetime_default)
    3370           0 : USRSCTP_SYSCTL_GET_DEF(sctp_rto_max_default)
    3371           0 : USRSCTP_SYSCTL_GET_DEF(sctp_rto_min_default)
    3372           0 : USRSCTP_SYSCTL_GET_DEF(sctp_rto_initial_default)
    3373           0 : USRSCTP_SYSCTL_GET_DEF(sctp_init_rto_max_default)
    3374           0 : USRSCTP_SYSCTL_GET_DEF(sctp_valid_cookie_life_default)
    3375           0 : USRSCTP_SYSCTL_GET_DEF(sctp_init_rtx_max_default)
    3376           0 : USRSCTP_SYSCTL_GET_DEF(sctp_assoc_rtx_max_default)
    3377           0 : USRSCTP_SYSCTL_GET_DEF(sctp_path_rtx_max_default)
    3378           0 : USRSCTP_SYSCTL_GET_DEF(sctp_add_more_threshold)
    3379           0 : USRSCTP_SYSCTL_GET_DEF(sctp_nr_outgoing_streams_default)
    3380           0 : USRSCTP_SYSCTL_GET_DEF(sctp_cmt_on_off)
    3381           0 : USRSCTP_SYSCTL_GET_DEF(sctp_cmt_use_dac)
    3382           0 : USRSCTP_SYSCTL_GET_DEF(sctp_use_cwnd_based_maxburst)
    3383           0 : USRSCTP_SYSCTL_GET_DEF(sctp_nat_friendly)
    3384           0 : USRSCTP_SYSCTL_GET_DEF(sctp_L2_abc_variable)
    3385           0 : USRSCTP_SYSCTL_GET_DEF(sctp_mbuf_threshold_count)
    3386           0 : USRSCTP_SYSCTL_GET_DEF(sctp_do_drain)
    3387           0 : USRSCTP_SYSCTL_GET_DEF(sctp_hb_maxburst)
    3388           0 : USRSCTP_SYSCTL_GET_DEF(sctp_abort_if_one_2_one_hits_limit)
    3389           0 : USRSCTP_SYSCTL_GET_DEF(sctp_strict_data_order)
    3390           0 : USRSCTP_SYSCTL_GET_DEF(sctp_min_residual)
    3391           0 : USRSCTP_SYSCTL_GET_DEF(sctp_max_retran_chunk)
    3392           0 : USRSCTP_SYSCTL_GET_DEF(sctp_logging_level)
    3393           0 : USRSCTP_SYSCTL_GET_DEF(sctp_default_cc_module)
    3394           0 : USRSCTP_SYSCTL_GET_DEF(sctp_default_frag_interleave)
    3395           0 : USRSCTP_SYSCTL_GET_DEF(sctp_mobility_base)
    3396           0 : USRSCTP_SYSCTL_GET_DEF(sctp_mobility_fasthandoff)
    3397           0 : USRSCTP_SYSCTL_GET_DEF(sctp_inits_include_nat_friendly)
    3398           0 : USRSCTP_SYSCTL_GET_DEF(sctp_udp_tunneling_port)
    3399           0 : USRSCTP_SYSCTL_GET_DEF(sctp_enable_sack_immediately)
    3400           0 : USRSCTP_SYSCTL_GET_DEF(sctp_vtag_time_wait)
    3401           0 : USRSCTP_SYSCTL_GET_DEF(sctp_blackhole)
    3402           0 : USRSCTP_SYSCTL_GET_DEF(sctp_diag_info_code)
    3403           0 : USRSCTP_SYSCTL_GET_DEF(sctp_fr_max_burst_default)
    3404           0 : USRSCTP_SYSCTL_GET_DEF(sctp_path_pf_threshold)
    3405           0 : USRSCTP_SYSCTL_GET_DEF(sctp_default_ss_module)
    3406           0 : USRSCTP_SYSCTL_GET_DEF(sctp_rttvar_bw)
    3407           0 : USRSCTP_SYSCTL_GET_DEF(sctp_rttvar_rtt)
    3408           0 : USRSCTP_SYSCTL_GET_DEF(sctp_rttvar_eqret)
    3409           0 : USRSCTP_SYSCTL_GET_DEF(sctp_steady_step)
    3410           0 : USRSCTP_SYSCTL_GET_DEF(sctp_use_dccc_ecn)
    3411           0 : USRSCTP_SYSCTL_GET_DEF(sctp_buffer_splitting)
    3412           0 : USRSCTP_SYSCTL_GET_DEF(sctp_initial_cwnd)
    3413             : #ifdef SCTP_DEBUG
    3414           0 : USRSCTP_SYSCTL_GET_DEF(sctp_debug_on)
    3415             : #endif
    3416             : 
    3417           0 : void usrsctp_get_stat(struct sctpstat *stat)
    3418             : {
    3419           0 :         *stat = SCTP_BASE_STATS;
    3420           0 : }

Generated by: LCOV version 1.13