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