1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/sctp/src/user_socket.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,3397 @@ 1.4 +/*- 1.5 + * Copyright (c) 1982, 1986, 1988, 1990, 1993 1.6 + * The Regents of the University of California. 1.7 + * Copyright (c) 2004 The FreeBSD Foundation 1.8 + * Copyright (c) 2004-2008 Robert N. M. Watson 1.9 + * Copyright (c) 2009-2010 Brad Penoff 1.10 + * Copyright (c) 2009-2010 Humaira Kamal 1.11 + * Copyright (c) 2011-2012 Irene Ruengeler 1.12 + * Copyright (c) 2011-2012 Michael Tuexen 1.13 + * All rights reserved. 1.14 + * 1.15 + * Redistribution and use in source and binary forms, with or without 1.16 + * modification, are permitted provided that the following conditions 1.17 + * are met: 1.18 + * 1. Redistributions of source code must retain the above copyright 1.19 + * notice, this list of conditions and the following disclaimer. 1.20 + * 2. Redistributions in binary form must reproduce the above copyright 1.21 + * notice, this list of conditions and the following disclaimer in the 1.22 + * documentation and/or other materials provided with the distribution. 1.23 + * 1.24 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1.25 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.26 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.27 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1.28 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1.29 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1.30 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1.31 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1.32 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1.33 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1.34 + * SUCH DAMAGE. 1.35 + * 1.36 + */ 1.37 + 1.38 +#include <netinet/sctp_os.h> 1.39 +#include <netinet/sctp_pcb.h> 1.40 +#include <netinet/sctputil.h> 1.41 +#include <netinet/sctp_var.h> 1.42 +#include <netinet/sctp_sysctl.h> 1.43 +#include <netinet/sctp_input.h> 1.44 +#include <netinet/sctp_peeloff.h> 1.45 +#ifdef INET6 1.46 +#include <netinet6/sctp6_var.h> 1.47 +#endif 1.48 +#if defined(__Userspace_os_Linux) 1.49 +#define __FAVOR_BSD /* (on Ubuntu at least) enables UDP header field names like BSD in RFC 768 */ 1.50 +#endif 1.51 +#if !defined (__Userspace_os_Windows) 1.52 +#include <netinet/udp.h> 1.53 +#include <arpa/inet.h> 1.54 +#else 1.55 +#include <user_socketvar.h> 1.56 +#endif 1.57 +userland_mutex_t accept_mtx; 1.58 +userland_cond_t accept_cond; 1.59 +#ifdef _WIN32 1.60 +#include <time.h> 1.61 +#include <sys/timeb.h> 1.62 +#endif 1.63 + 1.64 +MALLOC_DEFINE(M_PCB, "sctp_pcb", "sctp pcb"); 1.65 +MALLOC_DEFINE(M_SONAME, "sctp_soname", "sctp soname"); 1.66 +#define MAXLEN_MBUF_CHAIN 32 1.67 + 1.68 +/* Prototypes */ 1.69 +extern int sctp_sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, 1.70 + struct mbuf *top, struct mbuf *control, int flags, 1.71 + /* proc is a dummy in __Userspace__ and will not be passed to sctp_lower_sosend */ struct proc *p); 1.72 + 1.73 +extern int sctp_attach(struct socket *so, int proto, uint32_t vrf_id); 1.74 +extern int sctpconn_attach(struct socket *so, int proto, uint32_t vrf_id); 1.75 + 1.76 +void 1.77 +usrsctp_init(uint16_t port, 1.78 + int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df), 1.79 + void (*debug_printf)(const char *format, ...)) 1.80 +{ 1.81 + sctp_init(port, conn_output, debug_printf); 1.82 +} 1.83 + 1.84 + 1.85 +/* Taken from usr/src/sys/kern/uipc_sockbuf.c and modified for __Userspace__*/ 1.86 +/* 1.87 + * Socantsendmore indicates that no more data will be sent on the socket; it 1.88 + * would normally be applied to a socket when the user informs the system 1.89 + * that no more data is to be sent, by the protocol code (in case 1.90 + * PRU_SHUTDOWN). Socantrcvmore indicates that no more data will be 1.91 + * received, and will normally be applied to the socket by a protocol when it 1.92 + * detects that the peer will send no more data. Data queued for reading in 1.93 + * the socket may yet be read. 1.94 + */ 1.95 + 1.96 +void socantrcvmore_locked(struct socket *so) 1.97 +{ 1.98 + SOCKBUF_LOCK_ASSERT(&so->so_rcv); 1.99 + so->so_rcv.sb_state |= SBS_CANTRCVMORE; 1.100 + sorwakeup_locked(so); 1.101 +} 1.102 + 1.103 +void socantrcvmore(struct socket *so) 1.104 +{ 1.105 + SOCKBUF_LOCK(&so->so_rcv); 1.106 + socantrcvmore_locked(so); 1.107 +} 1.108 + 1.109 +void 1.110 +socantsendmore_locked(struct socket *so) 1.111 +{ 1.112 + SOCKBUF_LOCK_ASSERT(&so->so_snd); 1.113 + so->so_snd.sb_state |= SBS_CANTSENDMORE; 1.114 + sowwakeup_locked(so); 1.115 +} 1.116 + 1.117 +void 1.118 +socantsendmore(struct socket *so) 1.119 +{ 1.120 + SOCKBUF_LOCK(&so->so_snd); 1.121 + socantsendmore_locked(so); 1.122 +} 1.123 + 1.124 + 1.125 + 1.126 +/* Taken from usr/src/sys/kern/uipc_sockbuf.c and called within sctp_lower_sosend. 1.127 + */ 1.128 +int 1.129 +sbwait(struct sockbuf *sb) 1.130 +{ 1.131 +#if defined(__Userspace__) /* __Userspace__ */ 1.132 + 1.133 + SOCKBUF_LOCK_ASSERT(sb); 1.134 + 1.135 + sb->sb_flags |= SB_WAIT; 1.136 +#if defined (__Userspace_os_Windows) 1.137 + if (SleepConditionVariableCS(&(sb->sb_cond), &(sb->sb_mtx), INFINITE)) 1.138 + return 0; 1.139 + else 1.140 + return -1; 1.141 +#else 1.142 + return (pthread_cond_wait(&(sb->sb_cond), &(sb->sb_mtx))); 1.143 +#endif 1.144 + 1.145 +#else 1.146 + SOCKBUF_LOCK_ASSERT(sb); 1.147 + 1.148 + sb->sb_flags |= SB_WAIT; 1.149 + return (msleep(&sb->sb_cc, &sb->sb_mtx, 1.150 + (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "sbwait", 1.151 + sb->sb_timeo)); 1.152 +#endif 1.153 +} 1.154 + 1.155 + 1.156 + 1.157 + 1.158 +/* Taken from /src/sys/kern/uipc_socket.c 1.159 + * and modified for __Userspace__ 1.160 + */ 1.161 +static struct socket * 1.162 +soalloc(void) 1.163 +{ 1.164 + struct socket *so; 1.165 + 1.166 + /* 1.167 + * soalloc() sets of socket layer state for a socket, 1.168 + * called only by socreate() and sonewconn(). 1.169 + * 1.170 + * sodealloc() tears down socket layer state for a socket, 1.171 + * called only by sofree() and sonewconn(). 1.172 + * __Userspace__ TODO : Make sure so is properly deallocated 1.173 + * when tearing down the connection. 1.174 + */ 1.175 + 1.176 + so = (struct socket *)malloc(sizeof(struct socket)); 1.177 + 1.178 + if (so == NULL) { 1.179 + return (NULL); 1.180 + } 1.181 + memset(so, 0, sizeof(struct socket)); 1.182 + 1.183 + /* __Userspace__ Initializing the socket locks here */ 1.184 + SOCKBUF_LOCK_INIT(&so->so_snd, "so_snd"); 1.185 + SOCKBUF_LOCK_INIT(&so->so_rcv, "so_rcv"); 1.186 + SOCKBUF_COND_INIT(&so->so_snd); 1.187 + SOCKBUF_COND_INIT(&so->so_rcv); 1.188 + SOCK_COND_INIT(so); /* timeo_cond */ 1.189 + 1.190 + /* __Userspace__ Any ref counting required here? Will we have any use for aiojobq? 1.191 + What about gencnt and numopensockets?*/ 1.192 + TAILQ_INIT(&so->so_aiojobq); 1.193 + return (so); 1.194 +} 1.195 + 1.196 +static void 1.197 +sodealloc(struct socket *so) 1.198 +{ 1.199 + 1.200 + KASSERT(so->so_count == 0, ("sodealloc(): so_count %d", so->so_count)); 1.201 + KASSERT(so->so_pcb == NULL, ("sodealloc(): so_pcb != NULL")); 1.202 + 1.203 + SOCKBUF_COND_DESTROY(&so->so_snd); 1.204 + SOCKBUF_COND_DESTROY(&so->so_rcv); 1.205 + 1.206 + SOCK_COND_DESTROY(so); 1.207 + 1.208 + SOCKBUF_LOCK_DESTROY(&so->so_snd); 1.209 + SOCKBUF_LOCK_DESTROY(&so->so_rcv); 1.210 + 1.211 + free(so); 1.212 +} 1.213 + 1.214 +/* Taken from /src/sys/kern/uipc_socket.c 1.215 + * and modified for __Userspace__ 1.216 + */ 1.217 +void 1.218 +sofree(struct socket *so) 1.219 +{ 1.220 + struct socket *head; 1.221 + 1.222 + ACCEPT_LOCK_ASSERT(); 1.223 + SOCK_LOCK_ASSERT(so); 1.224 + /* SS_NOFDREF unset in accept call. this condition seems irrelevent 1.225 + * for __Userspace__... 1.226 + */ 1.227 + if (so->so_count != 0 || 1.228 + (so->so_state & SS_PROTOREF) || (so->so_qstate & SQ_COMP)) { 1.229 + SOCK_UNLOCK(so); 1.230 + ACCEPT_UNLOCK(); 1.231 + return; 1.232 + } 1.233 + head = so->so_head; 1.234 + if (head != NULL) { 1.235 + KASSERT((so->so_qstate & SQ_COMP) != 0 || 1.236 + (so->so_qstate & SQ_INCOMP) != 0, 1.237 + ("sofree: so_head != NULL, but neither SQ_COMP nor " 1.238 + "SQ_INCOMP")); 1.239 + KASSERT((so->so_qstate & SQ_COMP) == 0 || 1.240 + (so->so_qstate & SQ_INCOMP) == 0, 1.241 + ("sofree: so->so_qstate is SQ_COMP and also SQ_INCOMP")); 1.242 + TAILQ_REMOVE(&head->so_incomp, so, so_list); 1.243 + head->so_incqlen--; 1.244 + so->so_qstate &= ~SQ_INCOMP; 1.245 + so->so_head = NULL; 1.246 + } 1.247 + KASSERT((so->so_qstate & SQ_COMP) == 0 && 1.248 + (so->so_qstate & SQ_INCOMP) == 0, 1.249 + ("sofree: so_head == NULL, but still SQ_COMP(%d) or SQ_INCOMP(%d)", 1.250 + so->so_qstate & SQ_COMP, so->so_qstate & SQ_INCOMP)); 1.251 + if (so->so_options & SCTP_SO_ACCEPTCONN) { 1.252 + KASSERT((TAILQ_EMPTY(&so->so_comp)), ("sofree: so_comp populated")); 1.253 + KASSERT((TAILQ_EMPTY(&so->so_incomp)), ("sofree: so_comp populated")); 1.254 + } 1.255 + SOCK_UNLOCK(so); 1.256 + ACCEPT_UNLOCK(); 1.257 + sctp_close(so); /* was... sctp_detach(so); */ 1.258 + /* 1.259 + * From this point on, we assume that no other references to this 1.260 + * socket exist anywhere else in the stack. Therefore, no locks need 1.261 + * to be acquired or held. 1.262 + * 1.263 + * We used to do a lot of socket buffer and socket locking here, as 1.264 + * well as invoke sorflush() and perform wakeups. The direct call to 1.265 + * dom_dispose() and sbrelease_internal() are an inlining of what was 1.266 + * necessary from sorflush(). 1.267 + * 1.268 + * Notice that the socket buffer and kqueue state are torn down 1.269 + * before calling pru_detach. This means that protocols shold not 1.270 + * assume they can perform socket wakeups, etc, in their detach code. 1.271 + */ 1.272 + sodealloc(so); 1.273 +} 1.274 + 1.275 + 1.276 + 1.277 +/* Taken from /src/sys/kern/uipc_socket.c */ 1.278 +int 1.279 +soabort(so) 1.280 + struct socket *so; 1.281 +{ 1.282 + int error; 1.283 +#if defined(INET6) 1.284 + struct sctp_inpcb *inp; 1.285 +#endif 1.286 + 1.287 +#if defined(INET6) 1.288 + inp = (struct sctp_inpcb *)so->so_pcb; 1.289 + if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 1.290 + error = sctp6_abort(so); 1.291 + } else { 1.292 +#if defined(INET) 1.293 + error = sctp_abort(so); 1.294 +#else 1.295 + error = EAFNOSUPPORT; 1.296 +#endif 1.297 + } 1.298 +#elif defined(INET) 1.299 + error = sctp_abort(so); 1.300 +#else 1.301 + error = EAFNOSUPPORT; 1.302 +#endif 1.303 + if (error) { 1.304 + sofree(so); 1.305 + return error; 1.306 + } 1.307 + return (0); 1.308 +} 1.309 + 1.310 + 1.311 +/* Taken from usr/src/sys/kern/uipc_socket.c and called within sctp_connect (sctp_usrreq.c). 1.312 + * We use sctp_connect for send_one_init_real in ms1. 1.313 + */ 1.314 +void 1.315 +soisconnecting(struct socket *so) 1.316 +{ 1.317 + 1.318 + SOCK_LOCK(so); 1.319 + so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); 1.320 + so->so_state |= SS_ISCONNECTING; 1.321 + SOCK_UNLOCK(so); 1.322 +} 1.323 + 1.324 +/* Taken from usr/src/sys/kern/uipc_socket.c and called within sctp_disconnect (sctp_usrreq.c). 1.325 + * TODO Do we use sctp_disconnect? 1.326 + */ 1.327 +void 1.328 +soisdisconnecting(struct socket *so) 1.329 +{ 1.330 + 1.331 + /* 1.332 + * Note: This code assumes that SOCK_LOCK(so) and 1.333 + * SOCKBUF_LOCK(&so->so_rcv) are the same. 1.334 + */ 1.335 + SOCKBUF_LOCK(&so->so_rcv); 1.336 + so->so_state &= ~SS_ISCONNECTING; 1.337 + so->so_state |= SS_ISDISCONNECTING; 1.338 + so->so_rcv.sb_state |= SBS_CANTRCVMORE; 1.339 + sorwakeup_locked(so); 1.340 + SOCKBUF_LOCK(&so->so_snd); 1.341 + so->so_snd.sb_state |= SBS_CANTSENDMORE; 1.342 + sowwakeup_locked(so); 1.343 + wakeup("dummy",so); 1.344 + /* requires 2 args but this was in orig */ 1.345 + /* wakeup(&so->so_timeo); */ 1.346 +} 1.347 + 1.348 + 1.349 +/* Taken from sys/kern/kern_synch.c and 1.350 + modified for __Userspace__ 1.351 +*/ 1.352 + 1.353 +/* 1.354 + * Make all threads sleeping on the specified identifier runnable. 1.355 + * Associating wakeup with so_timeo identifier and timeo_cond 1.356 + * condition variable. TODO. If we use iterator thread then we need to 1.357 + * modify wakeup so it can distinguish between iterator identifier and 1.358 + * timeo identifier. 1.359 + */ 1.360 +void 1.361 +wakeup(ident, so) 1.362 + void *ident; 1.363 + struct socket *so; 1.364 +{ 1.365 + SOCK_LOCK(so); 1.366 +#if defined (__Userspace_os_Windows) 1.367 + WakeAllConditionVariable(&(so)->timeo_cond); 1.368 +#else 1.369 + pthread_cond_broadcast(&(so)->timeo_cond); 1.370 +#endif 1.371 + SOCK_UNLOCK(so); 1.372 +} 1.373 + 1.374 + 1.375 +/* 1.376 + * Make a thread sleeping on the specified identifier runnable. 1.377 + * May wake more than one thread if a target thread is currently 1.378 + * swapped out. 1.379 + */ 1.380 +void 1.381 +wakeup_one(ident) 1.382 + void *ident; 1.383 +{ 1.384 + /* __Userspace__ Check: We are using accept_cond for wakeup_one. 1.385 + It seems that wakeup_one is only called within 1.386 + soisconnected() and sonewconn() with ident &head->so_timeo 1.387 + head is so->so_head, which is back pointer to listen socket 1.388 + This seems to indicate that the use of accept_cond is correct 1.389 + since socket where accepts occur is so_head in all 1.390 + subsidiary sockets. 1.391 + */ 1.392 + ACCEPT_LOCK(); 1.393 +#if defined (__Userspace_os_Windows) 1.394 + WakeAllConditionVariable(&accept_cond); 1.395 +#else 1.396 + pthread_cond_broadcast(&accept_cond); 1.397 +#endif 1.398 + ACCEPT_UNLOCK(); 1.399 +} 1.400 + 1.401 + 1.402 +/* Called within sctp_process_cookie_[existing/new] */ 1.403 +void 1.404 +soisconnected(struct socket *so) 1.405 +{ 1.406 + struct socket *head; 1.407 + 1.408 + ACCEPT_LOCK(); 1.409 + SOCK_LOCK(so); 1.410 + so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING); 1.411 + so->so_state |= SS_ISCONNECTED; 1.412 + head = so->so_head; 1.413 + if (head != NULL && (so->so_qstate & SQ_INCOMP)) { 1.414 + SOCK_UNLOCK(so); 1.415 + TAILQ_REMOVE(&head->so_incomp, so, so_list); 1.416 + head->so_incqlen--; 1.417 + so->so_qstate &= ~SQ_INCOMP; 1.418 + TAILQ_INSERT_TAIL(&head->so_comp, so, so_list); 1.419 + head->so_qlen++; 1.420 + so->so_qstate |= SQ_COMP; 1.421 + ACCEPT_UNLOCK(); 1.422 + sorwakeup(head); 1.423 + wakeup_one(&head->so_timeo); 1.424 + return; 1.425 + } 1.426 + SOCK_UNLOCK(so); 1.427 + ACCEPT_UNLOCK(); 1.428 + wakeup(&so->so_timeo, so); 1.429 + sorwakeup(so); 1.430 + sowwakeup(so); 1.431 + 1.432 +} 1.433 + 1.434 +/* called within sctp_handle_cookie_echo */ 1.435 + 1.436 +struct socket * 1.437 +sonewconn(struct socket *head, int connstatus) 1.438 +{ 1.439 + struct socket *so; 1.440 + int over; 1.441 + 1.442 + ACCEPT_LOCK(); 1.443 + over = (head->so_qlen > 3 * head->so_qlimit / 2); 1.444 + ACCEPT_UNLOCK(); 1.445 +#ifdef REGRESSION 1.446 + if (regression_sonewconn_earlytest && over) 1.447 +#else 1.448 + if (over) 1.449 +#endif 1.450 + return (NULL); 1.451 + so = soalloc(); 1.452 + if (so == NULL) 1.453 + return (NULL); 1.454 + so->so_head = head; 1.455 + so->so_type = head->so_type; 1.456 + so->so_options = head->so_options &~ SCTP_SO_ACCEPTCONN; 1.457 + so->so_linger = head->so_linger; 1.458 + so->so_state = head->so_state | SS_NOFDREF; 1.459 + so->so_dom = head->so_dom; 1.460 +#ifdef MAC 1.461 + SOCK_LOCK(head); 1.462 + mac_create_socket_from_socket(head, so); 1.463 + SOCK_UNLOCK(head); 1.464 +#endif 1.465 + if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat)) { 1.466 + sodealloc(so); 1.467 + return (NULL); 1.468 + } 1.469 + switch (head->so_dom) { 1.470 +#ifdef INET 1.471 + case AF_INET: 1.472 + if (sctp_attach(so, IPPROTO_SCTP, SCTP_DEFAULT_VRFID)) { 1.473 + sodealloc(so); 1.474 + return (NULL); 1.475 + } 1.476 + break; 1.477 +#endif 1.478 +#ifdef INET6 1.479 + case AF_INET6: 1.480 + if (sctp6_attach(so, IPPROTO_SCTP, SCTP_DEFAULT_VRFID)) { 1.481 + sodealloc(so); 1.482 + return (NULL); 1.483 + } 1.484 + break; 1.485 +#endif 1.486 + case AF_CONN: 1.487 + if (sctpconn_attach(so, IPPROTO_SCTP, SCTP_DEFAULT_VRFID)) { 1.488 + sodealloc(so); 1.489 + return (NULL); 1.490 + } 1.491 + break; 1.492 + default: 1.493 + sodealloc(so); 1.494 + return (NULL); 1.495 + break; 1.496 + } 1.497 + so->so_rcv.sb_lowat = head->so_rcv.sb_lowat; 1.498 + so->so_snd.sb_lowat = head->so_snd.sb_lowat; 1.499 + so->so_rcv.sb_timeo = head->so_rcv.sb_timeo; 1.500 + so->so_snd.sb_timeo = head->so_snd.sb_timeo; 1.501 + so->so_rcv.sb_flags |= head->so_rcv.sb_flags & SB_AUTOSIZE; 1.502 + so->so_snd.sb_flags |= head->so_snd.sb_flags & SB_AUTOSIZE; 1.503 + so->so_state |= connstatus; 1.504 + ACCEPT_LOCK(); 1.505 + if (connstatus) { 1.506 + TAILQ_INSERT_TAIL(&head->so_comp, so, so_list); 1.507 + so->so_qstate |= SQ_COMP; 1.508 + head->so_qlen++; 1.509 + } else { 1.510 + /* 1.511 + * Keep removing sockets from the head until there's room for 1.512 + * us to insert on the tail. In pre-locking revisions, this 1.513 + * was a simple if(), but as we could be racing with other 1.514 + * threads and soabort() requires dropping locks, we must 1.515 + * loop waiting for the condition to be true. 1.516 + */ 1.517 + while (head->so_incqlen > head->so_qlimit) { 1.518 + struct socket *sp; 1.519 + sp = TAILQ_FIRST(&head->so_incomp); 1.520 + TAILQ_REMOVE(&head->so_incomp, sp, so_list); 1.521 + head->so_incqlen--; 1.522 + sp->so_qstate &= ~SQ_INCOMP; 1.523 + sp->so_head = NULL; 1.524 + ACCEPT_UNLOCK(); 1.525 + soabort(sp); 1.526 + ACCEPT_LOCK(); 1.527 + } 1.528 + TAILQ_INSERT_TAIL(&head->so_incomp, so, so_list); 1.529 + so->so_qstate |= SQ_INCOMP; 1.530 + head->so_incqlen++; 1.531 + } 1.532 + ACCEPT_UNLOCK(); 1.533 + if (connstatus) { 1.534 + sorwakeup(head); 1.535 + wakeup_one(&head->so_timeo); 1.536 + } 1.537 + return (so); 1.538 + 1.539 +} 1.540 + 1.541 +/* From /src/sys/sys/sysproto.h */ 1.542 +struct sctp_generic_sendmsg_args { 1.543 + int sd; 1.544 + caddr_t msg; 1.545 + int mlen; 1.546 + caddr_t to; 1.547 + socklen_t tolen; /* was __socklen_t */ 1.548 + struct sctp_sndrcvinfo * sinfo; 1.549 + int flags; 1.550 +}; 1.551 + 1.552 +struct sctp_generic_recvmsg_args { 1.553 + int sd; 1.554 + struct iovec *iov; 1.555 + int iovlen; 1.556 + struct sockaddr *from; 1.557 + socklen_t *fromlenaddr; /* was __socklen_t */ 1.558 + struct sctp_sndrcvinfo *sinfo; 1.559 + int *msg_flags; 1.560 +}; 1.561 + 1.562 + 1.563 + /* 1.564 + Source: /src/sys/gnu/fs/xfs/FreeBSD/xfs_ioctl.c 1.565 + */ 1.566 +static __inline__ int 1.567 +copy_to_user(void *dst, void *src, int len) { 1.568 + memcpy(dst, src, len); 1.569 + return 0; 1.570 +} 1.571 + 1.572 +static __inline__ int 1.573 +copy_from_user(void *dst, void *src, int len) { 1.574 + memcpy(dst, src, len); 1.575 + return 0; 1.576 +} 1.577 + 1.578 +/* 1.579 + References: 1.580 + src/sys/dev/lmc/if_lmc.h: 1.581 + src/sys/powerpc/powerpc/copyinout.c 1.582 + src/sys/sys/systm.h 1.583 +*/ 1.584 +# define copyin(u, k, len) copy_from_user(k, u, len) 1.585 + 1.586 +/* References: 1.587 + src/sys/powerpc/powerpc/copyinout.c 1.588 + src/sys/sys/systm.h 1.589 +*/ 1.590 +# define copyout(k, u, len) copy_to_user(u, k, len) 1.591 + 1.592 + 1.593 +/* copyiniov definition copied/modified from src/sys/kern/kern_subr.c */ 1.594 +int 1.595 +copyiniov(struct iovec *iovp, u_int iovcnt, struct iovec **iov, int error) 1.596 +{ 1.597 + u_int iovlen; 1.598 + 1.599 + *iov = NULL; 1.600 + if (iovcnt > UIO_MAXIOV) 1.601 + return (error); 1.602 + iovlen = iovcnt * sizeof (struct iovec); 1.603 + *iov = malloc(iovlen); /*, M_IOV, M_WAITOK); */ 1.604 + error = copyin(iovp, *iov, iovlen); 1.605 + if (error) { 1.606 + free(*iov); /*, M_IOV); */ 1.607 + *iov = NULL; 1.608 + } 1.609 + return (error); 1.610 +} 1.611 + 1.612 +/* (__Userspace__) version of uiomove */ 1.613 +int 1.614 +uiomove(void *cp, int n, struct uio *uio) 1.615 +{ 1.616 + struct iovec *iov; 1.617 + int cnt; 1.618 + int error = 0; 1.619 + 1.620 + if ((uio->uio_rw != UIO_READ) && 1.621 + (uio->uio_rw != UIO_WRITE)) { 1.622 + return (EINVAL); 1.623 + } 1.624 + 1.625 + while (n > 0 && uio->uio_resid) { 1.626 + iov = uio->uio_iov; 1.627 + cnt = iov->iov_len; 1.628 + if (cnt == 0) { 1.629 + uio->uio_iov++; 1.630 + uio->uio_iovcnt--; 1.631 + continue; 1.632 + } 1.633 + if (cnt > n) 1.634 + cnt = n; 1.635 + 1.636 + switch (uio->uio_segflg) { 1.637 + 1.638 + case UIO_USERSPACE: 1.639 + if (uio->uio_rw == UIO_READ) 1.640 + error = copyout(cp, iov->iov_base, cnt); 1.641 + else 1.642 + error = copyin(iov->iov_base, cp, cnt); 1.643 + if (error) 1.644 + goto out; 1.645 + break; 1.646 + 1.647 + case UIO_SYSSPACE: 1.648 + if (uio->uio_rw == UIO_READ) 1.649 + bcopy(cp, iov->iov_base, cnt); 1.650 + else 1.651 + bcopy(iov->iov_base, cp, cnt); 1.652 + break; 1.653 + } 1.654 + iov->iov_base = (char *)iov->iov_base + cnt; 1.655 + iov->iov_len -= cnt; 1.656 + uio->uio_resid -= cnt; 1.657 + uio->uio_offset += cnt; 1.658 + cp = (char *)cp + cnt; 1.659 + n -= cnt; 1.660 + } 1.661 +out: 1.662 + return (error); 1.663 +} 1.664 + 1.665 + 1.666 +/* Source: src/sys/kern/uipc_syscalls.c */ 1.667 +int 1.668 +getsockaddr(namp, uaddr, len) 1.669 + struct sockaddr **namp; 1.670 + caddr_t uaddr; 1.671 + size_t len; 1.672 +{ 1.673 + struct sockaddr *sa; 1.674 + int error; 1.675 + 1.676 + if (len > SOCK_MAXADDRLEN) 1.677 + return (ENAMETOOLONG); 1.678 + if (len < offsetof(struct sockaddr, sa_data)) 1.679 + return (EINVAL); 1.680 + MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK); 1.681 + error = copyin(uaddr, sa, len); 1.682 + if (error) { 1.683 + FREE(sa, M_SONAME); 1.684 + } else { 1.685 +#ifdef HAVE_SA_LEN 1.686 + sa->sa_len = len; 1.687 +#endif 1.688 + *namp = sa; 1.689 + } 1.690 + return (error); 1.691 +} 1.692 + 1.693 + 1.694 +/* Taken from /src/lib/libc/net/sctp_sys_calls.c 1.695 + * and modified for __Userspace__ 1.696 + * calling sctp_generic_sendmsg from this function 1.697 + */ 1.698 +ssize_t 1.699 +userspace_sctp_sendmsg(struct socket *so, 1.700 + const void *data, 1.701 + size_t len, 1.702 + struct sockaddr *to, 1.703 + socklen_t tolen, 1.704 + u_int32_t ppid, 1.705 + u_int32_t flags, 1.706 + u_int16_t stream_no, 1.707 + u_int32_t timetolive, 1.708 + u_int32_t context) 1.709 +{ 1.710 + struct sctp_sndrcvinfo sndrcvinfo, *sinfo = &sndrcvinfo; 1.711 + struct uio auio; 1.712 + struct iovec iov[1]; 1.713 + 1.714 + sinfo->sinfo_ppid = ppid; 1.715 + sinfo->sinfo_flags = flags; 1.716 + sinfo->sinfo_stream = stream_no; 1.717 + sinfo->sinfo_timetolive = timetolive; 1.718 + sinfo->sinfo_context = context; 1.719 + sinfo->sinfo_assoc_id = 0; 1.720 + 1.721 + 1.722 + /* Perform error checks on destination (to) */ 1.723 + if (tolen > SOCK_MAXADDRLEN){ 1.724 + errno = ENAMETOOLONG; 1.725 + return (-1); 1.726 + } 1.727 + if ((tolen > 0) && 1.728 + ((to == NULL) || (tolen < (socklen_t)sizeof(struct sockaddr)))) { 1.729 + errno = EINVAL; 1.730 + return (-1); 1.731 + } 1.732 + /* Adding the following as part of defensive programming, in case the application 1.733 + does not do it when preparing the destination address.*/ 1.734 +#ifdef HAVE_SA_LEN 1.735 + if (to != NULL) { 1.736 + to->sa_len = tolen; 1.737 + } 1.738 +#endif 1.739 + 1.740 + iov[0].iov_base = (caddr_t)data; 1.741 + iov[0].iov_len = len; 1.742 + 1.743 + auio.uio_iov = iov; 1.744 + auio.uio_iovcnt = 1; 1.745 + auio.uio_segflg = UIO_USERSPACE; 1.746 + auio.uio_rw = UIO_WRITE; 1.747 + auio.uio_offset = 0; /* XXX */ 1.748 + auio.uio_resid = len; 1.749 + errno = sctp_lower_sosend(so, to, &auio, NULL, NULL, 0, sinfo); 1.750 + if (errno == 0) { 1.751 + return (len - auio.uio_resid); 1.752 + } else { 1.753 + return (-1); 1.754 + } 1.755 +} 1.756 + 1.757 + 1.758 +ssize_t 1.759 +usrsctp_sendv(struct socket *so, 1.760 + const void *data, 1.761 + size_t len, 1.762 + struct sockaddr *to, 1.763 + int addrcnt, 1.764 + void *info, 1.765 + socklen_t infolen, 1.766 + unsigned int infotype, 1.767 + int flags) 1.768 +{ 1.769 + struct sctp_sndrcvinfo sinfo; 1.770 + struct uio auio; 1.771 + struct iovec iov[1]; 1.772 + int use_sinfo; 1.773 + 1.774 + if (so == NULL) { 1.775 + errno = EBADF; 1.776 + return (-1); 1.777 + } 1.778 + memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo)); 1.779 + use_sinfo = 0; 1.780 + switch (infotype) { 1.781 + case SCTP_SENDV_NOINFO: 1.782 + if ((infolen != 0) || (info != NULL)) { 1.783 + errno = EINVAL; 1.784 + return (-1); 1.785 + } 1.786 + break; 1.787 + case SCTP_SENDV_SNDINFO: 1.788 + if ((info == NULL) || (infolen != sizeof(struct sctp_sndinfo))) { 1.789 + errno = EINVAL; 1.790 + return (-1); 1.791 + } 1.792 + sinfo.sinfo_stream = ((struct sctp_sndinfo *)info)->snd_sid; 1.793 + sinfo.sinfo_flags = ((struct sctp_sndinfo *)info)->snd_flags; 1.794 + sinfo.sinfo_ppid = ((struct sctp_sndinfo *)info)->snd_ppid; 1.795 + sinfo.sinfo_context = ((struct sctp_sndinfo *)info)->snd_context; 1.796 + sinfo.sinfo_assoc_id = ((struct sctp_sndinfo *)info)->snd_assoc_id; 1.797 + use_sinfo = 1; 1.798 + break; 1.799 + case SCTP_SENDV_PRINFO: 1.800 + if ((info == NULL) || (infolen != sizeof(struct sctp_prinfo))) { 1.801 + errno = EINVAL; 1.802 + return (-1); 1.803 + } 1.804 + sinfo.sinfo_stream = 0; 1.805 + sinfo.sinfo_flags = PR_SCTP_POLICY(((struct sctp_prinfo *)info)->pr_policy); 1.806 + sinfo.sinfo_timetolive = ((struct sctp_prinfo *)info)->pr_value; 1.807 + use_sinfo = 1; 1.808 + break; 1.809 + case SCTP_SENDV_AUTHINFO: 1.810 + errno = EINVAL; 1.811 + return (-1); 1.812 + case SCTP_SENDV_SPA: 1.813 + if ((info == NULL) || (infolen != sizeof(struct sctp_sendv_spa))) { 1.814 + errno = EINVAL; 1.815 + return (-1); 1.816 + } 1.817 + if (((struct sctp_sendv_spa *)info)->sendv_flags & SCTP_SEND_SNDINFO_VALID) { 1.818 + sinfo.sinfo_stream = ((struct sctp_sendv_spa *)info)->sendv_sndinfo.snd_sid; 1.819 + sinfo.sinfo_flags = ((struct sctp_sendv_spa *)info)->sendv_sndinfo.snd_flags; 1.820 + sinfo.sinfo_ppid = ((struct sctp_sendv_spa *)info)->sendv_sndinfo.snd_ppid; 1.821 + sinfo.sinfo_context = ((struct sctp_sendv_spa *)info)->sendv_sndinfo.snd_context; 1.822 + sinfo.sinfo_assoc_id = ((struct sctp_sendv_spa *)info)->sendv_sndinfo.snd_assoc_id; 1.823 + } else { 1.824 + sinfo.sinfo_flags = 0; 1.825 + sinfo.sinfo_stream = 0; 1.826 + } 1.827 + if (((struct sctp_sendv_spa *)info)->sendv_flags & SCTP_SEND_PRINFO_VALID) { 1.828 + sinfo.sinfo_flags |= PR_SCTP_POLICY(((struct sctp_sendv_spa *)info)->sendv_prinfo.pr_policy); 1.829 + sinfo.sinfo_timetolive = ((struct sctp_sendv_spa *)info)->sendv_prinfo.pr_value; 1.830 + } 1.831 + if (((struct sctp_sendv_spa *)info)->sendv_flags & SCTP_SEND_AUTHINFO_VALID) { 1.832 + errno = EINVAL; 1.833 + return (-1); 1.834 + } 1.835 + use_sinfo = 1; 1.836 + break; 1.837 + default: 1.838 + errno = EINVAL; 1.839 + return (-1); 1.840 + } 1.841 + 1.842 + /* Perform error checks on destination (to) */ 1.843 + if (addrcnt > 1) { 1.844 + errno = EINVAL; 1.845 + return (-1); 1.846 + } 1.847 + 1.848 + iov[0].iov_base = (caddr_t)data; 1.849 + iov[0].iov_len = len; 1.850 + 1.851 + auio.uio_iov = iov; 1.852 + auio.uio_iovcnt = 1; 1.853 + auio.uio_segflg = UIO_USERSPACE; 1.854 + auio.uio_rw = UIO_WRITE; 1.855 + auio.uio_offset = 0; /* XXX */ 1.856 + auio.uio_resid = len; 1.857 + errno = sctp_lower_sosend(so, to, &auio, NULL, NULL, flags, use_sinfo ? &sinfo : NULL); 1.858 + if (errno == 0) { 1.859 + return (len - auio.uio_resid); 1.860 + } else { 1.861 + return (-1); 1.862 + } 1.863 +} 1.864 + 1.865 + 1.866 +ssize_t 1.867 +userspace_sctp_sendmbuf(struct socket *so, 1.868 + struct mbuf* mbufdata, 1.869 + size_t len, 1.870 + struct sockaddr *to, 1.871 + socklen_t tolen, 1.872 + u_int32_t ppid, 1.873 + u_int32_t flags, 1.874 + u_int16_t stream_no, 1.875 + u_int32_t timetolive, 1.876 + u_int32_t context) 1.877 +{ 1.878 + 1.879 + struct sctp_sndrcvinfo sndrcvinfo, *sinfo = &sndrcvinfo; 1.880 + /* struct uio auio; 1.881 + struct iovec iov[1]; */ 1.882 + int error = 0; 1.883 + int uflags = 0; 1.884 + int retvalsendmsg; 1.885 + 1.886 + sinfo->sinfo_ppid = ppid; 1.887 + sinfo->sinfo_flags = flags; 1.888 + sinfo->sinfo_stream = stream_no; 1.889 + sinfo->sinfo_timetolive = timetolive; 1.890 + sinfo->sinfo_context = context; 1.891 + sinfo->sinfo_assoc_id = 0; 1.892 + 1.893 + /* Perform error checks on destination (to) */ 1.894 + if (tolen > SOCK_MAXADDRLEN){ 1.895 + error = (ENAMETOOLONG); 1.896 + goto sendmsg_return; 1.897 + } 1.898 + if (tolen < (socklen_t)offsetof(struct sockaddr, sa_data)){ 1.899 + error = (EINVAL); 1.900 + goto sendmsg_return; 1.901 + } 1.902 + /* Adding the following as part of defensive programming, in case the application 1.903 + does not do it when preparing the destination address.*/ 1.904 +#ifdef HAVE_SA_LEN 1.905 + to->sa_len = tolen; 1.906 +#endif 1.907 + 1.908 + error = sctp_lower_sosend(so, to, NULL/*uio*/, 1.909 + (struct mbuf *)mbufdata, (struct mbuf *)NULL, 1.910 + uflags, sinfo); 1.911 +sendmsg_return: 1.912 + /* TODO: Needs a condition for non-blocking when error is EWOULDBLOCK */ 1.913 + if (0 == error) 1.914 + retvalsendmsg = len; 1.915 + else if(error == EWOULDBLOCK) { 1.916 + errno = EWOULDBLOCK; 1.917 + retvalsendmsg = (-1); 1.918 + } else { 1.919 + SCTP_PRINTF("%s: error = %d\n", __func__, error); 1.920 + errno = error; 1.921 + retvalsendmsg = (-1); 1.922 + } 1.923 + return retvalsendmsg; 1.924 + 1.925 +} 1.926 + 1.927 + 1.928 +/* taken from usr.lib/sctp_sys_calls.c and needed here */ 1.929 +#define SCTP_SMALL_IOVEC_SIZE 2 1.930 + 1.931 +/* Taken from /src/lib/libc/net/sctp_sys_calls.c 1.932 + * and modified for __Userspace__ 1.933 + * calling sctp_generic_recvmsg from this function 1.934 + */ 1.935 +ssize_t 1.936 +userspace_sctp_recvmsg(struct socket *so, 1.937 + void *dbuf, 1.938 + size_t len, 1.939 + struct sockaddr *from, 1.940 + socklen_t *fromlenp, 1.941 + struct sctp_sndrcvinfo *sinfo, 1.942 + int *msg_flags) 1.943 +{ 1.944 + struct uio auio; 1.945 + struct iovec iov[SCTP_SMALL_IOVEC_SIZE]; 1.946 + struct iovec *tiov; 1.947 + int iovlen = 1; 1.948 + int error = 0; 1.949 + int ulen, i, retval; 1.950 + socklen_t fromlen; 1.951 + 1.952 + iov[0].iov_base = dbuf; 1.953 + iov[0].iov_len = len; 1.954 + 1.955 + auio.uio_iov = iov; 1.956 + auio.uio_iovcnt = iovlen; 1.957 + auio.uio_segflg = UIO_USERSPACE; 1.958 + auio.uio_rw = UIO_READ; 1.959 + auio.uio_offset = 0; /* XXX */ 1.960 + auio.uio_resid = 0; 1.961 + tiov = iov; 1.962 + for (i = 0; i <iovlen; i++, tiov++) { 1.963 + if ((auio.uio_resid += tiov->iov_len) < 0) { 1.964 + error = EINVAL; 1.965 + SCTP_PRINTF("%s: error = %d\n", __func__, error); 1.966 + return (-1); 1.967 + } 1.968 + } 1.969 + ulen = auio.uio_resid; 1.970 + if (fromlenp != NULL) { 1.971 + fromlen = *fromlenp; 1.972 + } else { 1.973 + fromlen = 0; 1.974 + } 1.975 + error = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL, 1.976 + from, fromlen, msg_flags, 1.977 + (struct sctp_sndrcvinfo *)sinfo, 1); 1.978 + 1.979 + if (error) { 1.980 + if (auio.uio_resid != (int)ulen && 1.981 + (error == EINTR || 1.982 +#if !defined(__Userspace_os_NetBSD) 1.983 + error == ERESTART || 1.984 +#endif 1.985 + error == EWOULDBLOCK)) { 1.986 + error = 0; 1.987 + } 1.988 + } 1.989 + if ((fromlenp != NULL) && (fromlen > 0) && (from != NULL)) { 1.990 + switch (from->sa_family) { 1.991 +#if defined(INET) 1.992 + case AF_INET: 1.993 + *fromlenp = sizeof(struct sockaddr_in); 1.994 + break; 1.995 +#endif 1.996 +#if defined(INET6) 1.997 + case AF_INET6: 1.998 + *fromlenp = sizeof(struct sockaddr_in6); 1.999 + break; 1.1000 +#endif 1.1001 + case AF_CONN: 1.1002 + *fromlenp = sizeof(struct sockaddr_conn); 1.1003 + break; 1.1004 + default: 1.1005 + *fromlenp = 0; 1.1006 + break; 1.1007 + } 1.1008 + if (*fromlenp > fromlen) { 1.1009 + *fromlenp = fromlen; 1.1010 + } 1.1011 + } 1.1012 + if (error == 0){ 1.1013 + /* ready return value */ 1.1014 + retval = (int)ulen - auio.uio_resid; 1.1015 + return (retval); 1.1016 + } else { 1.1017 + SCTP_PRINTF("%s: error = %d\n", __func__, error); 1.1018 + return (-1); 1.1019 + } 1.1020 +} 1.1021 + 1.1022 +ssize_t 1.1023 +usrsctp_recvv(struct socket *so, 1.1024 + void *dbuf, 1.1025 + size_t len, 1.1026 + struct sockaddr *from, 1.1027 + socklen_t *fromlenp, 1.1028 + void *info, 1.1029 + socklen_t *infolen, 1.1030 + unsigned int *infotype, 1.1031 + int *msg_flags) 1.1032 +{ 1.1033 + struct uio auio; 1.1034 + struct iovec iov[SCTP_SMALL_IOVEC_SIZE]; 1.1035 + struct iovec *tiov; 1.1036 + int iovlen = 1; 1.1037 + int ulen, i; 1.1038 + socklen_t fromlen; 1.1039 + struct sctp_rcvinfo *rcv; 1.1040 + struct sctp_recvv_rn *rn; 1.1041 + struct sctp_extrcvinfo seinfo; 1.1042 + 1.1043 + if (so == NULL) { 1.1044 + errno = EBADF; 1.1045 + return (-1); 1.1046 + } 1.1047 + iov[0].iov_base = dbuf; 1.1048 + iov[0].iov_len = len; 1.1049 + 1.1050 + auio.uio_iov = iov; 1.1051 + auio.uio_iovcnt = iovlen; 1.1052 + auio.uio_segflg = UIO_USERSPACE; 1.1053 + auio.uio_rw = UIO_READ; 1.1054 + auio.uio_offset = 0; /* XXX */ 1.1055 + auio.uio_resid = 0; 1.1056 + tiov = iov; 1.1057 + for (i = 0; i <iovlen; i++, tiov++) { 1.1058 + if ((auio.uio_resid += tiov->iov_len) < 0) { 1.1059 + errno = EINVAL; 1.1060 + return (-1); 1.1061 + } 1.1062 + } 1.1063 + ulen = auio.uio_resid; 1.1064 + if (fromlenp != NULL) { 1.1065 + fromlen = *fromlenp; 1.1066 + } else { 1.1067 + fromlen = 0; 1.1068 + } 1.1069 + errno = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL, 1.1070 + from, fromlen, msg_flags, 1.1071 + (struct sctp_sndrcvinfo *)&seinfo, 1); 1.1072 + if (errno) { 1.1073 + if (auio.uio_resid != (int)ulen && 1.1074 + (errno == EINTR || 1.1075 +#if !defined(__Userspace_os_NetBSD) 1.1076 + errno == ERESTART || 1.1077 +#endif 1.1078 + errno == EWOULDBLOCK)) { 1.1079 + errno = 0; 1.1080 + } 1.1081 + } 1.1082 + if ((*msg_flags & MSG_NOTIFICATION) == 0) { 1.1083 + struct sctp_inpcb *inp; 1.1084 + 1.1085 + inp = (struct sctp_inpcb *)so->so_pcb; 1.1086 + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO) && 1.1087 + sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO) && 1.1088 + *infolen >= (socklen_t)sizeof(struct sctp_recvv_rn) && 1.1089 + seinfo.sreinfo_next_flags & SCTP_NEXT_MSG_AVAIL) { 1.1090 + rn = (struct sctp_recvv_rn *)info; 1.1091 + rn->recvv_rcvinfo.rcv_sid = seinfo.sinfo_stream; 1.1092 + rn->recvv_rcvinfo.rcv_ssn = seinfo.sinfo_ssn; 1.1093 + rn->recvv_rcvinfo.rcv_flags = seinfo.sinfo_flags; 1.1094 + rn->recvv_rcvinfo.rcv_ppid = seinfo.sinfo_ppid; 1.1095 + rn->recvv_rcvinfo.rcv_context = seinfo.sinfo_context; 1.1096 + rn->recvv_rcvinfo.rcv_tsn = seinfo.sinfo_tsn; 1.1097 + rn->recvv_rcvinfo.rcv_cumtsn = seinfo.sinfo_cumtsn; 1.1098 + rn->recvv_rcvinfo.rcv_assoc_id = seinfo.sinfo_assoc_id; 1.1099 + rn->recvv_nxtinfo.nxt_sid = seinfo.sreinfo_next_stream; 1.1100 + rn->recvv_nxtinfo.nxt_flags = 0; 1.1101 + if (seinfo.sreinfo_next_flags & SCTP_NEXT_MSG_IS_UNORDERED) { 1.1102 + rn->recvv_nxtinfo.nxt_flags |= SCTP_UNORDERED; 1.1103 + } 1.1104 + if (seinfo.sreinfo_next_flags & SCTP_NEXT_MSG_IS_NOTIFICATION) { 1.1105 + rn->recvv_nxtinfo.nxt_flags |= SCTP_NOTIFICATION; 1.1106 + } 1.1107 + if (seinfo.sreinfo_next_flags & SCTP_NEXT_MSG_ISCOMPLETE) { 1.1108 + rn->recvv_nxtinfo.nxt_flags |= SCTP_COMPLETE; 1.1109 + } 1.1110 + rn->recvv_nxtinfo.nxt_ppid = seinfo.sreinfo_next_ppid; 1.1111 + rn->recvv_nxtinfo.nxt_length = seinfo.sreinfo_next_length; 1.1112 + rn->recvv_nxtinfo.nxt_assoc_id = seinfo.sreinfo_next_aid; 1.1113 + *infolen = (socklen_t)sizeof(struct sctp_recvv_rn); 1.1114 + *infotype = SCTP_RECVV_RN; 1.1115 + } else if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO) && 1.1116 + *infolen >= (socklen_t)sizeof(struct sctp_rcvinfo)) { 1.1117 + rcv = (struct sctp_rcvinfo *)info; 1.1118 + rcv->rcv_sid = seinfo.sinfo_stream; 1.1119 + rcv->rcv_ssn = seinfo.sinfo_ssn; 1.1120 + rcv->rcv_flags = seinfo.sinfo_flags; 1.1121 + rcv->rcv_ppid = seinfo.sinfo_ppid; 1.1122 + rcv->rcv_context = seinfo.sinfo_context; 1.1123 + rcv->rcv_tsn = seinfo.sinfo_tsn; 1.1124 + rcv->rcv_cumtsn = seinfo.sinfo_cumtsn; 1.1125 + rcv->rcv_assoc_id = seinfo.sinfo_assoc_id; 1.1126 + *infolen = (socklen_t)sizeof(struct sctp_rcvinfo); 1.1127 + *infotype = SCTP_RECVV_RCVINFO; 1.1128 + } else { 1.1129 + *infotype = SCTP_RECVV_NOINFO; 1.1130 + *infolen = 0; 1.1131 + } 1.1132 + } 1.1133 + if ((fromlenp != NULL) && (fromlen > 0) && (from != NULL)) { 1.1134 + switch (from->sa_family) { 1.1135 +#if defined(INET) 1.1136 + case AF_INET: 1.1137 + *fromlenp = sizeof(struct sockaddr_in); 1.1138 + break; 1.1139 +#endif 1.1140 +#if defined(INET6) 1.1141 + case AF_INET6: 1.1142 + *fromlenp = sizeof(struct sockaddr_in6); 1.1143 + break; 1.1144 +#endif 1.1145 + case AF_CONN: 1.1146 + *fromlenp = sizeof(struct sockaddr_conn); 1.1147 + break; 1.1148 + default: 1.1149 + *fromlenp = 0; 1.1150 + break; 1.1151 + } 1.1152 + if (*fromlenp > fromlen) { 1.1153 + *fromlenp = fromlen; 1.1154 + } 1.1155 + } 1.1156 + if (errno == 0) { 1.1157 + /* ready return value */ 1.1158 + return ((int)ulen - auio.uio_resid); 1.1159 + } else { 1.1160 + return (-1); 1.1161 + } 1.1162 +} 1.1163 + 1.1164 + 1.1165 + 1.1166 + 1.1167 +#if defined(__Userspace__) 1.1168 +/* Taken from /src/sys/kern/uipc_socket.c 1.1169 + * and modified for __Userspace__ 1.1170 + * socreate returns a socket. The socket should be 1.1171 + * closed with soclose(). 1.1172 + */ 1.1173 +int 1.1174 +socreate(int dom, struct socket **aso, int type, int proto) 1.1175 +{ 1.1176 + struct socket *so; 1.1177 + int error; 1.1178 + 1.1179 + if ((dom != AF_CONN) && (dom != AF_INET) && (dom != AF_INET6)) { 1.1180 + return (EINVAL); 1.1181 + } 1.1182 + if ((type != SOCK_STREAM) && (type != SOCK_SEQPACKET)) { 1.1183 + return (EINVAL); 1.1184 + } 1.1185 + if (proto != IPPROTO_SCTP) { 1.1186 + return (EINVAL); 1.1187 + } 1.1188 + 1.1189 + so = soalloc(); 1.1190 + if (so == NULL) { 1.1191 + return (ENOBUFS); 1.1192 + } 1.1193 + 1.1194 + /* 1.1195 + * so_incomp represents a queue of connections that 1.1196 + * must be completed at protocol level before being 1.1197 + * returned. so_comp field heads a list of sockets 1.1198 + * that are ready to be returned to the listening process 1.1199 + *__Userspace__ These queues are being used at a number of places like accept etc. 1.1200 + */ 1.1201 + TAILQ_INIT(&so->so_incomp); 1.1202 + TAILQ_INIT(&so->so_comp); 1.1203 + so->so_type = type; 1.1204 + so->so_count = 1; 1.1205 + so->so_dom = dom; 1.1206 + /* 1.1207 + * Auto-sizing of socket buffers is managed by the protocols and 1.1208 + * the appropriate flags must be set in the pru_attach function. 1.1209 + * For __Userspace__ The pru_attach function in this case is sctp_attach. 1.1210 + */ 1.1211 + switch (dom) { 1.1212 +#if defined(INET) 1.1213 + case AF_INET: 1.1214 + error = sctp_attach(so, proto, SCTP_DEFAULT_VRFID); 1.1215 + break; 1.1216 +#endif 1.1217 +#if defined(INET6) 1.1218 + case AF_INET6: 1.1219 + error = sctp6_attach(so, proto, SCTP_DEFAULT_VRFID); 1.1220 + break; 1.1221 +#endif 1.1222 + case AF_CONN: 1.1223 + error = sctpconn_attach(so, proto, SCTP_DEFAULT_VRFID); 1.1224 + break; 1.1225 + default: 1.1226 + error = EAFNOSUPPORT; 1.1227 + break; 1.1228 + } 1.1229 + if (error) { 1.1230 + KASSERT(so->so_count == 1, ("socreate: so_count %d", so->so_count)); 1.1231 + so->so_count = 0; 1.1232 + sodealloc(so); 1.1233 + return (error); 1.1234 + } 1.1235 + *aso = so; 1.1236 + return (0); 1.1237 +} 1.1238 +#else 1.1239 +/* The kernel version for reference is below. The #else 1.1240 + should be removed once the __Userspace__ 1.1241 + version is tested. 1.1242 + * socreate returns a socket with a ref count of 1. The socket should be 1.1243 + * closed with soclose(). 1.1244 + */ 1.1245 +int 1.1246 +socreate(int dom, struct socket **aso, int type, int proto, 1.1247 + struct ucred *cred, struct thread *td) 1.1248 +{ 1.1249 + struct protosw *prp; 1.1250 + struct socket *so; 1.1251 + int error; 1.1252 + 1.1253 + if (proto) 1.1254 + prp = pffindproto(dom, proto, type); 1.1255 + else 1.1256 + prp = pffindtype(dom, type); 1.1257 + 1.1258 + if (prp == NULL || prp->pr_usrreqs->pru_attach == NULL || 1.1259 + prp->pr_usrreqs->pru_attach == pru_attach_notsupp) 1.1260 + return (EPROTONOSUPPORT); 1.1261 + 1.1262 + if (jailed(cred) && jail_socket_unixiproute_only && 1.1263 + prp->pr_domain->dom_family != PF_LOCAL && 1.1264 + prp->pr_domain->dom_family != PF_INET && 1.1265 + prp->pr_domain->dom_family != PF_ROUTE) { 1.1266 + return (EPROTONOSUPPORT); 1.1267 + } 1.1268 + 1.1269 + if (prp->pr_type != type) 1.1270 + return (EPROTOTYPE); 1.1271 + so = soalloc(); 1.1272 + if (so == NULL) 1.1273 + return (ENOBUFS); 1.1274 + 1.1275 + TAILQ_INIT(&so->so_incomp); 1.1276 + TAILQ_INIT(&so->so_comp); 1.1277 + so->so_type = type; 1.1278 + so->so_cred = crhold(cred); 1.1279 + so->so_proto = prp; 1.1280 +#ifdef MAC 1.1281 + mac_create_socket(cred, so); 1.1282 +#endif 1.1283 + knlist_init(&so->so_rcv.sb_sel.si_note, SOCKBUF_MTX(&so->so_rcv), 1.1284 + NULL, NULL, NULL); 1.1285 + knlist_init(&so->so_snd.sb_sel.si_note, SOCKBUF_MTX(&so->so_snd), 1.1286 + NULL, NULL, NULL); 1.1287 + so->so_count = 1; 1.1288 + /* 1.1289 + * Auto-sizing of socket buffers is managed by the protocols and 1.1290 + * the appropriate flags must be set in the pru_attach function. 1.1291 + */ 1.1292 + error = (*prp->pr_usrreqs->pru_attach)(so, proto, td); 1.1293 + if (error) { 1.1294 + KASSERT(so->so_count == 1, ("socreate: so_count %d", 1.1295 + so->so_count)); 1.1296 + so->so_count = 0; 1.1297 + sodealloc(so); 1.1298 + return (error); 1.1299 + } 1.1300 + *aso = so; 1.1301 + return (0); 1.1302 +} 1.1303 +#endif 1.1304 + 1.1305 + 1.1306 + 1.1307 + 1.1308 +/* Taken from /src/sys/kern/uipc_syscalls.c 1.1309 + * and modified for __Userspace__ 1.1310 + * Removing struct thread td. 1.1311 + */ 1.1312 +struct socket * 1.1313 +userspace_socket(int domain, int type, int protocol) 1.1314 +{ 1.1315 + struct socket *so = NULL; 1.1316 + 1.1317 + errno = socreate(domain, &so, type, protocol); 1.1318 + if (errno) { 1.1319 + return (NULL); 1.1320 + } 1.1321 + /* 1.1322 + * The original socket call returns the file descriptor fd. 1.1323 + * td->td_retval[0] = fd. 1.1324 + * We are returning struct socket *so. 1.1325 + */ 1.1326 + return (so); 1.1327 +} 1.1328 + 1.1329 +struct socket * 1.1330 +usrsctp_socket(int domain, int type, int protocol, 1.1331 + int (*receive_cb)(struct socket *sock, union sctp_sockstore addr, void *data, 1.1332 + size_t datalen, struct sctp_rcvinfo, int flags, void *ulp_info), 1.1333 + int (*send_cb)(struct socket *sock, uint32_t sb_free), 1.1334 + uint32_t sb_threshold, 1.1335 + void *ulp_info) 1.1336 +{ 1.1337 + struct socket *so; 1.1338 + 1.1339 + if ((protocol = IPPROTO_SCTP) && (SCTP_BASE_VAR(sctp_pcb_initialized) == 0)) { 1.1340 + errno = EPROTONOSUPPORT; 1.1341 + return (NULL); 1.1342 + } 1.1343 + if ((receive_cb == NULL) && 1.1344 + ((send_cb != NULL) || (sb_threshold != 0) || (ulp_info != NULL))) { 1.1345 + errno = EINVAL; 1.1346 + return (NULL); 1.1347 + } 1.1348 + if ((domain == AF_CONN) && (SCTP_BASE_VAR(conn_output) == NULL)) { 1.1349 + errno = EAFNOSUPPORT; 1.1350 + return (NULL); 1.1351 + } 1.1352 + errno = socreate(domain, &so, type, protocol); 1.1353 + if (errno) { 1.1354 + return (NULL); 1.1355 + } 1.1356 + /* 1.1357 + * The original socket call returns the file descriptor fd. 1.1358 + * td->td_retval[0] = fd. 1.1359 + * We are returning struct socket *so. 1.1360 + */ 1.1361 + register_recv_cb(so, receive_cb); 1.1362 + register_send_cb(so, sb_threshold, send_cb); 1.1363 + register_ulp_info(so, ulp_info); 1.1364 + return (so); 1.1365 +} 1.1366 + 1.1367 + 1.1368 +u_long sb_max = SB_MAX; 1.1369 +u_long sb_max_adj = 1.1370 + SB_MAX * MCLBYTES / (MSIZE + MCLBYTES); /* adjusted sb_max */ 1.1371 + 1.1372 +static u_long sb_efficiency = 8; /* parameter for sbreserve() */ 1.1373 + 1.1374 +/* 1.1375 + * Allot mbufs to a sockbuf. Attempt to scale mbmax so that mbcnt doesn't 1.1376 + * become limiting if buffering efficiency is near the normal case. 1.1377 + */ 1.1378 +int 1.1379 +sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so) 1.1380 +{ 1.1381 + SOCKBUF_LOCK_ASSERT(sb); 1.1382 + sb->sb_mbmax = (u_int)min(cc * sb_efficiency, sb_max); 1.1383 + sb->sb_hiwat = cc; 1.1384 + if (sb->sb_lowat > (int)sb->sb_hiwat) 1.1385 + sb->sb_lowat = (int)sb->sb_hiwat; 1.1386 + return (1); 1.1387 +} 1.1388 + 1.1389 +static int 1.1390 +sbreserve(struct sockbuf *sb, u_long cc, struct socket *so) 1.1391 +{ 1.1392 + int error; 1.1393 + 1.1394 + SOCKBUF_LOCK(sb); 1.1395 + error = sbreserve_locked(sb, cc, so); 1.1396 + SOCKBUF_UNLOCK(sb); 1.1397 + return (error); 1.1398 +} 1.1399 + 1.1400 +#if defined(__Userspace__) 1.1401 +int 1.1402 +soreserve(struct socket *so, u_long sndcc, u_long rcvcc) 1.1403 +{ 1.1404 + SOCKBUF_LOCK(&so->so_snd); 1.1405 + SOCKBUF_LOCK(&so->so_rcv); 1.1406 + so->so_snd.sb_hiwat = (uint32_t)sndcc; 1.1407 + so->so_rcv.sb_hiwat = (uint32_t)rcvcc; 1.1408 + 1.1409 + if (sbreserve_locked(&so->so_snd, sndcc, so) == 0) { 1.1410 + goto bad; 1.1411 + } 1.1412 + if (sbreserve_locked(&so->so_rcv, rcvcc, so) == 0) { 1.1413 + goto bad; 1.1414 + } 1.1415 + if (so->so_rcv.sb_lowat == 0) 1.1416 + so->so_rcv.sb_lowat = 1; 1.1417 + if (so->so_snd.sb_lowat == 0) 1.1418 + so->so_snd.sb_lowat = MCLBYTES; 1.1419 + if (so->so_snd.sb_lowat > (int)so->so_snd.sb_hiwat) 1.1420 + so->so_snd.sb_lowat = (int)so->so_snd.sb_hiwat; 1.1421 + SOCKBUF_UNLOCK(&so->so_rcv); 1.1422 + SOCKBUF_UNLOCK(&so->so_snd); 1.1423 + return (0); 1.1424 + 1.1425 + bad: 1.1426 + SOCKBUF_UNLOCK(&so->so_rcv); 1.1427 + SOCKBUF_UNLOCK(&so->so_snd); 1.1428 + return (ENOBUFS); 1.1429 +} 1.1430 +#else /* kernel version for reference */ 1.1431 +int 1.1432 +soreserve(struct socket *so, u_long sndcc, u_long rcvcc) 1.1433 +{ 1.1434 + struct thread *td = curthread; 1.1435 + 1.1436 + SOCKBUF_LOCK(&so->so_snd); 1.1437 + SOCKBUF_LOCK(&so->so_rcv); 1.1438 + if (sbreserve_locked(&so->so_snd, sndcc, so, td) == 0) 1.1439 + goto bad; 1.1440 + if (sbreserve_locked(&so->so_rcv, rcvcc, so, td) == 0) 1.1441 + goto bad2; 1.1442 + if (so->so_rcv.sb_lowat == 0) 1.1443 + so->so_rcv.sb_lowat = 1; 1.1444 + if (so->so_snd.sb_lowat == 0) 1.1445 + so->so_snd.sb_lowat = MCLBYTES; 1.1446 + if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat) 1.1447 + so->so_snd.sb_lowat = so->so_snd.sb_hiwat; 1.1448 + SOCKBUF_UNLOCK(&so->so_rcv); 1.1449 + SOCKBUF_UNLOCK(&so->so_snd); 1.1450 + return (0); 1.1451 +bad2: 1.1452 + sbrelease_locked(&so->so_snd, so); 1.1453 +bad: 1.1454 + SOCKBUF_UNLOCK(&so->so_rcv); 1.1455 + SOCKBUF_UNLOCK(&so->so_snd); 1.1456 + return (ENOBUFS); 1.1457 +} 1.1458 +#endif 1.1459 + 1.1460 + 1.1461 + 1.1462 + 1.1463 + 1.1464 +/* Taken from /src/sys/kern/uipc_sockbuf.c 1.1465 + * and modified for __Userspace__ 1.1466 + */ 1.1467 + 1.1468 +#if defined(__Userspace__) 1.1469 +void 1.1470 +sowakeup(struct socket *so, struct sockbuf *sb) 1.1471 +{ 1.1472 + 1.1473 + SOCKBUF_LOCK_ASSERT(sb); 1.1474 + 1.1475 + sb->sb_flags &= ~SB_SEL; 1.1476 + if (sb->sb_flags & SB_WAIT) { 1.1477 + sb->sb_flags &= ~SB_WAIT; 1.1478 +#if defined (__Userspace_os_Windows) 1.1479 + WakeAllConditionVariable(&(sb)->sb_cond); 1.1480 +#else 1.1481 + pthread_cond_broadcast(&(sb)->sb_cond); 1.1482 +#endif 1.1483 + } 1.1484 + SOCKBUF_UNLOCK(sb); 1.1485 + /*__Userspace__ what todo about so_upcall?*/ 1.1486 + 1.1487 +} 1.1488 +#else /* kernel version for reference */ 1.1489 +/* 1.1490 + * Wakeup processes waiting on a socket buffer. Do asynchronous notification 1.1491 + * via SIGIO if the socket has the SS_ASYNC flag set. 1.1492 + * 1.1493 + * Called with the socket buffer lock held; will release the lock by the end 1.1494 + * of the function. This allows the caller to acquire the socket buffer lock 1.1495 + * while testing for the need for various sorts of wakeup and hold it through 1.1496 + * to the point where it's no longer required. We currently hold the lock 1.1497 + * through calls out to other subsystems (with the exception of kqueue), and 1.1498 + * then release it to avoid lock order issues. It's not clear that's 1.1499 + * correct. 1.1500 + */ 1.1501 +void 1.1502 +sowakeup(struct socket *so, struct sockbuf *sb) 1.1503 +{ 1.1504 + 1.1505 + SOCKBUF_LOCK_ASSERT(sb); 1.1506 + 1.1507 + selwakeuppri(&sb->sb_sel, PSOCK); 1.1508 + sb->sb_flags &= ~SB_SEL; 1.1509 + if (sb->sb_flags & SB_WAIT) { 1.1510 + sb->sb_flags &= ~SB_WAIT; 1.1511 + wakeup(&sb->sb_cc); 1.1512 + } 1.1513 + KNOTE_LOCKED(&sb->sb_sel.si_note, 0); 1.1514 + SOCKBUF_UNLOCK(sb); 1.1515 + if ((so->so_state & SS_ASYNC) && so->so_sigio != NULL) 1.1516 + pgsigio(&so->so_sigio, SIGIO, 0); 1.1517 + if (sb->sb_flags & SB_UPCALL) 1.1518 + (*so->so_upcall)(so, so->so_upcallarg, M_NOWAIT); 1.1519 + if (sb->sb_flags & SB_AIO) 1.1520 + aio_swake(so, sb); 1.1521 + mtx_assert(SOCKBUF_MTX(sb), MA_NOTOWNED); 1.1522 +} 1.1523 +#endif 1.1524 + 1.1525 + 1.1526 + 1.1527 +/* Taken from /src/sys/kern/uipc_socket.c 1.1528 + * and modified for __Userspace__ 1.1529 + */ 1.1530 + 1.1531 +int 1.1532 +sobind(struct socket *so, struct sockaddr *nam) 1.1533 +{ 1.1534 + switch (nam->sa_family) { 1.1535 +#if defined(INET) 1.1536 + case AF_INET: 1.1537 + return (sctp_bind(so, nam)); 1.1538 +#endif 1.1539 +#if defined(INET6) 1.1540 + case AF_INET6: 1.1541 + return (sctp6_bind(so, nam, NULL)); 1.1542 +#endif 1.1543 + case AF_CONN: 1.1544 + return (sctpconn_bind(so, nam)); 1.1545 + default: 1.1546 + return EAFNOSUPPORT; 1.1547 + } 1.1548 +} 1.1549 + 1.1550 +/* Taken from /src/sys/kern/uipc_syscalls.c 1.1551 + * and modified for __Userspace__ 1.1552 + */ 1.1553 + 1.1554 +int 1.1555 +usrsctp_bind(struct socket *so, struct sockaddr *name, int namelen) 1.1556 +{ 1.1557 + struct sockaddr *sa; 1.1558 + 1.1559 + if (so == NULL) { 1.1560 + errno = EBADF; 1.1561 + return (-1); 1.1562 + } 1.1563 + if ((errno = getsockaddr(&sa, (caddr_t)name, namelen)) != 0) 1.1564 + return (-1); 1.1565 + 1.1566 + errno = sobind(so, sa); 1.1567 + FREE(sa, M_SONAME); 1.1568 + if (errno) { 1.1569 + return (-1); 1.1570 + } else { 1.1571 + return (0); 1.1572 + } 1.1573 +} 1.1574 + 1.1575 +int 1.1576 +userspace_bind(struct socket *so, struct sockaddr *name, int namelen) 1.1577 +{ 1.1578 + return (usrsctp_bind(so, name, namelen)); 1.1579 +} 1.1580 + 1.1581 +/* Taken from /src/sys/kern/uipc_socket.c 1.1582 + * and modified for __Userspace__ 1.1583 + */ 1.1584 + 1.1585 +int 1.1586 +solisten(struct socket *so, int backlog) 1.1587 +{ 1.1588 + if (so == NULL) { 1.1589 + return (EBADF); 1.1590 + } else { 1.1591 + return (sctp_listen(so, backlog, NULL)); 1.1592 + } 1.1593 +} 1.1594 + 1.1595 + 1.1596 +int 1.1597 +solisten_proto_check(struct socket *so) 1.1598 +{ 1.1599 + 1.1600 + SOCK_LOCK_ASSERT(so); 1.1601 + 1.1602 + if (so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING | 1.1603 + SS_ISDISCONNECTING)) 1.1604 + return (EINVAL); 1.1605 + return (0); 1.1606 +} 1.1607 + 1.1608 +static int somaxconn = SOMAXCONN; 1.1609 + 1.1610 +void 1.1611 +solisten_proto(struct socket *so, int backlog) 1.1612 +{ 1.1613 + 1.1614 + SOCK_LOCK_ASSERT(so); 1.1615 + 1.1616 + if (backlog < 0 || backlog > somaxconn) 1.1617 + backlog = somaxconn; 1.1618 + so->so_qlimit = backlog; 1.1619 + so->so_options |= SCTP_SO_ACCEPTCONN; 1.1620 +} 1.1621 + 1.1622 + 1.1623 + 1.1624 + 1.1625 +/* Taken from /src/sys/kern/uipc_syscalls.c 1.1626 + * and modified for __Userspace__ 1.1627 + */ 1.1628 + 1.1629 +int 1.1630 +usrsctp_listen(struct socket *so, int backlog) 1.1631 +{ 1.1632 + errno = solisten(so, backlog); 1.1633 + if (errno) { 1.1634 + return (-1); 1.1635 + } else { 1.1636 + return (0); 1.1637 + } 1.1638 +} 1.1639 + 1.1640 +int 1.1641 +userspace_listen(struct socket *so, int backlog) 1.1642 +{ 1.1643 + return (usrsctp_listen(so, backlog)); 1.1644 +} 1.1645 + 1.1646 +/* Taken from /src/sys/kern/uipc_socket.c 1.1647 + * and modified for __Userspace__ 1.1648 + */ 1.1649 + 1.1650 +int 1.1651 +soaccept(struct socket *so, struct sockaddr **nam) 1.1652 +{ 1.1653 + int error; 1.1654 + 1.1655 + SOCK_LOCK(so); 1.1656 + KASSERT((so->so_state & SS_NOFDREF) != 0, ("soaccept: !NOFDREF")); 1.1657 + so->so_state &= ~SS_NOFDREF; 1.1658 + SOCK_UNLOCK(so); 1.1659 + error = sctp_accept(so, nam); 1.1660 + return (error); 1.1661 +} 1.1662 + 1.1663 + 1.1664 + 1.1665 +/* Taken from /src/sys/kern/uipc_syscalls.c 1.1666 + * kern_accept modified for __Userspace__ 1.1667 + */ 1.1668 +int 1.1669 +user_accept(struct socket *head, struct sockaddr **name, socklen_t *namelen, struct socket **ptr_accept_ret_sock) 1.1670 +{ 1.1671 + struct sockaddr *sa = NULL; 1.1672 + int error; 1.1673 + struct socket *so = NULL; 1.1674 + 1.1675 + 1.1676 + if (name) { 1.1677 + *name = NULL; 1.1678 + } 1.1679 + 1.1680 + if ((head->so_options & SCTP_SO_ACCEPTCONN) == 0) { 1.1681 + error = EINVAL; 1.1682 + goto done; 1.1683 + } 1.1684 + 1.1685 + ACCEPT_LOCK(); 1.1686 + if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) { 1.1687 + ACCEPT_UNLOCK(); 1.1688 + error = EWOULDBLOCK; 1.1689 + goto noconnection; 1.1690 + } 1.1691 + while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) { 1.1692 + if (head->so_rcv.sb_state & SBS_CANTRCVMORE) { 1.1693 + head->so_error = ECONNABORTED; 1.1694 + break; 1.1695 + } 1.1696 +#if defined (__Userspace_os_Windows) 1.1697 + if (SleepConditionVariableCS(&accept_cond, &accept_mtx, INFINITE)) 1.1698 + error = 0; 1.1699 + else 1.1700 + error = GetLastError(); 1.1701 +#else 1.1702 + error = pthread_cond_wait(&accept_cond, &accept_mtx); 1.1703 +#endif 1.1704 + if (error) { 1.1705 + ACCEPT_UNLOCK(); 1.1706 + goto noconnection; 1.1707 + } 1.1708 + } 1.1709 + if (head->so_error) { 1.1710 + error = head->so_error; 1.1711 + head->so_error = 0; 1.1712 + ACCEPT_UNLOCK(); 1.1713 + goto noconnection; 1.1714 + } 1.1715 + so = TAILQ_FIRST(&head->so_comp); 1.1716 + KASSERT(!(so->so_qstate & SQ_INCOMP), ("accept1: so SQ_INCOMP")); 1.1717 + KASSERT(so->so_qstate & SQ_COMP, ("accept1: so not SQ_COMP")); 1.1718 + 1.1719 + /* 1.1720 + * Before changing the flags on the socket, we have to bump the 1.1721 + * reference count. Otherwise, if the protocol calls sofree(), 1.1722 + * the socket will be released due to a zero refcount. 1.1723 + */ 1.1724 + SOCK_LOCK(so); /* soref() and so_state update */ 1.1725 + soref(so); /* file descriptor reference */ 1.1726 + 1.1727 + TAILQ_REMOVE(&head->so_comp, so, so_list); 1.1728 + head->so_qlen--; 1.1729 + so->so_state |= (head->so_state & SS_NBIO); 1.1730 + so->so_qstate &= ~SQ_COMP; 1.1731 + so->so_head = NULL; 1.1732 + SOCK_UNLOCK(so); 1.1733 + ACCEPT_UNLOCK(); 1.1734 + 1.1735 + 1.1736 + /* 1.1737 + * The original accept returns fd value via td->td_retval[0] = fd; 1.1738 + * we will return the socket for accepted connection. 1.1739 + */ 1.1740 + 1.1741 + error = soaccept(so, &sa); 1.1742 + if (error) { 1.1743 + /* 1.1744 + * return a namelen of zero for older code which might 1.1745 + * ignore the return value from accept. 1.1746 + */ 1.1747 + if (name) 1.1748 + *namelen = 0; 1.1749 + goto noconnection; 1.1750 + } 1.1751 + if (sa == NULL) { 1.1752 + if (name) 1.1753 + *namelen = 0; 1.1754 + goto done; 1.1755 + } 1.1756 + if (name) { 1.1757 +#ifdef HAVE_SA_LEN 1.1758 + /* check sa_len before it is destroyed */ 1.1759 + if (*namelen > sa->sa_len) { 1.1760 + *namelen = sa->sa_len; 1.1761 + } 1.1762 +#else 1.1763 + socklen_t sa_len; 1.1764 + 1.1765 + switch (sa->sa_family) { 1.1766 +#ifdef INET 1.1767 + case AF_INET: 1.1768 + sa_len = sizeof(struct sockaddr_in); 1.1769 + break; 1.1770 +#endif 1.1771 +#ifdef INET6 1.1772 + case AF_INET6: 1.1773 + sa_len = sizeof(struct sockaddr_in6); 1.1774 + break; 1.1775 +#endif 1.1776 + case AF_CONN: 1.1777 + sa_len = sizeof(struct sockaddr_conn); 1.1778 + break; 1.1779 + default: 1.1780 + sa_len = 0; 1.1781 + break; 1.1782 + } 1.1783 + if (*namelen > sa_len) { 1.1784 + *namelen = sa_len; 1.1785 + } 1.1786 +#endif 1.1787 + *name = sa; 1.1788 + sa = NULL; 1.1789 + } 1.1790 +noconnection: 1.1791 + if (sa) { 1.1792 + FREE(sa, M_SONAME); 1.1793 + } 1.1794 + 1.1795 +done: 1.1796 + *ptr_accept_ret_sock = so; 1.1797 + return (error); 1.1798 +} 1.1799 + 1.1800 + 1.1801 + 1.1802 +/* Taken from /src/sys/kern/uipc_syscalls.c 1.1803 + * and modified for __Userspace__ 1.1804 + */ 1.1805 +/* 1.1806 + * accept1() 1.1807 + */ 1.1808 +static int 1.1809 +accept1(struct socket *so, struct sockaddr *aname, socklen_t *anamelen, struct socket **ptr_accept_ret_sock) 1.1810 +{ 1.1811 + struct sockaddr *name; 1.1812 + socklen_t namelen; 1.1813 + int error; 1.1814 + 1.1815 + if (so == NULL) { 1.1816 + return (EBADF); 1.1817 + } 1.1818 + if (aname == NULL) { 1.1819 + return (user_accept(so, NULL, NULL, ptr_accept_ret_sock)); 1.1820 + } 1.1821 + 1.1822 + error = copyin(anamelen, &namelen, sizeof (namelen)); 1.1823 + if (error) 1.1824 + return (error); 1.1825 + 1.1826 + error = user_accept(so, &name, &namelen, ptr_accept_ret_sock); 1.1827 + 1.1828 + /* 1.1829 + * return a namelen of zero for older code which might 1.1830 + * ignore the return value from accept. 1.1831 + */ 1.1832 + if (error) { 1.1833 + (void) copyout(&namelen, 1.1834 + anamelen, sizeof(*anamelen)); 1.1835 + return (error); 1.1836 + } 1.1837 + 1.1838 + if (error == 0 && name != NULL) { 1.1839 + error = copyout(name, aname, namelen); 1.1840 + } 1.1841 + if (error == 0) { 1.1842 + error = copyout(&namelen, anamelen, sizeof(namelen)); 1.1843 + } 1.1844 + 1.1845 + if (name) { 1.1846 + FREE(name, M_SONAME); 1.1847 + } 1.1848 + return (error); 1.1849 +} 1.1850 + 1.1851 +struct socket * 1.1852 +usrsctp_accept(struct socket *so, struct sockaddr *aname, socklen_t *anamelen) 1.1853 +{ 1.1854 + struct socket *accept_return_sock; 1.1855 + 1.1856 + errno = accept1(so, aname, anamelen, &accept_return_sock); 1.1857 + if (errno) { 1.1858 + return (NULL); 1.1859 + } else { 1.1860 + return (accept_return_sock); 1.1861 + } 1.1862 +} 1.1863 + 1.1864 +struct socket * 1.1865 +userspace_accept(struct socket *so, struct sockaddr *aname, socklen_t *anamelen) 1.1866 +{ 1.1867 + return (usrsctp_accept(so, aname, anamelen)); 1.1868 +} 1.1869 + 1.1870 +struct socket * 1.1871 +usrsctp_peeloff(struct socket *head, sctp_assoc_t id) 1.1872 +{ 1.1873 + struct socket *so; 1.1874 + 1.1875 + if ((errno = sctp_can_peel_off(head, id)) != 0) { 1.1876 + return (NULL); 1.1877 + } 1.1878 + if ((so = sonewconn(head, SS_ISCONNECTED)) == NULL) { 1.1879 + return (NULL); 1.1880 + } 1.1881 + ACCEPT_LOCK(); 1.1882 + SOCK_LOCK(so); 1.1883 + soref(so); 1.1884 + TAILQ_REMOVE(&head->so_comp, so, so_list); 1.1885 + head->so_qlen--; 1.1886 + so->so_state |= (head->so_state & SS_NBIO); 1.1887 + so->so_qstate &= ~SQ_COMP; 1.1888 + so->so_head = NULL; 1.1889 + SOCK_UNLOCK(so); 1.1890 + ACCEPT_UNLOCK(); 1.1891 + if ((errno = sctp_do_peeloff(head, so, id)) != 0) { 1.1892 + so->so_count = 0; 1.1893 + sodealloc(so); 1.1894 + return (NULL); 1.1895 + } 1.1896 + return (so); 1.1897 +} 1.1898 + 1.1899 +int 1.1900 +sodisconnect(struct socket *so) 1.1901 +{ 1.1902 + int error; 1.1903 + 1.1904 + if ((so->so_state & SS_ISCONNECTED) == 0) 1.1905 + return (ENOTCONN); 1.1906 + if (so->so_state & SS_ISDISCONNECTING) 1.1907 + return (EALREADY); 1.1908 + error = sctp_disconnect(so); 1.1909 + return (error); 1.1910 +} 1.1911 + 1.1912 +int 1.1913 +usrsctp_set_non_blocking(struct socket *so, int onoff) 1.1914 +{ 1.1915 + if (so == NULL) { 1.1916 + errno = EBADF; 1.1917 + return (-1); 1.1918 + } 1.1919 + SOCK_LOCK(so); 1.1920 + if (onoff != 0) { 1.1921 + so->so_state |= SS_NBIO; 1.1922 + } else { 1.1923 + so->so_state &= ~SS_NBIO; 1.1924 + } 1.1925 + SOCK_UNLOCK(so); 1.1926 + return (0); 1.1927 +} 1.1928 + 1.1929 +int 1.1930 +usrsctp_get_non_blocking(struct socket *so) 1.1931 +{ 1.1932 + int result; 1.1933 + 1.1934 + if (so == NULL) { 1.1935 + errno = EBADF; 1.1936 + return (-1); 1.1937 + } 1.1938 + SOCK_LOCK(so); 1.1939 + if (so->so_state | SS_NBIO) { 1.1940 + result = 1; 1.1941 + } else { 1.1942 + result = 0; 1.1943 + } 1.1944 + SOCK_UNLOCK(so); 1.1945 + return (result); 1.1946 +} 1.1947 + 1.1948 +int 1.1949 +soconnect(struct socket *so, struct sockaddr *nam) 1.1950 +{ 1.1951 + int error; 1.1952 + 1.1953 + if (so->so_options & SCTP_SO_ACCEPTCONN) 1.1954 + return (EOPNOTSUPP); 1.1955 + /* 1.1956 + * If protocol is connection-based, can only connect once. 1.1957 + * Otherwise, if connected, try to disconnect first. This allows 1.1958 + * user to disconnect by connecting to, e.g., a null address. 1.1959 + */ 1.1960 + if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && (error = sodisconnect(so))) { 1.1961 + error = EISCONN; 1.1962 + } else { 1.1963 + /* 1.1964 + * Prevent accumulated error from previous connection from 1.1965 + * biting us. 1.1966 + */ 1.1967 + so->so_error = 0; 1.1968 + switch (nam->sa_family) { 1.1969 +#if defined(INET) 1.1970 + case AF_INET: 1.1971 + error = sctp_connect(so, nam); 1.1972 + break; 1.1973 +#endif 1.1974 +#if defined(INET6) 1.1975 + case AF_INET6: 1.1976 + error = sctp6_connect(so, nam); 1.1977 + break; 1.1978 +#endif 1.1979 + case AF_CONN: 1.1980 + error = sctpconn_connect(so, nam); 1.1981 + break; 1.1982 + default: 1.1983 + error = EAFNOSUPPORT; 1.1984 + } 1.1985 + } 1.1986 + 1.1987 + return (error); 1.1988 +} 1.1989 + 1.1990 + 1.1991 + 1.1992 +int user_connect(struct socket *so, struct sockaddr *sa) 1.1993 +{ 1.1994 + int error; 1.1995 + int interrupted = 0; 1.1996 + 1.1997 + if (so == NULL) { 1.1998 + error = EBADF; 1.1999 + goto done1; 1.2000 + } 1.2001 + if (so->so_state & SS_ISCONNECTING) { 1.2002 + error = EALREADY; 1.2003 + goto done1; 1.2004 + } 1.2005 + 1.2006 + error = soconnect(so, sa); 1.2007 + if (error) { 1.2008 + goto bad; 1.2009 + } 1.2010 + if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 1.2011 + error = EINPROGRESS; 1.2012 + goto done1; 1.2013 + } 1.2014 + 1.2015 + SOCK_LOCK(so); 1.2016 + while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 1.2017 +#if defined (__Userspace_os_Windows) 1.2018 + if (SleepConditionVariableCS(SOCK_COND(so), SOCK_MTX(so), INFINITE)) 1.2019 + error = 0; 1.2020 + else 1.2021 + error = -1; 1.2022 +#else 1.2023 + error = pthread_cond_wait(SOCK_COND(so), SOCK_MTX(so)); 1.2024 +#endif 1.2025 + if (error) { 1.2026 +#if defined(__Userspace_os_NetBSD) 1.2027 + if (error == EINTR) { 1.2028 +#else 1.2029 + if (error == EINTR || error == ERESTART) { 1.2030 +#endif 1.2031 + interrupted = 1; 1.2032 + } 1.2033 + break; 1.2034 + } 1.2035 + } 1.2036 + if (error == 0) { 1.2037 + error = so->so_error; 1.2038 + so->so_error = 0; 1.2039 + } 1.2040 + SOCK_UNLOCK(so); 1.2041 + 1.2042 +bad: 1.2043 + if (!interrupted) { 1.2044 + so->so_state &= ~SS_ISCONNECTING; 1.2045 + } 1.2046 +#if !defined(__Userspace_os_NetBSD) 1.2047 + if (error == ERESTART) { 1.2048 + error = EINTR; 1.2049 + } 1.2050 +#endif 1.2051 +done1: 1.2052 + return (error); 1.2053 +} 1.2054 + 1.2055 +int usrsctp_connect(struct socket *so, struct sockaddr *name, int namelen) 1.2056 +{ 1.2057 + struct sockaddr *sa; 1.2058 + 1.2059 + errno = getsockaddr(&sa, (caddr_t)name, namelen); 1.2060 + if (errno) 1.2061 + return (-1); 1.2062 + 1.2063 + errno = user_connect(so, sa); 1.2064 + FREE(sa, M_SONAME); 1.2065 + if (errno) { 1.2066 + return (-1); 1.2067 + } else { 1.2068 + return (0); 1.2069 + } 1.2070 +} 1.2071 + 1.2072 +int userspace_connect(struct socket *so, struct sockaddr *name, int namelen) 1.2073 +{ 1.2074 + return (usrsctp_connect(so, name, namelen)); 1.2075 +} 1.2076 + 1.2077 +#define SCTP_STACK_BUF_SIZE 2048 1.2078 + 1.2079 +void 1.2080 +usrsctp_close(struct socket *so) { 1.2081 + if (so != NULL) { 1.2082 + if (so->so_options & SCTP_SO_ACCEPTCONN) { 1.2083 + struct socket *sp; 1.2084 + 1.2085 + ACCEPT_LOCK(); 1.2086 + while ((sp = TAILQ_FIRST(&so->so_comp)) != NULL) { 1.2087 + TAILQ_REMOVE(&so->so_comp, sp, so_list); 1.2088 + so->so_qlen--; 1.2089 + sp->so_qstate &= ~SQ_COMP; 1.2090 + sp->so_head = NULL; 1.2091 + ACCEPT_UNLOCK(); 1.2092 + soabort(sp); 1.2093 + ACCEPT_LOCK(); 1.2094 + } 1.2095 + ACCEPT_UNLOCK(); 1.2096 + } 1.2097 + ACCEPT_LOCK(); 1.2098 + SOCK_LOCK(so); 1.2099 + sorele(so); 1.2100 + } 1.2101 +} 1.2102 + 1.2103 +void 1.2104 +userspace_close(struct socket *so) 1.2105 +{ 1.2106 + usrsctp_close(so); 1.2107 +} 1.2108 + 1.2109 +int 1.2110 +usrsctp_shutdown(struct socket *so, int how) 1.2111 +{ 1.2112 + if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR)) { 1.2113 + errno = EINVAL; 1.2114 + return (-1); 1.2115 + } 1.2116 + if (so == NULL) { 1.2117 + errno = EBADF; 1.2118 + return (-1); 1.2119 + } 1.2120 + sctp_flush(so, how); 1.2121 + if (how != SHUT_WR) 1.2122 + socantrcvmore(so); 1.2123 + if (how != SHUT_RD) { 1.2124 + errno = sctp_shutdown(so); 1.2125 + if (errno) { 1.2126 + return (-1); 1.2127 + } else { 1.2128 + return (0); 1.2129 + } 1.2130 + } 1.2131 + return (0); 1.2132 +} 1.2133 + 1.2134 +int 1.2135 +userspace_shutdown(struct socket *so, int how) 1.2136 +{ 1.2137 + return (usrsctp_shutdown(so, how)); 1.2138 +} 1.2139 + 1.2140 +int 1.2141 +usrsctp_finish(void) 1.2142 +{ 1.2143 + if (SCTP_BASE_VAR(sctp_pcb_initialized) == 0) { 1.2144 + return (0); 1.2145 + } 1.2146 + if (SCTP_INP_INFO_TRYLOCK()) { 1.2147 + if (!LIST_EMPTY(&SCTP_BASE_INFO(listhead))) { 1.2148 + SCTP_INP_INFO_RUNLOCK(); 1.2149 + return (-1); 1.2150 + } 1.2151 + SCTP_INP_INFO_RUNLOCK(); 1.2152 + } else { 1.2153 + return (-1); 1.2154 + } 1.2155 + sctp_finish(); 1.2156 + return (0); 1.2157 +} 1.2158 + 1.2159 +int 1.2160 +userspace_finish(void) 1.2161 +{ 1.2162 + return (usrsctp_finish()); 1.2163 +} 1.2164 + 1.2165 +/* needed from sctp_usrreq.c */ 1.2166 +int 1.2167 +sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, void *p); 1.2168 + 1.2169 +int 1.2170 +usrsctp_setsockopt(struct socket *so, int level, int option_name, 1.2171 + const void *option_value, socklen_t option_len) 1.2172 +{ 1.2173 + if (so == NULL) { 1.2174 + errno = EBADF; 1.2175 + return (-1); 1.2176 + } 1.2177 + switch (level) { 1.2178 + case SOL_SOCKET: 1.2179 + { 1.2180 + switch (option_name) { 1.2181 + case SO_RCVBUF: 1.2182 + if (option_len < (socklen_t)sizeof(int)) { 1.2183 + errno = EINVAL; 1.2184 + return (-1); 1.2185 + } else { 1.2186 + int *buf_size; 1.2187 + 1.2188 + buf_size = (int *)option_value; 1.2189 + if (*buf_size < 1) { 1.2190 + errno = EINVAL; 1.2191 + return (-1); 1.2192 + } 1.2193 + sbreserve(&so->so_rcv, (u_long)*buf_size, so); 1.2194 + return (0); 1.2195 + } 1.2196 + break; 1.2197 + case SO_SNDBUF: 1.2198 + if (option_len < (socklen_t)sizeof(int)) { 1.2199 + errno = EINVAL; 1.2200 + return (-1); 1.2201 + } else { 1.2202 + int *buf_size; 1.2203 + 1.2204 + buf_size = (int *)option_value; 1.2205 + if (*buf_size < 1) { 1.2206 + errno = EINVAL; 1.2207 + return (-1); 1.2208 + } 1.2209 + sbreserve(&so->so_snd, (u_long)*buf_size, so); 1.2210 + return (0); 1.2211 + } 1.2212 + break; 1.2213 + case SO_LINGER: 1.2214 + if (option_len < (socklen_t)sizeof(struct linger)) { 1.2215 + errno = EINVAL; 1.2216 + return (-1); 1.2217 + } else { 1.2218 + struct linger *l; 1.2219 + 1.2220 + l = (struct linger *)option_value; 1.2221 + so->so_linger = l->l_linger; 1.2222 + if (l->l_onoff) { 1.2223 + so->so_options |= SCTP_SO_LINGER; 1.2224 + } else { 1.2225 + so->so_options &= ~SCTP_SO_LINGER; 1.2226 + } 1.2227 + return (0); 1.2228 + } 1.2229 + default: 1.2230 + errno = EINVAL; 1.2231 + return (-1); 1.2232 + } 1.2233 + } 1.2234 + case IPPROTO_SCTP: 1.2235 + errno = sctp_setopt(so, option_name, (void *) option_value, (size_t)option_len, NULL); 1.2236 + if (errno) { 1.2237 + return (-1); 1.2238 + } else { 1.2239 + return (0); 1.2240 + } 1.2241 + default: 1.2242 + errno = ENOPROTOOPT; 1.2243 + return (-1); 1.2244 + } 1.2245 +} 1.2246 + 1.2247 +int 1.2248 +userspace_setsockopt(struct socket *so, int level, int option_name, 1.2249 + const void *option_value, socklen_t option_len) 1.2250 +{ 1.2251 + return (usrsctp_setsockopt(so, level, option_name, option_value, option_len)); 1.2252 +} 1.2253 + 1.2254 +/* needed from sctp_usrreq.c */ 1.2255 +int 1.2256 +sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, 1.2257 + void *p); 1.2258 + 1.2259 +int 1.2260 +usrsctp_getsockopt(struct socket *so, int level, int option_name, 1.2261 + void *option_value, socklen_t *option_len) 1.2262 +{ 1.2263 + if (so == NULL) { 1.2264 + errno = EBADF; 1.2265 + return (-1); 1.2266 + } 1.2267 + if (option_len == NULL) { 1.2268 + errno = EFAULT; 1.2269 + return (-1); 1.2270 + } 1.2271 + switch (level) { 1.2272 + case SOL_SOCKET: 1.2273 + switch (option_name) { 1.2274 + case SO_RCVBUF: 1.2275 + if (*option_len < (socklen_t)sizeof(int)) { 1.2276 + errno = EINVAL; 1.2277 + return (-1); 1.2278 + } else { 1.2279 + int *buf_size; 1.2280 + 1.2281 + buf_size = (int *)option_value; 1.2282 + *buf_size = so->so_rcv.sb_hiwat;; 1.2283 + *option_len = (socklen_t)sizeof(int); 1.2284 + return (0); 1.2285 + } 1.2286 + break; 1.2287 + case SO_SNDBUF: 1.2288 + if (*option_len < (socklen_t)sizeof(int)) { 1.2289 + errno = EINVAL; 1.2290 + return (-1); 1.2291 + } else { 1.2292 + int *buf_size; 1.2293 + 1.2294 + buf_size = (int *)option_value; 1.2295 + *buf_size = so->so_snd.sb_hiwat; 1.2296 + *option_len = (socklen_t)sizeof(int); 1.2297 + return (0); 1.2298 + } 1.2299 + break; 1.2300 + case SO_LINGER: 1.2301 + if (*option_len < (socklen_t)sizeof(struct linger)) { 1.2302 + errno = EINVAL; 1.2303 + return (-1); 1.2304 + } else { 1.2305 + struct linger *l; 1.2306 + 1.2307 + l = (struct linger *)option_value; 1.2308 + l->l_linger = so->so_linger; 1.2309 + if (so->so_options & SCTP_SO_LINGER) { 1.2310 + l->l_onoff = 1; 1.2311 + } else { 1.2312 + l->l_onoff = 0; 1.2313 + } 1.2314 + *option_len = (socklen_t)sizeof(struct linger); 1.2315 + return (0); 1.2316 + } 1.2317 + default: 1.2318 + errno = EINVAL; 1.2319 + return (-1); 1.2320 + } 1.2321 + case IPPROTO_SCTP: 1.2322 + { 1.2323 + size_t len; 1.2324 + 1.2325 + len = (size_t)*option_len; 1.2326 + errno = sctp_getopt(so, option_name, option_value, &len, NULL); 1.2327 + *option_len = (socklen_t)len; 1.2328 + if (errno) { 1.2329 + return (-1); 1.2330 + } else { 1.2331 + return (0); 1.2332 + } 1.2333 + } 1.2334 + default: 1.2335 + errno = ENOPROTOOPT; 1.2336 + return (-1); 1.2337 + } 1.2338 +} 1.2339 + 1.2340 +int 1.2341 +userspace_getsockopt(struct socket *so, int level, int option_name, 1.2342 + void *option_value, socklen_t *option_len) 1.2343 +{ 1.2344 + return (usrsctp_getsockopt(so, level, option_name, option_value, option_len)); 1.2345 +} 1.2346 + 1.2347 +int 1.2348 +usrsctp_bindx(struct socket *so, struct sockaddr *addrs, int addrcnt, int flags) 1.2349 +{ 1.2350 + struct sctp_getaddresses *gaddrs; 1.2351 + struct sockaddr *sa; 1.2352 +#ifdef INET 1.2353 + struct sockaddr_in *sin; 1.2354 +#endif 1.2355 +#ifdef INET6 1.2356 + struct sockaddr_in6 *sin6; 1.2357 +#endif 1.2358 + int i; 1.2359 + size_t argsz; 1.2360 +#if defined(INET) || defined(INET6) 1.2361 + uint16_t sport = 0; 1.2362 +#endif 1.2363 + 1.2364 + /* validate the flags */ 1.2365 + if ((flags != SCTP_BINDX_ADD_ADDR) && 1.2366 + (flags != SCTP_BINDX_REM_ADDR)) { 1.2367 + errno = EFAULT; 1.2368 + return (-1); 1.2369 + } 1.2370 + /* validate the address count and list */ 1.2371 + if ((addrcnt <= 0) || (addrs == NULL)) { 1.2372 + errno = EINVAL; 1.2373 + return (-1); 1.2374 + } 1.2375 + /* First pre-screen the addresses */ 1.2376 + sa = addrs; 1.2377 + for (i = 0; i < addrcnt; i++) { 1.2378 + switch (sa->sa_family) { 1.2379 +#ifdef INET 1.2380 + case AF_INET: 1.2381 +#ifdef HAVE_SA_LEN 1.2382 + if (sa->sa_len != sizeof(struct sockaddr_in)) { 1.2383 + errno = EINVAL; 1.2384 + return (-1); 1.2385 + } 1.2386 +#endif 1.2387 + sin = (struct sockaddr_in *)sa; 1.2388 + if (sin->sin_port) { 1.2389 + /* non-zero port, check or save */ 1.2390 + if (sport) { 1.2391 + /* Check against our port */ 1.2392 + if (sport != sin->sin_port) { 1.2393 + errno = EINVAL; 1.2394 + return (-1); 1.2395 + } 1.2396 + } else { 1.2397 + /* save off the port */ 1.2398 + sport = sin->sin_port; 1.2399 + } 1.2400 + } 1.2401 +#ifndef HAVE_SA_LEN 1.2402 + sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in)); 1.2403 +#endif 1.2404 + break; 1.2405 +#endif 1.2406 +#ifdef INET6 1.2407 + case AF_INET6: 1.2408 +#ifdef HAVE_SA_LEN 1.2409 + if (sa->sa_len != sizeof(struct sockaddr_in6)) { 1.2410 + errno = EINVAL; 1.2411 + return (-1); 1.2412 + } 1.2413 +#endif 1.2414 + sin6 = (struct sockaddr_in6 *)sa; 1.2415 + if (sin6->sin6_port) { 1.2416 + /* non-zero port, check or save */ 1.2417 + if (sport) { 1.2418 + /* Check against our port */ 1.2419 + if (sport != sin6->sin6_port) { 1.2420 + errno = EINVAL; 1.2421 + return (-1); 1.2422 + } 1.2423 + } else { 1.2424 + /* save off the port */ 1.2425 + sport = sin6->sin6_port; 1.2426 + } 1.2427 + } 1.2428 +#ifndef HAVE_SA_LEN 1.2429 + sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6)); 1.2430 +#endif 1.2431 + break; 1.2432 +#endif 1.2433 + default: 1.2434 + /* Invalid address family specified. */ 1.2435 + errno = EAFNOSUPPORT; 1.2436 + return (-1); 1.2437 + } 1.2438 +#ifdef HAVE_SA_LEN 1.2439 + sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len); 1.2440 +#endif 1.2441 + } 1.2442 + argsz = sizeof(struct sctp_getaddresses) + 1.2443 + sizeof(struct sockaddr_storage); 1.2444 + if ((gaddrs = (struct sctp_getaddresses *)malloc(argsz)) == NULL) { 1.2445 + errno = ENOMEM; 1.2446 + return (-1); 1.2447 + } 1.2448 + sa = addrs; 1.2449 + for (i = 0; i < addrcnt; i++) { 1.2450 +#ifndef HAVE_SA_LEN 1.2451 + size_t sa_len; 1.2452 +#endif 1.2453 + memset(gaddrs, 0, argsz); 1.2454 + gaddrs->sget_assoc_id = 0; 1.2455 +#ifdef HAVE_SA_LEN 1.2456 + memcpy(gaddrs->addr, sa, sa->sa_len); 1.2457 + if (usrsctp_setsockopt(so, IPPROTO_SCTP, flags, gaddrs, (socklen_t)argsz) != 0) { 1.2458 + free(gaddrs); 1.2459 + return (-1); 1.2460 + } 1.2461 + sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len); 1.2462 +#else 1.2463 + switch (sa->sa_family) { 1.2464 +#ifdef INET 1.2465 + case AF_INET: 1.2466 + sa_len = sizeof(struct sockaddr_in); 1.2467 + break; 1.2468 +#endif 1.2469 +#ifdef INET6 1.2470 + case AF_INET6: 1.2471 + sa_len = sizeof(struct sockaddr_in6); 1.2472 + break; 1.2473 +#endif 1.2474 + default: 1.2475 + sa_len = 0; 1.2476 + break; 1.2477 + } 1.2478 + memcpy(gaddrs->addr, sa, sa_len); 1.2479 + /* 1.2480 + * Now, if there was a port mentioned, assure that the 1.2481 + * first address has that port to make sure it fails or 1.2482 + * succeeds correctly. 1.2483 + */ 1.2484 + if ((i == 0) && (sport != 0)) { 1.2485 + switch (gaddrs->addr->sa_family) { 1.2486 +#ifdef INET 1.2487 + case AF_INET: 1.2488 + sin = (struct sockaddr_in *)gaddrs->addr; 1.2489 + sin->sin_port = sport; 1.2490 + break; 1.2491 +#endif 1.2492 +#ifdef INET6 1.2493 + case AF_INET6: 1.2494 + sin6 = (struct sockaddr_in6 *)gaddrs->addr; 1.2495 + sin6->sin6_port = sport; 1.2496 + break; 1.2497 +#endif 1.2498 + } 1.2499 + } 1.2500 + if (usrsctp_setsockopt(so, IPPROTO_SCTP, flags, gaddrs, (socklen_t)argsz) != 0) { 1.2501 + free(gaddrs); 1.2502 + return (-1); 1.2503 + } 1.2504 + sa = (struct sockaddr *)((caddr_t)sa + sa_len); 1.2505 +#endif 1.2506 + } 1.2507 + free(gaddrs); 1.2508 + return (0); 1.2509 +} 1.2510 + 1.2511 +int 1.2512 +usrsctp_connectx(struct socket *so, 1.2513 + const struct sockaddr *addrs, int addrcnt, 1.2514 + sctp_assoc_t *id) 1.2515 +{ 1.2516 +#if defined(INET) || defined(INET6) 1.2517 + char buf[SCTP_STACK_BUF_SIZE]; 1.2518 + int i, ret, cnt, *aa; 1.2519 + char *cpto; 1.2520 + const struct sockaddr *at; 1.2521 + sctp_assoc_t *p_id; 1.2522 + size_t len = sizeof(int); 1.2523 + 1.2524 + /* validate the address count and list */ 1.2525 + if ((addrs == NULL) || (addrcnt <= 0)) { 1.2526 + errno = EINVAL; 1.2527 + return (-1); 1.2528 + } 1.2529 + at = addrs; 1.2530 + cnt = 0; 1.2531 + cpto = ((caddr_t)buf + sizeof(int)); 1.2532 + /* validate all the addresses and get the size */ 1.2533 + for (i = 0; i < addrcnt; i++) { 1.2534 + switch (at->sa_family) { 1.2535 +#ifdef INET 1.2536 + case AF_INET: 1.2537 +#ifdef HAVE_SA_LEN 1.2538 + if (at->sa_len != sizeof(struct sockaddr_in)) { 1.2539 + errno = EINVAL; 1.2540 + return (-1); 1.2541 + } 1.2542 +#endif 1.2543 + memcpy(cpto, at, sizeof(struct sockaddr_in)); 1.2544 + cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in)); 1.2545 + len += sizeof(struct sockaddr_in); 1.2546 + at = (struct sockaddr *)((caddr_t)at + sizeof(struct sockaddr_in)); 1.2547 + break; 1.2548 +#endif 1.2549 +#ifdef INET6 1.2550 + case AF_INET6: 1.2551 +#ifdef HAVE_SA_LEN 1.2552 + if (at->sa_len != sizeof(struct sockaddr_in6)) { 1.2553 + errno = EINVAL; 1.2554 + return (-1); 1.2555 + } 1.2556 +#endif 1.2557 + if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)at)->sin6_addr)) { 1.2558 + in6_sin6_2_sin((struct sockaddr_in *)cpto, (struct sockaddr_in6 *)at); 1.2559 + cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in)); 1.2560 + len += sizeof(struct sockaddr_in); 1.2561 + } else { 1.2562 + memcpy(cpto, at, sizeof(struct sockaddr_in6)); 1.2563 + cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in6)); 1.2564 + len += sizeof(struct sockaddr_in6); 1.2565 + } 1.2566 + at = (struct sockaddr *)((caddr_t)at + sizeof(struct sockaddr_in6)); 1.2567 + break; 1.2568 +#endif 1.2569 + default: 1.2570 + errno = EINVAL; 1.2571 + return (-1); 1.2572 + } 1.2573 + if (len > (sizeof(buf) - sizeof(int))) { 1.2574 + /* Never enough memory */ 1.2575 + errno = E2BIG; 1.2576 + return (-1); 1.2577 + } 1.2578 + cnt++; 1.2579 + } 1.2580 + /* do we have any? */ 1.2581 + if (cnt == 0) { 1.2582 + errno = EINVAL; 1.2583 + return (-1); 1.2584 + } 1.2585 + aa = (int *)buf; 1.2586 + *aa = cnt; 1.2587 + ret = usrsctp_setsockopt(so, IPPROTO_SCTP, SCTP_CONNECT_X, (void *)buf, (socklen_t)len); 1.2588 + if ((ret == 0) && id) { 1.2589 + p_id = (sctp_assoc_t *)buf; 1.2590 + *id = *p_id; 1.2591 + } 1.2592 + return (ret); 1.2593 +#else 1.2594 + errno = EINVAL; 1.2595 + return (-1); 1.2596 +#endif 1.2597 +} 1.2598 + 1.2599 +int 1.2600 +usrsctp_getpaddrs(struct socket *so, sctp_assoc_t id, struct sockaddr **raddrs) 1.2601 +{ 1.2602 + struct sctp_getaddresses *addrs; 1.2603 + struct sockaddr *sa; 1.2604 + sctp_assoc_t asoc; 1.2605 + caddr_t lim; 1.2606 + socklen_t opt_len; 1.2607 + int cnt; 1.2608 + 1.2609 + if (raddrs == NULL) { 1.2610 + errno = EFAULT; 1.2611 + return (-1); 1.2612 + } 1.2613 + asoc = id; 1.2614 + opt_len = (socklen_t)sizeof(sctp_assoc_t); 1.2615 + if (usrsctp_getsockopt(so, IPPROTO_SCTP, SCTP_GET_REMOTE_ADDR_SIZE, &asoc, &opt_len) != 0) { 1.2616 + return (-1); 1.2617 + } 1.2618 + /* size required is returned in 'asoc' */ 1.2619 + opt_len = (socklen_t)((size_t)asoc + sizeof(struct sctp_getaddresses)); 1.2620 + addrs = calloc(1, (size_t)opt_len); 1.2621 + if (addrs == NULL) { 1.2622 + errno = ENOMEM; 1.2623 + return (-1); 1.2624 + } 1.2625 + addrs->sget_assoc_id = id; 1.2626 + /* Now lets get the array of addresses */ 1.2627 + if (usrsctp_getsockopt(so, IPPROTO_SCTP, SCTP_GET_PEER_ADDRESSES, addrs, &opt_len) != 0) { 1.2628 + free(addrs); 1.2629 + return (-1); 1.2630 + } 1.2631 + *raddrs = (struct sockaddr *)&addrs->addr[0]; 1.2632 + cnt = 0; 1.2633 + sa = (struct sockaddr *)&addrs->addr[0]; 1.2634 + lim = (caddr_t)addrs + opt_len; 1.2635 +#ifdef HAVE_SA_LEN 1.2636 + while (((caddr_t)sa < lim) && (sa->sa_len > 0)) { 1.2637 + sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len); 1.2638 +#else 1.2639 + while ((caddr_t)sa < lim) { 1.2640 + switch (sa->sa_family) { 1.2641 +#ifdef INET 1.2642 + case AF_INET: 1.2643 + sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in)); 1.2644 + break; 1.2645 +#endif 1.2646 +#ifdef INET6 1.2647 + case AF_INET6: 1.2648 + sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6)); 1.2649 + break; 1.2650 +#endif 1.2651 + case AF_CONN: 1.2652 + sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_conn)); 1.2653 + break; 1.2654 + default: 1.2655 + return (cnt); 1.2656 + break; 1.2657 + } 1.2658 +#endif 1.2659 + cnt++; 1.2660 + } 1.2661 + return (cnt); 1.2662 +} 1.2663 + 1.2664 +void 1.2665 +usrsctp_freepaddrs(struct sockaddr *addrs) 1.2666 +{ 1.2667 + /* Take away the hidden association id */ 1.2668 + void *fr_addr; 1.2669 + 1.2670 + fr_addr = (void *)((caddr_t)addrs - sizeof(sctp_assoc_t)); 1.2671 + /* Now free it */ 1.2672 + free(fr_addr); 1.2673 +} 1.2674 + 1.2675 +int 1.2676 +usrsctp_getladdrs(struct socket *so, sctp_assoc_t id, struct sockaddr **raddrs) 1.2677 +{ 1.2678 + struct sctp_getaddresses *addrs; 1.2679 + caddr_t lim; 1.2680 + struct sockaddr *sa; 1.2681 + size_t size_of_addresses; 1.2682 + socklen_t opt_len; 1.2683 + int cnt; 1.2684 + 1.2685 + if (raddrs == NULL) { 1.2686 + errno = EFAULT; 1.2687 + return (-1); 1.2688 + } 1.2689 + size_of_addresses = 0; 1.2690 + opt_len = (socklen_t)sizeof(int); 1.2691 + if (usrsctp_getsockopt(so, IPPROTO_SCTP, SCTP_GET_LOCAL_ADDR_SIZE, &size_of_addresses, &opt_len) != 0) { 1.2692 + errno = ENOMEM; 1.2693 + return (-1); 1.2694 + } 1.2695 + if (size_of_addresses == 0) { 1.2696 + errno = ENOTCONN; 1.2697 + return (-1); 1.2698 + } 1.2699 + opt_len = (socklen_t)(size_of_addresses + 1.2700 + sizeof(struct sockaddr_storage) + 1.2701 + sizeof(struct sctp_getaddresses)); 1.2702 + addrs = calloc(1, (size_t)opt_len); 1.2703 + if (addrs == NULL) { 1.2704 + errno = ENOMEM; 1.2705 + return (-1); 1.2706 + } 1.2707 + addrs->sget_assoc_id = id; 1.2708 + /* Now lets get the array of addresses */ 1.2709 + if (usrsctp_getsockopt(so, IPPROTO_SCTP, SCTP_GET_LOCAL_ADDRESSES, addrs, &opt_len) != 0) { 1.2710 + free(addrs); 1.2711 + errno = ENOMEM; 1.2712 + return (-1); 1.2713 + } 1.2714 + *raddrs = (struct sockaddr *)&addrs->addr[0]; 1.2715 + cnt = 0; 1.2716 + sa = (struct sockaddr *)&addrs->addr[0]; 1.2717 + lim = (caddr_t)addrs + opt_len; 1.2718 +#ifdef HAVE_SA_LEN 1.2719 + while (((caddr_t)sa < lim) && (sa->sa_len > 0)) { 1.2720 + sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len); 1.2721 +#else 1.2722 + while ((caddr_t)sa < lim) { 1.2723 + switch (sa->sa_family) { 1.2724 +#ifdef INET 1.2725 + case AF_INET: 1.2726 + sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in)); 1.2727 + break; 1.2728 +#endif 1.2729 +#ifdef INET6 1.2730 + case AF_INET6: 1.2731 + sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6)); 1.2732 + break; 1.2733 +#endif 1.2734 + case AF_CONN: 1.2735 + sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_conn)); 1.2736 + break; 1.2737 + default: 1.2738 + return (cnt); 1.2739 + break; 1.2740 + } 1.2741 +#endif 1.2742 + cnt++; 1.2743 + } 1.2744 + return (cnt); 1.2745 +} 1.2746 + 1.2747 +void 1.2748 +usrsctp_freeladdrs(struct sockaddr *addrs) 1.2749 +{ 1.2750 + /* Take away the hidden association id */ 1.2751 + void *fr_addr; 1.2752 + 1.2753 + fr_addr = (void *)((caddr_t)addrs - sizeof(sctp_assoc_t)); 1.2754 + /* Now free it */ 1.2755 + free(fr_addr); 1.2756 +} 1.2757 + 1.2758 +#ifdef INET 1.2759 +void 1.2760 +sctp_userspace_ip_output(int *result, struct mbuf *o_pak, 1.2761 + sctp_route_t *ro, void *stcb, 1.2762 + uint32_t vrf_id) 1.2763 +{ 1.2764 + struct mbuf *m; 1.2765 + struct mbuf *m_orig; 1.2766 + int iovcnt; 1.2767 + int send_len; 1.2768 + int len; 1.2769 + int send_count; 1.2770 + struct ip *ip; 1.2771 + struct udphdr *udp; 1.2772 +#if !defined (__Userspace_os_Windows) 1.2773 + int res; 1.2774 +#endif 1.2775 + struct sockaddr_in dst; 1.2776 +#if defined (__Userspace_os_Windows) 1.2777 + WSAMSG win_msg_hdr; 1.2778 + int win_sent_len; 1.2779 + WSABUF send_iovec[MAXLEN_MBUF_CHAIN]; 1.2780 + WSABUF winbuf; 1.2781 +#else 1.2782 + struct iovec send_iovec[MAXLEN_MBUF_CHAIN]; 1.2783 + struct msghdr msg_hdr; 1.2784 +#endif 1.2785 + int use_udp_tunneling; 1.2786 + 1.2787 + *result = 0; 1.2788 + send_count = 0; 1.2789 + 1.2790 + m = SCTP_HEADER_TO_CHAIN(o_pak); 1.2791 + m_orig = m; 1.2792 + 1.2793 + len = sizeof(struct ip); 1.2794 + if (SCTP_BUF_LEN(m) < len) { 1.2795 + if ((m = m_pullup(m, len)) == 0) { 1.2796 + SCTP_PRINTF("Can not get the IP header in the first mbuf.\n"); 1.2797 + return; 1.2798 + } 1.2799 + } 1.2800 + ip = mtod(m, struct ip *); 1.2801 + use_udp_tunneling = (ip->ip_p == IPPROTO_UDP); 1.2802 + 1.2803 + if (use_udp_tunneling) { 1.2804 + len = sizeof(struct ip) + sizeof(struct udphdr); 1.2805 + if (SCTP_BUF_LEN(m) < len) { 1.2806 + if ((m = m_pullup(m, len)) == 0) { 1.2807 + SCTP_PRINTF("Can not get the UDP/IP header in the first mbuf.\n"); 1.2808 + return; 1.2809 + } 1.2810 + ip = mtod(m, struct ip *); 1.2811 + } 1.2812 + udp = (struct udphdr *)(ip + 1); 1.2813 + } else { 1.2814 + udp = NULL; 1.2815 + } 1.2816 + 1.2817 + if (!use_udp_tunneling) { 1.2818 + if (ip->ip_src.s_addr == INADDR_ANY) { 1.2819 + /* TODO get addr of outgoing interface */ 1.2820 + SCTP_PRINTF("Why did the SCTP implementation did not choose a source address?\n"); 1.2821 + } 1.2822 + /* TODO need to worry about ro->ro_dst as in ip_output? */ 1.2823 +#if defined(__Userspace_os_Linux) || defined (__Userspace_os_Windows) 1.2824 + /* need to put certain fields into network order for Linux */ 1.2825 + ip->ip_len = htons(ip->ip_len); 1.2826 + ip->ip_off = 0; 1.2827 +#endif 1.2828 + } 1.2829 + 1.2830 + memset((void *)&dst, 0, sizeof(struct sockaddr_in)); 1.2831 + dst.sin_family = AF_INET; 1.2832 + dst.sin_addr.s_addr = ip->ip_dst.s_addr; 1.2833 +#ifdef HAVE_SIN_LEN 1.2834 + dst.sin_len = sizeof(struct sockaddr_in); 1.2835 +#endif 1.2836 + if (use_udp_tunneling) { 1.2837 + dst.sin_port = udp->uh_dport; 1.2838 + } else { 1.2839 + dst.sin_port = 0; 1.2840 + } 1.2841 + 1.2842 + /* tweak the mbuf chain */ 1.2843 + if (use_udp_tunneling) { 1.2844 + m_adj(m, sizeof(struct ip) + sizeof(struct udphdr)); 1.2845 + } 1.2846 + 1.2847 + send_len = SCTP_HEADER_LEN(m); /* length of entire packet */ 1.2848 + send_count = 0; 1.2849 + for (iovcnt = 0; m != NULL && iovcnt < MAXLEN_MBUF_CHAIN; m = m->m_next, iovcnt++) { 1.2850 +#if !defined (__Userspace_os_Windows) 1.2851 + send_iovec[iovcnt].iov_base = (caddr_t)m->m_data; 1.2852 + send_iovec[iovcnt].iov_len = SCTP_BUF_LEN(m); 1.2853 + send_count += send_iovec[iovcnt].iov_len; 1.2854 +#else 1.2855 + send_iovec[iovcnt].buf = (caddr_t)m->m_data; 1.2856 + send_iovec[iovcnt].len = SCTP_BUF_LEN(m); 1.2857 + send_count += send_iovec[iovcnt].len; 1.2858 +#endif 1.2859 + } 1.2860 + 1.2861 + if (m != NULL) { 1.2862 + SCTP_PRINTF("mbuf chain couldn't be copied completely\n"); 1.2863 + goto free_mbuf; 1.2864 + } 1.2865 + 1.2866 +#if !defined (__Userspace_os_Windows) 1.2867 + msg_hdr.msg_name = (struct sockaddr *) &dst; 1.2868 + msg_hdr.msg_namelen = sizeof(struct sockaddr_in); 1.2869 + msg_hdr.msg_iov = send_iovec; 1.2870 + msg_hdr.msg_iovlen = iovcnt; 1.2871 + msg_hdr.msg_control = NULL; 1.2872 + msg_hdr.msg_controllen = 0; 1.2873 + msg_hdr.msg_flags = 0; 1.2874 + 1.2875 + if ((!use_udp_tunneling) && (SCTP_BASE_VAR(userspace_rawsctp) > -1)) { 1.2876 + if ((res = sendmsg(SCTP_BASE_VAR(userspace_rawsctp), &msg_hdr, MSG_DONTWAIT)) != send_len) { 1.2877 + *result = errno; 1.2878 + } 1.2879 + } 1.2880 + if ((use_udp_tunneling) && (SCTP_BASE_VAR(userspace_udpsctp) > -1)) { 1.2881 + if ((res = sendmsg(SCTP_BASE_VAR(userspace_udpsctp), &msg_hdr, MSG_DONTWAIT)) != send_len) { 1.2882 + *result = errno; 1.2883 + } 1.2884 + } 1.2885 +#else 1.2886 + win_msg_hdr.name = (struct sockaddr *) &dst; 1.2887 + win_msg_hdr.namelen = sizeof(struct sockaddr_in); 1.2888 + win_msg_hdr.lpBuffers = (LPWSABUF)send_iovec; 1.2889 + win_msg_hdr.dwBufferCount = iovcnt; 1.2890 + winbuf.len = 0; 1.2891 + winbuf.buf = NULL; 1.2892 + win_msg_hdr.Control = winbuf; 1.2893 + win_msg_hdr.dwFlags = 0; 1.2894 + 1.2895 + if ((!use_udp_tunneling) && (SCTP_BASE_VAR(userspace_rawsctp) > -1)) { 1.2896 + 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) { 1.2897 + *result = WSAGetLastError(); 1.2898 + } else if (win_sent_len != send_len) { 1.2899 + *result = WSAGetLastError(); 1.2900 + } 1.2901 + } 1.2902 + if ((use_udp_tunneling) && (SCTP_BASE_VAR(userspace_udpsctp) > -1)) { 1.2903 + 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) { 1.2904 + *result = WSAGetLastError(); 1.2905 + } else if (win_sent_len != send_len) { 1.2906 + *result = WSAGetLastError(); 1.2907 + } 1.2908 + } 1.2909 +#endif 1.2910 +free_mbuf: 1.2911 + sctp_m_freem(m_orig); 1.2912 +} 1.2913 +#endif 1.2914 + 1.2915 +#if defined (INET6) 1.2916 +void sctp_userspace_ip6_output(int *result, struct mbuf *o_pak, 1.2917 + struct route_in6 *ro, void *stcb, 1.2918 + uint32_t vrf_id) 1.2919 +{ 1.2920 + struct mbuf *m; 1.2921 + struct mbuf *m_orig; 1.2922 + int iovcnt; 1.2923 + int send_len; 1.2924 + int len; 1.2925 + int send_count; 1.2926 + struct ip6_hdr *ip6; 1.2927 + struct udphdr *udp; 1.2928 +#if !defined (__Userspace_os_Windows) 1.2929 + int res; 1.2930 +#endif 1.2931 + struct sockaddr_in6 dst; 1.2932 +#if defined (__Userspace_os_Windows) 1.2933 + WSAMSG win_msg_hdr; 1.2934 + int win_sent_len; 1.2935 + WSABUF send_iovec[MAXLEN_MBUF_CHAIN]; 1.2936 + WSABUF winbuf; 1.2937 +#else 1.2938 + struct iovec send_iovec[MAXLEN_MBUF_CHAIN]; 1.2939 + struct msghdr msg_hdr; 1.2940 +#endif 1.2941 + int use_udp_tunneling; 1.2942 + 1.2943 + *result = 0; 1.2944 + send_count = 0; 1.2945 + 1.2946 + m = SCTP_HEADER_TO_CHAIN(o_pak); 1.2947 + m_orig = m; 1.2948 + 1.2949 + len = sizeof(struct ip6_hdr); 1.2950 + 1.2951 + if (SCTP_BUF_LEN(m) < len) { 1.2952 + if ((m = m_pullup(m, len)) == 0) { 1.2953 + SCTP_PRINTF("Can not get the IP header in the first mbuf.\n"); 1.2954 + return; 1.2955 + } 1.2956 + } 1.2957 + 1.2958 + ip6 = mtod(m, struct ip6_hdr *); 1.2959 + use_udp_tunneling = (ip6->ip6_nxt == IPPROTO_UDP); 1.2960 + 1.2961 + if (use_udp_tunneling) { 1.2962 + len = sizeof(struct ip6_hdr) + sizeof(struct udphdr); 1.2963 + if (SCTP_BUF_LEN(m) < len) { 1.2964 + if ((m = m_pullup(m, len)) == 0) { 1.2965 + SCTP_PRINTF("Can not get the UDP/IP header in the first mbuf.\n"); 1.2966 + return; 1.2967 + } 1.2968 + ip6 = mtod(m, struct ip6_hdr *); 1.2969 + } 1.2970 + udp = (struct udphdr *)(ip6 + 1); 1.2971 + } else { 1.2972 + udp = NULL; 1.2973 + } 1.2974 + 1.2975 + if (!use_udp_tunneling) { 1.2976 + if (ip6->ip6_src.s6_addr == in6addr_any.s6_addr) { 1.2977 + /* TODO get addr of outgoing interface */ 1.2978 + SCTP_PRINTF("Why did the SCTP implementation did not choose a source address?\n"); 1.2979 + } 1.2980 + /* TODO need to worry about ro->ro_dst as in ip_output? */ 1.2981 +#if defined(__Userspace_os_Linux) || defined (__Userspace_os_Windows) 1.2982 + /* need to put certain fields into network order for Linux */ 1.2983 + ip6->ip6_plen = htons(ip6->ip6_plen); 1.2984 +#endif 1.2985 + } 1.2986 + 1.2987 + memset((void *)&dst, 0, sizeof(struct sockaddr_in6)); 1.2988 + dst.sin6_family = AF_INET6; 1.2989 + dst.sin6_addr = ip6->ip6_dst; 1.2990 +#ifdef HAVE_SIN6_LEN 1.2991 + dst.sin6_len = sizeof(struct sockaddr_in6); 1.2992 +#endif 1.2993 + 1.2994 + if (use_udp_tunneling) { 1.2995 + dst.sin6_port = udp->uh_dport; 1.2996 + } else { 1.2997 + dst.sin6_port = 0; 1.2998 + } 1.2999 + 1.3000 + /* tweak the mbuf chain */ 1.3001 + if (use_udp_tunneling) { 1.3002 + m_adj(m, sizeof(struct ip6_hdr) + sizeof(struct udphdr)); 1.3003 + } else { 1.3004 + m_adj(m, sizeof(struct ip6_hdr)); 1.3005 + } 1.3006 + 1.3007 + send_len = SCTP_HEADER_LEN(m); /* length of entire packet */ 1.3008 + send_count = 0; 1.3009 + for (iovcnt = 0; m != NULL && iovcnt < MAXLEN_MBUF_CHAIN; m = m->m_next, iovcnt++) { 1.3010 +#if !defined (__Userspace_os_Windows) 1.3011 + send_iovec[iovcnt].iov_base = (caddr_t)m->m_data; 1.3012 + send_iovec[iovcnt].iov_len = SCTP_BUF_LEN(m); 1.3013 + send_count += send_iovec[iovcnt].iov_len; 1.3014 +#else 1.3015 + send_iovec[iovcnt].buf = (caddr_t)m->m_data; 1.3016 + send_iovec[iovcnt].len = SCTP_BUF_LEN(m); 1.3017 + send_count += send_iovec[iovcnt].len; 1.3018 +#endif 1.3019 + } 1.3020 + if (m != NULL) { 1.3021 + SCTP_PRINTF("mbuf chain couldn't be copied completely\n"); 1.3022 + goto free_mbuf; 1.3023 + } 1.3024 + 1.3025 +#if !defined (__Userspace_os_Windows) 1.3026 + msg_hdr.msg_name = (struct sockaddr *) &dst; 1.3027 + msg_hdr.msg_namelen = sizeof(struct sockaddr_in6); 1.3028 + msg_hdr.msg_iov = send_iovec; 1.3029 + msg_hdr.msg_iovlen = iovcnt; 1.3030 + msg_hdr.msg_control = NULL; 1.3031 + msg_hdr.msg_controllen = 0; 1.3032 + msg_hdr.msg_flags = 0; 1.3033 + 1.3034 + if ((!use_udp_tunneling) && (SCTP_BASE_VAR(userspace_rawsctp6) > -1)) { 1.3035 + if ((res = sendmsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg_hdr, MSG_DONTWAIT)) != send_len) { 1.3036 + *result = errno; 1.3037 + } 1.3038 + } 1.3039 + if ((use_udp_tunneling) && (SCTP_BASE_VAR(userspace_udpsctp6) > -1)) { 1.3040 + if ((res = sendmsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg_hdr, MSG_DONTWAIT)) != send_len) { 1.3041 + *result = errno; 1.3042 + } 1.3043 + } 1.3044 +#else 1.3045 + win_msg_hdr.name = (struct sockaddr *) &dst; 1.3046 + win_msg_hdr.namelen = sizeof(struct sockaddr_in6); 1.3047 + win_msg_hdr.lpBuffers = (LPWSABUF)send_iovec; 1.3048 + win_msg_hdr.dwBufferCount = iovcnt; 1.3049 + winbuf.len = 0; 1.3050 + winbuf.buf = NULL; 1.3051 + win_msg_hdr.Control = winbuf; 1.3052 + win_msg_hdr.dwFlags = 0; 1.3053 + 1.3054 + if ((!use_udp_tunneling) && (SCTP_BASE_VAR(userspace_rawsctp6) > -1)) { 1.3055 + if (WSASendTo(SCTP_BASE_VAR(userspace_rawsctp6), (LPWSABUF) send_iovec, iovcnt, &win_sent_len, win_msg_hdr.dwFlags, win_msg_hdr.name, (int) win_msg_hdr.namelen, NULL, NULL) != 0) { 1.3056 + *result = WSAGetLastError(); 1.3057 + } else if (win_sent_len != send_len) { 1.3058 + *result = WSAGetLastError(); 1.3059 + } 1.3060 + } 1.3061 + if ((use_udp_tunneling) && (SCTP_BASE_VAR(userspace_udpsctp6) > -1)) { 1.3062 + if (WSASendTo(SCTP_BASE_VAR(userspace_udpsctp6), (LPWSABUF) send_iovec, iovcnt, &win_sent_len, win_msg_hdr.dwFlags, win_msg_hdr.name, (int) win_msg_hdr.namelen, NULL, NULL) != 0) { 1.3063 + *result = WSAGetLastError(); 1.3064 + } else if (win_sent_len != send_len) { 1.3065 + *result = WSAGetLastError(); 1.3066 + } 1.3067 + } 1.3068 +#endif 1.3069 +free_mbuf: 1.3070 + sctp_m_freem(m_orig); 1.3071 +} 1.3072 +#endif 1.3073 + 1.3074 +void 1.3075 +usrsctp_register_address(void *addr) 1.3076 +{ 1.3077 + struct sockaddr_conn sconn; 1.3078 + 1.3079 + memset(&sconn, 0, sizeof(struct sockaddr_conn)); 1.3080 + sconn.sconn_family = AF_CONN; 1.3081 +#ifdef HAVE_SCONN_LEN 1.3082 + sconn.sconn_len = sizeof(struct sockaddr_conn); 1.3083 +#endif 1.3084 + sconn.sconn_port = 0; 1.3085 + sconn.sconn_addr = addr; 1.3086 + sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, 1.3087 + NULL, 1.3088 + 0xffffffff, 1.3089 + 0, 1.3090 + "conn", 1.3091 + NULL, 1.3092 + (struct sockaddr *)&sconn, 1.3093 + 0, 1.3094 + 0); 1.3095 +} 1.3096 + 1.3097 +void 1.3098 +usrsctp_deregister_address(void *addr) 1.3099 +{ 1.3100 + struct sockaddr_conn sconn; 1.3101 + 1.3102 + memset(&sconn, 0, sizeof(struct sockaddr_conn)); 1.3103 + sconn.sconn_family = AF_CONN; 1.3104 +#ifdef HAVE_SCONN_LEN 1.3105 + sconn.sconn_len = sizeof(struct sockaddr_conn); 1.3106 +#endif 1.3107 + sconn.sconn_port = 0; 1.3108 + sconn.sconn_addr = addr; 1.3109 + sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, 1.3110 + (struct sockaddr *)&sconn, 1.3111 + 0xffffffff, 1.3112 + "conn"); 1.3113 +} 1.3114 + 1.3115 +#define PREAMBLE_FORMAT "\n%c %02d:%02d:%02d.%06ld " 1.3116 +#define PREAMBLE_LENGTH 19 1.3117 +#define HEADER "0000 " 1.3118 +#define TRAILER "# SCTP_PACKET\n" 1.3119 + 1.3120 +char * 1.3121 +usrsctp_dumppacket(void *buf, size_t len, int outbound) 1.3122 +{ 1.3123 + size_t i, pos; 1.3124 + char *dump_buf, *packet; 1.3125 +#ifdef _WIN32 1.3126 + struct timeb tb; 1.3127 + struct tm t; 1.3128 +#else 1.3129 + struct timeval tv; 1.3130 + struct tm *t; 1.3131 + time_t sec; 1.3132 +#endif 1.3133 + 1.3134 + if ((len == 0) || (buf == NULL)) { 1.3135 + return (NULL); 1.3136 + } 1.3137 + if ((dump_buf = malloc(PREAMBLE_LENGTH + strlen(HEADER) + 3 * len + strlen(TRAILER) + 1)) == NULL) { 1.3138 + return (NULL); 1.3139 + } 1.3140 + pos = 0; 1.3141 +#ifdef _WIN32 1.3142 + ftime(&tb); 1.3143 + localtime_s(&t, &tb.time); 1.3144 + _snprintf_s(dump_buf, PREAMBLE_LENGTH + 1, PREAMBLE_LENGTH, PREAMBLE_FORMAT, 1.3145 + outbound ? 'O' : 'I', 1.3146 + t.tm_hour, t.tm_min, t.tm_sec, (long)(1000 * tb.millitm)); 1.3147 +#else 1.3148 + gettimeofday(&tv, NULL); 1.3149 + sec = (time_t)tv.tv_sec; 1.3150 + t = localtime((const time_t *)&sec); 1.3151 + snprintf(dump_buf, PREAMBLE_LENGTH + 1, PREAMBLE_FORMAT, 1.3152 + outbound ? 'O' : 'I', 1.3153 + t->tm_hour, t->tm_min, t->tm_sec, (long)tv.tv_usec); 1.3154 +#endif 1.3155 + pos += PREAMBLE_LENGTH; 1.3156 +#ifdef _WIN32 1.3157 + strncpy_s(dump_buf + pos, strlen(HEADER) + 1, HEADER, strlen(HEADER)); 1.3158 +#else 1.3159 + strcpy(dump_buf + pos, HEADER); 1.3160 +#endif 1.3161 + pos += strlen(HEADER); 1.3162 + packet = (char *)buf; 1.3163 + for (i = 0; i < len; i++) { 1.3164 + uint8_t byte, low, high; 1.3165 + 1.3166 + byte = (uint8_t)packet[i]; 1.3167 + high = byte / 16; 1.3168 + low = byte % 16; 1.3169 + dump_buf[pos++] = high < 10 ? '0' + high : 'a' + (high - 10); 1.3170 + dump_buf[pos++] = low < 10 ? '0' + low : 'a' + (low - 10); 1.3171 + dump_buf[pos++] = ' '; 1.3172 + } 1.3173 +#ifdef _WIN32 1.3174 + strncpy_s(dump_buf + pos, strlen(TRAILER) + 1, TRAILER, strlen(TRAILER)); 1.3175 +#else 1.3176 + strcpy(dump_buf + pos, TRAILER); 1.3177 +#endif 1.3178 + pos += strlen(TRAILER); 1.3179 + dump_buf[pos++] = '\0'; 1.3180 + return (dump_buf); 1.3181 +} 1.3182 + 1.3183 +void 1.3184 +usrsctp_freedumpbuffer(char *buf) 1.3185 +{ 1.3186 + free(buf); 1.3187 +} 1.3188 + 1.3189 +void 1.3190 +usrsctp_conninput(void *addr, const void *buffer, size_t length, uint8_t ecn_bits) 1.3191 +{ 1.3192 + struct sockaddr_conn src, dst; 1.3193 + struct mbuf *m; 1.3194 + struct sctphdr *sh; 1.3195 + struct sctp_chunkhdr *ch; 1.3196 + 1.3197 + SCTP_STAT_INCR(sctps_recvpackets); 1.3198 + SCTP_STAT_INCR_COUNTER64(sctps_inpackets); 1.3199 + memset(&src, 0, sizeof(struct sockaddr_conn)); 1.3200 + src.sconn_family = AF_CONN; 1.3201 +#ifdef HAVE_SCONN_LEN 1.3202 + src.sconn_len = sizeof(struct sockaddr_conn); 1.3203 +#endif 1.3204 + src.sconn_addr = addr; 1.3205 + memset(&dst, 0, sizeof(struct sockaddr_conn)); 1.3206 + dst.sconn_family = AF_CONN; 1.3207 +#ifdef HAVE_SCONN_LEN 1.3208 + dst.sconn_len = sizeof(struct sockaddr_conn); 1.3209 +#endif 1.3210 + dst.sconn_addr = addr; 1.3211 + if ((m = sctp_get_mbuf_for_msg(length, 1, M_NOWAIT, 0, MT_DATA)) == NULL) { 1.3212 + return; 1.3213 + } 1.3214 + m_copyback(m, 0, length, (caddr_t)buffer); 1.3215 + if (SCTP_BUF_LEN(m) < (int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr))) { 1.3216 + if ((m = m_pullup(m, sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr))) == NULL) { 1.3217 + SCTP_STAT_INCR(sctps_hdrops); 1.3218 + return; 1.3219 + } 1.3220 + } 1.3221 + sh = mtod(m, struct sctphdr *);; 1.3222 + ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); 1.3223 + src.sconn_port = sh->src_port; 1.3224 + dst.sconn_port = sh->dest_port; 1.3225 + sctp_common_input_processing(&m, 0, sizeof(struct sctphdr), length, 1.3226 + (struct sockaddr *)&src, 1.3227 + (struct sockaddr *)&dst, 1.3228 + sh, ch, 1.3229 +#if !defined(SCTP_WITH_NO_CSUM) 1.3230 + 1, 1.3231 +#endif 1.3232 + ecn_bits, 1.3233 + SCTP_DEFAULT_VRFID, 0); 1.3234 + if (m) { 1.3235 + sctp_m_freem(m); 1.3236 + } 1.3237 + return; 1.3238 +} 1.3239 + 1.3240 + 1.3241 +#define USRSCTP_SYSCTL_SET_DEF(__field) \ 1.3242 +void usrsctp_sysctl_set_ ## __field(uint32_t value) { \ 1.3243 + SCTP_BASE_SYSCTL(__field) = value; \ 1.3244 +} 1.3245 + 1.3246 +USRSCTP_SYSCTL_SET_DEF(sctp_sendspace) 1.3247 +USRSCTP_SYSCTL_SET_DEF(sctp_recvspace) 1.3248 +USRSCTP_SYSCTL_SET_DEF(sctp_auto_asconf) 1.3249 +USRSCTP_SYSCTL_SET_DEF(sctp_multiple_asconfs) 1.3250 +USRSCTP_SYSCTL_SET_DEF(sctp_ecn_enable) 1.3251 +USRSCTP_SYSCTL_SET_DEF(sctp_strict_sacks) 1.3252 +#if !defined(SCTP_WITH_NO_CSUM) 1.3253 +USRSCTP_SYSCTL_SET_DEF(sctp_no_csum_on_loopback) 1.3254 +#endif 1.3255 +USRSCTP_SYSCTL_SET_DEF(sctp_peer_chunk_oh) 1.3256 +USRSCTP_SYSCTL_SET_DEF(sctp_max_burst_default) 1.3257 +USRSCTP_SYSCTL_SET_DEF(sctp_max_chunks_on_queue) 1.3258 +USRSCTP_SYSCTL_SET_DEF(sctp_hashtblsize) 1.3259 +USRSCTP_SYSCTL_SET_DEF(sctp_pcbtblsize) 1.3260 +USRSCTP_SYSCTL_SET_DEF(sctp_min_split_point) 1.3261 +USRSCTP_SYSCTL_SET_DEF(sctp_chunkscale) 1.3262 +USRSCTP_SYSCTL_SET_DEF(sctp_delayed_sack_time_default) 1.3263 +USRSCTP_SYSCTL_SET_DEF(sctp_sack_freq_default) 1.3264 +USRSCTP_SYSCTL_SET_DEF(sctp_system_free_resc_limit) 1.3265 +USRSCTP_SYSCTL_SET_DEF(sctp_asoc_free_resc_limit) 1.3266 +USRSCTP_SYSCTL_SET_DEF(sctp_heartbeat_interval_default) 1.3267 +USRSCTP_SYSCTL_SET_DEF(sctp_pmtu_raise_time_default) 1.3268 +USRSCTP_SYSCTL_SET_DEF(sctp_shutdown_guard_time_default) 1.3269 +USRSCTP_SYSCTL_SET_DEF(sctp_secret_lifetime_default) 1.3270 +USRSCTP_SYSCTL_SET_DEF(sctp_rto_max_default) 1.3271 +USRSCTP_SYSCTL_SET_DEF(sctp_rto_min_default) 1.3272 +USRSCTP_SYSCTL_SET_DEF(sctp_rto_initial_default) 1.3273 +USRSCTP_SYSCTL_SET_DEF(sctp_init_rto_max_default) 1.3274 +USRSCTP_SYSCTL_SET_DEF(sctp_valid_cookie_life_default) 1.3275 +USRSCTP_SYSCTL_SET_DEF(sctp_init_rtx_max_default) 1.3276 +USRSCTP_SYSCTL_SET_DEF(sctp_assoc_rtx_max_default) 1.3277 +USRSCTP_SYSCTL_SET_DEF(sctp_path_rtx_max_default) 1.3278 +USRSCTP_SYSCTL_SET_DEF(sctp_add_more_threshold) 1.3279 +USRSCTP_SYSCTL_SET_DEF(sctp_nr_outgoing_streams_default) 1.3280 +USRSCTP_SYSCTL_SET_DEF(sctp_cmt_on_off) 1.3281 +USRSCTP_SYSCTL_SET_DEF(sctp_cmt_use_dac) 1.3282 +USRSCTP_SYSCTL_SET_DEF(sctp_nr_sack_on_off) 1.3283 +USRSCTP_SYSCTL_SET_DEF(sctp_use_cwnd_based_maxburst) 1.3284 +USRSCTP_SYSCTL_SET_DEF(sctp_asconf_auth_nochk) 1.3285 +USRSCTP_SYSCTL_SET_DEF(sctp_auth_disable) 1.3286 +USRSCTP_SYSCTL_SET_DEF(sctp_nat_friendly) 1.3287 +USRSCTP_SYSCTL_SET_DEF(sctp_L2_abc_variable) 1.3288 +USRSCTP_SYSCTL_SET_DEF(sctp_mbuf_threshold_count) 1.3289 +USRSCTP_SYSCTL_SET_DEF(sctp_do_drain) 1.3290 +USRSCTP_SYSCTL_SET_DEF(sctp_hb_maxburst) 1.3291 +USRSCTP_SYSCTL_SET_DEF(sctp_abort_if_one_2_one_hits_limit) 1.3292 +USRSCTP_SYSCTL_SET_DEF(sctp_strict_data_order) 1.3293 +USRSCTP_SYSCTL_SET_DEF(sctp_min_residual) 1.3294 +USRSCTP_SYSCTL_SET_DEF(sctp_max_retran_chunk) 1.3295 +USRSCTP_SYSCTL_SET_DEF(sctp_logging_level) 1.3296 +USRSCTP_SYSCTL_SET_DEF(sctp_default_cc_module) 1.3297 +USRSCTP_SYSCTL_SET_DEF(sctp_default_frag_interleave) 1.3298 +USRSCTP_SYSCTL_SET_DEF(sctp_mobility_base) 1.3299 +USRSCTP_SYSCTL_SET_DEF(sctp_mobility_fasthandoff) 1.3300 +USRSCTP_SYSCTL_SET_DEF(sctp_inits_include_nat_friendly) 1.3301 +USRSCTP_SYSCTL_SET_DEF(sctp_udp_tunneling_port) 1.3302 +USRSCTP_SYSCTL_SET_DEF(sctp_enable_sack_immediately) 1.3303 +USRSCTP_SYSCTL_SET_DEF(sctp_vtag_time_wait) 1.3304 +USRSCTP_SYSCTL_SET_DEF(sctp_blackhole) 1.3305 +USRSCTP_SYSCTL_SET_DEF(sctp_fr_max_burst_default) 1.3306 +USRSCTP_SYSCTL_SET_DEF(sctp_path_pf_threshold) 1.3307 +USRSCTP_SYSCTL_SET_DEF(sctp_default_ss_module) 1.3308 +USRSCTP_SYSCTL_SET_DEF(sctp_rttvar_bw) 1.3309 +USRSCTP_SYSCTL_SET_DEF(sctp_rttvar_rtt) 1.3310 +USRSCTP_SYSCTL_SET_DEF(sctp_rttvar_eqret) 1.3311 +USRSCTP_SYSCTL_SET_DEF(sctp_steady_step) 1.3312 +USRSCTP_SYSCTL_SET_DEF(sctp_use_dccc_ecn) 1.3313 +USRSCTP_SYSCTL_SET_DEF(sctp_buffer_splitting) 1.3314 +USRSCTP_SYSCTL_SET_DEF(sctp_initial_cwnd) 1.3315 +#ifdef SCTP_DEBUG 1.3316 +USRSCTP_SYSCTL_SET_DEF(sctp_debug_on) 1.3317 +#endif 1.3318 + 1.3319 +#define USRSCTP_SYSCTL_GET_DEF(__field) \ 1.3320 +uint32_t usrsctp_sysctl_get_ ## __field(void) { \ 1.3321 + return SCTP_BASE_SYSCTL(__field); \ 1.3322 +} 1.3323 + 1.3324 +USRSCTP_SYSCTL_GET_DEF(sctp_sendspace) 1.3325 +USRSCTP_SYSCTL_GET_DEF(sctp_recvspace) 1.3326 +USRSCTP_SYSCTL_GET_DEF(sctp_auto_asconf) 1.3327 +USRSCTP_SYSCTL_GET_DEF(sctp_multiple_asconfs) 1.3328 +USRSCTP_SYSCTL_GET_DEF(sctp_ecn_enable) 1.3329 +USRSCTP_SYSCTL_GET_DEF(sctp_strict_sacks) 1.3330 +#if !defined(SCTP_WITH_NO_CSUM) 1.3331 +USRSCTP_SYSCTL_GET_DEF(sctp_no_csum_on_loopback) 1.3332 +#endif 1.3333 +USRSCTP_SYSCTL_GET_DEF(sctp_peer_chunk_oh) 1.3334 +USRSCTP_SYSCTL_GET_DEF(sctp_max_burst_default) 1.3335 +USRSCTP_SYSCTL_GET_DEF(sctp_max_chunks_on_queue) 1.3336 +USRSCTP_SYSCTL_GET_DEF(sctp_hashtblsize) 1.3337 +USRSCTP_SYSCTL_GET_DEF(sctp_pcbtblsize) 1.3338 +USRSCTP_SYSCTL_GET_DEF(sctp_min_split_point) 1.3339 +USRSCTP_SYSCTL_GET_DEF(sctp_chunkscale) 1.3340 +USRSCTP_SYSCTL_GET_DEF(sctp_delayed_sack_time_default) 1.3341 +USRSCTP_SYSCTL_GET_DEF(sctp_sack_freq_default) 1.3342 +USRSCTP_SYSCTL_GET_DEF(sctp_system_free_resc_limit) 1.3343 +USRSCTP_SYSCTL_GET_DEF(sctp_asoc_free_resc_limit) 1.3344 +USRSCTP_SYSCTL_GET_DEF(sctp_heartbeat_interval_default) 1.3345 +USRSCTP_SYSCTL_GET_DEF(sctp_pmtu_raise_time_default) 1.3346 +USRSCTP_SYSCTL_GET_DEF(sctp_shutdown_guard_time_default) 1.3347 +USRSCTP_SYSCTL_GET_DEF(sctp_secret_lifetime_default) 1.3348 +USRSCTP_SYSCTL_GET_DEF(sctp_rto_max_default) 1.3349 +USRSCTP_SYSCTL_GET_DEF(sctp_rto_min_default) 1.3350 +USRSCTP_SYSCTL_GET_DEF(sctp_rto_initial_default) 1.3351 +USRSCTP_SYSCTL_GET_DEF(sctp_init_rto_max_default) 1.3352 +USRSCTP_SYSCTL_GET_DEF(sctp_valid_cookie_life_default) 1.3353 +USRSCTP_SYSCTL_GET_DEF(sctp_init_rtx_max_default) 1.3354 +USRSCTP_SYSCTL_GET_DEF(sctp_assoc_rtx_max_default) 1.3355 +USRSCTP_SYSCTL_GET_DEF(sctp_path_rtx_max_default) 1.3356 +USRSCTP_SYSCTL_GET_DEF(sctp_add_more_threshold) 1.3357 +USRSCTP_SYSCTL_GET_DEF(sctp_nr_outgoing_streams_default) 1.3358 +USRSCTP_SYSCTL_GET_DEF(sctp_cmt_on_off) 1.3359 +USRSCTP_SYSCTL_GET_DEF(sctp_cmt_use_dac) 1.3360 +USRSCTP_SYSCTL_GET_DEF(sctp_nr_sack_on_off) 1.3361 +USRSCTP_SYSCTL_GET_DEF(sctp_use_cwnd_based_maxburst) 1.3362 +USRSCTP_SYSCTL_GET_DEF(sctp_asconf_auth_nochk) 1.3363 +USRSCTP_SYSCTL_GET_DEF(sctp_auth_disable) 1.3364 +USRSCTP_SYSCTL_GET_DEF(sctp_nat_friendly) 1.3365 +USRSCTP_SYSCTL_GET_DEF(sctp_L2_abc_variable) 1.3366 +USRSCTP_SYSCTL_GET_DEF(sctp_mbuf_threshold_count) 1.3367 +USRSCTP_SYSCTL_GET_DEF(sctp_do_drain) 1.3368 +USRSCTP_SYSCTL_GET_DEF(sctp_hb_maxburst) 1.3369 +USRSCTP_SYSCTL_GET_DEF(sctp_abort_if_one_2_one_hits_limit) 1.3370 +USRSCTP_SYSCTL_GET_DEF(sctp_strict_data_order) 1.3371 +USRSCTP_SYSCTL_GET_DEF(sctp_min_residual) 1.3372 +USRSCTP_SYSCTL_GET_DEF(sctp_max_retran_chunk) 1.3373 +USRSCTP_SYSCTL_GET_DEF(sctp_logging_level) 1.3374 +USRSCTP_SYSCTL_GET_DEF(sctp_default_cc_module) 1.3375 +USRSCTP_SYSCTL_GET_DEF(sctp_default_frag_interleave) 1.3376 +USRSCTP_SYSCTL_GET_DEF(sctp_mobility_base) 1.3377 +USRSCTP_SYSCTL_GET_DEF(sctp_mobility_fasthandoff) 1.3378 +USRSCTP_SYSCTL_GET_DEF(sctp_inits_include_nat_friendly) 1.3379 +USRSCTP_SYSCTL_GET_DEF(sctp_udp_tunneling_port) 1.3380 +USRSCTP_SYSCTL_GET_DEF(sctp_enable_sack_immediately) 1.3381 +USRSCTP_SYSCTL_GET_DEF(sctp_vtag_time_wait) 1.3382 +USRSCTP_SYSCTL_GET_DEF(sctp_blackhole) 1.3383 +USRSCTP_SYSCTL_GET_DEF(sctp_fr_max_burst_default) 1.3384 +USRSCTP_SYSCTL_GET_DEF(sctp_path_pf_threshold) 1.3385 +USRSCTP_SYSCTL_GET_DEF(sctp_default_ss_module) 1.3386 +USRSCTP_SYSCTL_GET_DEF(sctp_rttvar_bw) 1.3387 +USRSCTP_SYSCTL_GET_DEF(sctp_rttvar_rtt) 1.3388 +USRSCTP_SYSCTL_GET_DEF(sctp_rttvar_eqret) 1.3389 +USRSCTP_SYSCTL_GET_DEF(sctp_steady_step) 1.3390 +USRSCTP_SYSCTL_GET_DEF(sctp_use_dccc_ecn) 1.3391 +USRSCTP_SYSCTL_GET_DEF(sctp_buffer_splitting) 1.3392 +USRSCTP_SYSCTL_GET_DEF(sctp_initial_cwnd) 1.3393 +#ifdef SCTP_DEBUG 1.3394 +USRSCTP_SYSCTL_GET_DEF(sctp_debug_on) 1.3395 +#endif 1.3396 + 1.3397 +void usrsctp_get_stat(struct sctpstat *stat) 1.3398 +{ 1.3399 + *stat = SCTP_BASE_STATS; 1.3400 +}