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