/* __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);
	}
}
Exemple #4
0
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);
}
Exemple #5
0
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);
}
Exemple #6
0
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;