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