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
67void 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)
76static void
77sctp_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
91static void
92sctp_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
149static void *
150recv_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 */
192static void *
193recv_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
274static void *
275recv_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)
452static void *
453recv_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
639static void *
640recv_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)
847static void *
848recv_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
1037static void
1038setReceiveBufferSize(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
1052static void
1053setSendBufferSize(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 */
1068void
1069recv_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
1479void
1480recv_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
1523int foo;
1524#endif
1525