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