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