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