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