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