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