netwerk/sctp/src/user_recv_thread.c

changeset 0
6474c204b198
     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

mercurial