/* free the array itself */ free(udprecvmbuf6); return (NULL); } #endif static void setReceiveBufferSize(int sfd, int new_size) { int ch = new_size; if (setsockopt (sfd, SOL_SOCKET, SO_RCVBUF, (void*)&ch, sizeof(ch)) < 0) { #if defined (__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", WSAGetLastError()); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", errno); #endif } return; } static void setSendBufferSize(int sfd, int new_size) { int ch = new_size; if (setsockopt (sfd, SOL_SOCKET, SO_SNDBUF, (void*)&ch, sizeof(ch)) < 0) { #if defined (__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", WSAGetLastError()); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", errno); #endif } return; } #define SOCKET_TIMEOUT 100 /* in ms */ void recv_thread_init(void) { #if defined(INET) struct sockaddr_in addr_ipv4; const int hdrincl = 1; #endif #if defined(INET6) struct sockaddr_in6 addr_ipv6; #endif #if defined(INET) || defined(INET6) const int on = 1; #endif #if !defined(__Userspace_os_Windows) struct timeval timeout; timeout.tv_sec = (SOCKET_TIMEOUT / 1000); timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000; #else unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */ #endif #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) if (SCTP_BASE_VAR(userspace_route) == -1) { if ((SCTP_BASE_VAR(userspace_route) = socket(AF_ROUTE, SOCK_RAW, 0)) < 0) { SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d).\n", errno); } #if 0 struct sockaddr_nl sanl; if ((SCTP_BASE_VAR(userspace_route) = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) { SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d.\n", errno); } memset(&sanl, 0, sizeof(sanl)); sanl.nl_family = AF_NETLINK; sanl.nl_groups = 0; #ifdef INET sanl.nl_groups |= RTMGRP_IPV4_IFADDR; #endif #ifdef INET6 sanl.nl_groups |= RTMGRP_IPV6_IFADDR; #endif if (bind(SCTP_BASE_VAR(userspace_route), (struct sockaddr *) &sanl, sizeof(sanl)) < 0) { SCTPDBG(SCTP_DEBUG_USR, "Can't bind routing socket (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_route)); SCTP_BASE_VAR(userspace_route) = -1; } #endif if (SCTP_BASE_VAR(userspace_route) != -1) { if (setsockopt(SCTP_BASE_VAR(userspace_route), SOL_SOCKET, SO_RCVTIMEO,(const void*)&timeout, sizeof(struct timeval)) < 0) { SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on routing socket (errno = %d).\n", errno); #if defined(__Userspace_os_Windows) closesocket(SCTP_BASE_VAR(userspace_route)); #else close(SCTP_BASE_VAR(userspace_route)); #endif SCTP_BASE_VAR(userspace_route) = -1; } } } #endif #if defined(INET) if (SCTP_BASE_VAR(userspace_rawsctp) == -1) { if ((SCTP_BASE_VAR(userspace_rawsctp) = socket(AF_INET, SOCK_RAW, IPPROTO_SCTP)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", WSAGetLastError()); #else SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", errno); #endif } else { /* complete setting up the raw SCTP socket */ if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), IPPROTO_IP, IP_HDRINCL,(const void*)&hdrincl, sizeof(int)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", WSAGetLastError()); closesocket(SCTP_BASE_VAR(userspace_rawsctp)); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_rawsctp)); #endif SCTP_BASE_VAR(userspace_rawsctp) = -1; } else if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError()); closesocket(SCTP_BASE_VAR(userspace_rawsctp)); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_rawsctp)); #endif SCTP_BASE_VAR(userspace_rawsctp) = -1; } else { memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in)); #ifdef HAVE_SIN_LEN addr_ipv4.sin_len = sizeof(struct sockaddr_in); #endif addr_ipv4.sin_family = AF_INET; addr_ipv4.sin_port = htons(0); addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(SCTP_BASE_VAR(userspace_rawsctp), (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError()); closesocket(SCTP_BASE_VAR(userspace_rawsctp)); #else SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_rawsctp)); #endif SCTP_BASE_VAR(userspace_rawsctp) = -1; } else { setReceiveBufferSize(SCTP_BASE_VAR(userspace_rawsctp), SB_RAW); /* 128K */ setSendBufferSize(SCTP_BASE_VAR(userspace_rawsctp), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */ } } } } if (SCTP_BASE_VAR(userspace_udpsctp) == -1) { if ((SCTP_BASE_VAR(userspace_udpsctp) = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError()); #else SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", errno); #endif } else { #if defined(IP_PKTINFO) if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) { #else if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_RECVDSTADDR, (const void *)&on, (int)sizeof(int)) < 0) { #endif #if defined(__Userspace_os_Windows) #if defined(IP_PKTINFO) SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError()); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError()); #endif closesocket(SCTP_BASE_VAR(userspace_udpsctp)); #else #if defined(IP_PKTINFO) SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno); #endif close(SCTP_BASE_VAR(userspace_udpsctp)); #endif SCTP_BASE_VAR(userspace_udpsctp) = -1; } else if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError()); closesocket(SCTP_BASE_VAR(userspace_udpsctp)); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_udpsctp)); #endif SCTP_BASE_VAR(userspace_udpsctp) = -1; } else { memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in)); #ifdef HAVE_SIN_LEN addr_ipv4.sin_len = sizeof(struct sockaddr_in); #endif addr_ipv4.sin_family = AF_INET; addr_ipv4.sin_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)); addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(SCTP_BASE_VAR(userspace_udpsctp), (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError()); closesocket(SCTP_BASE_VAR(userspace_udpsctp)); #else SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_udpsctp)); #endif SCTP_BASE_VAR(userspace_udpsctp) = -1; } else { setReceiveBufferSize(SCTP_BASE_VAR(userspace_udpsctp), SB_RAW); /* 128K */ setSendBufferSize(SCTP_BASE_VAR(userspace_udpsctp), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */ } } } } #endif #if defined(INET6) if (SCTP_BASE_VAR(userspace_rawsctp6) == -1) { if ((SCTP_BASE_VAR(userspace_rawsctp6) = socket(AF_INET6, SOCK_RAW, IPPROTO_SCTP)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError()); #else SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", errno); #endif } else { /* complete setting up the raw SCTP socket */ #if defined(IPV6_RECVPKTINFO) if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, sizeof(on)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError()); closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_rawsctp6)); #endif SCTP_BASE_VAR(userspace_rawsctp6) = -1; } else { #else if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_PKTINFO,(const void*)&on, sizeof(on)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError()); closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_rawsctp6)); #endif SCTP_BASE_VAR(userspace_rawsctp6) = -1; } else { #endif if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&on, (socklen_t)sizeof(on)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError()); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", errno); #endif } if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError()); closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_rawsctp6)); #endif SCTP_BASE_VAR(userspace_rawsctp6) = -1; } else { memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6)); #ifdef HAVE_SIN6_LEN addr_ipv6.sin6_len = sizeof(struct sockaddr_in6); #endif addr_ipv6.sin6_family = AF_INET6; addr_ipv6.sin6_port = htons(0); addr_ipv6.sin6_addr = in6addr_any; if (bind(SCTP_BASE_VAR(userspace_rawsctp6), (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError()); closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); #else SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_rawsctp6)); #endif SCTP_BASE_VAR(userspace_rawsctp6) = -1; } else { setReceiveBufferSize(SCTP_BASE_VAR(userspace_rawsctp6), SB_RAW); /* 128K */ setSendBufferSize(SCTP_BASE_VAR(userspace_rawsctp6), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */ } } } } } if (SCTP_BASE_VAR(userspace_udpsctp6) == -1) { if ((SCTP_BASE_VAR(userspace_udpsctp6) = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError()); #else SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", errno); #endif } #if defined(IPV6_RECVPKTINFO) if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, (int)sizeof(int)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError()); closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_udpsctp6)); #endif SCTP_BASE_VAR(userspace_udpsctp6) = -1; } else { #else if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError()); closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_udpsctp6)); #endif SCTP_BASE_VAR(userspace_udpsctp6) = -1; } else { #endif if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&on, (socklen_t)sizeof(on)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError()); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno); #endif } if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError()); closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); #else SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_udpsctp6)); #endif SCTP_BASE_VAR(userspace_udpsctp6) = -1; } else { memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6)); #ifdef HAVE_SIN6_LEN addr_ipv6.sin6_len = sizeof(struct sockaddr_in6); #endif addr_ipv6.sin6_family = AF_INET6; addr_ipv6.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)); addr_ipv6.sin6_addr = in6addr_any; if (bind(SCTP_BASE_VAR(userspace_udpsctp6), (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) { #if defined(__Userspace_os_Windows) SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError()); closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); #else SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", errno); close(SCTP_BASE_VAR(userspace_udpsctp6)); #endif SCTP_BASE_VAR(userspace_udpsctp6) = -1; } else { setReceiveBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K */ setSendBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */ } } } } #endif #if !defined(__Userspace_os_Windows) #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) #if defined(INET) || defined(INET6) if (SCTP_BASE_VAR(userspace_route) != -1) { int rc; if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadroute), NULL, &recv_function_route, NULL))) { SCTPDBG(SCTP_DEBUG_USR, "Can't start routing thread (%d).\n", rc); close(SCTP_BASE_VAR(userspace_route)); SCTP_BASE_VAR(userspace_route) = -1; } } #endif #endif #if defined(INET) if (SCTP_BASE_VAR(userspace_rawsctp) != -1) { int rc; if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw), NULL, &recv_function_raw, NULL))) { SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread (%d).\n", rc); close(SCTP_BASE_VAR(userspace_rawsctp)); SCTP_BASE_VAR(userspace_rawsctp) = -1; } } if (SCTP_BASE_VAR(userspace_udpsctp) != -1) { int rc; if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp), NULL, &recv_function_udp, NULL))) { SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread (%d).\n", rc); close(SCTP_BASE_VAR(userspace_udpsctp)); SCTP_BASE_VAR(userspace_udpsctp) = -1; } } #endif #if defined(INET6) if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) { int rc; if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw6), NULL, &recv_function_raw6, NULL))) { SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread (%d).\n", rc); close(SCTP_BASE_VAR(userspace_rawsctp6)); SCTP_BASE_VAR(userspace_rawsctp6) = -1; } } if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) { int rc; if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp6), NULL, &recv_function_udp6, NULL))) { SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread (%d).\n", rc); close(SCTP_BASE_VAR(userspace_udpsctp6)); SCTP_BASE_VAR(userspace_udpsctp6) = -1; } } #endif #else #if defined(INET) if (SCTP_BASE_VAR(userspace_rawsctp) != -1) { if ((SCTP_BASE_VAR(recvthreadraw) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw, NULL, 0, NULL)) == NULL) { SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread.\n"); closesocket(SCTP_BASE_VAR(userspace_rawsctp)); SCTP_BASE_VAR(userspace_rawsctp) = -1; } } if (SCTP_BASE_VAR(userspace_udpsctp) != -1) { if ((SCTP_BASE_VAR(recvthreadudp) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp, NULL, 0, NULL)) == NULL) { SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread.\n"); closesocket(SCTP_BASE_VAR(userspace_udpsctp)); SCTP_BASE_VAR(userspace_udpsctp) = -1; } } #endif #if defined(INET6) if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) { if ((SCTP_BASE_VAR(recvthreadraw6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw6, NULL, 0, NULL)) == NULL) { SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread.\n"); closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); SCTP_BASE_VAR(userspace_rawsctp6) = -1; } } if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) { if ((SCTP_BASE_VAR(recvthreadudp6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp6, NULL, 0, NULL)) == NULL) { SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread.\n"); closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); SCTP_BASE_VAR(userspace_udpsctp6) = -1; } } #endif #endif } void recv_thread_destroy(void) { #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) #if defined(INET) || defined(INET6) if (SCTP_BASE_VAR(userspace_route) != -1) { close(SCTP_BASE_VAR(userspace_route)); } #endif #endif #if defined(INET) if (SCTP_BASE_VAR(userspace_rawsctp) != -1) { #if defined(__Userspace_os_Windows) closesocket(SCTP_BASE_VAR(userspace_rawsctp)); #else close(SCTP_BASE_VAR(userspace_rawsctp)); #endif } if (SCTP_BASE_VAR(userspace_udpsctp) != -1) { #if defined(__Userspace_os_Windows) closesocket(SCTP_BASE_VAR(userspace_udpsctp)); #else close(SCTP_BASE_VAR(userspace_udpsctp)); #endif } #endif #if defined(INET6) if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) { #if defined(__Userspace_os_Windows) closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); #else close(SCTP_BASE_VAR(userspace_rawsctp6)); #endif } if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) { #if defined(__Userspace_os_Windows) closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); #else close(SCTP_BASE_VAR(userspace_udpsctp6)); #endif } #endif } #else int foo;
struct socket * sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error) { struct socket *newso; struct sctp_inpcb *inp, *n_inp; struct sctp_tcb *stcb; SCTPDBG(SCTP_DEBUG_PEEL1, "SCTP peel-off called\n"); inp = (struct sctp_inpcb *)head->so_pcb; if (inp == NULL) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT); *error = EFAULT; return (NULL); } stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); if (stcb == NULL) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN); *error = ENOTCONN; return (NULL); } atomic_add_int(&stcb->asoc.refcnt, 1); SCTP_TCB_UNLOCK(stcb); newso = sonewconn(head, SS_ISCONNECTED ); if (newso == NULL) { SCTPDBG(SCTP_DEBUG_PEEL1, "sctp_peeloff:sonewconn failed\n"); SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOMEM); *error = ENOMEM; atomic_subtract_int(&stcb->asoc.refcnt, 1); return (NULL); } SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); n_inp = (struct sctp_inpcb *)newso->so_pcb; SOCK_LOCK(head); n_inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE | SCTP_PCB_FLAGS_CONNECTED | SCTP_PCB_FLAGS_IN_TCPPOOL | /* Turn on Blocking IO */ (SCTP_PCB_COPY_FLAGS & inp->sctp_flags)); n_inp->sctp_features = inp->sctp_features; n_inp->sctp_frag_point = inp->sctp_frag_point; n_inp->partial_delivery_point = inp->partial_delivery_point; n_inp->sctp_context = inp->sctp_context; n_inp->inp_starting_point_for_iterator = NULL; /* copy in the authentication parameters from the original endpoint */ if (n_inp->sctp_ep.local_hmacs) sctp_free_hmaclist(n_inp->sctp_ep.local_hmacs); n_inp->sctp_ep.local_hmacs = sctp_copy_hmaclist(inp->sctp_ep.local_hmacs); if (n_inp->sctp_ep.local_auth_chunks) sctp_free_chunklist(n_inp->sctp_ep.local_auth_chunks); n_inp->sctp_ep.local_auth_chunks = sctp_copy_chunklist(inp->sctp_ep.local_auth_chunks); (void)sctp_copy_skeylist(&inp->sctp_ep.shared_keys, &n_inp->sctp_ep.shared_keys); n_inp->sctp_socket = newso; if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { sctp_feature_off(n_inp, SCTP_PCB_FLAGS_AUTOCLOSE); n_inp->sctp_ep.auto_close_time = 0; sctp_timer_stop(SCTP_TIMER_TYPE_AUTOCLOSE, n_inp, stcb, NULL, SCTP_FROM_SCTP_PEELOFF + SCTP_LOC_1); } /* Turn off any non-blocking semantic. */ SCTP_CLEAR_SO_NBIO(newso); newso->so_state |= SS_ISCONNECTED; /* We remove it right away */ #ifdef SCTP_LOCK_LOGGING if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) { sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK); } #endif TAILQ_REMOVE(&head->so_comp, newso, so_list); head->so_qlen--; SOCK_UNLOCK(head); /* * Now we must move it from one hash table to another and get the * stcb in the right place. */ sctp_move_pcb_and_assoc(inp, n_inp, stcb); atomic_add_int(&stcb->asoc.refcnt, 1); SCTP_TCB_UNLOCK(stcb); /* * And now the final hack. We move data in the pending side i.e. * head to the new socket buffer. Let the GRUBBING begin :-0 */ sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, SBL_WAIT); atomic_subtract_int(&stcb->asoc.refcnt, 1); return (newso); }
int main(int argc, char **argv) { int i, j; int size, align_size; char *s_buf, *r_buf; double t_start = 0.0, t_end = 0.0, t = 0.0; struct sockaddr_in *dest = malloc(sizeof(struct sockaddr_in)); struct sctp_sndrcvinfo sri; struct sockaddr_in cli; socklen_t s = sizeof(struct sockaddr_in); int msg_flags = 0; int n=-1; char mode[15]; struct timeval start, end; struct dp datapoints[DATAPOINTS]; int num_dp = 0; FILE *file; char filename[PRINTARRAY]; char ascii_size[PRINTARRAY]; int name[] = {CTL_KERN, KERN_OSTYPE}; int namelen = 2; char oldval[15]; size_t len = sizeof(oldval); int error; if (argc < 3) { printf("Usage: %s dst-ip dest-port\n", argv[0]); exit(1); } #if defined(SCTP_USERMODE) uint32_t optval=1; struct socket *psock = NULL; strcpy(mode, "Userspace"); #else //kernel mode int sock_fd; strcpy(mode, "Kernel"); #endif align_size = getpagesize(); assert(align_size <= MAX_ALIGNMENT); s_buf = (char *) (((unsigned long) s_buf1 + (align_size - 1)) / align_size * align_size); r_buf = (char *) (((unsigned long) r_buf1 + (align_size - 1)) / align_size * align_size); error = sysctl (name, namelen, (void *)oldval, &len, NULL /* newval */, 0 /* newlen */); if (error) { printf("sysctl() error\n"); exit(1); } strcpy(filename, "BWbenchmark"); sprintf(ascii_size,"%s%smode",oldval,mode); strcat(filename, ascii_size); strcat(filename,".txt"); #if defined(SCTP_USERMODE) sctp_init(); SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable)=1; if( !(psock = userspace_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) ){ printf("user_socket() returned NULL\n"); exit(1); } #else //Kernel mode if((sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) == -1) { printf("socket error\n"); exit(1); } #endif /* prepare destination adddress */ bzero(dest, sizeof(struct sockaddr_in)); dest->sin_family = AF_INET; dest->sin_addr.s_addr = inet_addr(argv[1]); dest->sin_port = htons((unsigned short) atoi(argv[2])); #if defined(__Userspace_os_FreeBSD) dest->sin_len = sizeof(struct sockaddr); #endif #if defined(SCTP_USERMODE) /* call userspace_connect which eventually calls sctp_send_initiate */ if( userspace_connect(psock, (struct sockaddr *) dest, sizeof(struct sockaddr_in)) == -1 ) { printf("userspace_connect failed. exiting...\n"); exit(1); } sctp_setopt(psock, SCTP_NODELAY, &optval, sizeof(uint32_t), NULL); #else //Kernel mode if((connect(sock_fd, (struct sockaddr *) dest, sizeof(struct sockaddr_in))) == -1) { perror("connect error\n"); exit(1); } /* Setting the send and receive socket buffer sizes */ const int maxbufsize = 65536 * 3; int sndrcvbufsize = maxbufsize; int sndrcvbufsize_len; int rc; sndrcvbufsize_len = sizeof(sndrcvbufsize); rc = setsockopt(sock_fd, SOL_SOCKET, SO_SNDBUF, &sndrcvbufsize, sndrcvbufsize_len); if (rc == -1) { perror("can't set the socket send size to requested one"); exit(1); } rc = setsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, &sndrcvbufsize, sndrcvbufsize_len); if (rc == -1) { perror("can't set the socket receive size to requested one"); exit(1); } /* turning nagle off */ int no_nagle = 1; if (setsockopt(sock_fd, IPPROTO_SCTP, SCTP_NODELAY, (char *) &no_nagle, sizeof(no_nagle)) < 0){ perror("can't setsockopt to no_nagle\n"); exit(1); } #endif num_dp = 0; int retval = 0; printf("\nRunning in %s mode\nStoring results in file %s\n\n", mode, filename); fprintf(stdout, "# %s %s\n", mode, "Mode: Bandwidth Benchmark Similar to OSU"); fprintf(stdout, "%-*s%*s\n", 10, "# Size", FIELD_WIDTH, "Bandwidth (MB/s)"); fflush(stdout); /* Bandwidth test */ for(size = 1; size <= MAX_MSG_SIZE; size *= 2) { /* touch the data */ for(i = 0; i < size; i++) { s_buf[i] = 'a'; r_buf[i] = 'b'; } if(size > large_message_size) { loop = loop_large; skip = skip_large; window_size = window_size_large; } for(i = 0; i < loop + skip; i++) { if(i == skip) { gettimeofday(&start, NULL); t_start = (double) start.tv_sec + .000001 * (double) start.tv_usec; } for(j = 0; j < window_size; j++) { #if defined(SCTP_USERMODE) if((retval = userspace_sctp_sendmsg(psock /* struct socket *so */, s_buf /* const void *data */, size /* size_t len */, (struct sockaddr *)dest /* const struct sockaddr *to */, sizeof(struct sockaddr_in) /* socklen_t tolen */, 0 /* u_int32_t ppid */, 0 /* u_int32_t flags */, 3 /* u_int16_t stream_no */, 0 /* u_int32_t timetolive */, 0 /* u_int32_t context */))<=0) { printf("userspace_sctp_sendmsg returned retval=%d errno=%d\n", retval, errno); exit(1); } #else //Kernel mode if ((retval = sctp_sendmsg(sock_fd, (void *)s_buf, (size_t)size, NULL, 0, 0, 0, 3, 0, 0)) <=0 ) { printf("sctp_sendmsg returned retval=%d errno=%d\n", retval, errno); exit(1); } #endif } #if defined(SCTP_USERMODE) if ((n = userspace_sctp_recvmsg(psock, r_buf, 4, (struct sockaddr *) &cli, &s, &sri, &msg_flags)) <=0 ) { printf(".....userspace_sctp_recvmsg returned n=%d errno=%d\n", n, errno); break; } #else //Kernel mode if ((n = sctp_recvmsg(sock_fd, r_buf, 4, (struct sockaddr *) &cli, &s, &sri, &msg_flags)) <=0 ) { printf("sctp_recvmsg returned n=%d errno=%d\n", n, errno); break; } #endif } gettimeofday(&end, NULL); t_end = (double) end.tv_sec + .000001 * (double) end.tv_usec; t = t_end - t_start; double tmp = size / 1e6 * loop * window_size; fprintf(stdout, "%-*d%*.*f\n", 10, size, FIELD_WIDTH, FLOAT_PRECISION, tmp / t); fflush(stdout); datapoints[num_dp].msg_size = size; datapoints[num_dp].tottime = t; datapoints[num_dp].bw = tmp/t; num_dp++; } printf("Client closing socket...errno=%d\n", errno); free(dest); #if defined(SCTP_USERMODE) userspace_close(psock); #else close(sock_fd); #endif printf("Sleeping for 60 secs\n"); sleep(60); file = fopen(filename, "w+"); if(file == NULL) { perror("could not open results file"); } else { for (j=0; j<num_dp; j++) { fprintf(file,"%d , %.2f , %.2f\n",datapoints[j].msg_size, datapoints[j].tottime, datapoints[j].bw); /*write datapoints to file*/ } fclose(file); } #if defined(SCTP_USERMODE) sctp_finish(); // pthread_exit(NULL); #endif return 0; }