Home | History | Annotate | Download | only in usrsctplib
      1 /*-
      2  * Copyright (c) 2009-2010 Brad Penoff
      3  * Copyright (c) 2009-2010 Humaira Kamal
      4  * Copyright (c) 2011-2012 Irene Ruengeler
      5  * Copyright (c) 2011-2012 Michael Tuexen
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  *
     29  */
     30 
     31 #if defined(INET) || defined(INET6)
     32 #include <sys/types.h>
     33 #if !defined(__Userspace_os_Windows)
     34 #include <sys/socket.h>
     35 #include <netinet/in.h>
     36 #include <unistd.h>
     37 #include <pthread.h>
     38 #if !defined(__Userspace_os_DragonFly) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_NetBSD)
     39 #include <sys/uio.h>
     40 #else
     41 #include <user_ip6_var.h>
     42 #endif
     43 #endif
     44 #include <netinet/sctp_os.h>
     45 #include <netinet/sctp_var.h>
     46 #include <netinet/sctp_pcb.h>
     47 #include <netinet/sctp_input.h>
     48 #if 0
     49 #if defined(__Userspace_os_Linux)
     50 #include <linux/netlink.h>
     51 #ifdef HAVE_LINUX_IF_ADDR_H
     52 #include <linux/if_addr.h>
     53 #endif
     54 #ifdef HAVE_LINUX_RTNETLINK_H
     55 #include <linux/rtnetlink.h>
     56 #endif
     57 #endif
     58 #endif
     59 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
     60 #include <net/route.h>
     61 #endif
     62 /* local macros and datatypes used to get IP addresses system independently */
     63 #if !defined(IP_PKTINFO ) && ! defined(IP_RECVDSTADDR)
     64 # error "Can't determine socket option to use to get UDP IP"
     65 #endif
     66 
     67 void recv_thread_destroy(void);
     68 #define MAXLEN_MBUF_CHAIN 32 /* What should this value be? */
     69 #define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
     70 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
     71 #define NEXT_SA(ap) ap = (struct sockaddr *) \
     72 	((caddr_t) ap + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof (uint32_t)) : sizeof(uint32_t)))
     73 #endif
     74 
     75 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
     76 static void
     77 sctp_get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
     78 {
     79 	int i;
     80 
     81 	for (i = 0; i < RTAX_MAX; i++) {
     82 		if (addrs & (1 << i)) {
     83 			rti_info[i] = sa;
     84 			NEXT_SA(sa);
     85 		} else {
     86 			rti_info[i] = NULL;
     87 		}
     88 	}
     89 }
     90 
     91 static void
     92 sctp_handle_ifamsg(unsigned char type, unsigned short index, struct sockaddr *sa)
     93 {
     94 	int rc;
     95 	struct ifaddrs *ifa, *found_ifa = NULL;
     96 
     97 	/* handle only the types we want */
     98 	if ((type != RTM_NEWADDR) && (type != RTM_DELADDR)) {
     99 		return;
    100 	}
    101 
    102 	rc = getifaddrs(&g_interfaces);
    103 	if (rc != 0) {
    104 		return;
    105 	}
    106 	for (ifa = g_interfaces; ifa; ifa = ifa->ifa_next) {
    107 		if (index == if_nametoindex(ifa->ifa_name)) {
    108 			found_ifa = ifa;
    109 			break;
    110 		}
    111 	}
    112 	if (found_ifa == NULL) {
    113 		return;
    114 	}
    115 
    116 	switch (sa->sa_family) {
    117 #ifdef INET
    118 	case AF_INET:
    119 		ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
    120 		memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in));
    121 		break;
    122 #endif
    123 #ifdef INET6
    124 	case AF_INET6:
    125 		ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in6));
    126 		memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in6));
    127 		break;
    128 #endif
    129 	default:
    130 		SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", sa->sa_family);
    131 	}
    132 
    133 	/* relay the appropriate address change to the base code */
    134 	if (type == RTM_NEWADDR) {
    135 		(void)sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, ifa, if_nametoindex(ifa->ifa_name),
    136 		                           0,
    137 		                           ifa->ifa_name,
    138 		                           (void *)ifa,
    139 		                           ifa->ifa_addr,
    140 		                           0,
    141 		                           1);
    142 	} else {
    143 		sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
    144 		                       if_nametoindex(ifa->ifa_name),
    145 		                       ifa->ifa_name);
    146 	}
    147 }
    148 
    149 static void *
    150 recv_function_route(void *arg)
    151 {
    152 	ssize_t ret;
    153 	struct ifa_msghdr *ifa;
    154 	char rt_buffer[1024];
    155 	struct sockaddr *sa, *rti_info[RTAX_MAX];
    156 
    157 	while (1) {
    158 		bzero(rt_buffer, sizeof(rt_buffer));
    159 		ret = recv(SCTP_BASE_VAR(userspace_route), rt_buffer, sizeof(rt_buffer), 0);
    160 
    161 		if (ret > 0) {
    162 			ifa = (struct ifa_msghdr *) rt_buffer;
    163 			if (ifa->ifam_type != RTM_DELADDR && ifa->ifam_type != RTM_NEWADDR) {
    164 				continue;
    165 			}
    166 			sa = (struct sockaddr *) (ifa + 1);
    167 			sctp_get_rtaddrs(ifa->ifam_addrs, sa, rti_info);
    168 			switch (ifa->ifam_type) {
    169 			case RTM_DELADDR:
    170 			case RTM_NEWADDR:
    171 				sctp_handle_ifamsg(ifa->ifam_type, ifa->ifam_index, rti_info[RTAX_IFA]);
    172 				break;
    173 			default:
    174 				/* ignore this routing event */
    175 				break;
    176 			}
    177 		}
    178 		if (ret < 0) {
    179 			if (errno == EAGAIN) {
    180 				continue;
    181 			} else {
    182 				break;
    183 			}
    184 		}
    185 	}
    186 	return (NULL);
    187 }
    188 #endif
    189 
    190 #if 0
    191 /* This does not yet work on Linux */
    192 static void *
    193 recv_function_route(void *arg)
    194 {
    195 	int len;
    196 	char buf[4096];
    197 	struct iovec iov = { buf, sizeof(buf) };
    198 	struct msghdr msg;
    199 	struct nlmsghdr *nh;
    200 	struct ifaddrmsg *rtmsg;
    201 	struct rtattr *rtatp;
    202 	struct in_addr *inp;
    203 	struct sockaddr_nl sanl;
    204 #ifdef INET
    205 	struct sockaddr_in *sa;
    206 #endif
    207 #ifdef INET6
    208 	struct sockaddr_in6 *sa6;
    209 #endif
    210 
    211 	for (;;) {
    212 		memset(&sanl, 0, sizeof(sanl));
    213 		sanl.nl_family = AF_NETLINK;
    214 		sanl.nl_groups = RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_IFADDR;
    215 		memset(&msg, 0, sizeof(struct msghdr));
    216 		msg.msg_name = (void *)&sanl;
    217 		msg.msg_namelen = sizeof(sanl);
    218 		msg.msg_iov = &iov;
    219 		msg.msg_iovlen = 1;
    220 		msg.msg_control = NULL;
    221 		msg.msg_controllen = 0;
    222 
    223 		len = recvmsg(SCTP_BASE_VAR(userspace_route), &msg, 0);
    224 
    225 		if (len < 0) {
    226 			if (errno == EAGAIN) {
    227 				continue;
    228 			} else {
    229 				break;
    230 			}
    231 		}
    232 		for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len);
    233 			nh = NLMSG_NEXT (nh, len)) {
    234 			if (nh->nlmsg_type == NLMSG_DONE)
    235 				break;
    236 
    237 			if (nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR) {
    238 				rtmsg = (struct ifaddrmsg *)NLMSG_DATA(nh);
    239 				rtatp = (struct rtattr *)IFA_RTA(rtmsg);
    240 				if(rtatp->rta_type == IFA_ADDRESS) {
    241 					inp = (struct in_addr *)RTA_DATA(rtatp);
    242 					switch (rtmsg->ifa_family) {
    243 #ifdef INET
    244 					case AF_INET:
    245 						sa = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
    246 						sa->sin_family = rtmsg->ifa_family;
    247 						sa->sin_port = 0;
    248 						memcpy(&sa->sin_addr, inp, sizeof(struct in_addr));
    249 						sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa);
    250 						break;
    251 #endif
    252 #ifdef INET6
    253 					case AF_INET6:
    254 						sa6 = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6));
    255 						sa6->sin6_family = rtmsg->ifa_family;
    256 						sa6->sin6_port = 0;
    257 						memcpy(&sa6->sin6_addr, inp, sizeof(struct in6_addr));
    258 						sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa6);
    259 						break;
    260 #endif
    261 					default:
    262 						SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", rtmsg->ifa_family);
    263 						break;
    264 					}
    265 				}
    266 			}
    267 		}
    268 	}
    269 	return (NULL);
    270 }
    271 #endif
    272 
    273 #ifdef INET
    274 static void *
    275 recv_function_raw(void *arg)
    276 {
    277 	struct mbuf **recvmbuf;
    278 	struct ip *iphdr;
    279 	struct sctphdr *sh;
    280 	uint16_t port;
    281 	int offset, ecn = 0;
    282 #if !defined(SCTP_WITH_NO_CSUM)
    283 	int compute_crc = 1;
    284 #endif
    285 	struct sctp_chunkhdr *ch;
    286 	struct sockaddr_in src, dst;
    287 #if !defined(__Userspace_os_Windows)
    288 	struct msghdr msg;
    289 	struct iovec recv_iovec[MAXLEN_MBUF_CHAIN];
    290 #else
    291 	WSABUF recv_iovec[MAXLEN_MBUF_CHAIN];
    292 	int nResult, m_ErrorCode;
    293 	DWORD flags;
    294 	struct sockaddr_in from;
    295 	int fromlen;
    296 #endif
    297 
    298 	/*Initially the entire set of mbufs is to be allocated.
    299 	  to_fill indicates this amount. */
    300 	int to_fill = MAXLEN_MBUF_CHAIN;
    301 	/* iovlen is the size of each mbuf in the chain */
    302 	int i, n, ncounter = 0;
    303 	int iovlen = MCLBYTES;
    304 	int want_ext = (iovlen > MLEN)? 1 : 0;
    305 	int want_header = 0;
    306 
    307 	bzero((void *)&src, sizeof(struct sockaddr_in));
    308 	bzero((void *)&dst, sizeof(struct sockaddr_in));
    309 
    310 	recvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
    311 
    312 	while (1) {
    313 		for (i = 0; i < to_fill; i++) {
    314 			/* Not getting the packet header. Tests with chain of one run
    315 			   as usual without having the packet header.
    316 			   Have tried both sending and receiving
    317 			 */
    318 			recvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
    319 #if !defined(__Userspace_os_Windows)
    320 			recv_iovec[i].iov_base = (caddr_t)recvmbuf[i]->m_data;
    321 			recv_iovec[i].iov_len = iovlen;
    322 #else
    323 			recv_iovec[i].buf = (caddr_t)recvmbuf[i]->m_data;
    324 			recv_iovec[i].len = iovlen;
    325 #endif
    326 		}
    327 		to_fill = 0;
    328 #if defined(__Userspace_os_Windows)
    329 		flags = 0;
    330 		ncounter = 0;
    331 		fromlen = sizeof(struct sockaddr_in);
    332 		bzero((void *)&from, sizeof(struct sockaddr_in));
    333 
    334 		nResult = WSARecvFrom(SCTP_BASE_VAR(userspace_rawsctp), recv_iovec, MAXLEN_MBUF_CHAIN, (LPDWORD)&ncounter, (LPDWORD)&flags, (struct sockaddr*)&from, &fromlen, NULL, NULL);
    335 		if (nResult != 0) {
    336 			m_ErrorCode = WSAGetLastError();
    337 			if (m_ErrorCode == WSAETIMEDOUT) {
    338 				continue;
    339 			}
    340 			if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
    341 				break;
    342 			}
    343 		}
    344 		n = ncounter;
    345 #else
    346 		bzero((void *)&msg, sizeof(struct msghdr));
    347 		msg.msg_name = NULL;
    348 		msg.msg_namelen = 0;
    349 		msg.msg_iov = recv_iovec;
    350 		msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
    351 		msg.msg_control = NULL;
    352 		msg.msg_controllen = 0;
    353 		ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp), &msg, 0);
    354 		if (n < 0) {
    355 			if (errno == EAGAIN) {
    356 				continue;
    357 			} else {
    358 				break;
    359 			}
    360 		}
    361 #endif
    362 		SCTP_HEADER_LEN(recvmbuf[0]) = n; /* length of total packet */
    363 		SCTP_STAT_INCR(sctps_recvpackets);
    364 		SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
    365 
    366 		if (n <= iovlen) {
    367 			SCTP_BUF_LEN(recvmbuf[0]) = n;
    368 			(to_fill)++;
    369 		} else {
    370 			i = 0;
    371 			SCTP_BUF_LEN(recvmbuf[0]) = iovlen;
    372 
    373 			ncounter -= iovlen;
    374 			(to_fill)++;
    375 			do {
    376 				recvmbuf[i]->m_next = recvmbuf[i+1];
    377 				SCTP_BUF_LEN(recvmbuf[i]->m_next) = min(ncounter, iovlen);
    378 				i++;
    379 				ncounter -= iovlen;
    380 				(to_fill)++;
    381 			} while (ncounter > 0);
    382 		}
    383 
    384 		iphdr = mtod(recvmbuf[0], struct ip *);
    385 		sh = (struct sctphdr *)((caddr_t)iphdr + sizeof(struct ip));
    386 		ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
    387 		offset = sizeof(struct ip) + sizeof(struct sctphdr);
    388 
    389 		if (iphdr->ip_tos != 0) {
    390 			ecn = iphdr->ip_tos & 0x02;
    391 		}
    392 
    393 		dst.sin_family = AF_INET;
    394 #ifdef HAVE_SIN_LEN
    395 		dst.sin_len = sizeof(struct sockaddr_in);
    396 #endif
    397 		dst.sin_addr = iphdr->ip_dst;
    398 		dst.sin_port = sh->dest_port;
    399 
    400 		src.sin_family = AF_INET;
    401 #ifdef HAVE_SIN_LEN
    402 		src.sin_len = sizeof(struct sockaddr_in);
    403 #endif
    404 		src.sin_addr = iphdr->ip_src;
    405 		src.sin_port = sh->src_port;
    406 
    407 		/* SCTP does not allow broadcasts or multicasts */
    408 		if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
    409 			return (NULL);
    410 		}
    411 		if (SCTP_IS_IT_BROADCAST(dst.sin_addr, recvmbuf[0])) {
    412 			return (NULL);
    413 		}
    414 
    415 		port = 0;
    416 
    417 #if defined(SCTP_WITH_NO_CSUM)
    418 		SCTP_STAT_INCR(sctps_recvnocrc);
    419 #else
    420 		if (src.sin_addr.s_addr == dst.sin_addr.s_addr) {
    421 			compute_crc = 0;
    422 			SCTP_STAT_INCR(sctps_recvnocrc);
    423 		} else {
    424 			SCTP_STAT_INCR(sctps_recvswcrc);
    425 		}
    426 #endif
    427 		SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
    428 		SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
    429 		sctp_common_input_processing(&recvmbuf[0], sizeof(struct ip), offset, n,
    430 		                             (struct sockaddr *)&src,
    431 		                             (struct sockaddr *)&dst,
    432 		                             sh, ch,
    433 #if !defined(SCTP_WITH_NO_CSUM)
    434 		                             compute_crc,
    435 #endif
    436 		                             ecn,
    437 		                             SCTP_DEFAULT_VRFID, port);
    438 		if (recvmbuf[0]) {
    439 			m_freem(recvmbuf[0]);
    440 		}
    441 	}
    442 	for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
    443 		m_free(recvmbuf[i]);
    444 	}
    445 	/* free the array itself */
    446 	free(recvmbuf);
    447 	return (NULL);
    448 }
    449 #endif
    450 
    451 #if defined(INET6)
    452 static void *
    453 recv_function_raw6(void *arg)
    454 {
    455 	struct mbuf **recvmbuf6;
    456 #if !defined(__Userspace_os_Windows)
    457 	struct iovec recv_iovec[MAXLEN_MBUF_CHAIN];
    458 	struct msghdr msg;
    459 	struct cmsghdr *cmsgptr;
    460 	char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
    461 #else
    462 	WSABUF recv_iovec[MAXLEN_MBUF_CHAIN];
    463 	int nResult, m_ErrorCode;
    464 	DWORD flags;
    465 	struct sockaddr_in6 from;
    466 	int fromlen;
    467 	GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
    468 	LPFN_WSARECVMSG WSARecvMsg;
    469 	WSACMSGHDR *cmsgptr;
    470 	WSAMSG msg;
    471 	char ControlBuffer[1024];
    472 #endif
    473 	struct sockaddr_in6 src, dst;
    474 	struct sctphdr *sh;
    475 	int offset;
    476 	struct sctp_chunkhdr *ch;
    477 
    478 	/*Initially the entire set of mbufs is to be allocated.
    479 	  to_fill indicates this amount. */
    480 	int to_fill = MAXLEN_MBUF_CHAIN;
    481 	/* iovlen is the size of each mbuf in the chain */
    482 	int i, n, ncounter = 0;
    483 #if !defined(SCTP_WITH_NO_CSUM)
    484 	int compute_crc = 1;
    485 #endif
    486 	int iovlen = MCLBYTES;
    487 	int want_ext = (iovlen > MLEN)? 1 : 0;
    488 	int want_header = 0;
    489 
    490 	recvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
    491 
    492 	for (;;) {
    493 		for (i = 0; i < to_fill; i++) {
    494 			/* Not getting the packet header. Tests with chain of one run
    495 			   as usual without having the packet header.
    496 			   Have tried both sending and receiving
    497 			 */
    498 			recvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
    499 #if !defined(__Userspace_os_Windows)
    500 			recv_iovec[i].iov_base = (caddr_t)recvmbuf6[i]->m_data;
    501 			recv_iovec[i].iov_len = iovlen;
    502 #else
    503 			recv_iovec[i].buf = (caddr_t)recvmbuf6[i]->m_data;
    504 			recv_iovec[i].len = iovlen;
    505 #endif
    506 		}
    507 		to_fill = 0;
    508 #if defined(__Userspace_os_Windows)
    509 		flags = 0;
    510 		ncounter = 0;
    511 		fromlen = sizeof(struct sockaddr_in6);
    512 		bzero((void *)&from, sizeof(struct sockaddr_in6));
    513 		nResult = WSAIoctl(SCTP_BASE_VAR(userspace_rawsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER,
    514 		                   &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
    515 		                   &WSARecvMsg, sizeof WSARecvMsg,
    516 		                   &ncounter, NULL, NULL);
    517 		if (nResult == 0) {
    518 			msg.name = (void *)&src;
    519 			msg.namelen = sizeof(struct sockaddr_in6);
    520 			msg.lpBuffers = recv_iovec;
    521 			msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
    522 			msg.Control.len = sizeof ControlBuffer;
    523 			msg.Control.buf = ControlBuffer;
    524 			msg.dwFlags = 0;
    525 			nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, &ncounter, NULL, NULL);
    526 		}
    527 		if (nResult != 0) {
    528 			m_ErrorCode = WSAGetLastError();
    529 			if (m_ErrorCode == WSAETIMEDOUT)
    530 				continue;
    531 			if (m_ErrorCode == WSAENOTSOCK || m_ErrorCode == WSAEINTR)
    532 				break;
    533 		}
    534 		n = ncounter;
    535 #else
    536 		bzero((void *)&msg, sizeof(struct msghdr));
    537 		bzero((void *)&src, sizeof(struct sockaddr_in6));
    538 		bzero((void *)&dst, sizeof(struct sockaddr_in6));
    539 		bzero((void *)cmsgbuf, CMSG_SPACE(sizeof (struct in6_pktinfo)));
    540 		msg.msg_name = (void *)&src;
    541 		msg.msg_namelen = sizeof(struct sockaddr_in6);
    542 		msg.msg_iov = recv_iovec;
    543 		msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
    544 		msg.msg_control = (void *)cmsgbuf;
    545 		msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof (struct in6_pktinfo));
    546 		msg.msg_flags = 0;
    547 
    548 		ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, 0);
    549 		if (n < 0) {
    550 			if (errno == EAGAIN) {
    551 				continue;
    552 			} else {
    553 				break;
    554 			}
    555 		}
    556 #endif
    557 		SCTP_HEADER_LEN(recvmbuf6[0]) = n; /* length of total packet */
    558 		SCTP_STAT_INCR(sctps_recvpackets);
    559 		SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
    560 
    561 		if (n <= iovlen) {
    562 			SCTP_BUF_LEN(recvmbuf6[0]) = n;
    563 			(to_fill)++;
    564 		} else {
    565 			i = 0;
    566 			SCTP_BUF_LEN(recvmbuf6[0]) = iovlen;
    567 
    568 			ncounter -= iovlen;
    569 			(to_fill)++;
    570 			do {
    571 				recvmbuf6[i]->m_next = recvmbuf6[i+1];
    572 				SCTP_BUF_LEN(recvmbuf6[i]->m_next) = min(ncounter, iovlen);
    573 				i++;
    574 				ncounter -= iovlen;
    575 				(to_fill)++;
    576 			} while (ncounter > 0);
    577 		}
    578 
    579 		for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
    580 			if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) {
    581 				struct in6_pktinfo * info;
    582 
    583 				info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
    584 				memcpy((void *)&dst.sin6_addr, (const void *) &(info->ipi6_addr), sizeof(struct in6_addr));
    585 				break;
    586 			}
    587 		}
    588 
    589 		sh = mtod(recvmbuf6[0], struct sctphdr *);
    590 		ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
    591 		offset = sizeof(struct sctphdr);
    592 
    593 		dst.sin6_family = AF_INET6;
    594 #ifdef HAVE_SIN6_LEN
    595 		dst.sin6_len = sizeof(struct sockaddr_in6);
    596 #endif
    597 		dst.sin6_port = sh->dest_port;
    598 
    599 		src.sin6_family = AF_INET6;
    600 #ifdef HAVE_SIN6_LEN
    601 		src.sin6_len = sizeof(struct sockaddr_in6);
    602 #endif
    603 		src.sin6_port = sh->src_port;
    604 #if defined(SCTP_WITH_NO_CSUM)
    605 		SCTP_STAT_INCR(sctps_recvnocrc);
    606 #else
    607 		if (memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0) {
    608 			compute_crc = 0;
    609 			SCTP_STAT_INCR(sctps_recvnocrc);
    610 		} else {
    611 			SCTP_STAT_INCR(sctps_recvswcrc);
    612 		}
    613 #endif
    614 		SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
    615 		SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
    616 		sctp_common_input_processing(&recvmbuf6[0], 0, offset, n,
    617 		                             (struct sockaddr *)&src,
    618 		                             (struct sockaddr *)&dst,
    619 		                             sh, ch,
    620 #if !defined(SCTP_WITH_NO_CSUM)
    621 		                             compute_crc,
    622 #endif
    623 		                             0,
    624 		                             SCTP_DEFAULT_VRFID, 0);
    625 		if (recvmbuf6[0]) {
    626 			m_freem(recvmbuf6[0]);
    627 		}
    628 	}
    629 	for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
    630 		m_free(recvmbuf6[i]);
    631 	}
    632 	/* free the array itself */
    633 	free(recvmbuf6);
    634 	return (NULL);
    635 }
    636 #endif
    637 
    638 #ifdef INET
    639 static void *
    640 recv_function_udp(void *arg)
    641 {
    642 	struct mbuf **udprecvmbuf;
    643 	/*Initially the entire set of mbufs is to be allocated.
    644 	  to_fill indicates this amount. */
    645 	int to_fill = MAXLEN_MBUF_CHAIN;
    646 	/* iovlen is the size of each mbuf in the chain */
    647 	int i, n, ncounter, offset;
    648 	int iovlen = MCLBYTES;
    649 	int want_ext = (iovlen > MLEN)? 1 : 0;
    650 	int want_header = 0;
    651 	struct sctphdr *sh;
    652 	uint16_t port;
    653 	struct sctp_chunkhdr *ch;
    654 	struct sockaddr_in src, dst;
    655 #if defined(IP_PKTINFO)
    656 	char cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))];
    657 #else
    658 	char cmsgbuf[CMSG_SPACE(sizeof(struct in_addr))];
    659 #endif
    660 #if !defined(SCTP_WITH_NO_CSUM)
    661 	int compute_crc = 1;
    662 #endif
    663 #if !defined(__Userspace_os_Windows)
    664 	struct iovec iov[MAXLEN_MBUF_CHAIN];
    665 	struct msghdr msg;
    666 	struct cmsghdr *cmsgptr;
    667 #else
    668 	GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
    669 	LPFN_WSARECVMSG WSARecvMsg;
    670 	char ControlBuffer[1024];
    671 	WSABUF iov[MAXLEN_MBUF_CHAIN];
    672 	WSAMSG msg;
    673 	int nResult, m_ErrorCode;
    674 	WSACMSGHDR *cmsgptr;
    675 #endif
    676 
    677 	udprecvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
    678 
    679 	while (1) {
    680 		for (i = 0; i < to_fill; i++) {
    681 			/* Not getting the packet header. Tests with chain of one run
    682 			   as usual without having the packet header.
    683 			   Have tried both sending and receiving
    684 			 */
    685 			udprecvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
    686 #if !defined(__Userspace_os_Windows)
    687 			iov[i].iov_base = (caddr_t)udprecvmbuf[i]->m_data;
    688 			iov[i].iov_len = iovlen;
    689 #else
    690 			iov[i].buf = (caddr_t)udprecvmbuf[i]->m_data;
    691 			iov[i].len = iovlen;
    692 #endif
    693 		}
    694 		to_fill = 0;
    695 #if !defined(__Userspace_os_Windows)
    696 		bzero((void *)&msg, sizeof(struct msghdr));
    697 #else
    698 		bzero((void *)&msg, sizeof(WSAMSG));
    699 #endif
    700 		bzero((void *)&src, sizeof(struct sockaddr_in));
    701 		bzero((void *)&dst, sizeof(struct sockaddr_in));
    702 		bzero((void *)cmsgbuf, sizeof(cmsgbuf));
    703 
    704 #if !defined(__Userspace_os_Windows)
    705 		msg.msg_name = (void *)&src;
    706 		msg.msg_namelen = sizeof(struct sockaddr_in);
    707 		msg.msg_iov = iov;
    708 		msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
    709 		msg.msg_control = (void *)cmsgbuf;
    710 		msg.msg_controllen = sizeof(cmsgbuf);
    711 		msg.msg_flags = 0;
    712 
    713 		ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, 0);
    714 		if (n < 0) {
    715 			if (errno == EAGAIN) {
    716 				continue;
    717 			} else {
    718 				break;
    719 			}
    720 		}
    721 #else
    722 		nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp), SIO_GET_EXTENSION_FUNCTION_POINTER,
    723 		 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
    724 		 &WSARecvMsg, sizeof WSARecvMsg,
    725 		 &ncounter, NULL, NULL);
    726 		if (nResult == 0) {
    727 			msg.name = (void *)&src;
    728 			msg.namelen = sizeof(struct sockaddr_in);
    729 			msg.lpBuffers = iov;
    730 			msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
    731 			msg.Control.len = sizeof ControlBuffer;
    732 			msg.Control.buf = ControlBuffer;
    733 			msg.dwFlags = 0;
    734 			nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, &ncounter, NULL, NULL);
    735 		}
    736 		if (nResult != 0) {
    737 			m_ErrorCode = WSAGetLastError();
    738 			if (m_ErrorCode == WSAETIMEDOUT) {
    739 				continue;
    740 			}
    741 			if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
    742 				break;
    743 			}
    744 		}
    745 		n = ncounter;
    746 #endif
    747 		SCTP_HEADER_LEN(udprecvmbuf[0]) = n; /* length of total packet */
    748 		SCTP_STAT_INCR(sctps_recvpackets);
    749 		SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
    750 
    751 		if (n <= iovlen) {
    752 			SCTP_BUF_LEN(udprecvmbuf[0]) = n;
    753 			(to_fill)++;
    754 		} else {
    755 			i = 0;
    756 			SCTP_BUF_LEN(udprecvmbuf[0]) = iovlen;
    757 
    758 			ncounter -= iovlen;
    759 			(to_fill)++;
    760 			do {
    761 				udprecvmbuf[i]->m_next = udprecvmbuf[i+1];
    762 				SCTP_BUF_LEN(udprecvmbuf[i]->m_next) = min(ncounter, iovlen);
    763 				i++;
    764 				ncounter -= iovlen;
    765 				(to_fill)++;
    766 			} while (ncounter > 0);
    767 		}
    768 
    769 		for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
    770 #if defined(IP_PKTINFO)
    771 			if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_PKTINFO)) {
    772 				struct in_pktinfo *info;
    773 
    774 				dst.sin_family = AF_INET;
    775 #ifdef HAVE_SIN_LEN
    776 				dst.sin_len = sizeof(struct sockaddr_in);
    777 #endif
    778 				info = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
    779 				memcpy((void *)&dst.sin_addr, (const void *)&(info->ipi_addr), sizeof(struct in_addr));
    780 				break;
    781 			}
    782 #else
    783 			if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_RECVDSTADDR)) {
    784 				struct in_addr *addr;
    785 
    786 				dst.sin_family = AF_INET;
    787 #ifdef HAVE_SIN_LEN
    788 				dst.sin_len = sizeof(struct sockaddr_in);
    789 #endif
    790 				addr = (struct in_addr *)CMSG_DATA(cmsgptr);
    791 				memcpy((void *)&dst.sin_addr, (const void *)addr, sizeof(struct in_addr));
    792 				break;
    793 			}
    794 #endif
    795 		}
    796 
    797 		/* SCTP does not allow broadcasts or multicasts */
    798 		if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
    799 			return (NULL);
    800 		}
    801 		if (SCTP_IS_IT_BROADCAST(dst.sin_addr, udprecvmbuf[0])) {
    802 			return (NULL);
    803 		}
    804 
    805 		/*offset = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);*/
    806 		sh = mtod(udprecvmbuf[0], struct sctphdr *);
    807 		ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
    808 		offset = sizeof(struct sctphdr);
    809 		port = src.sin_port;
    810 		src.sin_port = sh->src_port;
    811 		dst.sin_port = sh->dest_port;
    812 #if defined(SCTP_WITH_NO_CSUM)
    813 		SCTP_STAT_INCR(sctps_recvnocrc);
    814 #else
    815 		if (src.sin_addr.s_addr == dst.sin_addr.s_addr) {
    816 			compute_crc = 0;
    817 			SCTP_STAT_INCR(sctps_recvnocrc);
    818 		} else {
    819 			SCTP_STAT_INCR(sctps_recvswcrc);
    820 		}
    821 #endif
    822 		SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
    823 		SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
    824 		sctp_common_input_processing(&udprecvmbuf[0], 0, offset, n,
    825 		                             (struct sockaddr *)&src,
    826 		                             (struct sockaddr *)&dst,
    827 		                             sh, ch,
    828 #if !defined(SCTP_WITH_NO_CSUM)
    829 		                             compute_crc,
    830 #endif
    831 		                             0,
    832 		                             SCTP_DEFAULT_VRFID, port);
    833 		if (udprecvmbuf[0]) {
    834 			m_freem(udprecvmbuf[0]);
    835 		}
    836 	}
    837 	for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
    838 		m_free(udprecvmbuf[i]);
    839 	}
    840 	/* free the array itself */
    841 	free(udprecvmbuf);
    842 	return (NULL);
    843 }
    844 #endif
    845 
    846 #if defined(INET6)
    847 static void *
    848 recv_function_udp6(void *arg)
    849 {
    850 	struct mbuf **udprecvmbuf6;
    851 	/*Initially the entire set of mbufs is to be allocated.
    852 	  to_fill indicates this amount. */
    853 	int to_fill = MAXLEN_MBUF_CHAIN;
    854 	/* iovlen is the size of each mbuf in the chain */
    855 	int i, n, ncounter, offset;
    856 	int iovlen = MCLBYTES;
    857 	int want_ext = (iovlen > MLEN)? 1 : 0;
    858 	int want_header = 0;
    859 	struct sockaddr_in6 src, dst;
    860 	struct sctphdr *sh;
    861 	uint16_t port;
    862 	struct sctp_chunkhdr *ch;
    863 	char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
    864 #if !defined(SCTP_WITH_NO_CSUM)
    865 	int compute_crc = 1;
    866 #endif
    867 #if !defined(__Userspace_os_Windows)
    868 	struct iovec iov[MAXLEN_MBUF_CHAIN];
    869 	struct msghdr msg;
    870 	struct cmsghdr *cmsgptr;
    871 #else
    872 	GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
    873 	LPFN_WSARECVMSG WSARecvMsg;
    874 	char ControlBuffer[1024];
    875 	WSABUF iov[MAXLEN_MBUF_CHAIN];
    876 	WSAMSG msg;
    877 	int nResult, m_ErrorCode;
    878 	WSACMSGHDR *cmsgptr;
    879 #endif
    880 
    881 	udprecvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
    882 	while (1) {
    883 		for (i = 0; i < to_fill; i++) {
    884 			/* Not getting the packet header. Tests with chain of one run
    885 			   as usual without having the packet header.
    886 			   Have tried both sending and receiving
    887 			 */
    888 			udprecvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
    889 #if !defined(__Userspace_os_Windows)
    890 			iov[i].iov_base = (caddr_t)udprecvmbuf6[i]->m_data;
    891 			iov[i].iov_len = iovlen;
    892 #else
    893 			iov[i].buf = (caddr_t)udprecvmbuf6[i]->m_data;
    894 			iov[i].len = iovlen;
    895 #endif
    896 		}
    897 		to_fill = 0;
    898 
    899 #if !defined(__Userspace_os_Windows)
    900 		bzero((void *)&msg, sizeof(struct msghdr));
    901 #else
    902 		bzero((void *)&msg, sizeof(WSAMSG));
    903 #endif
    904 		bzero((void *)&src, sizeof(struct sockaddr_in6));
    905 		bzero((void *)&dst, sizeof(struct sockaddr_in6));
    906 		bzero((void *)cmsgbuf, CMSG_SPACE(sizeof (struct in6_pktinfo)));
    907 
    908 #if !defined(__Userspace_os_Windows)
    909 		msg.msg_name = (void *)&src;
    910 		msg.msg_namelen = sizeof(struct sockaddr_in6);
    911 		msg.msg_iov = iov;
    912 		msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
    913 		msg.msg_control = (void *)cmsgbuf;
    914 		msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof (struct in6_pktinfo));
    915 		msg.msg_flags = 0;
    916 
    917 		ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, 0);
    918 		if (n < 0) {
    919 			if (errno == EAGAIN) {
    920 				continue;
    921 			} else {
    922 				break;
    923 			}
    924 		}
    925 #else
    926 		nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER,
    927 		                   &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
    928 		                   &WSARecvMsg, sizeof WSARecvMsg,
    929 		                   &ncounter, NULL, NULL);
    930 		if (nResult == SOCKET_ERROR) {
    931 			m_ErrorCode = WSAGetLastError();
    932 			WSARecvMsg = NULL;
    933 		}
    934 		if (nResult == 0) {
    935 			msg.name = (void *)&src;
    936 			msg.namelen = sizeof(struct sockaddr_in6);
    937 			msg.lpBuffers = iov;
    938 			msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
    939 			msg.Control.len = sizeof ControlBuffer;
    940 			msg.Control.buf = ControlBuffer;
    941 			msg.dwFlags = 0;
    942 			nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, &ncounter, NULL, NULL);
    943 		}
    944 		if (nResult != 0) {
    945 			m_ErrorCode = WSAGetLastError();
    946 			if (m_ErrorCode == WSAETIMEDOUT) {
    947 				continue;
    948 			}
    949 			if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
    950 				break;
    951 			}
    952 		}
    953 		n = ncounter;
    954 #endif
    955 		SCTP_HEADER_LEN(udprecvmbuf6[0]) = n; /* length of total packet */
    956 		SCTP_STAT_INCR(sctps_recvpackets);
    957 		SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
    958 
    959 		if (n <= iovlen) {
    960 			SCTP_BUF_LEN(udprecvmbuf6[0]) = n;
    961 			(to_fill)++;
    962 		} else {
    963 			i = 0;
    964 			SCTP_BUF_LEN(udprecvmbuf6[0]) = iovlen;
    965 
    966 			ncounter -= iovlen;
    967 			(to_fill)++;
    968 			do {
    969 				udprecvmbuf6[i]->m_next = udprecvmbuf6[i+1];
    970 				SCTP_BUF_LEN(udprecvmbuf6[i]->m_next) = min(ncounter, iovlen);
    971 				i++;
    972 				ncounter -= iovlen;
    973 				(to_fill)++;
    974 			} while (ncounter > 0);
    975 		}
    976 
    977 		for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
    978 			if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) {
    979 				struct in6_pktinfo *info;
    980 
    981 				dst.sin6_family = AF_INET6;
    982 #ifdef HAVE_SIN6_LEN
    983 				dst.sin6_len = sizeof(struct sockaddr_in6);
    984 #endif
    985 				info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
    986 				/*dst.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));*/
    987 				memcpy((void *)&dst.sin6_addr, (const void *)&(info->ipi6_addr), sizeof(struct in6_addr));
    988 			}
    989 		}
    990 
    991 		/* SCTP does not allow broadcasts or multicasts */
    992 		if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) {
    993 			return (NULL);
    994 		}
    995 
    996 		sh = mtod(udprecvmbuf6[0], struct sctphdr *);
    997 		ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
    998 		offset = sizeof(struct sctphdr);
    999 
   1000 		port = src.sin6_port;
   1001 		src.sin6_port = sh->src_port;
   1002 		dst.sin6_port = sh->dest_port;
   1003 #if defined(SCTP_WITH_NO_CSUM)
   1004 		SCTP_STAT_INCR(sctps_recvnocrc);
   1005 #else
   1006 		if ((memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0)) {
   1007 			compute_crc = 0;
   1008 			SCTP_STAT_INCR(sctps_recvnocrc);
   1009 		} else {
   1010 			SCTP_STAT_INCR(sctps_recvswcrc);
   1011 		}
   1012 #endif
   1013 		SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
   1014 		SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", (int)sizeof(struct sctphdr));
   1015 		sctp_common_input_processing(&udprecvmbuf6[0], 0, offset, n,
   1016 		                             (struct sockaddr *)&src,
   1017 		                             (struct sockaddr *)&dst,
   1018 		                             sh, ch,
   1019 #if !defined(SCTP_WITH_NO_CSUM)
   1020 		                             compute_crc,
   1021 #endif
   1022 		                             0,
   1023 		                             SCTP_DEFAULT_VRFID, port);
   1024 		if (udprecvmbuf6[0]) {
   1025 			m_freem(udprecvmbuf6[0]);
   1026 		}
   1027 	}
   1028 	for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
   1029 		m_free(udprecvmbuf6[i]);
   1030 	}
   1031 	/* free the array itself */
   1032 	free(udprecvmbuf6);
   1033 	return (NULL);
   1034 }
   1035 #endif
   1036 
   1037 static void
   1038 setReceiveBufferSize(int sfd, int new_size)
   1039 {
   1040 	int ch = new_size;
   1041 
   1042 	if (setsockopt (sfd, SOL_SOCKET, SO_RCVBUF, (void*)&ch, sizeof(ch)) < 0) {
   1043 #if defined (__Userspace_os_Windows)
   1044 		SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", WSAGetLastError());
   1045 #else
   1046 		SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", errno);
   1047 #endif
   1048 	}
   1049 	return;
   1050 }
   1051 
   1052 static void
   1053 setSendBufferSize(int sfd, int new_size)
   1054 {
   1055 	int ch = new_size;
   1056 
   1057 	if (setsockopt (sfd, SOL_SOCKET, SO_SNDBUF, (void*)&ch, sizeof(ch)) < 0) {
   1058 #if defined (__Userspace_os_Windows)
   1059 		SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", WSAGetLastError());
   1060 #else
   1061 		SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", errno);
   1062 #endif
   1063 	}
   1064 	return;
   1065 }
   1066 
   1067 #define SOCKET_TIMEOUT 100 /* in ms */
   1068 void
   1069 recv_thread_init(void)
   1070 {
   1071 #if defined(INET)
   1072 	struct sockaddr_in addr_ipv4;
   1073 	const int hdrincl = 1;
   1074 #endif
   1075 #if defined(INET6)
   1076 	struct sockaddr_in6 addr_ipv6;
   1077 #endif
   1078 #if defined(INET) || defined(INET6)
   1079 	const int on = 1;
   1080 #endif
   1081 #if !defined(__Userspace_os_Windows)
   1082 	struct timeval timeout;
   1083 
   1084 	timeout.tv_sec  = (SOCKET_TIMEOUT / 1000);
   1085 	timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
   1086 #else
   1087 	unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */
   1088 #endif
   1089 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
   1090 	if (SCTP_BASE_VAR(userspace_route) == -1) {
   1091 		if ((SCTP_BASE_VAR(userspace_route) = socket(AF_ROUTE, SOCK_RAW, 0)) < 0) {
   1092 			SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d).\n", errno);
   1093 		}
   1094 #if 0
   1095 		struct sockaddr_nl sanl;
   1096 
   1097 		if ((SCTP_BASE_VAR(userspace_route) = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
   1098 			SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d.\n", errno);
   1099 		}
   1100 		memset(&sanl, 0, sizeof(sanl));
   1101 		sanl.nl_family = AF_NETLINK;
   1102 		sanl.nl_groups = 0;
   1103 #ifdef INET
   1104 		sanl.nl_groups |= RTMGRP_IPV4_IFADDR;
   1105 #endif
   1106 #ifdef INET6
   1107 		sanl.nl_groups |= RTMGRP_IPV6_IFADDR;
   1108 #endif
   1109 		if (bind(SCTP_BASE_VAR(userspace_route), (struct sockaddr *) &sanl, sizeof(sanl)) < 0) {
   1110 			SCTPDBG(SCTP_DEBUG_USR, "Can't bind routing socket (errno = %d).\n", errno);
   1111 			close(SCTP_BASE_VAR(userspace_route));
   1112 			SCTP_BASE_VAR(userspace_route) = -1;
   1113 		}
   1114 #endif
   1115 		if (SCTP_BASE_VAR(userspace_route) != -1) {
   1116 			if (setsockopt(SCTP_BASE_VAR(userspace_route), SOL_SOCKET, SO_RCVTIMEO,(const void*)&timeout, sizeof(struct timeval)) < 0) {
   1117 				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on routing socket (errno = %d).\n", errno);
   1118 #if defined(__Userspace_os_Windows)
   1119 				closesocket(SCTP_BASE_VAR(userspace_route));
   1120 #else
   1121 				close(SCTP_BASE_VAR(userspace_route));
   1122 #endif
   1123 				SCTP_BASE_VAR(userspace_route) = -1;
   1124 			}
   1125 		}
   1126 	}
   1127 #endif
   1128 #if defined(INET)
   1129 	if (SCTP_BASE_VAR(userspace_rawsctp) == -1) {
   1130 		if ((SCTP_BASE_VAR(userspace_rawsctp) = socket(AF_INET, SOCK_RAW, IPPROTO_SCTP)) < 0) {
   1131 #if defined(__Userspace_os_Windows)
   1132 			SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", WSAGetLastError());
   1133 #else
   1134 			SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", errno);
   1135 #endif
   1136 		} else {
   1137 			/* complete setting up the raw SCTP socket */
   1138 			if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), IPPROTO_IP, IP_HDRINCL,(const void*)&hdrincl, sizeof(int)) < 0) {
   1139 #if defined(__Userspace_os_Windows)
   1140 				SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", WSAGetLastError());
   1141 				closesocket(SCTP_BASE_VAR(userspace_rawsctp));
   1142 #else
   1143 				SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", errno);
   1144 				close(SCTP_BASE_VAR(userspace_rawsctp));
   1145 #endif
   1146 				SCTP_BASE_VAR(userspace_rawsctp) = -1;
   1147 			} else if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
   1148 #if defined(__Userspace_os_Windows)
   1149 				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError());
   1150 				closesocket(SCTP_BASE_VAR(userspace_rawsctp));
   1151 #else
   1152 				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", errno);
   1153 				close(SCTP_BASE_VAR(userspace_rawsctp));
   1154 #endif
   1155 				SCTP_BASE_VAR(userspace_rawsctp) = -1;
   1156 			} else {
   1157 				memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in));
   1158 #ifdef HAVE_SIN_LEN
   1159 				addr_ipv4.sin_len         = sizeof(struct sockaddr_in);
   1160 #endif
   1161 				addr_ipv4.sin_family      = AF_INET;
   1162 				addr_ipv4.sin_port        = htons(0);
   1163 				addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
   1164 				if (bind(SCTP_BASE_VAR(userspace_rawsctp), (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) {
   1165 #if defined(__Userspace_os_Windows)
   1166 					SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError());
   1167 					closesocket(SCTP_BASE_VAR(userspace_rawsctp));
   1168 #else
   1169 					SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", errno);
   1170 					close(SCTP_BASE_VAR(userspace_rawsctp));
   1171 #endif
   1172 					SCTP_BASE_VAR(userspace_rawsctp) = -1;
   1173 				} else {
   1174 					setReceiveBufferSize(SCTP_BASE_VAR(userspace_rawsctp), SB_RAW); /* 128K */
   1175 					setSendBufferSize(SCTP_BASE_VAR(userspace_rawsctp), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
   1176 				}
   1177 			}
   1178 		}
   1179 	}
   1180 	if (SCTP_BASE_VAR(userspace_udpsctp) == -1) {
   1181 		if ((SCTP_BASE_VAR(userspace_udpsctp) = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
   1182 #if defined(__Userspace_os_Windows)
   1183 			SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
   1184 #else
   1185 			SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
   1186 #endif
   1187 		} else {
   1188 #if defined(IP_PKTINFO)
   1189 			if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
   1190 #else
   1191 			if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_RECVDSTADDR, (const void *)&on, (int)sizeof(int)) < 0) {
   1192 #endif
   1193 #if defined(__Userspace_os_Windows)
   1194 #if defined(IP_PKTINFO)
   1195 				SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
   1196 #else
   1197 				SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
   1198 #endif
   1199 				closesocket(SCTP_BASE_VAR(userspace_udpsctp));
   1200 #else
   1201 #if defined(IP_PKTINFO)
   1202 				SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
   1203 #else
   1204 				SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
   1205 #endif
   1206 				close(SCTP_BASE_VAR(userspace_udpsctp));
   1207 #endif
   1208 				SCTP_BASE_VAR(userspace_udpsctp) = -1;
   1209 			} else if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
   1210 #if defined(__Userspace_os_Windows)
   1211 				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
   1212 				closesocket(SCTP_BASE_VAR(userspace_udpsctp));
   1213 #else
   1214 				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
   1215 				close(SCTP_BASE_VAR(userspace_udpsctp));
   1216 #endif
   1217 				SCTP_BASE_VAR(userspace_udpsctp) = -1;
   1218 			} else {
   1219 				memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in));
   1220 #ifdef HAVE_SIN_LEN
   1221 				addr_ipv4.sin_len         = sizeof(struct sockaddr_in);
   1222 #endif
   1223 				addr_ipv4.sin_family      = AF_INET;
   1224 				addr_ipv4.sin_port        = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
   1225 				addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
   1226 				if (bind(SCTP_BASE_VAR(userspace_udpsctp), (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) {
   1227 #if defined(__Userspace_os_Windows)
   1228 					SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
   1229 					closesocket(SCTP_BASE_VAR(userspace_udpsctp));
   1230 #else
   1231 					SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
   1232 					close(SCTP_BASE_VAR(userspace_udpsctp));
   1233 #endif
   1234 					SCTP_BASE_VAR(userspace_udpsctp) = -1;
   1235 				} else {
   1236 					setReceiveBufferSize(SCTP_BASE_VAR(userspace_udpsctp), SB_RAW); /* 128K */
   1237 					setSendBufferSize(SCTP_BASE_VAR(userspace_udpsctp), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
   1238 				}
   1239 			}
   1240 		}
   1241 	}
   1242 #endif
   1243 #if defined(INET6)
   1244 	if (SCTP_BASE_VAR(userspace_rawsctp6) == -1) {
   1245 		if ((SCTP_BASE_VAR(userspace_rawsctp6) = socket(AF_INET6, SOCK_RAW, IPPROTO_SCTP)) < 0) {
   1246 #if defined(__Userspace_os_Windows)
   1247 			SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
   1248 #else
   1249 			SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", errno);
   1250 #endif
   1251 		} else {
   1252 			/* complete setting up the raw SCTP socket */
   1253 #if defined(IPV6_RECVPKTINFO)
   1254 			if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, sizeof(on)) < 0) {
   1255 #if defined(__Userspace_os_Windows)
   1256 				SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
   1257 				closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
   1258 #else
   1259 				SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno);
   1260 				close(SCTP_BASE_VAR(userspace_rawsctp6));
   1261 #endif
   1262 				SCTP_BASE_VAR(userspace_rawsctp6) = -1;
   1263 			} else {
   1264 #else
   1265 			if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_PKTINFO,(const void*)&on, sizeof(on)) < 0) {
   1266 #if defined(__Userspace_os_Windows)
   1267 				SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
   1268 				closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
   1269 #else
   1270 				SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno);
   1271 				close(SCTP_BASE_VAR(userspace_rawsctp6));
   1272 #endif
   1273 				SCTP_BASE_VAR(userspace_rawsctp6) = -1;
   1274 			} else {
   1275 #endif
   1276 				if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&on, (socklen_t)sizeof(on)) < 0) {
   1277 #if defined(__Userspace_os_Windows)
   1278 					SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
   1279 #else
   1280 					SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", errno);
   1281 #endif
   1282 				}
   1283 				if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
   1284 #if defined(__Userspace_os_Windows)
   1285 					SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
   1286 					closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
   1287 #else
   1288 					SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", errno);
   1289 					close(SCTP_BASE_VAR(userspace_rawsctp6));
   1290 #endif
   1291 					SCTP_BASE_VAR(userspace_rawsctp6) = -1;
   1292 				} else {
   1293 					memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6));
   1294 #ifdef HAVE_SIN6_LEN
   1295 					addr_ipv6.sin6_len         = sizeof(struct sockaddr_in6);
   1296 #endif
   1297 					addr_ipv6.sin6_family      = AF_INET6;
   1298 					addr_ipv6.sin6_port        = htons(0);
   1299 					addr_ipv6.sin6_addr        = in6addr_any;
   1300 					if (bind(SCTP_BASE_VAR(userspace_rawsctp6), (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) {
   1301 #if defined(__Userspace_os_Windows)
   1302 						SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
   1303 						closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
   1304 #else
   1305 						SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", errno);
   1306 						close(SCTP_BASE_VAR(userspace_rawsctp6));
   1307 #endif
   1308 						SCTP_BASE_VAR(userspace_rawsctp6) = -1;
   1309 					} else {
   1310 						setReceiveBufferSize(SCTP_BASE_VAR(userspace_rawsctp6), SB_RAW); /* 128K */
   1311 						setSendBufferSize(SCTP_BASE_VAR(userspace_rawsctp6), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
   1312 					}
   1313 				}
   1314 			}
   1315 		}
   1316 	}
   1317 	if (SCTP_BASE_VAR(userspace_udpsctp6) == -1) {
   1318 		if ((SCTP_BASE_VAR(userspace_udpsctp6) = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
   1319 #if defined(__Userspace_os_Windows)
   1320 			SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
   1321 #else
   1322 			SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
   1323 #endif
   1324 		}
   1325 #if defined(IPV6_RECVPKTINFO)
   1326 		if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
   1327 #if defined(__Userspace_os_Windows)
   1328 			SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
   1329 			closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
   1330 #else
   1331 			SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
   1332 			close(SCTP_BASE_VAR(userspace_udpsctp6));
   1333 #endif
   1334 			SCTP_BASE_VAR(userspace_udpsctp6) = -1;
   1335 		} else {
   1336 #else
   1337 		if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
   1338 #if defined(__Userspace_os_Windows)
   1339 			SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
   1340 			closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
   1341 #else
   1342 			SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
   1343 			close(SCTP_BASE_VAR(userspace_udpsctp6));
   1344 #endif
   1345 			SCTP_BASE_VAR(userspace_udpsctp6) = -1;
   1346 		} else {
   1347 #endif
   1348 			if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&on, (socklen_t)sizeof(on)) < 0) {
   1349 #if defined(__Userspace_os_Windows)
   1350 				SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
   1351 #else
   1352 				SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
   1353 #endif
   1354 			}
   1355 			if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
   1356 #if defined(__Userspace_os_Windows)
   1357 				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
   1358 				closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
   1359 #else
   1360 				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
   1361 				close(SCTP_BASE_VAR(userspace_udpsctp6));
   1362 #endif
   1363 				SCTP_BASE_VAR(userspace_udpsctp6) = -1;
   1364 			} else {
   1365 				memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6));
   1366 #ifdef HAVE_SIN6_LEN
   1367 				addr_ipv6.sin6_len         = sizeof(struct sockaddr_in6);
   1368 #endif
   1369 				addr_ipv6.sin6_family      = AF_INET6;
   1370 				addr_ipv6.sin6_port        = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
   1371 				addr_ipv6.sin6_addr        = in6addr_any;
   1372 				if (bind(SCTP_BASE_VAR(userspace_udpsctp6), (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) {
   1373 #if defined(__Userspace_os_Windows)
   1374 					SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
   1375 					closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
   1376 #else
   1377 					SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
   1378 					close(SCTP_BASE_VAR(userspace_udpsctp6));
   1379 #endif
   1380 					SCTP_BASE_VAR(userspace_udpsctp6) = -1;
   1381 				} else {
   1382 					setReceiveBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K */
   1383 					setSendBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
   1384 				}
   1385 			}
   1386 		}
   1387 	}
   1388 #endif
   1389 #if !defined(__Userspace_os_Windows)
   1390 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
   1391 #if defined(INET) || defined(INET6)
   1392 	if (SCTP_BASE_VAR(userspace_route) != -1) {
   1393 		int rc;
   1394 
   1395 		if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadroute), NULL, &recv_function_route, NULL))) {
   1396 			SCTPDBG(SCTP_DEBUG_USR, "Can't start routing thread (%d).\n", rc);
   1397 			close(SCTP_BASE_VAR(userspace_route));
   1398 			SCTP_BASE_VAR(userspace_route) = -1;
   1399 		}
   1400 	}
   1401 #endif
   1402 #endif
   1403 #if defined(INET)
   1404 	if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
   1405 		int rc;
   1406 
   1407 		if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw), NULL, &recv_function_raw, NULL))) {
   1408 			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread (%d).\n", rc);
   1409 			close(SCTP_BASE_VAR(userspace_rawsctp));
   1410 			SCTP_BASE_VAR(userspace_rawsctp) = -1;
   1411 		}
   1412 	}
   1413 	if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
   1414 		int rc;
   1415 
   1416 		if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp), NULL, &recv_function_udp, NULL))) {
   1417 			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread (%d).\n", rc);
   1418 			close(SCTP_BASE_VAR(userspace_udpsctp));
   1419 			SCTP_BASE_VAR(userspace_udpsctp) = -1;
   1420 		}
   1421 	}
   1422 #endif
   1423 #if defined(INET6)
   1424 	if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
   1425 		int rc;
   1426 
   1427 		if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw6), NULL, &recv_function_raw6, NULL))) {
   1428 			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread (%d).\n", rc);
   1429 			close(SCTP_BASE_VAR(userspace_rawsctp6));
   1430 			SCTP_BASE_VAR(userspace_rawsctp6) = -1;
   1431 		}
   1432 	}
   1433 	if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
   1434 		int rc;
   1435 
   1436 		if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp6), NULL, &recv_function_udp6, NULL))) {
   1437 			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread (%d).\n", rc);
   1438 			close(SCTP_BASE_VAR(userspace_udpsctp6));
   1439 			SCTP_BASE_VAR(userspace_udpsctp6) = -1;
   1440 		}
   1441 	}
   1442 #endif
   1443 #else
   1444 #if defined(INET)
   1445 	if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
   1446 		if ((SCTP_BASE_VAR(recvthreadraw) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw, NULL, 0, NULL)) == NULL) {
   1447 			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread.\n");
   1448 			closesocket(SCTP_BASE_VAR(userspace_rawsctp));
   1449 			SCTP_BASE_VAR(userspace_rawsctp) = -1;
   1450 		}
   1451 	}
   1452 	if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
   1453 		if ((SCTP_BASE_VAR(recvthreadudp) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp, NULL, 0, NULL)) == NULL) {
   1454 			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread.\n");
   1455 			closesocket(SCTP_BASE_VAR(userspace_udpsctp));
   1456 			SCTP_BASE_VAR(userspace_udpsctp) = -1;
   1457 		}
   1458 	}
   1459 #endif
   1460 #if defined(INET6)
   1461 	if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
   1462 		if ((SCTP_BASE_VAR(recvthreadraw6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw6, NULL, 0, NULL)) == NULL) {
   1463 			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread.\n");
   1464 			closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
   1465 			SCTP_BASE_VAR(userspace_rawsctp6) = -1;
   1466 		}
   1467 	}
   1468 	if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
   1469 		if ((SCTP_BASE_VAR(recvthreadudp6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp6, NULL, 0, NULL)) == NULL) {
   1470 			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread.\n");
   1471 			closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
   1472 			SCTP_BASE_VAR(userspace_udpsctp6) = -1;
   1473 		}
   1474 	}
   1475 #endif
   1476 #endif
   1477 }
   1478 
   1479 void
   1480 recv_thread_destroy(void)
   1481 {
   1482 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
   1483 #if defined(INET) || defined(INET6)
   1484 	if (SCTP_BASE_VAR(userspace_route) != -1) {
   1485 		close(SCTP_BASE_VAR(userspace_route));
   1486 	}
   1487 #endif
   1488 #endif
   1489 #if defined(INET)
   1490 	if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
   1491 #if defined(__Userspace_os_Windows)
   1492 		closesocket(SCTP_BASE_VAR(userspace_rawsctp));
   1493 #else
   1494 		close(SCTP_BASE_VAR(userspace_rawsctp));
   1495 #endif
   1496 	}
   1497 	if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
   1498 #if defined(__Userspace_os_Windows)
   1499 		closesocket(SCTP_BASE_VAR(userspace_udpsctp));
   1500 #else
   1501 		close(SCTP_BASE_VAR(userspace_udpsctp));
   1502 #endif
   1503 	}
   1504 #endif
   1505 #if defined(INET6)
   1506 	if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
   1507 #if defined(__Userspace_os_Windows)
   1508 		closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
   1509 #else
   1510 		close(SCTP_BASE_VAR(userspace_rawsctp6));
   1511 #endif
   1512 	}
   1513 	if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
   1514 #if defined(__Userspace_os_Windows)
   1515 		closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
   1516 #else
   1517 		close(SCTP_BASE_VAR(userspace_udpsctp6));
   1518 #endif
   1519 	}
   1520 #endif
   1521 }
   1522 #else
   1523 int foo;
   1524 #endif
   1525