1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/sctp/src/user_recv_thread.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1524 @@ 1.4 +/*- 1.5 + * Copyright (c) 2009-2010 Brad Penoff 1.6 + * Copyright (c) 2009-2010 Humaira Kamal 1.7 + * Copyright (c) 2011-2012 Irene Ruengeler 1.8 + * Copyright (c) 2011-2012 Michael Tuexen 1.9 + * All rights reserved. 1.10 + * 1.11 + * Redistribution and use in source and binary forms, with or without 1.12 + * modification, are permitted provided that the following conditions 1.13 + * are met: 1.14 + * 1. Redistributions of source code must retain the above copyright 1.15 + * notice, this list of conditions and the following disclaimer. 1.16 + * 2. Redistributions in binary form must reproduce the above copyright 1.17 + * notice, this list of conditions and the following disclaimer in the 1.18 + * documentation and/or other materials provided with the distribution. 1.19 + * 1.20 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1.21 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.22 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.23 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1.24 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1.25 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1.26 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1.27 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1.28 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1.29 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1.30 + * SUCH DAMAGE. 1.31 + * 1.32 + */ 1.33 + 1.34 +#if defined(INET) || defined(INET6) 1.35 +#include <sys/types.h> 1.36 +#if !defined(__Userspace_os_Windows) 1.37 +#include <sys/socket.h> 1.38 +#include <netinet/in.h> 1.39 +#include <unistd.h> 1.40 +#include <pthread.h> 1.41 +#if !defined(__Userspace_os_DragonFly) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_NetBSD) 1.42 +#include <sys/uio.h> 1.43 +#else 1.44 +#include <user_ip6_var.h> 1.45 +#endif 1.46 +#endif 1.47 +#include <netinet/sctp_os.h> 1.48 +#include <netinet/sctp_var.h> 1.49 +#include <netinet/sctp_pcb.h> 1.50 +#include <netinet/sctp_input.h> 1.51 +#if 0 1.52 +#if defined(__Userspace_os_Linux) 1.53 +#include <linux/netlink.h> 1.54 +#ifdef HAVE_LINUX_IF_ADDR_H 1.55 +#include <linux/if_addr.h> 1.56 +#endif 1.57 +#ifdef HAVE_LINUX_RTNETLINK_H 1.58 +#include <linux/rtnetlink.h> 1.59 +#endif 1.60 +#endif 1.61 +#endif 1.62 +#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) 1.63 +#include <net/route.h> 1.64 +#endif 1.65 +/* local macros and datatypes used to get IP addresses system independently */ 1.66 +#if !defined(IP_PKTINFO ) && ! defined(IP_RECVDSTADDR) 1.67 +# error "Can't determine socket option to use to get UDP IP" 1.68 +#endif 1.69 + 1.70 +void recv_thread_destroy(void); 1.71 +#define MAXLEN_MBUF_CHAIN 32 /* What should this value be? */ 1.72 +#define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) 1.73 +#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) 1.74 +#define NEXT_SA(ap) ap = (struct sockaddr *) \ 1.75 + ((caddr_t) ap + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof (uint32_t)) : sizeof(uint32_t))) 1.76 +#endif 1.77 + 1.78 +#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) 1.79 +static void 1.80 +sctp_get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 1.81 +{ 1.82 + int i; 1.83 + 1.84 + for (i = 0; i < RTAX_MAX; i++) { 1.85 + if (addrs & (1 << i)) { 1.86 + rti_info[i] = sa; 1.87 + NEXT_SA(sa); 1.88 + } else { 1.89 + rti_info[i] = NULL; 1.90 + } 1.91 + } 1.92 +} 1.93 + 1.94 +static void 1.95 +sctp_handle_ifamsg(unsigned char type, unsigned short index, struct sockaddr *sa) 1.96 +{ 1.97 + int rc; 1.98 + struct ifaddrs *ifa, *found_ifa = NULL; 1.99 + 1.100 + /* handle only the types we want */ 1.101 + if ((type != RTM_NEWADDR) && (type != RTM_DELADDR)) { 1.102 + return; 1.103 + } 1.104 + 1.105 + rc = getifaddrs(&g_interfaces); 1.106 + if (rc != 0) { 1.107 + return; 1.108 + } 1.109 + for (ifa = g_interfaces; ifa; ifa = ifa->ifa_next) { 1.110 + if (index == if_nametoindex(ifa->ifa_name)) { 1.111 + found_ifa = ifa; 1.112 + break; 1.113 + } 1.114 + } 1.115 + if (found_ifa == NULL) { 1.116 + return; 1.117 + } 1.118 + 1.119 + switch (sa->sa_family) { 1.120 +#ifdef INET 1.121 + case AF_INET: 1.122 + ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in)); 1.123 + memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in)); 1.124 + break; 1.125 +#endif 1.126 +#ifdef INET6 1.127 + case AF_INET6: 1.128 + ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in6)); 1.129 + memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in6)); 1.130 + break; 1.131 +#endif 1.132 + default: 1.133 + SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", sa->sa_family); 1.134 + } 1.135 + 1.136 + /* relay the appropriate address change to the base code */ 1.137 + if (type == RTM_NEWADDR) { 1.138 + (void)sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, ifa, if_nametoindex(ifa->ifa_name), 1.139 + 0, 1.140 + ifa->ifa_name, 1.141 + (void *)ifa, 1.142 + ifa->ifa_addr, 1.143 + 0, 1.144 + 1); 1.145 + } else { 1.146 + sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr, 1.147 + if_nametoindex(ifa->ifa_name), 1.148 + ifa->ifa_name); 1.149 + } 1.150 +} 1.151 + 1.152 +static void * 1.153 +recv_function_route(void *arg) 1.154 +{ 1.155 + ssize_t ret; 1.156 + struct ifa_msghdr *ifa; 1.157 + char rt_buffer[1024]; 1.158 + struct sockaddr *sa, *rti_info[RTAX_MAX]; 1.159 + 1.160 + while (1) { 1.161 + bzero(rt_buffer, sizeof(rt_buffer)); 1.162 + ret = recv(SCTP_BASE_VAR(userspace_route), rt_buffer, sizeof(rt_buffer), 0); 1.163 + 1.164 + if (ret > 0) { 1.165 + ifa = (struct ifa_msghdr *) rt_buffer; 1.166 + if (ifa->ifam_type != RTM_DELADDR && ifa->ifam_type != RTM_NEWADDR) { 1.167 + continue; 1.168 + } 1.169 + sa = (struct sockaddr *) (ifa + 1); 1.170 + sctp_get_rtaddrs(ifa->ifam_addrs, sa, rti_info); 1.171 + switch (ifa->ifam_type) { 1.172 + case RTM_DELADDR: 1.173 + case RTM_NEWADDR: 1.174 + sctp_handle_ifamsg(ifa->ifam_type, ifa->ifam_index, rti_info[RTAX_IFA]); 1.175 + break; 1.176 + default: 1.177 + /* ignore this routing event */ 1.178 + break; 1.179 + } 1.180 + } 1.181 + if (ret < 0) { 1.182 + if (errno == EAGAIN) { 1.183 + continue; 1.184 + } else { 1.185 + break; 1.186 + } 1.187 + } 1.188 + } 1.189 + return (NULL); 1.190 +} 1.191 +#endif 1.192 + 1.193 +#if 0 1.194 +/* This does not yet work on Linux */ 1.195 +static void * 1.196 +recv_function_route(void *arg) 1.197 +{ 1.198 + int len; 1.199 + char buf[4096]; 1.200 + struct iovec iov = { buf, sizeof(buf) }; 1.201 + struct msghdr msg; 1.202 + struct nlmsghdr *nh; 1.203 + struct ifaddrmsg *rtmsg; 1.204 + struct rtattr *rtatp; 1.205 + struct in_addr *inp; 1.206 + struct sockaddr_nl sanl; 1.207 +#ifdef INET 1.208 + struct sockaddr_in *sa; 1.209 +#endif 1.210 +#ifdef INET6 1.211 + struct sockaddr_in6 *sa6; 1.212 +#endif 1.213 + 1.214 + for (;;) { 1.215 + memset(&sanl, 0, sizeof(sanl)); 1.216 + sanl.nl_family = AF_NETLINK; 1.217 + sanl.nl_groups = RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_IFADDR; 1.218 + memset(&msg, 0, sizeof(struct msghdr)); 1.219 + msg.msg_name = (void *)&sanl; 1.220 + msg.msg_namelen = sizeof(sanl); 1.221 + msg.msg_iov = &iov; 1.222 + msg.msg_iovlen = 1; 1.223 + msg.msg_control = NULL; 1.224 + msg.msg_controllen = 0; 1.225 + 1.226 + len = recvmsg(SCTP_BASE_VAR(userspace_route), &msg, 0); 1.227 + 1.228 + if (len < 0) { 1.229 + if (errno == EAGAIN) { 1.230 + continue; 1.231 + } else { 1.232 + break; 1.233 + } 1.234 + } 1.235 + for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len); 1.236 + nh = NLMSG_NEXT (nh, len)) { 1.237 + if (nh->nlmsg_type == NLMSG_DONE) 1.238 + break; 1.239 + 1.240 + if (nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR) { 1.241 + rtmsg = (struct ifaddrmsg *)NLMSG_DATA(nh); 1.242 + rtatp = (struct rtattr *)IFA_RTA(rtmsg); 1.243 + if(rtatp->rta_type == IFA_ADDRESS) { 1.244 + inp = (struct in_addr *)RTA_DATA(rtatp); 1.245 + switch (rtmsg->ifa_family) { 1.246 +#ifdef INET 1.247 + case AF_INET: 1.248 + sa = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in)); 1.249 + sa->sin_family = rtmsg->ifa_family; 1.250 + sa->sin_port = 0; 1.251 + memcpy(&sa->sin_addr, inp, sizeof(struct in_addr)); 1.252 + sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa); 1.253 + break; 1.254 +#endif 1.255 +#ifdef INET6 1.256 + case AF_INET6: 1.257 + sa6 = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6)); 1.258 + sa6->sin6_family = rtmsg->ifa_family; 1.259 + sa6->sin6_port = 0; 1.260 + memcpy(&sa6->sin6_addr, inp, sizeof(struct in6_addr)); 1.261 + sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa6); 1.262 + break; 1.263 +#endif 1.264 + default: 1.265 + SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", rtmsg->ifa_family); 1.266 + break; 1.267 + } 1.268 + } 1.269 + } 1.270 + } 1.271 + } 1.272 + return (NULL); 1.273 +} 1.274 +#endif 1.275 + 1.276 +#ifdef INET 1.277 +static void * 1.278 +recv_function_raw(void *arg) 1.279 +{ 1.280 + struct mbuf **recvmbuf; 1.281 + struct ip *iphdr; 1.282 + struct sctphdr *sh; 1.283 + uint16_t port; 1.284 + int offset, ecn = 0; 1.285 +#if !defined(SCTP_WITH_NO_CSUM) 1.286 + int compute_crc = 1; 1.287 +#endif 1.288 + struct sctp_chunkhdr *ch; 1.289 + struct sockaddr_in src, dst; 1.290 +#if !defined(__Userspace_os_Windows) 1.291 + struct msghdr msg; 1.292 + struct iovec recv_iovec[MAXLEN_MBUF_CHAIN]; 1.293 +#else 1.294 + WSABUF recv_iovec[MAXLEN_MBUF_CHAIN]; 1.295 + int nResult, m_ErrorCode; 1.296 + DWORD flags; 1.297 + struct sockaddr_in from; 1.298 + int fromlen; 1.299 +#endif 1.300 + 1.301 + /*Initially the entire set of mbufs is to be allocated. 1.302 + to_fill indicates this amount. */ 1.303 + int to_fill = MAXLEN_MBUF_CHAIN; 1.304 + /* iovlen is the size of each mbuf in the chain */ 1.305 + int i, n, ncounter = 0; 1.306 + int iovlen = MCLBYTES; 1.307 + int want_ext = (iovlen > MLEN)? 1 : 0; 1.308 + int want_header = 0; 1.309 + 1.310 + bzero((void *)&src, sizeof(struct sockaddr_in)); 1.311 + bzero((void *)&dst, sizeof(struct sockaddr_in)); 1.312 + 1.313 + recvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN); 1.314 + 1.315 + while (1) { 1.316 + for (i = 0; i < to_fill; i++) { 1.317 + /* Not getting the packet header. Tests with chain of one run 1.318 + as usual without having the packet header. 1.319 + Have tried both sending and receiving 1.320 + */ 1.321 + recvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA); 1.322 +#if !defined(__Userspace_os_Windows) 1.323 + recv_iovec[i].iov_base = (caddr_t)recvmbuf[i]->m_data; 1.324 + recv_iovec[i].iov_len = iovlen; 1.325 +#else 1.326 + recv_iovec[i].buf = (caddr_t)recvmbuf[i]->m_data; 1.327 + recv_iovec[i].len = iovlen; 1.328 +#endif 1.329 + } 1.330 + to_fill = 0; 1.331 +#if defined(__Userspace_os_Windows) 1.332 + flags = 0; 1.333 + ncounter = 0; 1.334 + fromlen = sizeof(struct sockaddr_in); 1.335 + bzero((void *)&from, sizeof(struct sockaddr_in)); 1.336 + 1.337 + nResult = WSARecvFrom(SCTP_BASE_VAR(userspace_rawsctp), recv_iovec, MAXLEN_MBUF_CHAIN, (LPDWORD)&ncounter, (LPDWORD)&flags, (struct sockaddr*)&from, &fromlen, NULL, NULL); 1.338 + if (nResult != 0) { 1.339 + m_ErrorCode = WSAGetLastError(); 1.340 + if (m_ErrorCode == WSAETIMEDOUT) { 1.341 + continue; 1.342 + } 1.343 + if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) { 1.344 + break; 1.345 + } 1.346 + } 1.347 + n = ncounter; 1.348 +#else 1.349 + bzero((void *)&msg, sizeof(struct msghdr)); 1.350 + msg.msg_name = NULL; 1.351 + msg.msg_namelen = 0; 1.352 + msg.msg_iov = recv_iovec; 1.353 + msg.msg_iovlen = MAXLEN_MBUF_CHAIN; 1.354 + msg.msg_control = NULL; 1.355 + msg.msg_controllen = 0; 1.356 + ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp), &msg, 0); 1.357 + if (n < 0) { 1.358 + if (errno == EAGAIN) { 1.359 + continue; 1.360 + } else { 1.361 + break; 1.362 + } 1.363 + } 1.364 +#endif 1.365 + SCTP_HEADER_LEN(recvmbuf[0]) = n; /* length of total packet */ 1.366 + SCTP_STAT_INCR(sctps_recvpackets); 1.367 + SCTP_STAT_INCR_COUNTER64(sctps_inpackets); 1.368 + 1.369 + if (n <= iovlen) { 1.370 + SCTP_BUF_LEN(recvmbuf[0]) = n; 1.371 + (to_fill)++; 1.372 + } else { 1.373 + i = 0; 1.374 + SCTP_BUF_LEN(recvmbuf[0]) = iovlen; 1.375 + 1.376 + ncounter -= iovlen; 1.377 + (to_fill)++; 1.378 + do { 1.379 + recvmbuf[i]->m_next = recvmbuf[i+1]; 1.380 + SCTP_BUF_LEN(recvmbuf[i]->m_next) = min(ncounter, iovlen); 1.381 + i++; 1.382 + ncounter -= iovlen; 1.383 + (to_fill)++; 1.384 + } while (ncounter > 0); 1.385 + } 1.386 + 1.387 + iphdr = mtod(recvmbuf[0], struct ip *); 1.388 + sh = (struct sctphdr *)((caddr_t)iphdr + sizeof(struct ip)); 1.389 + ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); 1.390 + offset = sizeof(struct ip) + sizeof(struct sctphdr); 1.391 + 1.392 + if (iphdr->ip_tos != 0) { 1.393 + ecn = iphdr->ip_tos & 0x02; 1.394 + } 1.395 + 1.396 + dst.sin_family = AF_INET; 1.397 +#ifdef HAVE_SIN_LEN 1.398 + dst.sin_len = sizeof(struct sockaddr_in); 1.399 +#endif 1.400 + dst.sin_addr = iphdr->ip_dst; 1.401 + dst.sin_port = sh->dest_port; 1.402 + 1.403 + src.sin_family = AF_INET; 1.404 +#ifdef HAVE_SIN_LEN 1.405 + src.sin_len = sizeof(struct sockaddr_in); 1.406 +#endif 1.407 + src.sin_addr = iphdr->ip_src; 1.408 + src.sin_port = sh->src_port; 1.409 + 1.410 + /* SCTP does not allow broadcasts or multicasts */ 1.411 + if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) { 1.412 + return (NULL); 1.413 + } 1.414 + if (SCTP_IS_IT_BROADCAST(dst.sin_addr, recvmbuf[0])) { 1.415 + return (NULL); 1.416 + } 1.417 + 1.418 + port = 0; 1.419 + 1.420 +#if defined(SCTP_WITH_NO_CSUM) 1.421 + SCTP_STAT_INCR(sctps_recvnocrc); 1.422 +#else 1.423 + if (src.sin_addr.s_addr == dst.sin_addr.s_addr) { 1.424 + compute_crc = 0; 1.425 + SCTP_STAT_INCR(sctps_recvnocrc); 1.426 + } else { 1.427 + SCTP_STAT_INCR(sctps_recvswcrc); 1.428 + } 1.429 +#endif 1.430 + SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n); 1.431 + SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset); 1.432 + sctp_common_input_processing(&recvmbuf[0], sizeof(struct ip), offset, n, 1.433 + (struct sockaddr *)&src, 1.434 + (struct sockaddr *)&dst, 1.435 + sh, ch, 1.436 +#if !defined(SCTP_WITH_NO_CSUM) 1.437 + compute_crc, 1.438 +#endif 1.439 + ecn, 1.440 + SCTP_DEFAULT_VRFID, port); 1.441 + if (recvmbuf[0]) { 1.442 + m_freem(recvmbuf[0]); 1.443 + } 1.444 + } 1.445 + for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) { 1.446 + m_free(recvmbuf[i]); 1.447 + } 1.448 + /* free the array itself */ 1.449 + free(recvmbuf); 1.450 + return (NULL); 1.451 +} 1.452 +#endif 1.453 + 1.454 +#if defined(INET6) 1.455 +static void * 1.456 +recv_function_raw6(void *arg) 1.457 +{ 1.458 + struct mbuf **recvmbuf6; 1.459 +#if !defined(__Userspace_os_Windows) 1.460 + struct iovec recv_iovec[MAXLEN_MBUF_CHAIN]; 1.461 + struct msghdr msg; 1.462 + struct cmsghdr *cmsgptr; 1.463 + char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))]; 1.464 +#else 1.465 + WSABUF recv_iovec[MAXLEN_MBUF_CHAIN]; 1.466 + int nResult, m_ErrorCode; 1.467 + DWORD flags; 1.468 + struct sockaddr_in6 from; 1.469 + int fromlen; 1.470 + GUID WSARecvMsg_GUID = WSAID_WSARECVMSG; 1.471 + LPFN_WSARECVMSG WSARecvMsg; 1.472 + WSACMSGHDR *cmsgptr; 1.473 + WSAMSG msg; 1.474 + char ControlBuffer[1024]; 1.475 +#endif 1.476 + struct sockaddr_in6 src, dst; 1.477 + struct sctphdr *sh; 1.478 + int offset; 1.479 + struct sctp_chunkhdr *ch; 1.480 + 1.481 + /*Initially the entire set of mbufs is to be allocated. 1.482 + to_fill indicates this amount. */ 1.483 + int to_fill = MAXLEN_MBUF_CHAIN; 1.484 + /* iovlen is the size of each mbuf in the chain */ 1.485 + int i, n, ncounter = 0; 1.486 +#if !defined(SCTP_WITH_NO_CSUM) 1.487 + int compute_crc = 1; 1.488 +#endif 1.489 + int iovlen = MCLBYTES; 1.490 + int want_ext = (iovlen > MLEN)? 1 : 0; 1.491 + int want_header = 0; 1.492 + 1.493 + recvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN); 1.494 + 1.495 + for (;;) { 1.496 + for (i = 0; i < to_fill; i++) { 1.497 + /* Not getting the packet header. Tests with chain of one run 1.498 + as usual without having the packet header. 1.499 + Have tried both sending and receiving 1.500 + */ 1.501 + recvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA); 1.502 +#if !defined(__Userspace_os_Windows) 1.503 + recv_iovec[i].iov_base = (caddr_t)recvmbuf6[i]->m_data; 1.504 + recv_iovec[i].iov_len = iovlen; 1.505 +#else 1.506 + recv_iovec[i].buf = (caddr_t)recvmbuf6[i]->m_data; 1.507 + recv_iovec[i].len = iovlen; 1.508 +#endif 1.509 + } 1.510 + to_fill = 0; 1.511 +#if defined(__Userspace_os_Windows) 1.512 + flags = 0; 1.513 + ncounter = 0; 1.514 + fromlen = sizeof(struct sockaddr_in6); 1.515 + bzero((void *)&from, sizeof(struct sockaddr_in6)); 1.516 + nResult = WSAIoctl(SCTP_BASE_VAR(userspace_rawsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER, 1.517 + &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID, 1.518 + &WSARecvMsg, sizeof WSARecvMsg, 1.519 + &ncounter, NULL, NULL); 1.520 + if (nResult == 0) { 1.521 + msg.name = (void *)&src; 1.522 + msg.namelen = sizeof(struct sockaddr_in6); 1.523 + msg.lpBuffers = recv_iovec; 1.524 + msg.dwBufferCount = MAXLEN_MBUF_CHAIN; 1.525 + msg.Control.len = sizeof ControlBuffer; 1.526 + msg.Control.buf = ControlBuffer; 1.527 + msg.dwFlags = 0; 1.528 + nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, &ncounter, NULL, NULL); 1.529 + } 1.530 + if (nResult != 0) { 1.531 + m_ErrorCode = WSAGetLastError(); 1.532 + if (m_ErrorCode == WSAETIMEDOUT) 1.533 + continue; 1.534 + if (m_ErrorCode == WSAENOTSOCK || m_ErrorCode == WSAEINTR) 1.535 + break; 1.536 + } 1.537 + n = ncounter; 1.538 +#else 1.539 + bzero((void *)&msg, sizeof(struct msghdr)); 1.540 + bzero((void *)&src, sizeof(struct sockaddr_in6)); 1.541 + bzero((void *)&dst, sizeof(struct sockaddr_in6)); 1.542 + bzero((void *)cmsgbuf, CMSG_SPACE(sizeof (struct in6_pktinfo))); 1.543 + msg.msg_name = (void *)&src; 1.544 + msg.msg_namelen = sizeof(struct sockaddr_in6); 1.545 + msg.msg_iov = recv_iovec; 1.546 + msg.msg_iovlen = MAXLEN_MBUF_CHAIN; 1.547 + msg.msg_control = (void *)cmsgbuf; 1.548 + msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof (struct in6_pktinfo)); 1.549 + msg.msg_flags = 0; 1.550 + 1.551 + ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, 0); 1.552 + if (n < 0) { 1.553 + if (errno == EAGAIN) { 1.554 + continue; 1.555 + } else { 1.556 + break; 1.557 + } 1.558 + } 1.559 +#endif 1.560 + SCTP_HEADER_LEN(recvmbuf6[0]) = n; /* length of total packet */ 1.561 + SCTP_STAT_INCR(sctps_recvpackets); 1.562 + SCTP_STAT_INCR_COUNTER64(sctps_inpackets); 1.563 + 1.564 + if (n <= iovlen) { 1.565 + SCTP_BUF_LEN(recvmbuf6[0]) = n; 1.566 + (to_fill)++; 1.567 + } else { 1.568 + i = 0; 1.569 + SCTP_BUF_LEN(recvmbuf6[0]) = iovlen; 1.570 + 1.571 + ncounter -= iovlen; 1.572 + (to_fill)++; 1.573 + do { 1.574 + recvmbuf6[i]->m_next = recvmbuf6[i+1]; 1.575 + SCTP_BUF_LEN(recvmbuf6[i]->m_next) = min(ncounter, iovlen); 1.576 + i++; 1.577 + ncounter -= iovlen; 1.578 + (to_fill)++; 1.579 + } while (ncounter > 0); 1.580 + } 1.581 + 1.582 + for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { 1.583 + if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) { 1.584 + struct in6_pktinfo * info; 1.585 + 1.586 + info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); 1.587 + memcpy((void *)&dst.sin6_addr, (const void *) &(info->ipi6_addr), sizeof(struct in6_addr)); 1.588 + break; 1.589 + } 1.590 + } 1.591 + 1.592 + sh = mtod(recvmbuf6[0], struct sctphdr *); 1.593 + ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); 1.594 + offset = sizeof(struct sctphdr); 1.595 + 1.596 + dst.sin6_family = AF_INET6; 1.597 +#ifdef HAVE_SIN6_LEN 1.598 + dst.sin6_len = sizeof(struct sockaddr_in6); 1.599 +#endif 1.600 + dst.sin6_port = sh->dest_port; 1.601 + 1.602 + src.sin6_family = AF_INET6; 1.603 +#ifdef HAVE_SIN6_LEN 1.604 + src.sin6_len = sizeof(struct sockaddr_in6); 1.605 +#endif 1.606 + src.sin6_port = sh->src_port; 1.607 +#if defined(SCTP_WITH_NO_CSUM) 1.608 + SCTP_STAT_INCR(sctps_recvnocrc); 1.609 +#else 1.610 + if (memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0) { 1.611 + compute_crc = 0; 1.612 + SCTP_STAT_INCR(sctps_recvnocrc); 1.613 + } else { 1.614 + SCTP_STAT_INCR(sctps_recvswcrc); 1.615 + } 1.616 +#endif 1.617 + SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n); 1.618 + SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset); 1.619 + sctp_common_input_processing(&recvmbuf6[0], 0, offset, n, 1.620 + (struct sockaddr *)&src, 1.621 + (struct sockaddr *)&dst, 1.622 + sh, ch, 1.623 +#if !defined(SCTP_WITH_NO_CSUM) 1.624 + compute_crc, 1.625 +#endif 1.626 + 0, 1.627 + SCTP_DEFAULT_VRFID, 0); 1.628 + if (recvmbuf6[0]) { 1.629 + m_freem(recvmbuf6[0]); 1.630 + } 1.631 + } 1.632 + for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) { 1.633 + m_free(recvmbuf6[i]); 1.634 + } 1.635 + /* free the array itself */ 1.636 + free(recvmbuf6); 1.637 + return (NULL); 1.638 +} 1.639 +#endif 1.640 + 1.641 +#ifdef INET 1.642 +static void * 1.643 +recv_function_udp(void *arg) 1.644 +{ 1.645 + struct mbuf **udprecvmbuf; 1.646 + /*Initially the entire set of mbufs is to be allocated. 1.647 + to_fill indicates this amount. */ 1.648 + int to_fill = MAXLEN_MBUF_CHAIN; 1.649 + /* iovlen is the size of each mbuf in the chain */ 1.650 + int i, n, ncounter, offset; 1.651 + int iovlen = MCLBYTES; 1.652 + int want_ext = (iovlen > MLEN)? 1 : 0; 1.653 + int want_header = 0; 1.654 + struct sctphdr *sh; 1.655 + uint16_t port; 1.656 + struct sctp_chunkhdr *ch; 1.657 + struct sockaddr_in src, dst; 1.658 +#if defined(IP_PKTINFO) 1.659 + char cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))]; 1.660 +#else 1.661 + char cmsgbuf[CMSG_SPACE(sizeof(struct in_addr))]; 1.662 +#endif 1.663 +#if !defined(SCTP_WITH_NO_CSUM) 1.664 + int compute_crc = 1; 1.665 +#endif 1.666 +#if !defined(__Userspace_os_Windows) 1.667 + struct iovec iov[MAXLEN_MBUF_CHAIN]; 1.668 + struct msghdr msg; 1.669 + struct cmsghdr *cmsgptr; 1.670 +#else 1.671 + GUID WSARecvMsg_GUID = WSAID_WSARECVMSG; 1.672 + LPFN_WSARECVMSG WSARecvMsg; 1.673 + char ControlBuffer[1024]; 1.674 + WSABUF iov[MAXLEN_MBUF_CHAIN]; 1.675 + WSAMSG msg; 1.676 + int nResult, m_ErrorCode; 1.677 + WSACMSGHDR *cmsgptr; 1.678 +#endif 1.679 + 1.680 + udprecvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN); 1.681 + 1.682 + while (1) { 1.683 + for (i = 0; i < to_fill; i++) { 1.684 + /* Not getting the packet header. Tests with chain of one run 1.685 + as usual without having the packet header. 1.686 + Have tried both sending and receiving 1.687 + */ 1.688 + udprecvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA); 1.689 +#if !defined(__Userspace_os_Windows) 1.690 + iov[i].iov_base = (caddr_t)udprecvmbuf[i]->m_data; 1.691 + iov[i].iov_len = iovlen; 1.692 +#else 1.693 + iov[i].buf = (caddr_t)udprecvmbuf[i]->m_data; 1.694 + iov[i].len = iovlen; 1.695 +#endif 1.696 + } 1.697 + to_fill = 0; 1.698 +#if !defined(__Userspace_os_Windows) 1.699 + bzero((void *)&msg, sizeof(struct msghdr)); 1.700 +#else 1.701 + bzero((void *)&msg, sizeof(WSAMSG)); 1.702 +#endif 1.703 + bzero((void *)&src, sizeof(struct sockaddr_in)); 1.704 + bzero((void *)&dst, sizeof(struct sockaddr_in)); 1.705 + bzero((void *)cmsgbuf, sizeof(cmsgbuf)); 1.706 + 1.707 +#if !defined(__Userspace_os_Windows) 1.708 + msg.msg_name = (void *)&src; 1.709 + msg.msg_namelen = sizeof(struct sockaddr_in); 1.710 + msg.msg_iov = iov; 1.711 + msg.msg_iovlen = MAXLEN_MBUF_CHAIN; 1.712 + msg.msg_control = (void *)cmsgbuf; 1.713 + msg.msg_controllen = sizeof(cmsgbuf); 1.714 + msg.msg_flags = 0; 1.715 + 1.716 + ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, 0); 1.717 + if (n < 0) { 1.718 + if (errno == EAGAIN) { 1.719 + continue; 1.720 + } else { 1.721 + break; 1.722 + } 1.723 + } 1.724 +#else 1.725 + nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp), SIO_GET_EXTENSION_FUNCTION_POINTER, 1.726 + &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID, 1.727 + &WSARecvMsg, sizeof WSARecvMsg, 1.728 + &ncounter, NULL, NULL); 1.729 + if (nResult == 0) { 1.730 + msg.name = (void *)&src; 1.731 + msg.namelen = sizeof(struct sockaddr_in); 1.732 + msg.lpBuffers = iov; 1.733 + msg.dwBufferCount = MAXLEN_MBUF_CHAIN; 1.734 + msg.Control.len = sizeof ControlBuffer; 1.735 + msg.Control.buf = ControlBuffer; 1.736 + msg.dwFlags = 0; 1.737 + nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, &ncounter, NULL, NULL); 1.738 + } 1.739 + if (nResult != 0) { 1.740 + m_ErrorCode = WSAGetLastError(); 1.741 + if (m_ErrorCode == WSAETIMEDOUT) { 1.742 + continue; 1.743 + } 1.744 + if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) { 1.745 + break; 1.746 + } 1.747 + } 1.748 + n = ncounter; 1.749 +#endif 1.750 + SCTP_HEADER_LEN(udprecvmbuf[0]) = n; /* length of total packet */ 1.751 + SCTP_STAT_INCR(sctps_recvpackets); 1.752 + SCTP_STAT_INCR_COUNTER64(sctps_inpackets); 1.753 + 1.754 + if (n <= iovlen) { 1.755 + SCTP_BUF_LEN(udprecvmbuf[0]) = n; 1.756 + (to_fill)++; 1.757 + } else { 1.758 + i = 0; 1.759 + SCTP_BUF_LEN(udprecvmbuf[0]) = iovlen; 1.760 + 1.761 + ncounter -= iovlen; 1.762 + (to_fill)++; 1.763 + do { 1.764 + udprecvmbuf[i]->m_next = udprecvmbuf[i+1]; 1.765 + SCTP_BUF_LEN(udprecvmbuf[i]->m_next) = min(ncounter, iovlen); 1.766 + i++; 1.767 + ncounter -= iovlen; 1.768 + (to_fill)++; 1.769 + } while (ncounter > 0); 1.770 + } 1.771 + 1.772 + for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { 1.773 +#if defined(IP_PKTINFO) 1.774 + if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_PKTINFO)) { 1.775 + struct in_pktinfo *info; 1.776 + 1.777 + dst.sin_family = AF_INET; 1.778 +#ifdef HAVE_SIN_LEN 1.779 + dst.sin_len = sizeof(struct sockaddr_in); 1.780 +#endif 1.781 + info = (struct in_pktinfo *)CMSG_DATA(cmsgptr); 1.782 + memcpy((void *)&dst.sin_addr, (const void *)&(info->ipi_addr), sizeof(struct in_addr)); 1.783 + break; 1.784 + } 1.785 +#else 1.786 + if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_RECVDSTADDR)) { 1.787 + struct in_addr *addr; 1.788 + 1.789 + dst.sin_family = AF_INET; 1.790 +#ifdef HAVE_SIN_LEN 1.791 + dst.sin_len = sizeof(struct sockaddr_in); 1.792 +#endif 1.793 + addr = (struct in_addr *)CMSG_DATA(cmsgptr); 1.794 + memcpy((void *)&dst.sin_addr, (const void *)addr, sizeof(struct in_addr)); 1.795 + break; 1.796 + } 1.797 +#endif 1.798 + } 1.799 + 1.800 + /* SCTP does not allow broadcasts or multicasts */ 1.801 + if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) { 1.802 + return (NULL); 1.803 + } 1.804 + if (SCTP_IS_IT_BROADCAST(dst.sin_addr, udprecvmbuf[0])) { 1.805 + return (NULL); 1.806 + } 1.807 + 1.808 + /*offset = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);*/ 1.809 + sh = mtod(udprecvmbuf[0], struct sctphdr *); 1.810 + ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); 1.811 + offset = sizeof(struct sctphdr); 1.812 + port = src.sin_port; 1.813 + src.sin_port = sh->src_port; 1.814 + dst.sin_port = sh->dest_port; 1.815 +#if defined(SCTP_WITH_NO_CSUM) 1.816 + SCTP_STAT_INCR(sctps_recvnocrc); 1.817 +#else 1.818 + if (src.sin_addr.s_addr == dst.sin_addr.s_addr) { 1.819 + compute_crc = 0; 1.820 + SCTP_STAT_INCR(sctps_recvnocrc); 1.821 + } else { 1.822 + SCTP_STAT_INCR(sctps_recvswcrc); 1.823 + } 1.824 +#endif 1.825 + SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n); 1.826 + SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset); 1.827 + sctp_common_input_processing(&udprecvmbuf[0], 0, offset, n, 1.828 + (struct sockaddr *)&src, 1.829 + (struct sockaddr *)&dst, 1.830 + sh, ch, 1.831 +#if !defined(SCTP_WITH_NO_CSUM) 1.832 + compute_crc, 1.833 +#endif 1.834 + 0, 1.835 + SCTP_DEFAULT_VRFID, port); 1.836 + if (udprecvmbuf[0]) { 1.837 + m_freem(udprecvmbuf[0]); 1.838 + } 1.839 + } 1.840 + for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) { 1.841 + m_free(udprecvmbuf[i]); 1.842 + } 1.843 + /* free the array itself */ 1.844 + free(udprecvmbuf); 1.845 + return (NULL); 1.846 +} 1.847 +#endif 1.848 + 1.849 +#if defined(INET6) 1.850 +static void * 1.851 +recv_function_udp6(void *arg) 1.852 +{ 1.853 + struct mbuf **udprecvmbuf6; 1.854 + /*Initially the entire set of mbufs is to be allocated. 1.855 + to_fill indicates this amount. */ 1.856 + int to_fill = MAXLEN_MBUF_CHAIN; 1.857 + /* iovlen is the size of each mbuf in the chain */ 1.858 + int i, n, ncounter, offset; 1.859 + int iovlen = MCLBYTES; 1.860 + int want_ext = (iovlen > MLEN)? 1 : 0; 1.861 + int want_header = 0; 1.862 + struct sockaddr_in6 src, dst; 1.863 + struct sctphdr *sh; 1.864 + uint16_t port; 1.865 + struct sctp_chunkhdr *ch; 1.866 + char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))]; 1.867 +#if !defined(SCTP_WITH_NO_CSUM) 1.868 + int compute_crc = 1; 1.869 +#endif 1.870 +#if !defined(__Userspace_os_Windows) 1.871 + struct iovec iov[MAXLEN_MBUF_CHAIN]; 1.872 + struct msghdr msg; 1.873 + struct cmsghdr *cmsgptr; 1.874 +#else 1.875 + GUID WSARecvMsg_GUID = WSAID_WSARECVMSG; 1.876 + LPFN_WSARECVMSG WSARecvMsg; 1.877 + char ControlBuffer[1024]; 1.878 + WSABUF iov[MAXLEN_MBUF_CHAIN]; 1.879 + WSAMSG msg; 1.880 + int nResult, m_ErrorCode; 1.881 + WSACMSGHDR *cmsgptr; 1.882 +#endif 1.883 + 1.884 + udprecvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN); 1.885 + while (1) { 1.886 + for (i = 0; i < to_fill; i++) { 1.887 + /* Not getting the packet header. Tests with chain of one run 1.888 + as usual without having the packet header. 1.889 + Have tried both sending and receiving 1.890 + */ 1.891 + udprecvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA); 1.892 +#if !defined(__Userspace_os_Windows) 1.893 + iov[i].iov_base = (caddr_t)udprecvmbuf6[i]->m_data; 1.894 + iov[i].iov_len = iovlen; 1.895 +#else 1.896 + iov[i].buf = (caddr_t)udprecvmbuf6[i]->m_data; 1.897 + iov[i].len = iovlen; 1.898 +#endif 1.899 + } 1.900 + to_fill = 0; 1.901 + 1.902 +#if !defined(__Userspace_os_Windows) 1.903 + bzero((void *)&msg, sizeof(struct msghdr)); 1.904 +#else 1.905 + bzero((void *)&msg, sizeof(WSAMSG)); 1.906 +#endif 1.907 + bzero((void *)&src, sizeof(struct sockaddr_in6)); 1.908 + bzero((void *)&dst, sizeof(struct sockaddr_in6)); 1.909 + bzero((void *)cmsgbuf, CMSG_SPACE(sizeof (struct in6_pktinfo))); 1.910 + 1.911 +#if !defined(__Userspace_os_Windows) 1.912 + msg.msg_name = (void *)&src; 1.913 + msg.msg_namelen = sizeof(struct sockaddr_in6); 1.914 + msg.msg_iov = iov; 1.915 + msg.msg_iovlen = MAXLEN_MBUF_CHAIN; 1.916 + msg.msg_control = (void *)cmsgbuf; 1.917 + msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof (struct in6_pktinfo)); 1.918 + msg.msg_flags = 0; 1.919 + 1.920 + ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, 0); 1.921 + if (n < 0) { 1.922 + if (errno == EAGAIN) { 1.923 + continue; 1.924 + } else { 1.925 + break; 1.926 + } 1.927 + } 1.928 +#else 1.929 + nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER, 1.930 + &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID, 1.931 + &WSARecvMsg, sizeof WSARecvMsg, 1.932 + &ncounter, NULL, NULL); 1.933 + if (nResult == SOCKET_ERROR) { 1.934 + m_ErrorCode = WSAGetLastError(); 1.935 + WSARecvMsg = NULL; 1.936 + } 1.937 + if (nResult == 0) { 1.938 + msg.name = (void *)&src; 1.939 + msg.namelen = sizeof(struct sockaddr_in6); 1.940 + msg.lpBuffers = iov; 1.941 + msg.dwBufferCount = MAXLEN_MBUF_CHAIN; 1.942 + msg.Control.len = sizeof ControlBuffer; 1.943 + msg.Control.buf = ControlBuffer; 1.944 + msg.dwFlags = 0; 1.945 + nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, &ncounter, NULL, NULL); 1.946 + } 1.947 + if (nResult != 0) { 1.948 + m_ErrorCode = WSAGetLastError(); 1.949 + if (m_ErrorCode == WSAETIMEDOUT) { 1.950 + continue; 1.951 + } 1.952 + if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) { 1.953 + break; 1.954 + } 1.955 + } 1.956 + n = ncounter; 1.957 +#endif 1.958 + SCTP_HEADER_LEN(udprecvmbuf6[0]) = n; /* length of total packet */ 1.959 + SCTP_STAT_INCR(sctps_recvpackets); 1.960 + SCTP_STAT_INCR_COUNTER64(sctps_inpackets); 1.961 + 1.962 + if (n <= iovlen) { 1.963 + SCTP_BUF_LEN(udprecvmbuf6[0]) = n; 1.964 + (to_fill)++; 1.965 + } else { 1.966 + i = 0; 1.967 + SCTP_BUF_LEN(udprecvmbuf6[0]) = iovlen; 1.968 + 1.969 + ncounter -= iovlen; 1.970 + (to_fill)++; 1.971 + do { 1.972 + udprecvmbuf6[i]->m_next = udprecvmbuf6[i+1]; 1.973 + SCTP_BUF_LEN(udprecvmbuf6[i]->m_next) = min(ncounter, iovlen); 1.974 + i++; 1.975 + ncounter -= iovlen; 1.976 + (to_fill)++; 1.977 + } while (ncounter > 0); 1.978 + } 1.979 + 1.980 + for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { 1.981 + if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) { 1.982 + struct in6_pktinfo *info; 1.983 + 1.984 + dst.sin6_family = AF_INET6; 1.985 +#ifdef HAVE_SIN6_LEN 1.986 + dst.sin6_len = sizeof(struct sockaddr_in6); 1.987 +#endif 1.988 + info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); 1.989 + /*dst.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));*/ 1.990 + memcpy((void *)&dst.sin6_addr, (const void *)&(info->ipi6_addr), sizeof(struct in6_addr)); 1.991 + } 1.992 + } 1.993 + 1.994 + /* SCTP does not allow broadcasts or multicasts */ 1.995 + if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) { 1.996 + return (NULL); 1.997 + } 1.998 + 1.999 + sh = mtod(udprecvmbuf6[0], struct sctphdr *); 1.1000 + ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); 1.1001 + offset = sizeof(struct sctphdr); 1.1002 + 1.1003 + port = src.sin6_port; 1.1004 + src.sin6_port = sh->src_port; 1.1005 + dst.sin6_port = sh->dest_port; 1.1006 +#if defined(SCTP_WITH_NO_CSUM) 1.1007 + SCTP_STAT_INCR(sctps_recvnocrc); 1.1008 +#else 1.1009 + if ((memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0)) { 1.1010 + compute_crc = 0; 1.1011 + SCTP_STAT_INCR(sctps_recvnocrc); 1.1012 + } else { 1.1013 + SCTP_STAT_INCR(sctps_recvswcrc); 1.1014 + } 1.1015 +#endif 1.1016 + SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n); 1.1017 + SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", (int)sizeof(struct sctphdr)); 1.1018 + sctp_common_input_processing(&udprecvmbuf6[0], 0, offset, n, 1.1019 + (struct sockaddr *)&src, 1.1020 + (struct sockaddr *)&dst, 1.1021 + sh, ch, 1.1022 +#if !defined(SCTP_WITH_NO_CSUM) 1.1023 + compute_crc, 1.1024 +#endif 1.1025 + 0, 1.1026 + SCTP_DEFAULT_VRFID, port); 1.1027 + if (udprecvmbuf6[0]) { 1.1028 + m_freem(udprecvmbuf6[0]); 1.1029 + } 1.1030 + } 1.1031 + for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) { 1.1032 + m_free(udprecvmbuf6[i]); 1.1033 + } 1.1034 + /* free the array itself */ 1.1035 + free(udprecvmbuf6); 1.1036 + return (NULL); 1.1037 +} 1.1038 +#endif 1.1039 + 1.1040 +static void 1.1041 +setReceiveBufferSize(int sfd, int new_size) 1.1042 +{ 1.1043 + int ch = new_size; 1.1044 + 1.1045 + if (setsockopt (sfd, SOL_SOCKET, SO_RCVBUF, (void*)&ch, sizeof(ch)) < 0) { 1.1046 +#if defined (__Userspace_os_Windows) 1.1047 + SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", WSAGetLastError()); 1.1048 +#else 1.1049 + SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", errno); 1.1050 +#endif 1.1051 + } 1.1052 + return; 1.1053 +} 1.1054 + 1.1055 +static void 1.1056 +setSendBufferSize(int sfd, int new_size) 1.1057 +{ 1.1058 + int ch = new_size; 1.1059 + 1.1060 + if (setsockopt (sfd, SOL_SOCKET, SO_SNDBUF, (void*)&ch, sizeof(ch)) < 0) { 1.1061 +#if defined (__Userspace_os_Windows) 1.1062 + SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", WSAGetLastError()); 1.1063 +#else 1.1064 + SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", errno); 1.1065 +#endif 1.1066 + } 1.1067 + return; 1.1068 +} 1.1069 + 1.1070 +#define SOCKET_TIMEOUT 100 /* in ms */ 1.1071 +void 1.1072 +recv_thread_init(void) 1.1073 +{ 1.1074 +#if defined(INET) 1.1075 + struct sockaddr_in addr_ipv4; 1.1076 + const int hdrincl = 1; 1.1077 +#endif 1.1078 +#if defined(INET6) 1.1079 + struct sockaddr_in6 addr_ipv6; 1.1080 +#endif 1.1081 +#if defined(INET) || defined(INET6) 1.1082 + const int on = 1; 1.1083 +#endif 1.1084 +#if !defined(__Userspace_os_Windows) 1.1085 + struct timeval timeout; 1.1086 + 1.1087 + timeout.tv_sec = (SOCKET_TIMEOUT / 1000); 1.1088 + timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000; 1.1089 +#else 1.1090 + unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */ 1.1091 +#endif 1.1092 +#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) 1.1093 + if (SCTP_BASE_VAR(userspace_route) == -1) { 1.1094 + if ((SCTP_BASE_VAR(userspace_route) = socket(AF_ROUTE, SOCK_RAW, 0)) < 0) { 1.1095 + SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d).\n", errno); 1.1096 + } 1.1097 +#if 0 1.1098 + struct sockaddr_nl sanl; 1.1099 + 1.1100 + if ((SCTP_BASE_VAR(userspace_route) = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) { 1.1101 + SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d.\n", errno); 1.1102 + } 1.1103 + memset(&sanl, 0, sizeof(sanl)); 1.1104 + sanl.nl_family = AF_NETLINK; 1.1105 + sanl.nl_groups = 0; 1.1106 +#ifdef INET 1.1107 + sanl.nl_groups |= RTMGRP_IPV4_IFADDR; 1.1108 +#endif 1.1109 +#ifdef INET6 1.1110 + sanl.nl_groups |= RTMGRP_IPV6_IFADDR; 1.1111 +#endif 1.1112 + if (bind(SCTP_BASE_VAR(userspace_route), (struct sockaddr *) &sanl, sizeof(sanl)) < 0) { 1.1113 + SCTPDBG(SCTP_DEBUG_USR, "Can't bind routing socket (errno = %d).\n", errno); 1.1114 + close(SCTP_BASE_VAR(userspace_route)); 1.1115 + SCTP_BASE_VAR(userspace_route) = -1; 1.1116 + } 1.1117 +#endif 1.1118 + if (SCTP_BASE_VAR(userspace_route) != -1) { 1.1119 + if (setsockopt(SCTP_BASE_VAR(userspace_route), SOL_SOCKET, SO_RCVTIMEO,(const void*)&timeout, sizeof(struct timeval)) < 0) { 1.1120 + SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on routing socket (errno = %d).\n", errno); 1.1121 +#if defined(__Userspace_os_Windows) 1.1122 + closesocket(SCTP_BASE_VAR(userspace_route)); 1.1123 +#else 1.1124 + close(SCTP_BASE_VAR(userspace_route)); 1.1125 +#endif 1.1126 + SCTP_BASE_VAR(userspace_route) = -1; 1.1127 + } 1.1128 + } 1.1129 + } 1.1130 +#endif 1.1131 +#if defined(INET) 1.1132 + if (SCTP_BASE_VAR(userspace_rawsctp) == -1) { 1.1133 + if ((SCTP_BASE_VAR(userspace_rawsctp) = socket(AF_INET, SOCK_RAW, IPPROTO_SCTP)) < 0) { 1.1134 +#if defined(__Userspace_os_Windows) 1.1135 + SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", WSAGetLastError()); 1.1136 +#else 1.1137 + SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", errno); 1.1138 +#endif 1.1139 + } else { 1.1140 + /* complete setting up the raw SCTP socket */ 1.1141 + if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), IPPROTO_IP, IP_HDRINCL,(const void*)&hdrincl, sizeof(int)) < 0) { 1.1142 +#if defined(__Userspace_os_Windows) 1.1143 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", WSAGetLastError()); 1.1144 + closesocket(SCTP_BASE_VAR(userspace_rawsctp)); 1.1145 +#else 1.1146 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", errno); 1.1147 + close(SCTP_BASE_VAR(userspace_rawsctp)); 1.1148 +#endif 1.1149 + SCTP_BASE_VAR(userspace_rawsctp) = -1; 1.1150 + } else if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) { 1.1151 +#if defined(__Userspace_os_Windows) 1.1152 + SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError()); 1.1153 + closesocket(SCTP_BASE_VAR(userspace_rawsctp)); 1.1154 +#else 1.1155 + SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", errno); 1.1156 + close(SCTP_BASE_VAR(userspace_rawsctp)); 1.1157 +#endif 1.1158 + SCTP_BASE_VAR(userspace_rawsctp) = -1; 1.1159 + } else { 1.1160 + memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in)); 1.1161 +#ifdef HAVE_SIN_LEN 1.1162 + addr_ipv4.sin_len = sizeof(struct sockaddr_in); 1.1163 +#endif 1.1164 + addr_ipv4.sin_family = AF_INET; 1.1165 + addr_ipv4.sin_port = htons(0); 1.1166 + addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY); 1.1167 + if (bind(SCTP_BASE_VAR(userspace_rawsctp), (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) { 1.1168 +#if defined(__Userspace_os_Windows) 1.1169 + SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError()); 1.1170 + closesocket(SCTP_BASE_VAR(userspace_rawsctp)); 1.1171 +#else 1.1172 + SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", errno); 1.1173 + close(SCTP_BASE_VAR(userspace_rawsctp)); 1.1174 +#endif 1.1175 + SCTP_BASE_VAR(userspace_rawsctp) = -1; 1.1176 + } else { 1.1177 + setReceiveBufferSize(SCTP_BASE_VAR(userspace_rawsctp), SB_RAW); /* 128K */ 1.1178 + setSendBufferSize(SCTP_BASE_VAR(userspace_rawsctp), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */ 1.1179 + } 1.1180 + } 1.1181 + } 1.1182 + } 1.1183 + if (SCTP_BASE_VAR(userspace_udpsctp) == -1) { 1.1184 + if ((SCTP_BASE_VAR(userspace_udpsctp) = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 1.1185 +#if defined(__Userspace_os_Windows) 1.1186 + SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError()); 1.1187 +#else 1.1188 + SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", errno); 1.1189 +#endif 1.1190 + } else { 1.1191 +#if defined(IP_PKTINFO) 1.1192 + if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) { 1.1193 +#else 1.1194 + if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_RECVDSTADDR, (const void *)&on, (int)sizeof(int)) < 0) { 1.1195 +#endif 1.1196 +#if defined(__Userspace_os_Windows) 1.1197 +#if defined(IP_PKTINFO) 1.1198 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError()); 1.1199 +#else 1.1200 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError()); 1.1201 +#endif 1.1202 + closesocket(SCTP_BASE_VAR(userspace_udpsctp)); 1.1203 +#else 1.1204 +#if defined(IP_PKTINFO) 1.1205 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno); 1.1206 +#else 1.1207 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno); 1.1208 +#endif 1.1209 + close(SCTP_BASE_VAR(userspace_udpsctp)); 1.1210 +#endif 1.1211 + SCTP_BASE_VAR(userspace_udpsctp) = -1; 1.1212 + } else if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) { 1.1213 +#if defined(__Userspace_os_Windows) 1.1214 + SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError()); 1.1215 + closesocket(SCTP_BASE_VAR(userspace_udpsctp)); 1.1216 +#else 1.1217 + SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno); 1.1218 + close(SCTP_BASE_VAR(userspace_udpsctp)); 1.1219 +#endif 1.1220 + SCTP_BASE_VAR(userspace_udpsctp) = -1; 1.1221 + } else { 1.1222 + memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in)); 1.1223 +#ifdef HAVE_SIN_LEN 1.1224 + addr_ipv4.sin_len = sizeof(struct sockaddr_in); 1.1225 +#endif 1.1226 + addr_ipv4.sin_family = AF_INET; 1.1227 + addr_ipv4.sin_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)); 1.1228 + addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY); 1.1229 + if (bind(SCTP_BASE_VAR(userspace_udpsctp), (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) { 1.1230 +#if defined(__Userspace_os_Windows) 1.1231 + SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError()); 1.1232 + closesocket(SCTP_BASE_VAR(userspace_udpsctp)); 1.1233 +#else 1.1234 + SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", errno); 1.1235 + close(SCTP_BASE_VAR(userspace_udpsctp)); 1.1236 +#endif 1.1237 + SCTP_BASE_VAR(userspace_udpsctp) = -1; 1.1238 + } else { 1.1239 + setReceiveBufferSize(SCTP_BASE_VAR(userspace_udpsctp), SB_RAW); /* 128K */ 1.1240 + setSendBufferSize(SCTP_BASE_VAR(userspace_udpsctp), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */ 1.1241 + } 1.1242 + } 1.1243 + } 1.1244 + } 1.1245 +#endif 1.1246 +#if defined(INET6) 1.1247 + if (SCTP_BASE_VAR(userspace_rawsctp6) == -1) { 1.1248 + if ((SCTP_BASE_VAR(userspace_rawsctp6) = socket(AF_INET6, SOCK_RAW, IPPROTO_SCTP)) < 0) { 1.1249 +#if defined(__Userspace_os_Windows) 1.1250 + SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError()); 1.1251 +#else 1.1252 + SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", errno); 1.1253 +#endif 1.1254 + } else { 1.1255 + /* complete setting up the raw SCTP socket */ 1.1256 +#if defined(IPV6_RECVPKTINFO) 1.1257 + if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, sizeof(on)) < 0) { 1.1258 +#if defined(__Userspace_os_Windows) 1.1259 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError()); 1.1260 + closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); 1.1261 +#else 1.1262 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno); 1.1263 + close(SCTP_BASE_VAR(userspace_rawsctp6)); 1.1264 +#endif 1.1265 + SCTP_BASE_VAR(userspace_rawsctp6) = -1; 1.1266 + } else { 1.1267 +#else 1.1268 + if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_PKTINFO,(const void*)&on, sizeof(on)) < 0) { 1.1269 +#if defined(__Userspace_os_Windows) 1.1270 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError()); 1.1271 + closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); 1.1272 +#else 1.1273 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno); 1.1274 + close(SCTP_BASE_VAR(userspace_rawsctp6)); 1.1275 +#endif 1.1276 + SCTP_BASE_VAR(userspace_rawsctp6) = -1; 1.1277 + } else { 1.1278 +#endif 1.1279 + if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&on, (socklen_t)sizeof(on)) < 0) { 1.1280 +#if defined(__Userspace_os_Windows) 1.1281 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError()); 1.1282 +#else 1.1283 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", errno); 1.1284 +#endif 1.1285 + } 1.1286 + if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) { 1.1287 +#if defined(__Userspace_os_Windows) 1.1288 + SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError()); 1.1289 + closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); 1.1290 +#else 1.1291 + SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", errno); 1.1292 + close(SCTP_BASE_VAR(userspace_rawsctp6)); 1.1293 +#endif 1.1294 + SCTP_BASE_VAR(userspace_rawsctp6) = -1; 1.1295 + } else { 1.1296 + memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6)); 1.1297 +#ifdef HAVE_SIN6_LEN 1.1298 + addr_ipv6.sin6_len = sizeof(struct sockaddr_in6); 1.1299 +#endif 1.1300 + addr_ipv6.sin6_family = AF_INET6; 1.1301 + addr_ipv6.sin6_port = htons(0); 1.1302 + addr_ipv6.sin6_addr = in6addr_any; 1.1303 + if (bind(SCTP_BASE_VAR(userspace_rawsctp6), (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) { 1.1304 +#if defined(__Userspace_os_Windows) 1.1305 + SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError()); 1.1306 + closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); 1.1307 +#else 1.1308 + SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", errno); 1.1309 + close(SCTP_BASE_VAR(userspace_rawsctp6)); 1.1310 +#endif 1.1311 + SCTP_BASE_VAR(userspace_rawsctp6) = -1; 1.1312 + } else { 1.1313 + setReceiveBufferSize(SCTP_BASE_VAR(userspace_rawsctp6), SB_RAW); /* 128K */ 1.1314 + setSendBufferSize(SCTP_BASE_VAR(userspace_rawsctp6), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */ 1.1315 + } 1.1316 + } 1.1317 + } 1.1318 + } 1.1319 + } 1.1320 + if (SCTP_BASE_VAR(userspace_udpsctp6) == -1) { 1.1321 + if ((SCTP_BASE_VAR(userspace_udpsctp6) = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 1.1322 +#if defined(__Userspace_os_Windows) 1.1323 + SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError()); 1.1324 +#else 1.1325 + SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", errno); 1.1326 +#endif 1.1327 + } 1.1328 +#if defined(IPV6_RECVPKTINFO) 1.1329 + if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, (int)sizeof(int)) < 0) { 1.1330 +#if defined(__Userspace_os_Windows) 1.1331 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError()); 1.1332 + closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); 1.1333 +#else 1.1334 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno); 1.1335 + close(SCTP_BASE_VAR(userspace_udpsctp6)); 1.1336 +#endif 1.1337 + SCTP_BASE_VAR(userspace_udpsctp6) = -1; 1.1338 + } else { 1.1339 +#else 1.1340 + if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) { 1.1341 +#if defined(__Userspace_os_Windows) 1.1342 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError()); 1.1343 + closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); 1.1344 +#else 1.1345 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno); 1.1346 + close(SCTP_BASE_VAR(userspace_udpsctp6)); 1.1347 +#endif 1.1348 + SCTP_BASE_VAR(userspace_udpsctp6) = -1; 1.1349 + } else { 1.1350 +#endif 1.1351 + if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&on, (socklen_t)sizeof(on)) < 0) { 1.1352 +#if defined(__Userspace_os_Windows) 1.1353 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError()); 1.1354 +#else 1.1355 + SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno); 1.1356 +#endif 1.1357 + } 1.1358 + if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) { 1.1359 +#if defined(__Userspace_os_Windows) 1.1360 + SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError()); 1.1361 + closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); 1.1362 +#else 1.1363 + SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno); 1.1364 + close(SCTP_BASE_VAR(userspace_udpsctp6)); 1.1365 +#endif 1.1366 + SCTP_BASE_VAR(userspace_udpsctp6) = -1; 1.1367 + } else { 1.1368 + memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6)); 1.1369 +#ifdef HAVE_SIN6_LEN 1.1370 + addr_ipv6.sin6_len = sizeof(struct sockaddr_in6); 1.1371 +#endif 1.1372 + addr_ipv6.sin6_family = AF_INET6; 1.1373 + addr_ipv6.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)); 1.1374 + addr_ipv6.sin6_addr = in6addr_any; 1.1375 + if (bind(SCTP_BASE_VAR(userspace_udpsctp6), (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) { 1.1376 +#if defined(__Userspace_os_Windows) 1.1377 + SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError()); 1.1378 + closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); 1.1379 +#else 1.1380 + SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", errno); 1.1381 + close(SCTP_BASE_VAR(userspace_udpsctp6)); 1.1382 +#endif 1.1383 + SCTP_BASE_VAR(userspace_udpsctp6) = -1; 1.1384 + } else { 1.1385 + setReceiveBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K */ 1.1386 + setSendBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */ 1.1387 + } 1.1388 + } 1.1389 + } 1.1390 + } 1.1391 +#endif 1.1392 +#if !defined(__Userspace_os_Windows) 1.1393 +#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) 1.1394 +#if defined(INET) || defined(INET6) 1.1395 + if (SCTP_BASE_VAR(userspace_route) != -1) { 1.1396 + int rc; 1.1397 + 1.1398 + if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadroute), NULL, &recv_function_route, NULL))) { 1.1399 + SCTPDBG(SCTP_DEBUG_USR, "Can't start routing thread (%d).\n", rc); 1.1400 + close(SCTP_BASE_VAR(userspace_route)); 1.1401 + SCTP_BASE_VAR(userspace_route) = -1; 1.1402 + } 1.1403 + } 1.1404 +#endif 1.1405 +#endif 1.1406 +#if defined(INET) 1.1407 + if (SCTP_BASE_VAR(userspace_rawsctp) != -1) { 1.1408 + int rc; 1.1409 + 1.1410 + if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw), NULL, &recv_function_raw, NULL))) { 1.1411 + SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread (%d).\n", rc); 1.1412 + close(SCTP_BASE_VAR(userspace_rawsctp)); 1.1413 + SCTP_BASE_VAR(userspace_rawsctp) = -1; 1.1414 + } 1.1415 + } 1.1416 + if (SCTP_BASE_VAR(userspace_udpsctp) != -1) { 1.1417 + int rc; 1.1418 + 1.1419 + if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp), NULL, &recv_function_udp, NULL))) { 1.1420 + SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread (%d).\n", rc); 1.1421 + close(SCTP_BASE_VAR(userspace_udpsctp)); 1.1422 + SCTP_BASE_VAR(userspace_udpsctp) = -1; 1.1423 + } 1.1424 + } 1.1425 +#endif 1.1426 +#if defined(INET6) 1.1427 + if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) { 1.1428 + int rc; 1.1429 + 1.1430 + if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw6), NULL, &recv_function_raw6, NULL))) { 1.1431 + SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread (%d).\n", rc); 1.1432 + close(SCTP_BASE_VAR(userspace_rawsctp6)); 1.1433 + SCTP_BASE_VAR(userspace_rawsctp6) = -1; 1.1434 + } 1.1435 + } 1.1436 + if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) { 1.1437 + int rc; 1.1438 + 1.1439 + if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp6), NULL, &recv_function_udp6, NULL))) { 1.1440 + SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread (%d).\n", rc); 1.1441 + close(SCTP_BASE_VAR(userspace_udpsctp6)); 1.1442 + SCTP_BASE_VAR(userspace_udpsctp6) = -1; 1.1443 + } 1.1444 + } 1.1445 +#endif 1.1446 +#else 1.1447 +#if defined(INET) 1.1448 + if (SCTP_BASE_VAR(userspace_rawsctp) != -1) { 1.1449 + if ((SCTP_BASE_VAR(recvthreadraw) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw, NULL, 0, NULL)) == NULL) { 1.1450 + SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread.\n"); 1.1451 + closesocket(SCTP_BASE_VAR(userspace_rawsctp)); 1.1452 + SCTP_BASE_VAR(userspace_rawsctp) = -1; 1.1453 + } 1.1454 + } 1.1455 + if (SCTP_BASE_VAR(userspace_udpsctp) != -1) { 1.1456 + if ((SCTP_BASE_VAR(recvthreadudp) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp, NULL, 0, NULL)) == NULL) { 1.1457 + SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread.\n"); 1.1458 + closesocket(SCTP_BASE_VAR(userspace_udpsctp)); 1.1459 + SCTP_BASE_VAR(userspace_udpsctp) = -1; 1.1460 + } 1.1461 + } 1.1462 +#endif 1.1463 +#if defined(INET6) 1.1464 + if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) { 1.1465 + if ((SCTP_BASE_VAR(recvthreadraw6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw6, NULL, 0, NULL)) == NULL) { 1.1466 + SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread.\n"); 1.1467 + closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); 1.1468 + SCTP_BASE_VAR(userspace_rawsctp6) = -1; 1.1469 + } 1.1470 + } 1.1471 + if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) { 1.1472 + if ((SCTP_BASE_VAR(recvthreadudp6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp6, NULL, 0, NULL)) == NULL) { 1.1473 + SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread.\n"); 1.1474 + closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); 1.1475 + SCTP_BASE_VAR(userspace_udpsctp6) = -1; 1.1476 + } 1.1477 + } 1.1478 +#endif 1.1479 +#endif 1.1480 +} 1.1481 + 1.1482 +void 1.1483 +recv_thread_destroy(void) 1.1484 +{ 1.1485 +#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) 1.1486 +#if defined(INET) || defined(INET6) 1.1487 + if (SCTP_BASE_VAR(userspace_route) != -1) { 1.1488 + close(SCTP_BASE_VAR(userspace_route)); 1.1489 + } 1.1490 +#endif 1.1491 +#endif 1.1492 +#if defined(INET) 1.1493 + if (SCTP_BASE_VAR(userspace_rawsctp) != -1) { 1.1494 +#if defined(__Userspace_os_Windows) 1.1495 + closesocket(SCTP_BASE_VAR(userspace_rawsctp)); 1.1496 +#else 1.1497 + close(SCTP_BASE_VAR(userspace_rawsctp)); 1.1498 +#endif 1.1499 + } 1.1500 + if (SCTP_BASE_VAR(userspace_udpsctp) != -1) { 1.1501 +#if defined(__Userspace_os_Windows) 1.1502 + closesocket(SCTP_BASE_VAR(userspace_udpsctp)); 1.1503 +#else 1.1504 + close(SCTP_BASE_VAR(userspace_udpsctp)); 1.1505 +#endif 1.1506 + } 1.1507 +#endif 1.1508 +#if defined(INET6) 1.1509 + if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) { 1.1510 +#if defined(__Userspace_os_Windows) 1.1511 + closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); 1.1512 +#else 1.1513 + close(SCTP_BASE_VAR(userspace_rawsctp6)); 1.1514 +#endif 1.1515 + } 1.1516 + if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) { 1.1517 +#if defined(__Userspace_os_Windows) 1.1518 + closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); 1.1519 +#else 1.1520 + close(SCTP_BASE_VAR(userspace_udpsctp6)); 1.1521 +#endif 1.1522 + } 1.1523 +#endif 1.1524 +} 1.1525 +#else 1.1526 +int foo; 1.1527 +#endif