1b735c0f45be3595abe0c88e2b5667780be2e27dctuexen/*-
2829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * Copyright (c) 2009-2010 Brad Penoff
3829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * Copyright (c) 2009-2010 Humaira Kamal
4829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * Copyright (c) 2011-2012 Irene Ruengeler
5829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * Copyright (c) 2011-2012 Michael Tuexen
6b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * All rights reserved.
7b735c0f45be3595abe0c88e2b5667780be2e27dctuexen *
8b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * Redistribution and use in source and binary forms, with or without
9b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * modification, are permitted provided that the following conditions
10b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * are met:
11b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * 1. Redistributions of source code must retain the above copyright
12b735c0f45be3595abe0c88e2b5667780be2e27dctuexen *    notice, this list of conditions and the following disclaimer.
13b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * 2. Redistributions in binary form must reproduce the above copyright
14b735c0f45be3595abe0c88e2b5667780be2e27dctuexen *    notice, this list of conditions and the following disclaimer in the
15b735c0f45be3595abe0c88e2b5667780be2e27dctuexen *    documentation and/or other materials provided with the distribution.
16b735c0f45be3595abe0c88e2b5667780be2e27dctuexen *
17b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27b735c0f45be3595abe0c88e2b5667780be2e27dctuexen * SUCH DAMAGE.
28b735c0f45be3595abe0c88e2b5667780be2e27dctuexen *
29b735c0f45be3595abe0c88e2b5667780be2e27dctuexen */
30b735c0f45be3595abe0c88e2b5667780be2e27dctuexen
31a4fb576fabdb7d366af0e6ed880c0176a5b3a4e3tuexen#if defined(INET) || defined(INET6)
32bca1dae6587a640359abee04337c0463b0a3893tuexen#include <sys/types.h>
3307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
34bca1dae6587a640359abee04337c0463b0a3893tuexen#include <sys/socket.h>
352356c9c75abdcc735cfcc8f9cb7c023375dac7b6t#include <netinet/in.h>
36587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#include <unistd.h>
37587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#include <pthread.h>
3822a33a1debfe70529be4aa018a2912bfe5dcd8dat#if !defined(__Userspace_os_DragonFly) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_NetBSD)
39bca1dae6587a640359abee04337c0463b0a3893tuexen#include <sys/uio.h>
403a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#else
413a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#include <user_ip6_var.h>
42ebe006254bc340627d5cdc106f4524aac98d46a9tuexen#endif
4307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
44bca1dae6587a640359abee04337c0463b0a3893tuexen#include <netinet/sctp_os.h>
45bca1dae6587a640359abee04337c0463b0a3893tuexen#include <netinet/sctp_var.h>
46bca1dae6587a640359abee04337c0463b0a3893tuexen#include <netinet/sctp_pcb.h>
47968138a650335b8836df7433026face9535f9641t#include <netinet/sctp_input.h>
487943a5e518ee0e8d37d70b5637430137cedc918dt#if 0
493a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#if defined(__Userspace_os_Linux)
503a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#include <linux/netlink.h>
512356c9c75abdcc735cfcc8f9cb7c023375dac7b6t#ifdef HAVE_LINUX_IF_ADDR_H
523a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#include <linux/if_addr.h>
533a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
542356c9c75abdcc735cfcc8f9cb7c023375dac7b6t#ifdef HAVE_LINUX_RTNETLINK_H
552356c9c75abdcc735cfcc8f9cb7c023375dac7b6t#include <linux/rtnetlink.h>
562356c9c75abdcc735cfcc8f9cb7c023375dac7b6t#endif
572356c9c75abdcc735cfcc8f9cb7c023375dac7b6t#endif
587943a5e518ee0e8d37d70b5637430137cedc918dt#endif
5922a33a1debfe70529be4aa018a2912bfe5dcd8dat#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
602356c9c75abdcc735cfcc8f9cb7c023375dac7b6t#include <net/route.h>
612356c9c75abdcc735cfcc8f9cb7c023375dac7b6t#endif
62bca1dae6587a640359abee04337c0463b0a3893tuexen/* local macros and datatypes used to get IP addresses system independently */
632e9986e0a84ab51dee01167310708e598b5b9994t#if !defined(IP_PKTINFO ) && ! defined(IP_RECVDSTADDR)
642e9986e0a84ab51dee01167310708e598b5b9994t# error "Can't determine socket option to use to get UDP IP"
65bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
66bca1dae6587a640359abee04337c0463b0a3893tuexen
673a33bc97bd0dd721a91035f5cf26c1956f264d3etuexenvoid recv_thread_destroy(void);
68587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#define MAXLEN_MBUF_CHAIN 32 /* What should this value be? */
693a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
7022a33a1debfe70529be4aa018a2912bfe5dcd8dat#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
713a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#define NEXT_SA(ap) ap = (struct sockaddr *) \
723a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	((caddr_t) ap + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof (uint32_t)) : sizeof(uint32_t)))
733a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
743a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
7522a33a1debfe70529be4aa018a2912bfe5dcd8dat#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
763a33bc97bd0dd721a91035f5cf26c1956f264d3etuexenstatic void
773a33bc97bd0dd721a91035f5cf26c1956f264d3etuexensctp_get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
783a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen{
793a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	int i;
803a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
813a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	for (i = 0; i < RTAX_MAX; i++) {
823a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		if (addrs & (1 << i)) {
833a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			rti_info[i] = sa;
843a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			NEXT_SA(sa);
853a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		} else {
863a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			rti_info[i] = NULL;
873a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		}
883a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
893a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen}
903a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
913a33bc97bd0dd721a91035f5cf26c1956f264d3etuexenstatic void
923a33bc97bd0dd721a91035f5cf26c1956f264d3etuexensctp_handle_ifamsg(unsigned char type, unsigned short index, struct sockaddr *sa)
933a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen{
943a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	int rc;
953a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	struct ifaddrs *ifa, *found_ifa = NULL;
963a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
973a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	/* handle only the types we want */
983a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	if ((type != RTM_NEWADDR) && (type != RTM_DELADDR)) {
993a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		return;
1003a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
1013a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
1023a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	rc = getifaddrs(&g_interfaces);
1033a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	if (rc != 0) {
1043a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		return;
1053a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
1063a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	for (ifa = g_interfaces; ifa; ifa = ifa->ifa_next) {
1073a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		if (index == if_nametoindex(ifa->ifa_name)) {
1083a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			found_ifa = ifa;
1093a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			break;
1103a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		}
1113a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
1123a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	if (found_ifa == NULL) {
1133a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		return;
1143a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
1153a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
1163a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	switch (sa->sa_family) {
1173a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#ifdef INET
1183a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	case AF_INET:
1193a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
1203a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in));
1213a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		break;
1223a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
1233a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#ifdef INET6
1243a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	case AF_INET6:
1253a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in6));
1263a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in6));
1273a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		break;
1283a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
1293a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	default:
130a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", sa->sa_family);
1313a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
1323a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
1333a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	/* relay the appropriate address change to the base code */
1343a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	if (type == RTM_NEWADDR) {
1353a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		(void)sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, ifa, if_nametoindex(ifa->ifa_name),
1363a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		                           0,
1373a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		                           ifa->ifa_name,
1383a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		                           (void *)ifa,
1393a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		                           ifa->ifa_addr,
1403a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		                           0,
1413a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		                           1);
1423a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	} else {
1433a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
1443a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		                       if_nametoindex(ifa->ifa_name),
1453a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		                       ifa->ifa_name);
1463a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
1473a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen}
1483a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
1493a33bc97bd0dd721a91035f5cf26c1956f264d3etuexenstatic void *
1503a33bc97bd0dd721a91035f5cf26c1956f264d3etuexenrecv_function_route(void *arg)
1513a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen{
1523a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	ssize_t ret;
1533a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	struct ifa_msghdr *ifa;
1543a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	char rt_buffer[1024];
1553a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	struct sockaddr *sa, *rti_info[RTAX_MAX];
1563a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
157b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	while (1) {
1583a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		bzero(rt_buffer, sizeof(rt_buffer));
159b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		ret = recv(SCTP_BASE_VAR(userspace_route), rt_buffer, sizeof(rt_buffer), 0);
1603a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
1613a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		if (ret > 0) {
1623a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			ifa = (struct ifa_msghdr *) rt_buffer;
1633a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			if (ifa->ifam_type != RTM_DELADDR && ifa->ifam_type != RTM_NEWADDR) {
1643a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen				continue;
1653a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			}
1663a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			sa = (struct sockaddr *) (ifa + 1);
1673a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			sctp_get_rtaddrs(ifa->ifam_addrs, sa, rti_info);
1683a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			switch (ifa->ifam_type) {
1693a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			case RTM_DELADDR:
1703a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			case RTM_NEWADDR:
1713a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen				sctp_handle_ifamsg(ifa->ifam_type, ifa->ifam_index, rti_info[RTAX_IFA]);
1723a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen				break;
1733a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			default:
1743a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen				/* ignore this routing event */
1753a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen				break;
1763a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			}
1773a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		}
178b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if (ret < 0) {
179b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			if (errno == EAGAIN) {
180b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				continue;
181b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			} else {
182b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				break;
183b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			}
184b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		}
1853a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
18690c82b7f9b4290337239cf31926a8b87879f0357t	return (NULL);
1873a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen}
1887943a5e518ee0e8d37d70b5637430137cedc918dt#endif
1897943a5e518ee0e8d37d70b5637430137cedc918dt
1907943a5e518ee0e8d37d70b5637430137cedc918dt#if 0
1917943a5e518ee0e8d37d70b5637430137cedc918dt/* This does not yet work on Linux */
1923a33bc97bd0dd721a91035f5cf26c1956f264d3etuexenstatic void *
1933a33bc97bd0dd721a91035f5cf26c1956f264d3etuexenrecv_function_route(void *arg)
1943a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen{
1953a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	int len;
1963a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	char buf[4096];
1973a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	struct iovec iov = { buf, sizeof(buf) };
1983a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	struct msghdr msg;
1993a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	struct nlmsghdr *nh;
2003a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	struct ifaddrmsg *rtmsg;
201b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	struct rtattr *rtatp;
2023a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	struct in_addr *inp;
203a29d53bfbc46f125218c86f5271187b7b9ea497btuexen	struct sockaddr_nl sanl;
2043a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#ifdef INET
2053a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	struct sockaddr_in *sa;
2063a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
2073a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#ifdef INET6
2083a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	struct sockaddr_in6 *sa6;
2093a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
2103a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
211a29d53bfbc46f125218c86f5271187b7b9ea497btuexen	for (;;) {
212a29d53bfbc46f125218c86f5271187b7b9ea497btuexen		memset(&sanl, 0, sizeof(sanl));
213a29d53bfbc46f125218c86f5271187b7b9ea497btuexen		sanl.nl_family = AF_NETLINK;
214a29d53bfbc46f125218c86f5271187b7b9ea497btuexen		sanl.nl_groups = RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_IFADDR;
2153a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		memset(&msg, 0, sizeof(struct msghdr));
2163a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		msg.msg_name = (void *)&sanl;
2173a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		msg.msg_namelen = sizeof(sanl);
2183a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		msg.msg_iov = &iov;
2193a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		msg.msg_iovlen = 1;
2203a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		msg.msg_control = NULL;
2213a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		msg.msg_controllen = 0;
2223a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
223b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		len = recvmsg(SCTP_BASE_VAR(userspace_route), &msg, 0);
2243a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
225b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if (len < 0) {
226b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			if (errno == EAGAIN) {
227b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				continue;
228b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			} else {
229b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				break;
230b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			}
231b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		}
2323a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len);
2333a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			nh = NLMSG_NEXT (nh, len)) {
2343a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			if (nh->nlmsg_type == NLMSG_DONE)
235b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				break;
2363a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
2373a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			if (nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR) {
2383a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen				rtmsg = (struct ifaddrmsg *)NLMSG_DATA(nh);
2393a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen				rtatp = (struct rtattr *)IFA_RTA(rtmsg);
2403a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen				if(rtatp->rta_type == IFA_ADDRESS) {
2413a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen					inp = (struct in_addr *)RTA_DATA(rtatp);
2423a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen					switch (rtmsg->ifa_family) {
2433a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#ifdef INET
2443a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen					case AF_INET:
2453a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen						sa = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
2463a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen						sa->sin_family = rtmsg->ifa_family;
2473a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen						sa->sin_port = 0;
2483a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen						memcpy(&sa->sin_addr, inp, sizeof(struct in_addr));
2493a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen						sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa);
2503a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen						break;
2513a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
2523a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#ifdef INET6
2533a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen					case AF_INET6:
2543a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen						sa6 = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6));
2553a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen						sa6->sin6_family = rtmsg->ifa_family;
2563a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen						sa6->sin6_port = 0;
2573a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen						memcpy(&sa6->sin6_addr, inp, sizeof(struct in6_addr));
2583a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen						sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa6);
2593a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen						break;
2603a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
2613a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen					default:
26208da49d4f59189260e186f37275bddab6c148ad8ruengeler						SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", rtmsg->ifa_family);
263b735c0f45be3595abe0c88e2b5667780be2e27dctuexen						break;
2643a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen					}
2653a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen				}
2663a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen			}
2673a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		}
2683a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
26990c82b7f9b4290337239cf31926a8b87879f0357t	return (NULL);
2703a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen}
2713a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
272bca1dae6587a640359abee04337c0463b0a3893tuexen
273656fe4c72b7f60bbbee48b00610b20c70edf8f32tuexen#ifdef INET
274bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void *
275bca1dae6587a640359abee04337c0463b0a3893tuexenrecv_function_raw(void *arg)
276bca1dae6587a640359abee04337c0463b0a3893tuexen{
277b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	struct mbuf **recvmbuf;
2786fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	struct ip *iphdr;
2796fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	struct sctphdr *sh;
2806fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	uint16_t port;
281890e1a3b80e879f0a3d527173d7922aa8da54064t	int offset, ecn = 0;
282890e1a3b80e879f0a3d527173d7922aa8da54064t#if !defined(SCTP_WITH_NO_CSUM)
283890e1a3b80e879f0a3d527173d7922aa8da54064t	int compute_crc = 1;
284890e1a3b80e879f0a3d527173d7922aa8da54064t#endif
2856fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	struct sctp_chunkhdr *ch;
2866fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	struct sockaddr_in src, dst;
28707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
288b21b4a1e7685ebf4b404727a184da403dff77bd3t	struct msghdr msg;
289bca1dae6587a640359abee04337c0463b0a3893tuexen	struct iovec recv_iovec[MAXLEN_MBUF_CHAIN];
290587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#else
291587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	WSABUF recv_iovec[MAXLEN_MBUF_CHAIN];
292587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	int nResult, m_ErrorCode;
293587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	DWORD flags;
29459caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	struct sockaddr_in from;
295587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	int fromlen;
296587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#endif
297587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen
298bca1dae6587a640359abee04337c0463b0a3893tuexen	/*Initially the entire set of mbufs is to be allocated.
299bca1dae6587a640359abee04337c0463b0a3893tuexen	  to_fill indicates this amount. */
300bca1dae6587a640359abee04337c0463b0a3893tuexen	int to_fill = MAXLEN_MBUF_CHAIN;
301bca1dae6587a640359abee04337c0463b0a3893tuexen	/* iovlen is the size of each mbuf in the chain */
302587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	int i, n, ncounter = 0;
303bca1dae6587a640359abee04337c0463b0a3893tuexen	int iovlen = MCLBYTES;
304bca1dae6587a640359abee04337c0463b0a3893tuexen	int want_ext = (iovlen > MLEN)? 1 : 0;
305bca1dae6587a640359abee04337c0463b0a3893tuexen	int want_header = 0;
3066fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler
3076fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	bzero((void *)&src, sizeof(struct sockaddr_in));
3086fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	bzero((void *)&dst, sizeof(struct sockaddr_in));
309bca1dae6587a640359abee04337c0463b0a3893tuexen
310587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	recvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
311587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen
312bca1dae6587a640359abee04337c0463b0a3893tuexen	while (1) {
313bca1dae6587a640359abee04337c0463b0a3893tuexen		for (i = 0; i < to_fill; i++) {
314bca1dae6587a640359abee04337c0463b0a3893tuexen			/* Not getting the packet header. Tests with chain of one run
315bca1dae6587a640359abee04337c0463b0a3893tuexen			   as usual without having the packet header.
316bca1dae6587a640359abee04337c0463b0a3893tuexen			   Have tried both sending and receiving
317bca1dae6587a640359abee04337c0463b0a3893tuexen			 */
318218d5d0df143e859e241afb12d6aaa1e4969d714t			recvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
31907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
320bca1dae6587a640359abee04337c0463b0a3893tuexen			recv_iovec[i].iov_base = (caddr_t)recvmbuf[i]->m_data;
321bca1dae6587a640359abee04337c0463b0a3893tuexen			recv_iovec[i].iov_len = iovlen;
322587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#else
323587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen			recv_iovec[i].buf = (caddr_t)recvmbuf[i]->m_data;
324587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen			recv_iovec[i].len = iovlen;
325587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#endif
326bca1dae6587a640359abee04337c0463b0a3893tuexen		}
327bca1dae6587a640359abee04337c0463b0a3893tuexen		to_fill = 0;
32807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if defined(__Userspace_os_Windows)
329587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		flags = 0;
330587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		ncounter = 0;
33159caa502fe5258530a6f6eab10155a6dac5d8d5atuexen		fromlen = sizeof(struct sockaddr_in);
33259caa502fe5258530a6f6eab10155a6dac5d8d5atuexen		bzero((void *)&from, sizeof(struct sockaddr_in));
333587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen
334b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		nResult = WSARecvFrom(SCTP_BASE_VAR(userspace_rawsctp), recv_iovec, MAXLEN_MBUF_CHAIN, (LPDWORD)&ncounter, (LPDWORD)&flags, (struct sockaddr*)&from, &fromlen, NULL, NULL);
335587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		if (nResult != 0) {
336587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen			m_ErrorCode = WSAGetLastError();
337f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			if (m_ErrorCode == WSAETIMEDOUT) {
338f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				continue;
339f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			}
340f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
341f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				break;
342f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			}
343587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		}
3443ab67fee2e89498e06d10f12109b818bdc49ddc3tuexen		n = ncounter;
345587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#else
346b21b4a1e7685ebf4b404727a184da403dff77bd3t		bzero((void *)&msg, sizeof(struct msghdr));
347b21b4a1e7685ebf4b404727a184da403dff77bd3t		msg.msg_name = NULL;
348b21b4a1e7685ebf4b404727a184da403dff77bd3t		msg.msg_namelen = 0;
349b21b4a1e7685ebf4b404727a184da403dff77bd3t		msg.msg_iov = recv_iovec;
350b21b4a1e7685ebf4b404727a184da403dff77bd3t		msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
351b21b4a1e7685ebf4b404727a184da403dff77bd3t		msg.msg_control = NULL;
352b21b4a1e7685ebf4b404727a184da403dff77bd3t		msg.msg_controllen = 0;
353b21b4a1e7685ebf4b404727a184da403dff77bd3t		ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp), &msg, 0);
35467a1a0842895b84f6665b31c4a299ec2c1e182c9tuexen		if (n < 0) {
355b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			if (errno == EAGAIN) {
356b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				continue;
357b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			} else {
358b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				break;
359b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			}
36067a1a0842895b84f6665b31c4a299ec2c1e182c9tuexen		}
361587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#endif
362bca1dae6587a640359abee04337c0463b0a3893tuexen		SCTP_HEADER_LEN(recvmbuf[0]) = n; /* length of total packet */
3636b5474dec62bc128acb56d0ad4ae413b91fedb09t		SCTP_STAT_INCR(sctps_recvpackets);
3646b5474dec62bc128acb56d0ad4ae413b91fedb09t		SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
365b735c0f45be3595abe0c88e2b5667780be2e27dctuexen
366bca1dae6587a640359abee04337c0463b0a3893tuexen		if (n <= iovlen) {
367bca1dae6587a640359abee04337c0463b0a3893tuexen			SCTP_BUF_LEN(recvmbuf[0]) = n;
368bca1dae6587a640359abee04337c0463b0a3893tuexen			(to_fill)++;
369bca1dae6587a640359abee04337c0463b0a3893tuexen		} else {
370bca1dae6587a640359abee04337c0463b0a3893tuexen			i = 0;
371bca1dae6587a640359abee04337c0463b0a3893tuexen			SCTP_BUF_LEN(recvmbuf[0]) = iovlen;
372bca1dae6587a640359abee04337c0463b0a3893tuexen
373bca1dae6587a640359abee04337c0463b0a3893tuexen			ncounter -= iovlen;
374bca1dae6587a640359abee04337c0463b0a3893tuexen			(to_fill)++;
375bca1dae6587a640359abee04337c0463b0a3893tuexen			do {
376bca1dae6587a640359abee04337c0463b0a3893tuexen				recvmbuf[i]->m_next = recvmbuf[i+1];
377bca1dae6587a640359abee04337c0463b0a3893tuexen				SCTP_BUF_LEN(recvmbuf[i]->m_next) = min(ncounter, iovlen);
378bca1dae6587a640359abee04337c0463b0a3893tuexen				i++;
379bca1dae6587a640359abee04337c0463b0a3893tuexen				ncounter -= iovlen;
380bca1dae6587a640359abee04337c0463b0a3893tuexen				(to_fill)++;
381bca1dae6587a640359abee04337c0463b0a3893tuexen			} while (ncounter > 0);
382bca1dae6587a640359abee04337c0463b0a3893tuexen		}
3836fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler
3846fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		iphdr = mtod(recvmbuf[0], struct ip *);
3856fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		sh = (struct sctphdr *)((caddr_t)iphdr + sizeof(struct ip));
3866fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
3876fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		offset = sizeof(struct ip) + sizeof(struct sctphdr);
3886fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler
3896fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		if (iphdr->ip_tos != 0) {
3906fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			ecn = iphdr->ip_tos & 0x02;
3916fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		}
3926fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler
3936fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		dst.sin_family = AF_INET;
3946fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#ifdef HAVE_SIN_LEN
3956fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		dst.sin_len = sizeof(struct sockaddr_in);
3966fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
3976fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		dst.sin_addr = iphdr->ip_dst;
3986fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		dst.sin_port = sh->dest_port;
3996fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler
4006fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		src.sin_family = AF_INET;
4016fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#ifdef HAVE_SIN_LEN
4026fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		src.sin_len = sizeof(struct sockaddr_in);
4036fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
4046fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		src.sin_addr = iphdr->ip_src;
4056fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		src.sin_port = sh->src_port;
4066fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler
4076fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		/* SCTP does not allow broadcasts or multicasts */
4086fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
40990c82b7f9b4290337239cf31926a8b87879f0357t			return (NULL);
4106fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		}
4116fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		if (SCTP_IS_IT_BROADCAST(dst.sin_addr, recvmbuf[0])) {
41290c82b7f9b4290337239cf31926a8b87879f0357t			return (NULL);
4136fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		}
4146fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler
4156fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		port = 0;
416890e1a3b80e879f0a3d527173d7922aa8da54064t
417a84e47fce6e5dd47a37cce19c040652bd9cc2ecat#if defined(SCTP_WITH_NO_CSUM)
418a84e47fce6e5dd47a37cce19c040652bd9cc2ecat		SCTP_STAT_INCR(sctps_recvnocrc);
419a84e47fce6e5dd47a37cce19c040652bd9cc2ecat#else
420890e1a3b80e879f0a3d527173d7922aa8da54064t		if (src.sin_addr.s_addr == dst.sin_addr.s_addr) {
4216fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			compute_crc = 0;
422a84e47fce6e5dd47a37cce19c040652bd9cc2ecat			SCTP_STAT_INCR(sctps_recvnocrc);
423a84e47fce6e5dd47a37cce19c040652bd9cc2ecat		} else {
424a84e47fce6e5dd47a37cce19c040652bd9cc2ecat			SCTP_STAT_INCR(sctps_recvswcrc);
4256fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		}
426890e1a3b80e879f0a3d527173d7922aa8da54064t#endif
427a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
4282356c9c75abdcc735cfcc8f9cb7c023375dac7b6t		SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
4296fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		sctp_common_input_processing(&recvmbuf[0], sizeof(struct ip), offset, n,
4306fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             (struct sockaddr *)&src,
4316fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             (struct sockaddr *)&dst,
4326fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             sh, ch,
433890e1a3b80e879f0a3d527173d7922aa8da54064t#if !defined(SCTP_WITH_NO_CSUM)
4346fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             compute_crc,
435890e1a3b80e879f0a3d527173d7922aa8da54064t#endif
4366fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             ecn,
4376fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             SCTP_DEFAULT_VRFID, port);
438efdae3619f066b0a23c163043bf1a26f4ba0504ct		if (recvmbuf[0]) {
439efdae3619f066b0a23c163043bf1a26f4ba0504ct			m_freem(recvmbuf[0]);
440efdae3619f066b0a23c163043bf1a26f4ba0504ct		}
441bca1dae6587a640359abee04337c0463b0a3893tuexen	}
442b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
443b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		m_free(recvmbuf[i]);
444b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	}
445b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	/* free the array itself */
446b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	free(recvmbuf);
447f2c34c37a0bf05f900b2b316559ce4ae9c7be287t	return (NULL);
448bca1dae6587a640359abee04337c0463b0a3893tuexen}
449656fe4c72b7f60bbbee48b00610b20c70edf8f32tuexen#endif
450bca1dae6587a640359abee04337c0463b0a3893tuexen
45107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if defined(INET6)
45207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenstatic void *
45307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenrecv_function_raw6(void *arg)
45407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen{
455b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	struct mbuf **recvmbuf6;
45607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
45707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	struct iovec recv_iovec[MAXLEN_MBUF_CHAIN];
45807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	struct msghdr msg;
45907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	struct cmsghdr *cmsgptr;
46007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
46107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#else
46207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	WSABUF recv_iovec[MAXLEN_MBUF_CHAIN];
46307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int nResult, m_ErrorCode;
46407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	DWORD flags;
46559caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	struct sockaddr_in6 from;
46607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int fromlen;
46759caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
46859caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	LPFN_WSARECVMSG WSARecvMsg;
4692e9986e0a84ab51dee01167310708e598b5b9994t	WSACMSGHDR *cmsgptr;
4702e9986e0a84ab51dee01167310708e598b5b9994t	WSAMSG msg;
47159caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	char ControlBuffer[1024];
47207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
47359caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	struct sockaddr_in6 src, dst;
4746fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	struct sctphdr *sh;
47559caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	int offset;
4766fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	struct sctp_chunkhdr *ch;
47707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
47807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/*Initially the entire set of mbufs is to be allocated.
47907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	  to_fill indicates this amount. */
48007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int to_fill = MAXLEN_MBUF_CHAIN;
48107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/* iovlen is the size of each mbuf in the chain */
482890e1a3b80e879f0a3d527173d7922aa8da54064t	int i, n, ncounter = 0;
483890e1a3b80e879f0a3d527173d7922aa8da54064t#if !defined(SCTP_WITH_NO_CSUM)
484890e1a3b80e879f0a3d527173d7922aa8da54064t	int compute_crc = 1;
485890e1a3b80e879f0a3d527173d7922aa8da54064t#endif
48607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int iovlen = MCLBYTES;
48707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int want_ext = (iovlen > MLEN)? 1 : 0;
48807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int want_header = 0;
48907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
49007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	recvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
49107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
49207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	for (;;) {
49307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		for (i = 0; i < to_fill; i++) {
49407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			/* Not getting the packet header. Tests with chain of one run
49507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			   as usual without having the packet header.
49607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			   Have tried both sending and receiving
49707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			 */
498218d5d0df143e859e241afb12d6aaa1e4969d714t			recvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
49907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
50007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			recv_iovec[i].iov_base = (caddr_t)recvmbuf6[i]->m_data;
50107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			recv_iovec[i].iov_len = iovlen;
50207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#else
50307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			recv_iovec[i].buf = (caddr_t)recvmbuf6[i]->m_data;
50407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			recv_iovec[i].len = iovlen;
50507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
50607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
50707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		to_fill = 0;
50807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if defined(__Userspace_os_Windows)
50907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		flags = 0;
51007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		ncounter = 0;
51159caa502fe5258530a6f6eab10155a6dac5d8d5atuexen		fromlen = sizeof(struct sockaddr_in6);
51259caa502fe5258530a6f6eab10155a6dac5d8d5atuexen		bzero((void *)&from, sizeof(struct sockaddr_in6));
513b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		nResult = WSAIoctl(SCTP_BASE_VAR(userspace_rawsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER,
51459caa502fe5258530a6f6eab10155a6dac5d8d5atuexen		                   &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
51559caa502fe5258530a6f6eab10155a6dac5d8d5atuexen		                   &WSARecvMsg, sizeof WSARecvMsg,
51659caa502fe5258530a6f6eab10155a6dac5d8d5atuexen		                   &ncounter, NULL, NULL);
517f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen		if (nResult == 0) {
5182e9986e0a84ab51dee01167310708e598b5b9994t			msg.name = (void *)&src;
5192e9986e0a84ab51dee01167310708e598b5b9994t			msg.namelen = sizeof(struct sockaddr_in6);
5202e9986e0a84ab51dee01167310708e598b5b9994t			msg.lpBuffers = recv_iovec;
5212e9986e0a84ab51dee01167310708e598b5b9994t			msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
5222e9986e0a84ab51dee01167310708e598b5b9994t			msg.Control.len = sizeof ControlBuffer;
5232e9986e0a84ab51dee01167310708e598b5b9994t			msg.Control.buf = ControlBuffer;
5242e9986e0a84ab51dee01167310708e598b5b9994t			msg.dwFlags = 0;
5252e9986e0a84ab51dee01167310708e598b5b9994t			nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, &ncounter, NULL, NULL);
52659caa502fe5258530a6f6eab10155a6dac5d8d5atuexen		}
52707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		if (nResult != 0) {
52807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			m_ErrorCode = WSAGetLastError();
529f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			if (m_ErrorCode == WSAETIMEDOUT)
530f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				continue;
531f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			if (m_ErrorCode == WSAENOTSOCK || m_ErrorCode == WSAEINTR)
532f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				break;
53307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
53407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		n = ncounter;
53507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#else
53607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		bzero((void *)&msg, sizeof(struct msghdr));
53707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		bzero((void *)&src, sizeof(struct sockaddr_in6));
53807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		bzero((void *)&dst, sizeof(struct sockaddr_in6));
53907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		bzero((void *)cmsgbuf, CMSG_SPACE(sizeof (struct in6_pktinfo)));
54007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_name = (void *)&src;
54107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_namelen = sizeof(struct sockaddr_in6);
54207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_iov = recv_iovec;
54307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
54407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_control = (void *)cmsgbuf;
54507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof (struct in6_pktinfo));
54607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_flags = 0;
54707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
548b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, 0);
54967a1a0842895b84f6665b31c4a299ec2c1e182c9tuexen		if (n < 0) {
550b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			if (errno == EAGAIN) {
551b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				continue;
552b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			} else {
553b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				break;
554b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			}
55567a1a0842895b84f6665b31c4a299ec2c1e182c9tuexen		}
55607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
55707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		SCTP_HEADER_LEN(recvmbuf6[0]) = n; /* length of total packet */
5586b5474dec62bc128acb56d0ad4ae413b91fedb09t		SCTP_STAT_INCR(sctps_recvpackets);
5596b5474dec62bc128acb56d0ad4ae413b91fedb09t		SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
56007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
56107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		if (n <= iovlen) {
56207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			SCTP_BUF_LEN(recvmbuf6[0]) = n;
56307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			(to_fill)++;
56407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		} else {
56507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			i = 0;
56607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			SCTP_BUF_LEN(recvmbuf6[0]) = iovlen;
56707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
56807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			ncounter -= iovlen;
56907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			(to_fill)++;
57007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			do {
57107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen				recvmbuf6[i]->m_next = recvmbuf6[i+1];
57207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen				SCTP_BUF_LEN(recvmbuf6[i]->m_next) = min(ncounter, iovlen);
57307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen				i++;
57407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen				ncounter -= iovlen;
57507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen				(to_fill)++;
57607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			} while (ncounter > 0);
57707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
57807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
57907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
58007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) {
5812e9986e0a84ab51dee01167310708e598b5b9994t				struct in6_pktinfo * info;
5822e9986e0a84ab51dee01167310708e598b5b9994t
5832e9986e0a84ab51dee01167310708e598b5b9994t				info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
5842e9986e0a84ab51dee01167310708e598b5b9994t				memcpy((void *)&dst.sin6_addr, (const void *) &(info->ipi6_addr), sizeof(struct in6_addr));
5852e9986e0a84ab51dee01167310708e598b5b9994t				break;
58659caa502fe5258530a6f6eab10155a6dac5d8d5atuexen			}
58759caa502fe5258530a6f6eab10155a6dac5d8d5atuexen		}
58807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
5896fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		sh = mtod(recvmbuf6[0], struct sctphdr *);
5906fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
5916fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		offset = sizeof(struct sctphdr);
5926fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler
5936fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		dst.sin6_family = AF_INET6;
5947b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
5956fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		dst.sin6_len = sizeof(struct sockaddr_in6);
5966fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
5976fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		dst.sin6_port = sh->dest_port;
5986fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler
5996fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		src.sin6_family = AF_INET6;
6007b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
6016fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		src.sin6_len = sizeof(struct sockaddr_in6);
6026fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
6036fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		src.sin6_port = sh->src_port;
604a84e47fce6e5dd47a37cce19c040652bd9cc2ecat#if defined(SCTP_WITH_NO_CSUM)
605a84e47fce6e5dd47a37cce19c040652bd9cc2ecat		SCTP_STAT_INCR(sctps_recvnocrc);
606a84e47fce6e5dd47a37cce19c040652bd9cc2ecat#else
607890e1a3b80e879f0a3d527173d7922aa8da54064t		if (memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0) {
6086fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			compute_crc = 0;
609a84e47fce6e5dd47a37cce19c040652bd9cc2ecat			SCTP_STAT_INCR(sctps_recvnocrc);
610a84e47fce6e5dd47a37cce19c040652bd9cc2ecat		} else {
611a84e47fce6e5dd47a37cce19c040652bd9cc2ecat			SCTP_STAT_INCR(sctps_recvswcrc);
6126fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		}
613890e1a3b80e879f0a3d527173d7922aa8da54064t#endif
614a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
6152356c9c75abdcc735cfcc8f9cb7c023375dac7b6t		SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
6166fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		sctp_common_input_processing(&recvmbuf6[0], 0, offset, n,
6176fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             (struct sockaddr *)&src,
6186fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             (struct sockaddr *)&dst,
6196fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             sh, ch,
620890e1a3b80e879f0a3d527173d7922aa8da54064t#if !defined(SCTP_WITH_NO_CSUM)
621890e1a3b80e879f0a3d527173d7922aa8da54064t		                             compute_crc,
622890e1a3b80e879f0a3d527173d7922aa8da54064t#endif
6236fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             0,
6246fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             SCTP_DEFAULT_VRFID, 0);
625efdae3619f066b0a23c163043bf1a26f4ba0504ct		if (recvmbuf6[0]) {
626efdae3619f066b0a23c163043bf1a26f4ba0504ct			m_freem(recvmbuf6[0]);
627efdae3619f066b0a23c163043bf1a26f4ba0504ct		}
62807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
629b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
630b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		m_free(recvmbuf6[i]);
631b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	}
632b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	/* free the array itself */
633b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	free(recvmbuf6);
634f2c34c37a0bf05f900b2b316559ce4ae9c7be287t	return (NULL);
63507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen}
63607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
63707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
638656fe4c72b7f60bbbee48b00610b20c70edf8f32tuexen#ifdef INET
639bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void *
640bca1dae6587a640359abee04337c0463b0a3893tuexenrecv_function_udp(void *arg)
641bca1dae6587a640359abee04337c0463b0a3893tuexen{
642b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	struct mbuf **udprecvmbuf;
643bca1dae6587a640359abee04337c0463b0a3893tuexen	/*Initially the entire set of mbufs is to be allocated.
644bca1dae6587a640359abee04337c0463b0a3893tuexen	  to_fill indicates this amount. */
645bca1dae6587a640359abee04337c0463b0a3893tuexen	int to_fill = MAXLEN_MBUF_CHAIN;
646bca1dae6587a640359abee04337c0463b0a3893tuexen	/* iovlen is the size of each mbuf in the chain */
6476fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	int i, n, ncounter, offset;
648bca1dae6587a640359abee04337c0463b0a3893tuexen	int iovlen = MCLBYTES;
649bca1dae6587a640359abee04337c0463b0a3893tuexen	int want_ext = (iovlen > MLEN)? 1 : 0;
650bca1dae6587a640359abee04337c0463b0a3893tuexen	int want_header = 0;
6516fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	struct sctphdr *sh;
6526fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	uint16_t port;
6536fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	struct sctp_chunkhdr *ch;
654bca1dae6587a640359abee04337c0463b0a3893tuexen	struct sockaddr_in src, dst;
65526dd10ff80a0682f81d8bcad6017143f8a508a3dt#if defined(IP_PKTINFO)
6562e9986e0a84ab51dee01167310708e598b5b9994t	char cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))];
65726dd10ff80a0682f81d8bcad6017143f8a508a3dt#else
65826dd10ff80a0682f81d8bcad6017143f8a508a3dt	char cmsgbuf[CMSG_SPACE(sizeof(struct in_addr))];
6592e9986e0a84ab51dee01167310708e598b5b9994t#endif
660890e1a3b80e879f0a3d527173d7922aa8da54064t#if !defined(SCTP_WITH_NO_CSUM)
661890e1a3b80e879f0a3d527173d7922aa8da54064t	int compute_crc = 1;
662890e1a3b80e879f0a3d527173d7922aa8da54064t#endif
66307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
664587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	struct iovec iov[MAXLEN_MBUF_CHAIN];
665587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	struct msghdr msg;
666bca1dae6587a640359abee04337c0463b0a3893tuexen	struct cmsghdr *cmsgptr;
667587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#else
668587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
669587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	LPFN_WSARECVMSG WSARecvMsg;
670587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	char ControlBuffer[1024];
671587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	WSABUF iov[MAXLEN_MBUF_CHAIN];
6722e9986e0a84ab51dee01167310708e598b5b9994t	WSAMSG msg;
673587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	int nResult, m_ErrorCode;
6742e9986e0a84ab51dee01167310708e598b5b9994t	WSACMSGHDR *cmsgptr;
675bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
676587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen
677587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	udprecvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
678587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen
679bca1dae6587a640359abee04337c0463b0a3893tuexen	while (1) {
680bca1dae6587a640359abee04337c0463b0a3893tuexen		for (i = 0; i < to_fill; i++) {
681bca1dae6587a640359abee04337c0463b0a3893tuexen			/* Not getting the packet header. Tests with chain of one run
682bca1dae6587a640359abee04337c0463b0a3893tuexen			   as usual without having the packet header.
683bca1dae6587a640359abee04337c0463b0a3893tuexen			   Have tried both sending and receiving
684bca1dae6587a640359abee04337c0463b0a3893tuexen			 */
685218d5d0df143e859e241afb12d6aaa1e4969d714t			udprecvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
68607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
687bca1dae6587a640359abee04337c0463b0a3893tuexen			iov[i].iov_base = (caddr_t)udprecvmbuf[i]->m_data;
688bca1dae6587a640359abee04337c0463b0a3893tuexen			iov[i].iov_len = iovlen;
689587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#else
690587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen			iov[i].buf = (caddr_t)udprecvmbuf[i]->m_data;
691587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen			iov[i].len = iovlen;
692587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#endif
693bca1dae6587a640359abee04337c0463b0a3893tuexen		}
694bca1dae6587a640359abee04337c0463b0a3893tuexen		to_fill = 0;
69507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
696bca1dae6587a640359abee04337c0463b0a3893tuexen		bzero((void *)&msg, sizeof(struct msghdr));
697587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#else
6982e9986e0a84ab51dee01167310708e598b5b9994t		bzero((void *)&msg, sizeof(WSAMSG));
699587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#endif
700bca1dae6587a640359abee04337c0463b0a3893tuexen		bzero((void *)&src, sizeof(struct sockaddr_in));
701bca1dae6587a640359abee04337c0463b0a3893tuexen		bzero((void *)&dst, sizeof(struct sockaddr_in));
7022e9986e0a84ab51dee01167310708e598b5b9994t		bzero((void *)cmsgbuf, sizeof(cmsgbuf));
703587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen
70407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
705bca1dae6587a640359abee04337c0463b0a3893tuexen		msg.msg_name = (void *)&src;
706bca1dae6587a640359abee04337c0463b0a3893tuexen		msg.msg_namelen = sizeof(struct sockaddr_in);
707bca1dae6587a640359abee04337c0463b0a3893tuexen		msg.msg_iov = iov;
708bca1dae6587a640359abee04337c0463b0a3893tuexen		msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
709bca1dae6587a640359abee04337c0463b0a3893tuexen		msg.msg_control = (void *)cmsgbuf;
7102e9986e0a84ab51dee01167310708e598b5b9994t		msg.msg_controllen = sizeof(cmsgbuf);
711bca1dae6587a640359abee04337c0463b0a3893tuexen		msg.msg_flags = 0;
712bca1dae6587a640359abee04337c0463b0a3893tuexen
713b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, 0);
71467a1a0842895b84f6665b31c4a299ec2c1e182c9tuexen		if (n < 0) {
715b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			if (errno == EAGAIN) {
716b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				continue;
717b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			} else {
718b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				break;
719b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			}
72067a1a0842895b84f6665b31c4a299ec2c1e182c9tuexen		}
721587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#else
722b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp), SIO_GET_EXTENSION_FUNCTION_POINTER,
723587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
724587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		 &WSARecvMsg, sizeof WSARecvMsg,
725587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		 &ncounter, NULL, NULL);
726f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen		if (nResult == 0) {
7272e9986e0a84ab51dee01167310708e598b5b9994t			msg.name = (void *)&src;
7282e9986e0a84ab51dee01167310708e598b5b9994t			msg.namelen = sizeof(struct sockaddr_in);
7292e9986e0a84ab51dee01167310708e598b5b9994t			msg.lpBuffers = iov;
7302e9986e0a84ab51dee01167310708e598b5b9994t			msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
7312e9986e0a84ab51dee01167310708e598b5b9994t			msg.Control.len = sizeof ControlBuffer;
7322e9986e0a84ab51dee01167310708e598b5b9994t			msg.Control.buf = ControlBuffer;
7332e9986e0a84ab51dee01167310708e598b5b9994t			msg.dwFlags = 0;
7342e9986e0a84ab51dee01167310708e598b5b9994t			nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, &ncounter, NULL, NULL);
735587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		}
736587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		if (nResult != 0) {
737587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen			m_ErrorCode = WSAGetLastError();
738f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			if (m_ErrorCode == WSAETIMEDOUT) {
739f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				continue;
740f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			}
741f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
742f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				break;
743f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			}
744587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		}
745587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		n = ncounter;
746587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#endif
747bca1dae6587a640359abee04337c0463b0a3893tuexen		SCTP_HEADER_LEN(udprecvmbuf[0]) = n; /* length of total packet */
7486b5474dec62bc128acb56d0ad4ae413b91fedb09t		SCTP_STAT_INCR(sctps_recvpackets);
7496b5474dec62bc128acb56d0ad4ae413b91fedb09t		SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
750587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen
751bca1dae6587a640359abee04337c0463b0a3893tuexen		if (n <= iovlen) {
752bca1dae6587a640359abee04337c0463b0a3893tuexen			SCTP_BUF_LEN(udprecvmbuf[0]) = n;
753bca1dae6587a640359abee04337c0463b0a3893tuexen			(to_fill)++;
754bca1dae6587a640359abee04337c0463b0a3893tuexen		} else {
755bca1dae6587a640359abee04337c0463b0a3893tuexen			i = 0;
756bca1dae6587a640359abee04337c0463b0a3893tuexen			SCTP_BUF_LEN(udprecvmbuf[0]) = iovlen;
757bca1dae6587a640359abee04337c0463b0a3893tuexen
758bca1dae6587a640359abee04337c0463b0a3893tuexen			ncounter -= iovlen;
759bca1dae6587a640359abee04337c0463b0a3893tuexen			(to_fill)++;
760bca1dae6587a640359abee04337c0463b0a3893tuexen			do {
761bca1dae6587a640359abee04337c0463b0a3893tuexen				udprecvmbuf[i]->m_next = udprecvmbuf[i+1];
762bca1dae6587a640359abee04337c0463b0a3893tuexen				SCTP_BUF_LEN(udprecvmbuf[i]->m_next) = min(ncounter, iovlen);
763bca1dae6587a640359abee04337c0463b0a3893tuexen				i++;
764bca1dae6587a640359abee04337c0463b0a3893tuexen				ncounter -= iovlen;
765bca1dae6587a640359abee04337c0463b0a3893tuexen				(to_fill)++;
766bca1dae6587a640359abee04337c0463b0a3893tuexen			} while (ncounter > 0);
767bca1dae6587a640359abee04337c0463b0a3893tuexen		}
768bca1dae6587a640359abee04337c0463b0a3893tuexen
769bca1dae6587a640359abee04337c0463b0a3893tuexen		for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
77026dd10ff80a0682f81d8bcad6017143f8a508a3dt#if defined(IP_PKTINFO)
7712e9986e0a84ab51dee01167310708e598b5b9994t			if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_PKTINFO)) {
7722e9986e0a84ab51dee01167310708e598b5b9994t				struct in_pktinfo *info;
7732e9986e0a84ab51dee01167310708e598b5b9994t
774bca1dae6587a640359abee04337c0463b0a3893tuexen				dst.sin_family = AF_INET;
775bca1dae6587a640359abee04337c0463b0a3893tuexen#ifdef HAVE_SIN_LEN
776bca1dae6587a640359abee04337c0463b0a3893tuexen				dst.sin_len = sizeof(struct sockaddr_in);
777bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
7782e9986e0a84ab51dee01167310708e598b5b9994t				info = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
7792e9986e0a84ab51dee01167310708e598b5b9994t				memcpy((void *)&dst.sin_addr, (const void *)&(info->ipi_addr), sizeof(struct in_addr));
7802e9986e0a84ab51dee01167310708e598b5b9994t				break;
781bca1dae6587a640359abee04337c0463b0a3893tuexen			}
78233bf9a0eb4b1aa87412b2dffbced5c322f300ddbt#else
7832e9986e0a84ab51dee01167310708e598b5b9994t			if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_RECVDSTADDR)) {
7842e9986e0a84ab51dee01167310708e598b5b9994t				struct in_addr *addr;
7852e9986e0a84ab51dee01167310708e598b5b9994t
786587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen				dst.sin_family = AF_INET;
7872e9986e0a84ab51dee01167310708e598b5b9994t#ifdef HAVE_SIN_LEN
7882e9986e0a84ab51dee01167310708e598b5b9994t				dst.sin_len = sizeof(struct sockaddr_in);
7892e9986e0a84ab51dee01167310708e598b5b9994t#endif
7902e9986e0a84ab51dee01167310708e598b5b9994t				addr = (struct in_addr *)CMSG_DATA(cmsgptr);
7912e9986e0a84ab51dee01167310708e598b5b9994t				memcpy((void *)&dst.sin_addr, (const void *)addr, sizeof(struct in_addr));
7922e9986e0a84ab51dee01167310708e598b5b9994t				break;
793587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen			}
794587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#endif
7952e9986e0a84ab51dee01167310708e598b5b9994t		}
796bca1dae6587a640359abee04337c0463b0a3893tuexen
797890e1a3b80e879f0a3d527173d7922aa8da54064t		/* SCTP does not allow broadcasts or multicasts */
798890e1a3b80e879f0a3d527173d7922aa8da54064t		if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
79990c82b7f9b4290337239cf31926a8b87879f0357t			return (NULL);
800890e1a3b80e879f0a3d527173d7922aa8da54064t		}
801890e1a3b80e879f0a3d527173d7922aa8da54064t		if (SCTP_IS_IT_BROADCAST(dst.sin_addr, udprecvmbuf[0])) {
80290c82b7f9b4290337239cf31926a8b87879f0357t			return (NULL);
803890e1a3b80e879f0a3d527173d7922aa8da54064t		}
804bca1dae6587a640359abee04337c0463b0a3893tuexen
8056fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		/*offset = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);*/
8066fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		sh = mtod(udprecvmbuf[0], struct sctphdr *);
8076fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
8086fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		offset = sizeof(struct sctphdr);
8096fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		port = src.sin_port;
8106fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		src.sin_port = sh->src_port;
8116fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		dst.sin_port = sh->dest_port;
812a84e47fce6e5dd47a37cce19c040652bd9cc2ecat#if defined(SCTP_WITH_NO_CSUM)
813a84e47fce6e5dd47a37cce19c040652bd9cc2ecat		SCTP_STAT_INCR(sctps_recvnocrc);
814a84e47fce6e5dd47a37cce19c040652bd9cc2ecat#else
815890e1a3b80e879f0a3d527173d7922aa8da54064t		if (src.sin_addr.s_addr == dst.sin_addr.s_addr) {
816890e1a3b80e879f0a3d527173d7922aa8da54064t			compute_crc = 0;
817a84e47fce6e5dd47a37cce19c040652bd9cc2ecat			SCTP_STAT_INCR(sctps_recvnocrc);
818a84e47fce6e5dd47a37cce19c040652bd9cc2ecat		} else {
819a84e47fce6e5dd47a37cce19c040652bd9cc2ecat			SCTP_STAT_INCR(sctps_recvswcrc);
820890e1a3b80e879f0a3d527173d7922aa8da54064t		}
821890e1a3b80e879f0a3d527173d7922aa8da54064t#endif
822a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
8232356c9c75abdcc735cfcc8f9cb7c023375dac7b6t		SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
8246fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		sctp_common_input_processing(&udprecvmbuf[0], 0, offset, n,
8256fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             (struct sockaddr *)&src,
8266fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             (struct sockaddr *)&dst,
8276fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             sh, ch,
8286fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#if !defined(SCTP_WITH_NO_CSUM)
829890e1a3b80e879f0a3d527173d7922aa8da54064t		                             compute_crc,
8306fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
8316fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             0,
8326fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             SCTP_DEFAULT_VRFID, port);
833efdae3619f066b0a23c163043bf1a26f4ba0504ct		if (udprecvmbuf[0]) {
834efdae3619f066b0a23c163043bf1a26f4ba0504ct			m_freem(udprecvmbuf[0]);
835efdae3619f066b0a23c163043bf1a26f4ba0504ct		}
836bca1dae6587a640359abee04337c0463b0a3893tuexen	}
837b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
838b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		m_free(udprecvmbuf[i]);
839b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	}
840b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	/* free the array itself */
841b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	free(udprecvmbuf);
842f2c34c37a0bf05f900b2b316559ce4ae9c7be287t	return (NULL);
843bca1dae6587a640359abee04337c0463b0a3893tuexen}
844656fe4c72b7f60bbbee48b00610b20c70edf8f32tuexen#endif
845bca1dae6587a640359abee04337c0463b0a3893tuexen
84607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if defined(INET6)
84707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenstatic void *
84807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenrecv_function_udp6(void *arg)
84907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen{
850b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	struct mbuf **udprecvmbuf6;
85107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/*Initially the entire set of mbufs is to be allocated.
85207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	  to_fill indicates this amount. */
85307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int to_fill = MAXLEN_MBUF_CHAIN;
85407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/* iovlen is the size of each mbuf in the chain */
85507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int i, n, ncounter, offset;
85607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int iovlen = MCLBYTES;
85707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int want_ext = (iovlen > MLEN)? 1 : 0;
85807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int want_header = 0;
85907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	struct sockaddr_in6 src, dst;
8606fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	struct sctphdr *sh;
8616fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	uint16_t port;
8626fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	struct sctp_chunkhdr *ch;
86307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
864890e1a3b80e879f0a3d527173d7922aa8da54064t#if !defined(SCTP_WITH_NO_CSUM)
865890e1a3b80e879f0a3d527173d7922aa8da54064t	int compute_crc = 1;
866890e1a3b80e879f0a3d527173d7922aa8da54064t#endif
86707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
86807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	struct iovec iov[MAXLEN_MBUF_CHAIN];
86907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	struct msghdr msg;
87007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	struct cmsghdr *cmsgptr;
87107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#else
87207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
87307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	LPFN_WSARECVMSG WSARecvMsg;
87407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	char ControlBuffer[1024];
87507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	WSABUF iov[MAXLEN_MBUF_CHAIN];
8762e9986e0a84ab51dee01167310708e598b5b9994t	WSAMSG msg;
87707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int nResult, m_ErrorCode;
8782e9986e0a84ab51dee01167310708e598b5b9994t	WSACMSGHDR *cmsgptr;
87907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
88007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
88107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	udprecvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
8826fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler	while (1) {
88307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		for (i = 0; i < to_fill; i++) {
88407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			/* Not getting the packet header. Tests with chain of one run
88507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			   as usual without having the packet header.
88607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			   Have tried both sending and receiving
88707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			 */
888218d5d0df143e859e241afb12d6aaa1e4969d714t			udprecvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
88907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
89007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			iov[i].iov_base = (caddr_t)udprecvmbuf6[i]->m_data;
89107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			iov[i].iov_len = iovlen;
89207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#else
89307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			iov[i].buf = (caddr_t)udprecvmbuf6[i]->m_data;
89459caa502fe5258530a6f6eab10155a6dac5d8d5atuexen			iov[i].len = iovlen;
89507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
89607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
89707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		to_fill = 0;
89807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
89907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
90007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		bzero((void *)&msg, sizeof(struct msghdr));
90107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#else
9022e9986e0a84ab51dee01167310708e598b5b9994t		bzero((void *)&msg, sizeof(WSAMSG));
90307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
90407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		bzero((void *)&src, sizeof(struct sockaddr_in6));
90507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		bzero((void *)&dst, sizeof(struct sockaddr_in6));
90607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		bzero((void *)cmsgbuf, CMSG_SPACE(sizeof (struct in6_pktinfo)));
90707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
90807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
90907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_name = (void *)&src;
91007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_namelen = sizeof(struct sockaddr_in6);
91107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_iov = iov;
91207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
91307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_control = (void *)cmsgbuf;
91407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof (struct in6_pktinfo));
91507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		msg.msg_flags = 0;
91607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
917b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, 0);
91867a1a0842895b84f6665b31c4a299ec2c1e182c9tuexen		if (n < 0) {
919b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			if (errno == EAGAIN) {
920b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				continue;
921b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			} else {
922b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				break;
923b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			}
92467a1a0842895b84f6665b31c4a299ec2c1e182c9tuexen		}
92507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#else
926b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER,
92707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		                   &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
92807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		                   &WSARecvMsg, sizeof WSARecvMsg,
92907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		                   &ncounter, NULL, NULL);
9306fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		if (nResult == SOCKET_ERROR) {
9316fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			m_ErrorCode = WSAGetLastError();
9326fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			WSARecvMsg = NULL;
9336fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		}
934f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen		if (nResult == 0) {
9352e9986e0a84ab51dee01167310708e598b5b9994t			msg.name = (void *)&src;
9362e9986e0a84ab51dee01167310708e598b5b9994t			msg.namelen = sizeof(struct sockaddr_in6);
9372e9986e0a84ab51dee01167310708e598b5b9994t			msg.lpBuffers = iov;
9382e9986e0a84ab51dee01167310708e598b5b9994t			msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
9392e9986e0a84ab51dee01167310708e598b5b9994t			msg.Control.len = sizeof ControlBuffer;
9402e9986e0a84ab51dee01167310708e598b5b9994t			msg.Control.buf = ControlBuffer;
9412e9986e0a84ab51dee01167310708e598b5b9994t			msg.dwFlags = 0;
9422e9986e0a84ab51dee01167310708e598b5b9994t			nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, &ncounter, NULL, NULL);
94307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
94407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		if (nResult != 0) {
94507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			m_ErrorCode = WSAGetLastError();
946f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			if (m_ErrorCode == WSAETIMEDOUT) {
947f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				continue;
948f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			}
949f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
950f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				break;
951f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			}
95207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
95307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		n = ncounter;
95407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
95507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		SCTP_HEADER_LEN(udprecvmbuf6[0]) = n; /* length of total packet */
9566b5474dec62bc128acb56d0ad4ae413b91fedb09t		SCTP_STAT_INCR(sctps_recvpackets);
9576b5474dec62bc128acb56d0ad4ae413b91fedb09t		SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
95807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
95907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		if (n <= iovlen) {
96007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			SCTP_BUF_LEN(udprecvmbuf6[0]) = n;
96107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			(to_fill)++;
96207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		} else {
96307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			i = 0;
96407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			SCTP_BUF_LEN(udprecvmbuf6[0]) = iovlen;
96507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
96607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			ncounter -= iovlen;
96707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			(to_fill)++;
96807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			do {
96907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen				udprecvmbuf6[i]->m_next = udprecvmbuf6[i+1];
97007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen				SCTP_BUF_LEN(udprecvmbuf6[i]->m_next) = min(ncounter, iovlen);
97107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen				i++;
97207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen				ncounter -= iovlen;
97307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen				(to_fill)++;
97407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			} while (ncounter > 0);
97507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
97607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
97707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
97807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) {
9792e9986e0a84ab51dee01167310708e598b5b9994t				struct in6_pktinfo *info;
9802e9986e0a84ab51dee01167310708e598b5b9994t
98107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen				dst.sin6_family = AF_INET6;
9827b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
98307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen				dst.sin6_len = sizeof(struct sockaddr_in6);
98407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
9852e9986e0a84ab51dee01167310708e598b5b9994t				info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
9866fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				/*dst.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));*/
9872e9986e0a84ab51dee01167310708e598b5b9994t				memcpy((void *)&dst.sin6_addr, (const void *)&(info->ipi6_addr), sizeof(struct in6_addr));
98807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			}
98907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
99007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
991890e1a3b80e879f0a3d527173d7922aa8da54064t		/* SCTP does not allow broadcasts or multicasts */
992890e1a3b80e879f0a3d527173d7922aa8da54064t		if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) {
99390c82b7f9b4290337239cf31926a8b87879f0357t			return (NULL);
994890e1a3b80e879f0a3d527173d7922aa8da54064t		}
9956fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler
9966fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		sh = mtod(udprecvmbuf6[0], struct sctphdr *);
9976fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
9986fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		offset = sizeof(struct sctphdr);
9996fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler
10006fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		port = src.sin6_port;
10016fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		src.sin6_port = sh->src_port;
10026fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		dst.sin6_port = sh->dest_port;
1003a84e47fce6e5dd47a37cce19c040652bd9cc2ecat#if defined(SCTP_WITH_NO_CSUM)
1004a84e47fce6e5dd47a37cce19c040652bd9cc2ecat		SCTP_STAT_INCR(sctps_recvnocrc);
1005a84e47fce6e5dd47a37cce19c040652bd9cc2ecat#else
1006890e1a3b80e879f0a3d527173d7922aa8da54064t		if ((memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0)) {
1007890e1a3b80e879f0a3d527173d7922aa8da54064t			compute_crc = 0;
1008a84e47fce6e5dd47a37cce19c040652bd9cc2ecat			SCTP_STAT_INCR(sctps_recvnocrc);
1009a84e47fce6e5dd47a37cce19c040652bd9cc2ecat		} else {
1010a84e47fce6e5dd47a37cce19c040652bd9cc2ecat			SCTP_STAT_INCR(sctps_recvswcrc);
1011890e1a3b80e879f0a3d527173d7922aa8da54064t		}
1012890e1a3b80e879f0a3d527173d7922aa8da54064t#endif
1013a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
10142356c9c75abdcc735cfcc8f9cb7c023375dac7b6t		SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", (int)sizeof(struct sctphdr));
10152356c9c75abdcc735cfcc8f9cb7c023375dac7b6t		sctp_common_input_processing(&udprecvmbuf6[0], 0, offset, n,
10166fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             (struct sockaddr *)&src,
10176fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             (struct sockaddr *)&dst,
10186fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             sh, ch,
10196fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#if !defined(SCTP_WITH_NO_CSUM)
1020890e1a3b80e879f0a3d527173d7922aa8da54064t		                             compute_crc,
10216fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
10226fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             0,
10236fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		                             SCTP_DEFAULT_VRFID, port);
1024efdae3619f066b0a23c163043bf1a26f4ba0504ct		if (udprecvmbuf6[0]) {
1025efdae3619f066b0a23c163043bf1a26f4ba0504ct			m_freem(udprecvmbuf6[0]);
1026efdae3619f066b0a23c163043bf1a26f4ba0504ct		}
102707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
1028b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
1029b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		m_free(udprecvmbuf6[i]);
1030b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	}
1031b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	/* free the array itself */
1032b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	free(udprecvmbuf6);
1033f2c34c37a0bf05f900b2b316559ce4ae9c7be287t	return (NULL);
103407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen}
103507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
1036bca1dae6587a640359abee04337c0463b0a3893tuexen
10370622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexenstatic void
1038bca1dae6587a640359abee04337c0463b0a3893tuexensetReceiveBufferSize(int sfd, int new_size)
1039bca1dae6587a640359abee04337c0463b0a3893tuexen{
1040bca1dae6587a640359abee04337c0463b0a3893tuexen	int ch = new_size;
10410622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen
1042bca1dae6587a640359abee04337c0463b0a3893tuexen	if (setsockopt (sfd, SOL_SOCKET, SO_RCVBUF, (void*)&ch, sizeof(ch)) < 0) {
10436fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#if defined (__Userspace_os_Windows)
10446fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", WSAGetLastError());
10456fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#else
10460622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen		SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", errno);
10476fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
1048bca1dae6587a640359abee04337c0463b0a3893tuexen	}
10490622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen	return;
1050bca1dae6587a640359abee04337c0463b0a3893tuexen}
1051bca1dae6587a640359abee04337c0463b0a3893tuexen
10520622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexenstatic void
1053bca1dae6587a640359abee04337c0463b0a3893tuexensetSendBufferSize(int sfd, int new_size)
1054bca1dae6587a640359abee04337c0463b0a3893tuexen{
1055bca1dae6587a640359abee04337c0463b0a3893tuexen	int ch = new_size;
1056b735c0f45be3595abe0c88e2b5667780be2e27dctuexen
1057bca1dae6587a640359abee04337c0463b0a3893tuexen	if (setsockopt (sfd, SOL_SOCKET, SO_SNDBUF, (void*)&ch, sizeof(ch)) < 0) {
10586fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#if defined (__Userspace_os_Windows)
10596fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", WSAGetLastError());
10606fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#else
10616fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler		SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", errno);
10626fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
1063bca1dae6587a640359abee04337c0463b0a3893tuexen	}
10640622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen	return;
1065bca1dae6587a640359abee04337c0463b0a3893tuexen}
1066bca1dae6587a640359abee04337c0463b0a3893tuexen
1067f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen#define SOCKET_TIMEOUT 100 /* in ms */
1068b735c0f45be3595abe0c88e2b5667780be2e27dctuexenvoid
10693a33bc97bd0dd721a91035f5cf26c1956f264d3etuexenrecv_thread_init(void)
1070bca1dae6587a640359abee04337c0463b0a3893tuexen{
1071b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#if defined(INET)
1072bca1dae6587a640359abee04337c0463b0a3893tuexen	struct sockaddr_in addr_ipv4;
1073b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	const int hdrincl = 1;
1074b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
107507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if defined(INET6)
107607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	struct sockaddr_in6 addr_ipv6;
107707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
1078b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#if defined(INET) || defined(INET6)
1079b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	const int on = 1;
1080b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
10811b9c2d28d9c82d0ef42cc20d5274016d8060785ctuexen#if !defined(__Userspace_os_Windows)
10821b9c2d28d9c82d0ef42cc20d5274016d8060785ctuexen	struct timeval timeout;
1083bca1dae6587a640359abee04337c0463b0a3893tuexen
1084f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen	timeout.tv_sec  = (SOCKET_TIMEOUT / 1000);
1085f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen	timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
1086f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen#else
1087f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen	unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */
10881b9c2d28d9c82d0ef42cc20d5274016d8060785ctuexen#endif
108922a33a1debfe70529be4aa018a2912bfe5dcd8dat#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
1090b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_route) == -1) {
1091b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if ((SCTP_BASE_VAR(userspace_route) = socket(AF_ROUTE, SOCK_RAW, 0)) < 0) {
10920622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d).\n", errno);
1093b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		}
1094c48387a1b77565240a8a488026d3d550c9823caft#if 0
1095b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		struct sockaddr_nl sanl;
10963a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
1097b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if ((SCTP_BASE_VAR(userspace_route) = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
10980622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d.\n", errno);
10993a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		}
1100b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		memset(&sanl, 0, sizeof(sanl));
1101b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		sanl.nl_family = AF_NETLINK;
1102b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		sanl.nl_groups = 0;
1103b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#ifdef INET
1104b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		sanl.nl_groups |= RTMGRP_IPV4_IFADDR;
1105b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
1106b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#ifdef INET6
1107b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		sanl.nl_groups |= RTMGRP_IPV6_IFADDR;
1108b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
1109b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if (bind(SCTP_BASE_VAR(userspace_route), (struct sockaddr *) &sanl, sizeof(sanl)) < 0) {
11100622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't bind routing socket (errno = %d).\n", errno);
1111b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			close(SCTP_BASE_VAR(userspace_route));
1112b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			SCTP_BASE_VAR(userspace_route) = -1;
1113b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		}
1114b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
1115ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen		if (SCTP_BASE_VAR(userspace_route) != -1) {
1116ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen			if (setsockopt(SCTP_BASE_VAR(userspace_route), SOL_SOCKET, SO_RCVTIMEO,(const void*)&timeout, sizeof(struct timeval)) < 0) {
11170622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on routing socket (errno = %d).\n", errno);
1118ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen#if defined(__Userspace_os_Windows)
1119f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				closesocket(SCTP_BASE_VAR(userspace_route));
1120ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen#else
1121ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen				close(SCTP_BASE_VAR(userspace_route));
1122ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen#endif
1123ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen				SCTP_BASE_VAR(userspace_route) = -1;
1124ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen			}
1125ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen		}
11263a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
11273a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
1128b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#if defined(INET)
1129b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_rawsctp) == -1) {
1130b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if ((SCTP_BASE_VAR(userspace_rawsctp) = socket(AF_INET, SOCK_RAW, IPPROTO_SCTP)) < 0) {
11316fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#if defined(__Userspace_os_Windows)
11326fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", WSAGetLastError());
11336fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#else
11340622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", errno);
11356fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
1136e2c40ae4fa585324830f2e0ba98ef24eb9332246tuexen		} else {
1137e2c40ae4fa585324830f2e0ba98ef24eb9332246tuexen			/* complete setting up the raw SCTP socket */
1138b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), IPPROTO_IP, IP_HDRINCL,(const void*)&hdrincl, sizeof(int)) < 0) {
1139b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#if defined(__Userspace_os_Windows)
11406fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", WSAGetLastError());
1141f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				closesocket(SCTP_BASE_VAR(userspace_rawsctp));
1142b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#else
11436fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", errno);
1144b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				close(SCTP_BASE_VAR(userspace_rawsctp));
1145b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
11461b9c2d28d9c82d0ef42cc20d5274016d8060785ctuexen				SCTP_BASE_VAR(userspace_rawsctp) = -1;
1147f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			} else if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
11481b9c2d28d9c82d0ef42cc20d5274016d8060785ctuexen#if defined(__Userspace_os_Windows)
11496fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError());
1150f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				closesocket(SCTP_BASE_VAR(userspace_rawsctp));
11511b9c2d28d9c82d0ef42cc20d5274016d8060785ctuexen#else
11526fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", errno);
11531b9c2d28d9c82d0ef42cc20d5274016d8060785ctuexen				close(SCTP_BASE_VAR(userspace_rawsctp));
11541b9c2d28d9c82d0ef42cc20d5274016d8060785ctuexen#endif
1155b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				SCTP_BASE_VAR(userspace_rawsctp) = -1;
1156b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			} else {
1157b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in));
1158587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#ifdef HAVE_SIN_LEN
1159b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				addr_ipv4.sin_len         = sizeof(struct sockaddr_in);
1160587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#endif
1161b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				addr_ipv4.sin_family      = AF_INET;
1162b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				addr_ipv4.sin_port        = htons(0);
1163b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
1164b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				if (bind(SCTP_BASE_VAR(userspace_rawsctp), (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) {
1165b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#if defined(__Userspace_os_Windows)
11666fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler					SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError());
1167f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen					closesocket(SCTP_BASE_VAR(userspace_rawsctp));
1168b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#else
11696fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler					SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", errno);
1170b735c0f45be3595abe0c88e2b5667780be2e27dctuexen					close(SCTP_BASE_VAR(userspace_rawsctp));
1171b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
1172b735c0f45be3595abe0c88e2b5667780be2e27dctuexen					SCTP_BASE_VAR(userspace_rawsctp) = -1;
1173b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				} else {
1174b735c0f45be3595abe0c88e2b5667780be2e27dctuexen					setReceiveBufferSize(SCTP_BASE_VAR(userspace_rawsctp), SB_RAW); /* 128K */
1175b735c0f45be3595abe0c88e2b5667780be2e27dctuexen					setSendBufferSize(SCTP_BASE_VAR(userspace_rawsctp), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
1176b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				}
117759caa502fe5258530a6f6eab10155a6dac5d8d5atuexen			}
1178e2c40ae4fa585324830f2e0ba98ef24eb9332246tuexen		}
1179bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1180b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_udpsctp) == -1) {
1181b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if ((SCTP_BASE_VAR(userspace_udpsctp) = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
11826fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#if defined(__Userspace_os_Windows)
11836fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
11846fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#else
11850622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
11866fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
1187b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		} else {
118826dd10ff80a0682f81d8bcad6017143f8a508a3dt#if defined(IP_PKTINFO)
11892e9986e0a84ab51dee01167310708e598b5b9994t			if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
119026dd10ff80a0682f81d8bcad6017143f8a508a3dt#else
119126dd10ff80a0682f81d8bcad6017143f8a508a3dt			if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_RECVDSTADDR, (const void *)&on, (int)sizeof(int)) < 0) {
11922e9986e0a84ab51dee01167310708e598b5b9994t#endif
1193b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#if defined(__Userspace_os_Windows)
119426dd10ff80a0682f81d8bcad6017143f8a508a3dt#if defined(IP_PKTINFO)
11952e9986e0a84ab51dee01167310708e598b5b9994t				SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
119626dd10ff80a0682f81d8bcad6017143f8a508a3dt#else
119726dd10ff80a0682f81d8bcad6017143f8a508a3dt				SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
11982e9986e0a84ab51dee01167310708e598b5b9994t#endif
1199f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				closesocket(SCTP_BASE_VAR(userspace_udpsctp));
1200b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#else
120126dd10ff80a0682f81d8bcad6017143f8a508a3dt#if defined(IP_PKTINFO)
12022e9986e0a84ab51dee01167310708e598b5b9994t				SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
120326dd10ff80a0682f81d8bcad6017143f8a508a3dt#else
120426dd10ff80a0682f81d8bcad6017143f8a508a3dt				SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
12052e9986e0a84ab51dee01167310708e598b5b9994t#endif
1206b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				close(SCTP_BASE_VAR(userspace_udpsctp));
12071b9c2d28d9c82d0ef42cc20d5274016d8060785ctuexen#endif
12081b9c2d28d9c82d0ef42cc20d5274016d8060785ctuexen				SCTP_BASE_VAR(userspace_udpsctp) = -1;
1209f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			} else if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
12101b9c2d28d9c82d0ef42cc20d5274016d8060785ctuexen#if defined(__Userspace_os_Windows)
12116fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
1212f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				closesocket(SCTP_BASE_VAR(userspace_udpsctp));
12131b9c2d28d9c82d0ef42cc20d5274016d8060785ctuexen#else
12146fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
12151b9c2d28d9c82d0ef42cc20d5274016d8060785ctuexen				close(SCTP_BASE_VAR(userspace_udpsctp));
1216b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
1217b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				SCTP_BASE_VAR(userspace_udpsctp) = -1;
1218b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			} else {
1219b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in));
1220bca1dae6587a640359abee04337c0463b0a3893tuexen#ifdef HAVE_SIN_LEN
1221b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				addr_ipv4.sin_len         = sizeof(struct sockaddr_in);
1222bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
1223b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				addr_ipv4.sin_family      = AF_INET;
1224b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				addr_ipv4.sin_port        = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
1225b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
1226b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				if (bind(SCTP_BASE_VAR(userspace_udpsctp), (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) {
1227b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#if defined(__Userspace_os_Windows)
12286fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler					SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
1229f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen					closesocket(SCTP_BASE_VAR(userspace_udpsctp));
1230b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#else
12316fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler					SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
1232b735c0f45be3595abe0c88e2b5667780be2e27dctuexen					close(SCTP_BASE_VAR(userspace_udpsctp));
1233b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
1234b735c0f45be3595abe0c88e2b5667780be2e27dctuexen					SCTP_BASE_VAR(userspace_udpsctp) = -1;
1235b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				} else {
1236b735c0f45be3595abe0c88e2b5667780be2e27dctuexen					setReceiveBufferSize(SCTP_BASE_VAR(userspace_udpsctp), SB_RAW); /* 128K */
1237b735c0f45be3595abe0c88e2b5667780be2e27dctuexen					setSendBufferSize(SCTP_BASE_VAR(userspace_udpsctp), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
1238b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				}
1239b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			}
1240bca1dae6587a640359abee04337c0463b0a3893tuexen		}
1241bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1242b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
124307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if defined(INET6)
1244b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_rawsctp6) == -1) {
1245b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if ((SCTP_BASE_VAR(userspace_rawsctp6) = socket(AF_INET6, SOCK_RAW, IPPROTO_SCTP)) < 0) {
12466fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#if defined(__Userspace_os_Windows)
12476fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
12486fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#else
12490622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", errno);
12506fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
125107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		} else {
125207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			/* complete setting up the raw SCTP socket */
12539cf61baf77a644c6a5ab2dff61d0d78e2ea94fb2tuexen#if defined(IPV6_RECVPKTINFO)
12546fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, sizeof(on)) < 0) {
1255b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#if defined(__Userspace_os_Windows)
12566fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1257f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
125807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#else
12596fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno);
1260b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				close(SCTP_BASE_VAR(userspace_rawsctp6));
1261b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
1262b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				SCTP_BASE_VAR(userspace_rawsctp6) = -1;
1263b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			} else {
1264b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#else
1265b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_PKTINFO,(const void*)&on, sizeof(on)) < 0) {
1266b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#if defined(__Userspace_os_Windows)
12676fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1268f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
1269b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#else
12706fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno);
1271b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				close(SCTP_BASE_VAR(userspace_rawsctp6));
127207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
1273b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				SCTP_BASE_VAR(userspace_rawsctp6) = -1;
1274b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			} else {
1275b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
1276b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&on, (socklen_t)sizeof(on)) < 0) {
12776fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#if defined(__Userspace_os_Windows)
12786fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler					SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
12796fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#else
12800622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen					SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", errno);
12816fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
1282b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				}
1283f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
1284ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen#if defined(__Userspace_os_Windows)
12856fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler					SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1286f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen					closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
1287ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen#else
12886fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler					SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", errno);
1289f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen					close(SCTP_BASE_VAR(userspace_rawsctp6));
1290ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen#endif
1291f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen					SCTP_BASE_VAR(userspace_rawsctp6) = -1;
1292ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen				} else {
1293ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen					memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6));
12947b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
1295ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen					addr_ipv6.sin6_len         = sizeof(struct sockaddr_in6);
129607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
1297ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen					addr_ipv6.sin6_family      = AF_INET6;
1298ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen					addr_ipv6.sin6_port        = htons(0);
1299ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen					addr_ipv6.sin6_addr        = in6addr_any;
1300ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen					if (bind(SCTP_BASE_VAR(userspace_rawsctp6), (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) {
1301b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#if defined(__Userspace_os_Windows)
13026fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler						SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1303f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen						closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
1304b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#else
13056fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler						SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", errno);
1306ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen						close(SCTP_BASE_VAR(userspace_rawsctp6));
1307b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
1308ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen						SCTP_BASE_VAR(userspace_rawsctp6) = -1;
1309ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen					} else {
1310ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen						setReceiveBufferSize(SCTP_BASE_VAR(userspace_rawsctp6), SB_RAW); /* 128K */
1311ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen						setSendBufferSize(SCTP_BASE_VAR(userspace_rawsctp6), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
1312ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen					}
1313b735c0f45be3595abe0c88e2b5667780be2e27dctuexen				}
1314b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			}
131507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
131607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
1317b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_udpsctp6) == -1) {
1318b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if ((SCTP_BASE_VAR(userspace_udpsctp6) = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
13196fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#if defined(__Userspace_os_Windows)
13206fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
13216fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#else
13220622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
13236fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
132407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
13259cf61baf77a644c6a5ab2dff61d0d78e2ea94fb2tuexen#if defined(IPV6_RECVPKTINFO)
1326b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
1327f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen#if defined(__Userspace_os_Windows)
13286fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1329f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1330f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen#else
13316fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1332b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			close(SCTP_BASE_VAR(userspace_udpsctp6));
1333f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen#endif
1334b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1335b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		} else {
133607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#else
1337b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
1338f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen#if defined(__Userspace_os_Windows)
13396fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1340f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1341f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen#else
13426fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler			SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1343b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			close(SCTP_BASE_VAR(userspace_udpsctp6));
1344f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen#endif
1345b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1346b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		} else {
134707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
1348f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&on, (socklen_t)sizeof(on)) < 0) {
13496fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#if defined(__Userspace_os_Windows)
13506fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
13516fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#else
13520622a9e51f1ec476ccf5d038c4e3b11fdfc07197tuexen				SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
13536fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler#endif
1354b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			}
1355f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
1356ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen#if defined(__Userspace_os_Windows)
13576fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1358f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1359f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen#else
13606fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1361f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				close(SCTP_BASE_VAR(userspace_udpsctp6));
1362ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen#endif
1363f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen				SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1364b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			} else {
1365ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen				memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6));
13667b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
1367ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen				addr_ipv6.sin6_len         = sizeof(struct sockaddr_in6);
1368ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen#endif
1369ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen				addr_ipv6.sin6_family      = AF_INET6;
1370ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen				addr_ipv6.sin6_port        = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
1371ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen				addr_ipv6.sin6_addr        = in6addr_any;
13726fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler				if (bind(SCTP_BASE_VAR(userspace_udpsctp6), (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) {
1373f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen#if defined(__Userspace_os_Windows)
13746fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler					SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1375f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen					closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1376f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen#else
13776fc7a71fd6b23541e3f5c9ab85f089ded5ad2e49ruengeler					SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1378ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen					close(SCTP_BASE_VAR(userspace_udpsctp6));
1379f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen#endif
1380ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen					SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1381ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen				} else {
1382ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen					setReceiveBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K */
1383ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen					setSendBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
1384ba1ce00b85a38f8276850a5fd7bbc14c1dfdeff7tuexen				}
1385b735c0f45be3595abe0c88e2b5667780be2e27dctuexen			}
138607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
138707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
138807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
138907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#if !defined(__Userspace_os_Windows)
139022a33a1debfe70529be4aa018a2912bfe5dcd8dat#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
1391b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#if defined(INET) || defined(INET6)
1392b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_route) != -1) {
13933a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		int rc;
13943a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen
1395b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadroute), NULL, &recv_function_route, NULL))) {
1396a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't start routing thread (%d).\n", rc);
1397d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			close(SCTP_BASE_VAR(userspace_route));
1398d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			SCTP_BASE_VAR(userspace_route) = -1;
13993a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen		}
14003a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
1401b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
14027943a5e518ee0e8d37d70b5637430137cedc918dt#endif
1403085a50552dced389ab59174355a4ec1ee478be97tuexen#if defined(INET)
1404b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
1405587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		int rc;
1406587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen
1407b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw), NULL, &recv_function_raw, NULL))) {
1408a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread (%d).\n", rc);
1409d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			close(SCTP_BASE_VAR(userspace_rawsctp));
1410d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			SCTP_BASE_VAR(userspace_rawsctp) = -1;
1411bca1dae6587a640359abee04337c0463b0a3893tuexen		}
1412bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1413b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
1414587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		int rc;
1415587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen
1416b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp), NULL, &recv_function_udp, NULL))) {
1417a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread (%d).\n", rc);
1418d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			close(SCTP_BASE_VAR(userspace_udpsctp));
1419d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			SCTP_BASE_VAR(userspace_udpsctp) = -1;
142007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
142107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
1422085a50552dced389ab59174355a4ec1ee478be97tuexen#endif
1423085a50552dced389ab59174355a4ec1ee478be97tuexen#if defined(INET6)
1424b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
142507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		int rc;
142607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
1427b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw6), NULL, &recv_function_raw6, NULL))) {
1428a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread (%d).\n", rc);
1429d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			close(SCTP_BASE_VAR(userspace_rawsctp6));
1430d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			SCTP_BASE_VAR(userspace_rawsctp6) = -1;
143107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
143207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
1433b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
143407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		int rc;
143507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
1436b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp6), NULL, &recv_function_udp6, NULL))) {
1437a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread (%d).\n", rc);
1438d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			close(SCTP_BASE_VAR(userspace_udpsctp6));
1439d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1440bca1dae6587a640359abee04337c0463b0a3893tuexen		}
1441bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1442085a50552dced389ab59174355a4ec1ee478be97tuexen#endif
1443587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#else
1444085a50552dced389ab59174355a4ec1ee478be97tuexen#if defined(INET)
1445b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
1446b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		if ((SCTP_BASE_VAR(recvthreadraw) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw, NULL, 0, NULL)) == NULL) {
1447a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread.\n");
1448f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			closesocket(SCTP_BASE_VAR(userspace_rawsctp));
1449d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			SCTP_BASE_VAR(userspace_rawsctp) = -1;
1450587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		}
1451587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	}
1452b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
1453a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		if ((SCTP_BASE_VAR(recvthreadudp) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp, NULL, 0, NULL)) == NULL) {
1454a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread.\n");
1455f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			closesocket(SCTP_BASE_VAR(userspace_udpsctp));
1456d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			SCTP_BASE_VAR(userspace_udpsctp) = -1;
1457587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen		}
1458587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	}
1459085a50552dced389ab59174355a4ec1ee478be97tuexen#endif
1460085a50552dced389ab59174355a4ec1ee478be97tuexen#if defined(INET6)
1461b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
1462a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		if ((SCTP_BASE_VAR(recvthreadraw6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw6, NULL, 0, NULL)) == NULL) {
1463a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread.\n");
1464f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
1465d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			SCTP_BASE_VAR(userspace_rawsctp6) = -1;
146659caa502fe5258530a6f6eab10155a6dac5d8d5atuexen		}
146759caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	}
1468b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
1469a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		if ((SCTP_BASE_VAR(recvthreadudp6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp6, NULL, 0, NULL)) == NULL) {
1470a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen			SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread.\n");
1471f83a7fabb73ab722cdbd1ee394eb24237dfe5c33tuexen			closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1472d93dfec9706e00ca6d9ceeb72462367b22d74ccetuexen			SCTP_BASE_VAR(userspace_udpsctp6) = -1;
147359caa502fe5258530a6f6eab10155a6dac5d8d5atuexen		}
147459caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	}
1475587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen#endif
1476085a50552dced389ab59174355a4ec1ee478be97tuexen#endif
1477bca1dae6587a640359abee04337c0463b0a3893tuexen}
1478bca1dae6587a640359abee04337c0463b0a3893tuexen
1479bca1dae6587a640359abee04337c0463b0a3893tuexenvoid
14803a33bc97bd0dd721a91035f5cf26c1956f264d3etuexenrecv_thread_destroy(void)
1481587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen{
148222a33a1debfe70529be4aa018a2912bfe5dcd8dat#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
1483b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#if defined(INET) || defined(INET6)
1484b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_route) != -1) {
1485b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		close(SCTP_BASE_VAR(userspace_route));
14863a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
1487b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
1488b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
1489b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#if defined(INET)
1490b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
14913a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#if defined(__Userspace_os_Windows)
1492b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		closesocket(SCTP_BASE_VAR(userspace_rawsctp));
14933a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#else
1494b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		close(SCTP_BASE_VAR(userspace_rawsctp));
1495c5fa57e95fcabaa1ab0fcbd4ccab1e68487798c4tuexen#endif
1496587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	}
1497b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
14983a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#if defined(__Userspace_os_Windows)
1499b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		closesocket(SCTP_BASE_VAR(userspace_udpsctp));
15003a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#else
1501b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		close(SCTP_BASE_VAR(userspace_udpsctp));
15023a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
1503587a0a600ce5ed1f37d26deeabb0fe9be27da00etuexen	}
1504b735c0f45be3595abe0c88e2b5667780be2e27dctuexen#endif
15053a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#if defined(INET6)
1506b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
15073a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#if defined(__Userspace_os_Windows)
1508b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
15093a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#else
1510b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		close(SCTP_BASE_VAR(userspace_rawsctp6));
15113a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
15123a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
1513b735c0f45be3595abe0c88e2b5667780be2e27dctuexen	if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
15143a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#if defined(__Userspace_os_Windows)
1515b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
15163a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#else
1517b735c0f45be3595abe0c88e2b5667780be2e27dctuexen		close(SCTP_BASE_VAR(userspace_udpsctp6));
15183a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
15193a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen	}
15203a33bc97bd0dd721a91035f5cf26c1956f264d3etuexen#endif
1521bca1dae6587a640359abee04337c0463b0a3893tuexen}
15226b5474dec62bc128acb56d0ad4ae413b91fedb09t#else
15236b5474dec62bc128acb56d0ad4ae413b91fedb09tint foo;
152400e1eea74e46d1a26092bf75dc0147015547aaf8tuexen#endif
1525