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