/* __Userspace__ */ void m_clget(struct mbuf *m, int how) { caddr_t mclust_ret; if (m->m_flags & M_EXT) { SCTPDBG(SCTP_DEBUG_USR, "%s: %p mbuf already has cluster\n", __func__, (void *)m); } m->m_ext.ext_buf = (char *)NULL; #if USING_MBUF_CONSTRUCTOR set_clust_mb_args(m); #endif mclust_ret = SCTP_ZONE_GET(zone_clust, char); #if defined(SCTP_SIMPLE_ALLOCATOR) mb_ctor_clust(mclust_ret, &clust_mb_args, 0); #endif /*mclust_ret = umem_cache_alloc(zone_clust, UMEM_DEFAULT);*/ /* On a cluster allocation failure, call umem_reap() and retry. */ if (mclust_ret == NULL) { #if !defined(SCTP_SIMPLE_ALLOCATOR) /* mclust_ret = SCTP_ZONE_GET(zone_clust, char); mb_ctor_clust(mclust_ret, &clust_mb_args, 0); #else*/ umem_reap(); mclust_ret = SCTP_ZONE_GET(zone_clust, char); #endif /*mclust_ret = umem_cache_alloc(zone_clust, UMEM_DEFAULT);*/ if (NULL == mclust_ret) { SCTPDBG(SCTP_DEBUG_USR, "Memory allocation failure in %s\n", __func__); } }
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; }
static void sctp_handle_ifamsg(unsigned char type, unsigned short index, struct sockaddr *sa) { int rc; struct ifaddrs *ifa, *found_ifa = NULL; /* handle only the types we want */ if ((type != RTM_NEWADDR) && (type != RTM_DELADDR)) { return; } rc = getifaddrs(&g_interfaces); if (rc != 0) { return; } for (ifa = g_interfaces; ifa; ifa = ifa->ifa_next) { if (index == if_nametoindex(ifa->ifa_name)) { found_ifa = ifa; break; } } if (found_ifa == NULL) { return; } switch (sa->sa_family) { #ifdef INET case AF_INET: ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in)); memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in)); break; #endif #ifdef INET6 case AF_INET6: ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in6)); memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in6)); break; #endif default: SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", sa->sa_family); } /* relay the appropriate address change to the base code */ if (type == RTM_NEWADDR) { (void)sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, ifa, if_nametoindex(ifa->ifa_name), 0, ifa->ifa_name, (void *)ifa, ifa->ifa_addr, 0, 1); } else { sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr, if_nametoindex(ifa->ifa_name), ifa->ifa_name); } }
int sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af) { PIP_ADAPTER_ADDRESSES pAdapterAddrs, pAdapt; DWORD AdapterAddrsSize, Err; int ret; ret = 0; AdapterAddrsSize = 0; pAdapterAddrs = NULL; if ((Err = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &AdapterAddrsSize)) != 0) { if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) { SCTPDBG(SCTP_DEBUG_USR, "GetAdaptersAddresses() sizing failed with error code %d, AdapterAddrsSize = %d\n", Err, AdapterAddrsSize); ret = -1; goto cleanup; } } if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) { SCTPDBG(SCTP_DEBUG_USR, "Memory allocation error!\n"); ret = -1; goto cleanup; } if ((Err = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) { SCTPDBG(SCTP_DEBUG_USR, "GetAdaptersAddresses() failed with error code %d\n", Err); ret = -1; goto cleanup; } for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) { if (pAdapt->IfIndex == if_index) ret = pAdapt->Mtu; break; } cleanup: if (pAdapterAddrs != NULL) { GlobalFree(pAdapterAddrs); } return (ret); }
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 Win_getifaddrs(struct ifaddrs** interfaces) { int ret; #if defined(INET) || defined(INET6) DWORD Err, AdapterAddrsSize; int count; PIP_ADAPTER_ADDRESSES pAdapterAddrs, pAdapt; struct ifaddrs *ifa; #endif #if defined(INET) struct sockaddr_in *addr; #endif #if defined(INET6) struct sockaddr_in6 *addr6; #endif #if defined(INET) || defined(INET6) count = 0; #endif ret = 0; #if defined(INET) AdapterAddrsSize = 0; pAdapterAddrs = NULL; if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, NULL, &AdapterAddrsSize)) != 0) { if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) { SCTPDBG(SCTP_DEBUG_USR, "GetAdaptersV4Addresses() sizing failed with error code %d and AdapterAddrsSize = %d\n", Err, AdapterAddrsSize); ret = -1; goto cleanup; } } /* Allocate memory from sizing information */ if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) { SCTPDBG(SCTP_DEBUG_USR, "Memory allocation error!\n"); ret = -1; goto cleanup; } /* Get actual adapter information */ if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) { SCTPDBG(SCTP_DEBUG_USR, "GetAdaptersV4Addresses() failed with error code %d\n", Err); ret = -1; goto cleanup; } /* Enumerate through each returned adapter and save its information */ for (pAdapt = pAdapterAddrs, count; pAdapt; pAdapt = pAdapt->Next, count++) { addr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in)); ifa = (struct ifaddrs *)malloc(sizeof(struct ifaddrs)); if ((addr == NULL) || (ifa == NULL)) { SCTPDBG(SCTP_DEBUG_USR, "Can't allocate memory\n"); ret = -1; goto cleanup; } ifa->ifa_name = _strdup(pAdapt->AdapterName); ifa->ifa_flags = pAdapt->Flags; ifa->ifa_addr = (struct sockaddr *)addr; memcpy(addr, &pAdapt->FirstUnicastAddress->Address.lpSockaddr, sizeof(struct sockaddr_in)); interfaces[count] = ifa; } GlobalFree(pAdapterAddrs); #endif #if defined(INET6) AdapterAddrsSize = 0; pAdapterAddrs = NULL; if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, NULL, &AdapterAddrsSize)) != 0) { if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) { SCTPDBG(SCTP_DEBUG_USR, "GetAdaptersV6Addresses() sizing failed with error code %d AdapterAddrsSize = %d\n", Err, AdapterAddrsSize); ret = -1; goto cleanup; } } /* Allocate memory from sizing information */ if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) { SCTPDBG(SCTP_DEBUG_USR, "Memory allocation error!\n"); ret = -1; goto cleanup; } /* Get actual adapter information */ if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) { SCTPDBG(SCTP_DEBUG_USR, "GetAdaptersV6Addresses() failed with error code %d\n", Err); ret = -1; goto cleanup; } /* Enumerate through each returned adapter and save its information */ for (pAdapt = pAdapterAddrs, count; pAdapt; pAdapt = pAdapt->Next, count++) { addr6 = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6)); ifa = (struct ifaddrs *)malloc(sizeof(struct ifaddrs)); if ((addr6 == NULL) || (ifa == NULL)) { SCTPDBG(SCTP_DEBUG_USR, "Can't allocate memory\n"); ret = -1; goto cleanup; } ifa->ifa_name = _strdup(pAdapt->AdapterName); ifa->ifa_flags = pAdapt->Flags; ifa->ifa_addr = (struct sockaddr *)addr6; memcpy(addr6, &pAdapt->FirstUnicastAddress->Address.lpSockaddr, sizeof(struct sockaddr_in6)); interfaces[count] = ifa; } #endif cleanup: if (pAdapterAddrs != NULL) { GlobalFree(pAdapterAddrs); } return (ret); }
static void * recv_function_udp6(void *arg) { struct mbuf **udprecvmbuf6; /*Initially the entire set of mbufs is to be allocated. to_fill indicates this amount. */ int to_fill = MAXLEN_MBUF_CHAIN; /* iovlen is the size of each mbuf in the chain */ int i, n, ncounter, offset; int iovlen = MCLBYTES; int want_ext = (iovlen > MLEN)? 1 : 0; int want_header = 0; struct sockaddr_in6 src, dst; struct sctphdr *sh; uint16_t port; struct sctp_chunkhdr *ch; char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))]; #if !defined(SCTP_WITH_NO_CSUM) int compute_crc = 1; #endif #if !defined(__Userspace_os_Windows) struct iovec iov[MAXLEN_MBUF_CHAIN]; struct msghdr msg; struct cmsghdr *cmsgptr; #else GUID WSARecvMsg_GUID = WSAID_WSARECVMSG; LPFN_WSARECVMSG WSARecvMsg; char ControlBuffer[1024]; WSABUF iov[MAXLEN_MBUF_CHAIN]; WSAMSG msg; int nResult, m_ErrorCode; WSACMSGHDR *cmsgptr; #endif udprecvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN); while (1) { for (i = 0; i < to_fill; i++) { /* Not getting the packet header. Tests with chain of one run as usual without having the packet header. Have tried both sending and receiving */ udprecvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA); #if !defined(__Userspace_os_Windows) iov[i].iov_base = (caddr_t)udprecvmbuf6[i]->m_data; iov[i].iov_len = iovlen; #else iov[i].buf = (caddr_t)udprecvmbuf6[i]->m_data; iov[i].len = iovlen; #endif } to_fill = 0; #if !defined(__Userspace_os_Windows) bzero((void *)&msg, sizeof(struct msghdr)); #else bzero((void *)&msg, sizeof(WSAMSG)); #endif bzero((void *)&src, sizeof(struct sockaddr_in6)); bzero((void *)&dst, sizeof(struct sockaddr_in6)); bzero((void *)cmsgbuf, CMSG_SPACE(sizeof (struct in6_pktinfo))); #if !defined(__Userspace_os_Windows) msg.msg_name = (void *)&src; msg.msg_namelen = sizeof(struct sockaddr_in6); msg.msg_iov = iov; msg.msg_iovlen = MAXLEN_MBUF_CHAIN; msg.msg_control = (void *)cmsgbuf; msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof (struct in6_pktinfo)); msg.msg_flags = 0; ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, 0); if (n < 0) { if (errno == EAGAIN) { continue; } else { break; } } #else nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER, &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID, &WSARecvMsg, sizeof WSARecvMsg, &ncounter, NULL, NULL); if (nResult == SOCKET_ERROR) { m_ErrorCode = WSAGetLastError(); WSARecvMsg = NULL; } if (nResult == 0) { msg.name = (void *)&src; msg.namelen = sizeof(struct sockaddr_in6); msg.lpBuffers = iov; msg.dwBufferCount = MAXLEN_MBUF_CHAIN; msg.Control.len = sizeof ControlBuffer; msg.Control.buf = ControlBuffer; msg.dwFlags = 0; nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, &ncounter, NULL, NULL); } if (nResult != 0) { m_ErrorCode = WSAGetLastError(); if (m_ErrorCode == WSAETIMEDOUT) { continue; } if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) { break; } } n = ncounter; #endif SCTP_HEADER_LEN(udprecvmbuf6[0]) = n; /* length of total packet */ SCTP_STAT_INCR(sctps_recvpackets); SCTP_STAT_INCR_COUNTER64(sctps_inpackets); if (n <= iovlen) { SCTP_BUF_LEN(udprecvmbuf6[0]) = n; (to_fill)++; } else { i = 0; SCTP_BUF_LEN(udprecvmbuf6[0]) = iovlen; ncounter -= iovlen; (to_fill)++; do { udprecvmbuf6[i]->m_next = udprecvmbuf6[i+1]; SCTP_BUF_LEN(udprecvmbuf6[i]->m_next) = min(ncounter, iovlen); i++; ncounter -= iovlen; (to_fill)++; } while (ncounter > 0); } for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) { struct in6_pktinfo *info; dst.sin6_family = AF_INET6; #ifdef HAVE_SIN6_LEN dst.sin6_len = sizeof(struct sockaddr_in6); #endif info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); /*dst.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));*/ memcpy((void *)&dst.sin6_addr, (const void *)&(info->ipi6_addr), sizeof(struct in6_addr)); } } /* SCTP does not allow broadcasts or multicasts */ if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) { return (NULL); } sh = mtod(udprecvmbuf6[0], struct sctphdr *); ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); offset = sizeof(struct sctphdr); port = src.sin6_port; src.sin6_port = sh->src_port; dst.sin6_port = sh->dest_port; #if defined(SCTP_WITH_NO_CSUM) SCTP_STAT_INCR(sctps_recvnocrc); #else if ((memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0)) { compute_crc = 0; SCTP_STAT_INCR(sctps_recvnocrc); } else { SCTP_STAT_INCR(sctps_recvswcrc); } #endif SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n); SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", (int)sizeof(struct sctphdr)); sctp_common_input_processing(&udprecvmbuf6[0], 0, offset, n, (struct sockaddr *)&src, (struct sockaddr *)&dst, sh, ch, #if !defined(SCTP_WITH_NO_CSUM) compute_crc, #endif 0, SCTP_DEFAULT_VRFID, port); if (udprecvmbuf6[0]) { m_freem(udprecvmbuf6[0]); } } for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) { m_free(udprecvmbuf6[i]); } /* free the array itself */ free(udprecvmbuf6); return (NULL); }
static void * recv_function_raw(void *arg) { struct mbuf **recvmbuf; struct ip *iphdr; struct sctphdr *sh; uint16_t port; int offset, ecn = 0; #if !defined(SCTP_WITH_NO_CSUM) int compute_crc = 1; #endif struct sctp_chunkhdr *ch; struct sockaddr_in src, dst; #if !defined(__Userspace_os_Windows) struct msghdr msg; struct iovec recv_iovec[MAXLEN_MBUF_CHAIN]; #else WSABUF recv_iovec[MAXLEN_MBUF_CHAIN]; int nResult, m_ErrorCode; DWORD flags; struct sockaddr_in from; int fromlen; #endif /*Initially the entire set of mbufs is to be allocated. to_fill indicates this amount. */ int to_fill = MAXLEN_MBUF_CHAIN; /* iovlen is the size of each mbuf in the chain */ int i, n, ncounter = 0; int iovlen = MCLBYTES; int want_ext = (iovlen > MLEN)? 1 : 0; int want_header = 0; bzero((void *)&src, sizeof(struct sockaddr_in)); bzero((void *)&dst, sizeof(struct sockaddr_in)); recvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN); while (1) { for (i = 0; i < to_fill; i++) { /* Not getting the packet header. Tests with chain of one run as usual without having the packet header. Have tried both sending and receiving */ recvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA); #if !defined(__Userspace_os_Windows) recv_iovec[i].iov_base = (caddr_t)recvmbuf[i]->m_data; recv_iovec[i].iov_len = iovlen; #else recv_iovec[i].buf = (caddr_t)recvmbuf[i]->m_data; recv_iovec[i].len = iovlen; #endif } to_fill = 0; #if defined(__Userspace_os_Windows) flags = 0; ncounter = 0; fromlen = sizeof(struct sockaddr_in); bzero((void *)&from, sizeof(struct sockaddr_in)); nResult = WSARecvFrom(SCTP_BASE_VAR(userspace_rawsctp), recv_iovec, MAXLEN_MBUF_CHAIN, (LPDWORD)&ncounter, (LPDWORD)&flags, (struct sockaddr*)&from, &fromlen, NULL, NULL); if (nResult != 0) { m_ErrorCode = WSAGetLastError(); if (m_ErrorCode == WSAETIMEDOUT) { continue; } if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) { break; } } n = ncounter; #else bzero((void *)&msg, sizeof(struct msghdr)); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = recv_iovec; msg.msg_iovlen = MAXLEN_MBUF_CHAIN; msg.msg_control = NULL; msg.msg_controllen = 0; ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp), &msg, 0); if (n < 0) { if (errno == EAGAIN) { continue; } else { break; } } #endif SCTP_HEADER_LEN(recvmbuf[0]) = n; /* length of total packet */ SCTP_STAT_INCR(sctps_recvpackets); SCTP_STAT_INCR_COUNTER64(sctps_inpackets); if (n <= iovlen) { SCTP_BUF_LEN(recvmbuf[0]) = n; (to_fill)++; } else { i = 0; SCTP_BUF_LEN(recvmbuf[0]) = iovlen; ncounter -= iovlen; (to_fill)++; do { recvmbuf[i]->m_next = recvmbuf[i+1]; SCTP_BUF_LEN(recvmbuf[i]->m_next) = min(ncounter, iovlen); i++; ncounter -= iovlen; (to_fill)++; } while (ncounter > 0); } iphdr = mtod(recvmbuf[0], struct ip *); sh = (struct sctphdr *)((caddr_t)iphdr + sizeof(struct ip)); ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); offset = sizeof(struct ip) + sizeof(struct sctphdr); if (iphdr->ip_tos != 0) { ecn = iphdr->ip_tos & 0x02; } dst.sin_family = AF_INET; #ifdef HAVE_SIN_LEN dst.sin_len = sizeof(struct sockaddr_in); #endif dst.sin_addr = iphdr->ip_dst; dst.sin_port = sh->dest_port; src.sin_family = AF_INET; #ifdef HAVE_SIN_LEN src.sin_len = sizeof(struct sockaddr_in); #endif src.sin_addr = iphdr->ip_src; src.sin_port = sh->src_port; /* SCTP does not allow broadcasts or multicasts */ if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) { return (NULL); } if (SCTP_IS_IT_BROADCAST(dst.sin_addr, recvmbuf[0])) { return (NULL); } port = 0; #if defined(SCTP_WITH_NO_CSUM) SCTP_STAT_INCR(sctps_recvnocrc); #else if (src.sin_addr.s_addr == dst.sin_addr.s_addr) { compute_crc = 0; SCTP_STAT_INCR(sctps_recvnocrc); } else { SCTP_STAT_INCR(sctps_recvswcrc); } #endif SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n); SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset); sctp_common_input_processing(&recvmbuf[0], sizeof(struct ip), offset, n, (struct sockaddr *)&src, (struct sockaddr *)&dst, sh, ch, #if !defined(SCTP_WITH_NO_CSUM) compute_crc, #endif ecn, SCTP_DEFAULT_VRFID, port); if (recvmbuf[0]) { m_freem(recvmbuf[0]); } } for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) { m_free(recvmbuf[i]); } /* free the array itself */ free(recvmbuf); return (NULL); }
/* This does not yet work on Linux */ static void * recv_function_route(void *arg) { int len; char buf[4096]; struct iovec iov = { buf, sizeof(buf) }; struct msghdr msg; struct nlmsghdr *nh; struct ifaddrmsg *rtmsg; struct rtattr *rtatp; struct in_addr *inp; struct sockaddr_nl sanl; #ifdef INET struct sockaddr_in *sa; #endif #ifdef INET6 struct sockaddr_in6 *sa6; #endif for (;;) { memset(&sanl, 0, sizeof(sanl)); sanl.nl_family = AF_NETLINK; sanl.nl_groups = RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_IFADDR; memset(&msg, 0, sizeof(struct msghdr)); msg.msg_name = (void *)&sanl; msg.msg_namelen = sizeof(sanl); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; msg.msg_controllen = 0; len = recvmsg(SCTP_BASE_VAR(userspace_route), &msg, 0); if (len < 0) { if (errno == EAGAIN) { continue; } else { break; } } for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len); nh = NLMSG_NEXT (nh, len)) { if (nh->nlmsg_type == NLMSG_DONE) break; if (nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR) { rtmsg = (struct ifaddrmsg *)NLMSG_DATA(nh); rtatp = (struct rtattr *)IFA_RTA(rtmsg); if(rtatp->rta_type == IFA_ADDRESS) { inp = (struct in_addr *)RTA_DATA(rtatp); switch (rtmsg->ifa_family) { #ifdef INET case AF_INET: sa = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in)); sa->sin_family = rtmsg->ifa_family; sa->sin_port = 0; memcpy(&sa->sin_addr, inp, sizeof(struct in_addr)); sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa); break; #endif #ifdef INET6 case AF_INET6: sa6 = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6)); sa6->sin6_family = rtmsg->ifa_family; sa6->sin6_port = 0; memcpy(&sa6->sin6_addr, inp, sizeof(struct in6_addr)); sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa6); break; #endif default: SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", rtmsg->ifa_family); break; } } } } } return (NULL); }
/* 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;