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