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