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