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