netwerk/sctp/src/user_socket.c

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rwxr-xr-x

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

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

mercurial