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