blob: 7b2ff584647177e5bb445df3a156651baa6aad28 [file] [log] [blame]
tuexenb735c0f2012-04-28 16:43:56 +00001/*-
tuexen829d1a72012-05-23 09:39:05 +00002 * Copyright (c) 2009-2010 Brad Penoff
3 * Copyright (c) 2009-2010 Humaira Kamal
4 * Copyright (c) 2011-2012 Irene Ruengeler
5 * Copyright (c) 2011-2012 Michael Tuexen
tuexenb735c0f2012-04-28 16:43:56 +00006 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
tuexena4fb5762012-07-15 21:03:56 +000031#if defined(INET) || defined(INET6)
tuexenbca1dae2011-11-01 23:02:02 +000032#include <sys/types.h>
tuexen07961c42011-12-23 15:39:36 +000033#if !defined(__Userspace_os_Windows)
tuexenbca1dae2011-11-01 23:02:02 +000034#include <sys/socket.h>
t00fcxen2356c9c2012-09-04 20:21:12 +000035#include <netinet/in.h>
tuexen587a0a62011-12-15 17:32:38 +000036#include <unistd.h>
37#include <pthread.h>
t00fcxen22a33a12013-12-27 19:21:25 +000038#if !defined(__Userspace_os_DragonFly) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_NetBSD)
tuexenbca1dae2011-11-01 23:02:02 +000039#include <sys/uio.h>
tuexen3a33bc92012-01-15 12:10:06 +000040#else
41#include <user_ip6_var.h>
tuexenebe00622011-12-15 21:26:11 +000042#endif
tuexen07961c42011-12-23 15:39:36 +000043#endif
tuexenbca1dae2011-11-01 23:02:02 +000044#include <netinet/sctp_os.h>
45#include <netinet/sctp_var.h>
46#include <netinet/sctp_pcb.h>
t00fcxen968138a2012-09-05 07:17:28 +000047#include <netinet/sctp_input.h>
t00fcxen7943a5e2012-09-04 20:32:11 +000048#if 0
tuexen3a33bc92012-01-15 12:10:06 +000049#if defined(__Userspace_os_Linux)
50#include <linux/netlink.h>
t00fcxen2356c9c2012-09-04 20:21:12 +000051#ifdef HAVE_LINUX_IF_ADDR_H
tuexen3a33bc92012-01-15 12:10:06 +000052#include <linux/if_addr.h>
53#endif
t00fcxen2356c9c2012-09-04 20:21:12 +000054#ifdef HAVE_LINUX_RTNETLINK_H
55#include <linux/rtnetlink.h>
56#endif
57#endif
t00fcxen7943a5e2012-09-04 20:32:11 +000058#endif
t00fcxen22a33a12013-12-27 19:21:25 +000059#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
t00fcxen2356c9c2012-09-04 20:21:12 +000060#include <net/route.h>
61#endif
tuexenbca1dae2011-11-01 23:02:02 +000062/* local macros and datatypes used to get IP addresses system independently */
t00fcxen2e9986e2012-09-15 12:42:22 +000063#if !defined(IP_PKTINFO ) && ! defined(IP_RECVDSTADDR)
64# error "Can't determine socket option to use to get UDP IP"
tuexenbca1dae2011-11-01 23:02:02 +000065#endif
66
tuexen3a33bc92012-01-15 12:10:06 +000067void recv_thread_destroy(void);
tuexen587a0a62011-12-15 17:32:38 +000068#define MAXLEN_MBUF_CHAIN 32 /* What should this value be? */
tuexen3a33bc92012-01-15 12:10:06 +000069#define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
t00fcxen22a33a12013-12-27 19:21:25 +000070#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
tuexen3a33bc92012-01-15 12:10:06 +000071#define NEXT_SA(ap) ap = (struct sockaddr *) \
72 ((caddr_t) ap + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof (uint32_t)) : sizeof(uint32_t)))
73#endif
74
t00fcxen22a33a12013-12-27 19:21:25 +000075#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
tuexen3a33bc92012-01-15 12:10:06 +000076static void
77sctp_get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
78{
79 int i;
80
81 for (i = 0; i < RTAX_MAX; i++) {
82 if (addrs & (1 << i)) {
83 rti_info[i] = sa;
84 NEXT_SA(sa);
85 } else {
86 rti_info[i] = NULL;
87 }
88 }
89}
tuexen3a33bc92012-01-15 12:10:06 +000090
91static void
92sctp_handle_ifamsg(unsigned char type, unsigned short index, struct sockaddr *sa)
93{
94 int rc;
95 struct ifaddrs *ifa, *found_ifa = NULL;
96
97 /* handle only the types we want */
98 if ((type != RTM_NEWADDR) && (type != RTM_DELADDR)) {
99 return;
100 }
101
102 rc = getifaddrs(&g_interfaces);
103 if (rc != 0) {
tuexen3a33bc92012-01-15 12:10:06 +0000104 return;
105 }
106 for (ifa = g_interfaces; ifa; ifa = ifa->ifa_next) {
107 if (index == if_nametoindex(ifa->ifa_name)) {
108 found_ifa = ifa;
109 break;
110 }
111 }
112 if (found_ifa == NULL) {
tuexen3a33bc92012-01-15 12:10:06 +0000113 return;
114 }
115
116 switch (sa->sa_family) {
117#ifdef INET
118 case AF_INET:
119 ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
120 memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in));
121 break;
122#endif
123#ifdef INET6
124 case AF_INET6:
125 ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in6));
126 memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in6));
127 break;
128#endif
129 default:
tuexena1d7a852012-05-19 14:55:19 +0000130 SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", sa->sa_family);
tuexen3a33bc92012-01-15 12:10:06 +0000131 }
132
133 /* relay the appropriate address change to the base code */
134 if (type == RTM_NEWADDR) {
135 (void)sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, ifa, if_nametoindex(ifa->ifa_name),
136 0,
137 ifa->ifa_name,
138 (void *)ifa,
139 ifa->ifa_addr,
140 0,
141 1);
142 } else {
143 sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
144 if_nametoindex(ifa->ifa_name),
145 ifa->ifa_name);
146 }
147}
148
tuexen3a33bc92012-01-15 12:10:06 +0000149static void *
150recv_function_route(void *arg)
151{
152 ssize_t ret;
153 struct ifa_msghdr *ifa;
154 char rt_buffer[1024];
155 struct sockaddr *sa, *rti_info[RTAX_MAX];
156
tuexenb735c0f2012-04-28 16:43:56 +0000157 while (1) {
tuexen3a33bc92012-01-15 12:10:06 +0000158 bzero(rt_buffer, sizeof(rt_buffer));
tuexenb735c0f2012-04-28 16:43:56 +0000159 ret = recv(SCTP_BASE_VAR(userspace_route), rt_buffer, sizeof(rt_buffer), 0);
tuexen3a33bc92012-01-15 12:10:06 +0000160
161 if (ret > 0) {
162 ifa = (struct ifa_msghdr *) rt_buffer;
163 if (ifa->ifam_type != RTM_DELADDR && ifa->ifam_type != RTM_NEWADDR) {
164 continue;
165 }
166 sa = (struct sockaddr *) (ifa + 1);
167 sctp_get_rtaddrs(ifa->ifam_addrs, sa, rti_info);
168 switch (ifa->ifam_type) {
169 case RTM_DELADDR:
170 case RTM_NEWADDR:
171 sctp_handle_ifamsg(ifa->ifam_type, ifa->ifam_index, rti_info[RTAX_IFA]);
172 break;
173 default:
174 /* ignore this routing event */
175 break;
176 }
177 }
tuexenb735c0f2012-04-28 16:43:56 +0000178 if (ret < 0) {
179 if (errno == EAGAIN) {
180 continue;
181 } else {
182 break;
183 }
184 }
tuexen3a33bc92012-01-15 12:10:06 +0000185 }
t00fcxen90c82b72013-11-14 20:51:33 +0000186 return (NULL);
tuexen3a33bc92012-01-15 12:10:06 +0000187}
t00fcxen7943a5e2012-09-04 20:32:11 +0000188#endif
189
190#if 0
191/* This does not yet work on Linux */
tuexen3a33bc92012-01-15 12:10:06 +0000192static void *
193recv_function_route(void *arg)
194{
tuexen3a33bc92012-01-15 12:10:06 +0000195 int len;
196 char buf[4096];
197 struct iovec iov = { buf, sizeof(buf) };
198 struct msghdr msg;
199 struct nlmsghdr *nh;
tuexen3a33bc92012-01-15 12:10:06 +0000200 struct ifaddrmsg *rtmsg;
tuexenb735c0f2012-04-28 16:43:56 +0000201 struct rtattr *rtatp;
tuexen3a33bc92012-01-15 12:10:06 +0000202 struct in_addr *inp;
tuexena29d53b2012-04-28 17:55:57 +0000203 struct sockaddr_nl sanl;
tuexen3a33bc92012-01-15 12:10:06 +0000204#ifdef INET
205 struct sockaddr_in *sa;
206#endif
207#ifdef INET6
208 struct sockaddr_in6 *sa6;
209#endif
tuexen3a33bc92012-01-15 12:10:06 +0000210
tuexena29d53b2012-04-28 17:55:57 +0000211 for (;;) {
212 memset(&sanl, 0, sizeof(sanl));
213 sanl.nl_family = AF_NETLINK;
214 sanl.nl_groups = RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_IFADDR;
tuexen3a33bc92012-01-15 12:10:06 +0000215 memset(&msg, 0, sizeof(struct msghdr));
216 msg.msg_name = (void *)&sanl;
217 msg.msg_namelen = sizeof(sanl);
218 msg.msg_iov = &iov;
219 msg.msg_iovlen = 1;
220 msg.msg_control = NULL;
221 msg.msg_controllen = 0;
222
tuexenb735c0f2012-04-28 16:43:56 +0000223 len = recvmsg(SCTP_BASE_VAR(userspace_route), &msg, 0);
tuexen3a33bc92012-01-15 12:10:06 +0000224
tuexenb735c0f2012-04-28 16:43:56 +0000225 if (len < 0) {
226 if (errno == EAGAIN) {
227 continue;
228 } else {
229 break;
230 }
231 }
tuexen3a33bc92012-01-15 12:10:06 +0000232 for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len);
233 nh = NLMSG_NEXT (nh, len)) {
234 if (nh->nlmsg_type == NLMSG_DONE)
tuexenb735c0f2012-04-28 16:43:56 +0000235 break;
tuexen3a33bc92012-01-15 12:10:06 +0000236
237 if (nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR) {
238 rtmsg = (struct ifaddrmsg *)NLMSG_DATA(nh);
239 rtatp = (struct rtattr *)IFA_RTA(rtmsg);
240 if(rtatp->rta_type == IFA_ADDRESS) {
241 inp = (struct in_addr *)RTA_DATA(rtatp);
242 switch (rtmsg->ifa_family) {
243#ifdef INET
244 case AF_INET:
245 sa = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
246 sa->sin_family = rtmsg->ifa_family;
247 sa->sin_port = 0;
248 memcpy(&sa->sin_addr, inp, sizeof(struct in_addr));
249 sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa);
250 break;
251#endif
252#ifdef INET6
253 case AF_INET6:
254 sa6 = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6));
255 sa6->sin6_family = rtmsg->ifa_family;
256 sa6->sin6_port = 0;
257 memcpy(&sa6->sin6_addr, inp, sizeof(struct in6_addr));
258 sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa6);
259 break;
260#endif
261 default:
ruengeler08da49d2012-05-21 08:17:29 +0000262 SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", rtmsg->ifa_family);
tuexenb735c0f2012-04-28 16:43:56 +0000263 break;
tuexen3a33bc92012-01-15 12:10:06 +0000264 }
265 }
266 }
267 }
268 }
t00fcxen90c82b72013-11-14 20:51:33 +0000269 return (NULL);
tuexen3a33bc92012-01-15 12:10:06 +0000270}
271#endif
tuexenbca1dae2011-11-01 23:02:02 +0000272
tuexen656fe4c2012-06-28 16:54:10 +0000273#ifdef INET
tuexenbca1dae2011-11-01 23:02:02 +0000274static void *
275recv_function_raw(void *arg)
276{
tuexenb735c0f2012-04-28 16:43:56 +0000277 struct mbuf **recvmbuf;
ruengeler6fc7a712012-07-31 12:16:29 +0000278 struct ip *iphdr;
279 struct sctphdr *sh;
280 uint16_t port;
t00fcxen890e1a32012-09-14 14:30:39 +0000281 int offset, ecn = 0;
282#if !defined(SCTP_WITH_NO_CSUM)
283 int compute_crc = 1;
284#endif
ruengeler6fc7a712012-07-31 12:16:29 +0000285 struct sctp_chunkhdr *ch;
286 struct sockaddr_in src, dst;
tuexen07961c42011-12-23 15:39:36 +0000287#if !defined(__Userspace_os_Windows)
t00fcxenb21b4a12012-09-14 18:03:34 +0000288 struct msghdr msg;
tuexenbca1dae2011-11-01 23:02:02 +0000289 struct iovec recv_iovec[MAXLEN_MBUF_CHAIN];
tuexen587a0a62011-12-15 17:32:38 +0000290#else
291 WSABUF recv_iovec[MAXLEN_MBUF_CHAIN];
292 int nResult, m_ErrorCode;
293 DWORD flags;
tuexen59caa502012-01-08 10:27:02 +0000294 struct sockaddr_in from;
tuexen587a0a62011-12-15 17:32:38 +0000295 int fromlen;
296#endif
297
tuexenbca1dae2011-11-01 23:02:02 +0000298 /*Initially the entire set of mbufs is to be allocated.
299 to_fill indicates this amount. */
300 int to_fill = MAXLEN_MBUF_CHAIN;
301 /* iovlen is the size of each mbuf in the chain */
tuexen587a0a62011-12-15 17:32:38 +0000302 int i, n, ncounter = 0;
tuexenbca1dae2011-11-01 23:02:02 +0000303 int iovlen = MCLBYTES;
304 int want_ext = (iovlen > MLEN)? 1 : 0;
305 int want_header = 0;
ruengeler6fc7a712012-07-31 12:16:29 +0000306
307 bzero((void *)&src, sizeof(struct sockaddr_in));
308 bzero((void *)&dst, sizeof(struct sockaddr_in));
tuexenbca1dae2011-11-01 23:02:02 +0000309
tuexen587a0a62011-12-15 17:32:38 +0000310 recvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
311
tuexenbca1dae2011-11-01 23:02:02 +0000312 while (1) {
313 for (i = 0; i < to_fill; i++) {
314 /* Not getting the packet header. Tests with chain of one run
315 as usual without having the packet header.
316 Have tried both sending and receiving
317 */
t00fcxen218d5d02012-12-10 20:28:19 +0000318 recvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
tuexen07961c42011-12-23 15:39:36 +0000319#if !defined(__Userspace_os_Windows)
tuexenbca1dae2011-11-01 23:02:02 +0000320 recv_iovec[i].iov_base = (caddr_t)recvmbuf[i]->m_data;
321 recv_iovec[i].iov_len = iovlen;
tuexen587a0a62011-12-15 17:32:38 +0000322#else
323 recv_iovec[i].buf = (caddr_t)recvmbuf[i]->m_data;
324 recv_iovec[i].len = iovlen;
325#endif
tuexenbca1dae2011-11-01 23:02:02 +0000326 }
327 to_fill = 0;
tuexen07961c42011-12-23 15:39:36 +0000328#if defined(__Userspace_os_Windows)
tuexen587a0a62011-12-15 17:32:38 +0000329 flags = 0;
330 ncounter = 0;
tuexen59caa502012-01-08 10:27:02 +0000331 fromlen = sizeof(struct sockaddr_in);
332 bzero((void *)&from, sizeof(struct sockaddr_in));
tuexen587a0a62011-12-15 17:32:38 +0000333
tuexenb735c0f2012-04-28 16:43:56 +0000334 nResult = WSARecvFrom(SCTP_BASE_VAR(userspace_rawsctp), recv_iovec, MAXLEN_MBUF_CHAIN, (LPDWORD)&ncounter, (LPDWORD)&flags, (struct sockaddr*)&from, &fromlen, NULL, NULL);
tuexen587a0a62011-12-15 17:32:38 +0000335 if (nResult != 0) {
336 m_ErrorCode = WSAGetLastError();
tuexenf83a7fa2012-05-18 05:44:04 +0000337 if (m_ErrorCode == WSAETIMEDOUT) {
338 continue;
339 }
340 if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
341 break;
342 }
tuexen587a0a62011-12-15 17:32:38 +0000343 }
tuexen3ab67fe2011-12-15 19:42:29 +0000344 n = ncounter;
tuexen587a0a62011-12-15 17:32:38 +0000345#else
t00fcxenb21b4a12012-09-14 18:03:34 +0000346 bzero((void *)&msg, sizeof(struct msghdr));
347 msg.msg_name = NULL;
348 msg.msg_namelen = 0;
349 msg.msg_iov = recv_iovec;
350 msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
351 msg.msg_control = NULL;
352 msg.msg_controllen = 0;
353 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp), &msg, 0);
tuexen67a1a082012-01-20 11:09:46 +0000354 if (n < 0) {
tuexenb735c0f2012-04-28 16:43:56 +0000355 if (errno == EAGAIN) {
356 continue;
357 } else {
358 break;
359 }
tuexen67a1a082012-01-20 11:09:46 +0000360 }
tuexen587a0a62011-12-15 17:32:38 +0000361#endif
tuexenbca1dae2011-11-01 23:02:02 +0000362 SCTP_HEADER_LEN(recvmbuf[0]) = n; /* length of total packet */
t00fcxen6b5474d2013-08-03 13:14:37 +0000363 SCTP_STAT_INCR(sctps_recvpackets);
364 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
tuexenb735c0f2012-04-28 16:43:56 +0000365
tuexenbca1dae2011-11-01 23:02:02 +0000366 if (n <= iovlen) {
367 SCTP_BUF_LEN(recvmbuf[0]) = n;
368 (to_fill)++;
369 } else {
tuexenbca1dae2011-11-01 23:02:02 +0000370 i = 0;
371 SCTP_BUF_LEN(recvmbuf[0]) = iovlen;
372
373 ncounter -= iovlen;
374 (to_fill)++;
375 do {
376 recvmbuf[i]->m_next = recvmbuf[i+1];
377 SCTP_BUF_LEN(recvmbuf[i]->m_next) = min(ncounter, iovlen);
378 i++;
379 ncounter -= iovlen;
380 (to_fill)++;
381 } while (ncounter > 0);
382 }
ruengeler6fc7a712012-07-31 12:16:29 +0000383
384 iphdr = mtod(recvmbuf[0], struct ip *);
385 sh = (struct sctphdr *)((caddr_t)iphdr + sizeof(struct ip));
386 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
387 offset = sizeof(struct ip) + sizeof(struct sctphdr);
388
389 if (iphdr->ip_tos != 0) {
390 ecn = iphdr->ip_tos & 0x02;
391 }
392
393 dst.sin_family = AF_INET;
394#ifdef HAVE_SIN_LEN
395 dst.sin_len = sizeof(struct sockaddr_in);
396#endif
397 dst.sin_addr = iphdr->ip_dst;
398 dst.sin_port = sh->dest_port;
399
400 src.sin_family = AF_INET;
401#ifdef HAVE_SIN_LEN
402 src.sin_len = sizeof(struct sockaddr_in);
403#endif
404 src.sin_addr = iphdr->ip_src;
405 src.sin_port = sh->src_port;
406
407 /* SCTP does not allow broadcasts or multicasts */
408 if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
t00fcxen90c82b72013-11-14 20:51:33 +0000409 return (NULL);
ruengeler6fc7a712012-07-31 12:16:29 +0000410 }
411 if (SCTP_IS_IT_BROADCAST(dst.sin_addr, recvmbuf[0])) {
t00fcxen90c82b72013-11-14 20:51:33 +0000412 return (NULL);
ruengeler6fc7a712012-07-31 12:16:29 +0000413 }
414
415 port = 0;
t00fcxen890e1a32012-09-14 14:30:39 +0000416
t00fcxena84e47f2013-10-29 21:06:25 +0000417#if defined(SCTP_WITH_NO_CSUM)
418 SCTP_STAT_INCR(sctps_recvnocrc);
419#else
t00fcxen890e1a32012-09-14 14:30:39 +0000420 if (src.sin_addr.s_addr == dst.sin_addr.s_addr) {
ruengeler6fc7a712012-07-31 12:16:29 +0000421 compute_crc = 0;
t00fcxena84e47f2013-10-29 21:06:25 +0000422 SCTP_STAT_INCR(sctps_recvnocrc);
423 } else {
424 SCTP_STAT_INCR(sctps_recvswcrc);
ruengeler6fc7a712012-07-31 12:16:29 +0000425 }
t00fcxen890e1a32012-09-14 14:30:39 +0000426#endif
tuexena1d7a852012-05-19 14:55:19 +0000427 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
t00fcxen2356c9c2012-09-04 20:21:12 +0000428 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
ruengeler6fc7a712012-07-31 12:16:29 +0000429 sctp_common_input_processing(&recvmbuf[0], sizeof(struct ip), offset, n,
430 (struct sockaddr *)&src,
431 (struct sockaddr *)&dst,
432 sh, ch,
t00fcxen890e1a32012-09-14 14:30:39 +0000433#if !defined(SCTP_WITH_NO_CSUM)
ruengeler6fc7a712012-07-31 12:16:29 +0000434 compute_crc,
t00fcxen890e1a32012-09-14 14:30:39 +0000435#endif
ruengeler6fc7a712012-07-31 12:16:29 +0000436 ecn,
437 SCTP_DEFAULT_VRFID, port);
t00fcxenefdae362013-11-14 18:30:47 +0000438 if (recvmbuf[0]) {
439 m_freem(recvmbuf[0]);
440 }
tuexenbca1dae2011-11-01 23:02:02 +0000441 }
tuexenb735c0f2012-04-28 16:43:56 +0000442 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
443 m_free(recvmbuf[i]);
444 }
445 /* free the array itself */
446 free(recvmbuf);
t00fcxenf2c34c32013-02-10 20:35:51 +0000447 return (NULL);
tuexenbca1dae2011-11-01 23:02:02 +0000448}
tuexen656fe4c2012-06-28 16:54:10 +0000449#endif
tuexenbca1dae2011-11-01 23:02:02 +0000450
tuexen07961c42011-12-23 15:39:36 +0000451#if defined(INET6)
tuexen07961c42011-12-23 15:39:36 +0000452static void *
453recv_function_raw6(void *arg)
454{
tuexenb735c0f2012-04-28 16:43:56 +0000455 struct mbuf **recvmbuf6;
tuexen07961c42011-12-23 15:39:36 +0000456#if !defined(__Userspace_os_Windows)
457 struct iovec recv_iovec[MAXLEN_MBUF_CHAIN];
tuexen07961c42011-12-23 15:39:36 +0000458 struct msghdr msg;
459 struct cmsghdr *cmsgptr;
tuexen07961c42011-12-23 15:39:36 +0000460 char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
461#else
462 WSABUF recv_iovec[MAXLEN_MBUF_CHAIN];
463 int nResult, m_ErrorCode;
464 DWORD flags;
tuexen59caa502012-01-08 10:27:02 +0000465 struct sockaddr_in6 from;
tuexen07961c42011-12-23 15:39:36 +0000466 int fromlen;
tuexen59caa502012-01-08 10:27:02 +0000467 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
468 LPFN_WSARECVMSG WSARecvMsg;
t00fcxen2e9986e2012-09-15 12:42:22 +0000469 WSACMSGHDR *cmsgptr;
470 WSAMSG msg;
tuexen59caa502012-01-08 10:27:02 +0000471 char ControlBuffer[1024];
tuexen07961c42011-12-23 15:39:36 +0000472#endif
tuexen59caa502012-01-08 10:27:02 +0000473 struct sockaddr_in6 src, dst;
ruengeler6fc7a712012-07-31 12:16:29 +0000474 struct sctphdr *sh;
tuexen59caa502012-01-08 10:27:02 +0000475 int offset;
ruengeler6fc7a712012-07-31 12:16:29 +0000476 struct sctp_chunkhdr *ch;
tuexen07961c42011-12-23 15:39:36 +0000477
478 /*Initially the entire set of mbufs is to be allocated.
479 to_fill indicates this amount. */
480 int to_fill = MAXLEN_MBUF_CHAIN;
481 /* iovlen is the size of each mbuf in the chain */
t00fcxen890e1a32012-09-14 14:30:39 +0000482 int i, n, ncounter = 0;
483#if !defined(SCTP_WITH_NO_CSUM)
484 int compute_crc = 1;
485#endif
tuexen07961c42011-12-23 15:39:36 +0000486 int iovlen = MCLBYTES;
487 int want_ext = (iovlen > MLEN)? 1 : 0;
488 int want_header = 0;
489
490 recvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
491
492 for (;;) {
493 for (i = 0; i < to_fill; i++) {
494 /* Not getting the packet header. Tests with chain of one run
495 as usual without having the packet header.
496 Have tried both sending and receiving
497 */
t00fcxen218d5d02012-12-10 20:28:19 +0000498 recvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
tuexen07961c42011-12-23 15:39:36 +0000499#if !defined(__Userspace_os_Windows)
500 recv_iovec[i].iov_base = (caddr_t)recvmbuf6[i]->m_data;
501 recv_iovec[i].iov_len = iovlen;
502#else
503 recv_iovec[i].buf = (caddr_t)recvmbuf6[i]->m_data;
504 recv_iovec[i].len = iovlen;
505#endif
506 }
507 to_fill = 0;
508#if defined(__Userspace_os_Windows)
509 flags = 0;
510 ncounter = 0;
tuexen59caa502012-01-08 10:27:02 +0000511 fromlen = sizeof(struct sockaddr_in6);
512 bzero((void *)&from, sizeof(struct sockaddr_in6));
tuexenb735c0f2012-04-28 16:43:56 +0000513 nResult = WSAIoctl(SCTP_BASE_VAR(userspace_rawsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER,
tuexen59caa502012-01-08 10:27:02 +0000514 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
515 &WSARecvMsg, sizeof WSARecvMsg,
516 &ncounter, NULL, NULL);
tuexenf83a7fa2012-05-18 05:44:04 +0000517 if (nResult == 0) {
t00fcxen2e9986e2012-09-15 12:42:22 +0000518 msg.name = (void *)&src;
519 msg.namelen = sizeof(struct sockaddr_in6);
520 msg.lpBuffers = recv_iovec;
521 msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
522 msg.Control.len = sizeof ControlBuffer;
523 msg.Control.buf = ControlBuffer;
524 msg.dwFlags = 0;
525 nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, &ncounter, NULL, NULL);
tuexen59caa502012-01-08 10:27:02 +0000526 }
tuexen07961c42011-12-23 15:39:36 +0000527 if (nResult != 0) {
528 m_ErrorCode = WSAGetLastError();
tuexenf83a7fa2012-05-18 05:44:04 +0000529 if (m_ErrorCode == WSAETIMEDOUT)
530 continue;
531 if (m_ErrorCode == WSAENOTSOCK || m_ErrorCode == WSAEINTR)
532 break;
tuexen07961c42011-12-23 15:39:36 +0000533 }
534 n = ncounter;
535#else
536 bzero((void *)&msg, sizeof(struct msghdr));
537 bzero((void *)&src, sizeof(struct sockaddr_in6));
538 bzero((void *)&dst, sizeof(struct sockaddr_in6));
539 bzero((void *)cmsgbuf, CMSG_SPACE(sizeof (struct in6_pktinfo)));
540 msg.msg_name = (void *)&src;
541 msg.msg_namelen = sizeof(struct sockaddr_in6);
542 msg.msg_iov = recv_iovec;
543 msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
544 msg.msg_control = (void *)cmsgbuf;
545 msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof (struct in6_pktinfo));
546 msg.msg_flags = 0;
547
tuexenb735c0f2012-04-28 16:43:56 +0000548 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, 0);
tuexen67a1a082012-01-20 11:09:46 +0000549 if (n < 0) {
tuexenb735c0f2012-04-28 16:43:56 +0000550 if (errno == EAGAIN) {
551 continue;
552 } else {
553 break;
554 }
tuexen67a1a082012-01-20 11:09:46 +0000555 }
tuexen07961c42011-12-23 15:39:36 +0000556#endif
tuexen07961c42011-12-23 15:39:36 +0000557 SCTP_HEADER_LEN(recvmbuf6[0]) = n; /* length of total packet */
t00fcxen6b5474d2013-08-03 13:14:37 +0000558 SCTP_STAT_INCR(sctps_recvpackets);
559 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
tuexen07961c42011-12-23 15:39:36 +0000560
561 if (n <= iovlen) {
562 SCTP_BUF_LEN(recvmbuf6[0]) = n;
563 (to_fill)++;
564 } else {
565 i = 0;
566 SCTP_BUF_LEN(recvmbuf6[0]) = iovlen;
567
568 ncounter -= iovlen;
569 (to_fill)++;
570 do {
571 recvmbuf6[i]->m_next = recvmbuf6[i+1];
572 SCTP_BUF_LEN(recvmbuf6[i]->m_next) = min(ncounter, iovlen);
573 i++;
574 ncounter -= iovlen;
575 (to_fill)++;
576 } while (ncounter > 0);
577 }
tuexen07961c42011-12-23 15:39:36 +0000578
tuexen07961c42011-12-23 15:39:36 +0000579 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
580 if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) {
t00fcxen2e9986e2012-09-15 12:42:22 +0000581 struct in6_pktinfo * info;
582
583 info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
584 memcpy((void *)&dst.sin6_addr, (const void *) &(info->ipi6_addr), sizeof(struct in6_addr));
585 break;
tuexen07961c42011-12-23 15:39:36 +0000586 }
587 }
tuexen07961c42011-12-23 15:39:36 +0000588
ruengeler6fc7a712012-07-31 12:16:29 +0000589 sh = mtod(recvmbuf6[0], struct sctphdr *);
590 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
591 offset = sizeof(struct sctphdr);
592
593 dst.sin6_family = AF_INET6;
t00fcxen7b0ab5c2012-09-04 16:41:39 +0000594#ifdef HAVE_SIN6_LEN
ruengeler6fc7a712012-07-31 12:16:29 +0000595 dst.sin6_len = sizeof(struct sockaddr_in6);
596#endif
597 dst.sin6_port = sh->dest_port;
598
599 src.sin6_family = AF_INET6;
t00fcxen7b0ab5c2012-09-04 16:41:39 +0000600#ifdef HAVE_SIN6_LEN
ruengeler6fc7a712012-07-31 12:16:29 +0000601 src.sin6_len = sizeof(struct sockaddr_in6);
602#endif
603 src.sin6_port = sh->src_port;
t00fcxena84e47f2013-10-29 21:06:25 +0000604#if defined(SCTP_WITH_NO_CSUM)
605 SCTP_STAT_INCR(sctps_recvnocrc);
606#else
t00fcxen890e1a32012-09-14 14:30:39 +0000607 if (memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0) {
ruengeler6fc7a712012-07-31 12:16:29 +0000608 compute_crc = 0;
t00fcxena84e47f2013-10-29 21:06:25 +0000609 SCTP_STAT_INCR(sctps_recvnocrc);
610 } else {
611 SCTP_STAT_INCR(sctps_recvswcrc);
ruengeler6fc7a712012-07-31 12:16:29 +0000612 }
t00fcxen890e1a32012-09-14 14:30:39 +0000613#endif
tuexena1d7a852012-05-19 14:55:19 +0000614 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
t00fcxen2356c9c2012-09-04 20:21:12 +0000615 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
ruengeler6fc7a712012-07-31 12:16:29 +0000616 sctp_common_input_processing(&recvmbuf6[0], 0, offset, n,
617 (struct sockaddr *)&src,
618 (struct sockaddr *)&dst,
619 sh, ch,
t00fcxen890e1a32012-09-14 14:30:39 +0000620#if !defined(SCTP_WITH_NO_CSUM)
621 compute_crc,
t00fcxen890e1a32012-09-14 14:30:39 +0000622#endif
ruengeler6fc7a712012-07-31 12:16:29 +0000623 0,
624 SCTP_DEFAULT_VRFID, 0);
t00fcxenefdae362013-11-14 18:30:47 +0000625 if (recvmbuf6[0]) {
626 m_freem(recvmbuf6[0]);
627 }
tuexen07961c42011-12-23 15:39:36 +0000628 }
tuexenb735c0f2012-04-28 16:43:56 +0000629 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
630 m_free(recvmbuf6[i]);
631 }
632 /* free the array itself */
633 free(recvmbuf6);
t00fcxenf2c34c32013-02-10 20:35:51 +0000634 return (NULL);
tuexen07961c42011-12-23 15:39:36 +0000635}
636#endif
637
tuexen656fe4c2012-06-28 16:54:10 +0000638#ifdef INET
tuexenbca1dae2011-11-01 23:02:02 +0000639static void *
640recv_function_udp(void *arg)
641{
tuexenb735c0f2012-04-28 16:43:56 +0000642 struct mbuf **udprecvmbuf;
tuexenbca1dae2011-11-01 23:02:02 +0000643 /*Initially the entire set of mbufs is to be allocated.
644 to_fill indicates this amount. */
645 int to_fill = MAXLEN_MBUF_CHAIN;
646 /* iovlen is the size of each mbuf in the chain */
ruengeler6fc7a712012-07-31 12:16:29 +0000647 int i, n, ncounter, offset;
tuexenbca1dae2011-11-01 23:02:02 +0000648 int iovlen = MCLBYTES;
649 int want_ext = (iovlen > MLEN)? 1 : 0;
650 int want_header = 0;
ruengeler6fc7a712012-07-31 12:16:29 +0000651 struct sctphdr *sh;
652 uint16_t port;
653 struct sctp_chunkhdr *ch;
tuexenbca1dae2011-11-01 23:02:02 +0000654 struct sockaddr_in src, dst;
t00fcxen26dd10f2012-09-17 07:36:15 +0000655#if defined(IP_PKTINFO)
t00fcxen2e9986e2012-09-15 12:42:22 +0000656 char cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))];
t00fcxen26dd10f2012-09-17 07:36:15 +0000657#else
658 char cmsgbuf[CMSG_SPACE(sizeof(struct in_addr))];
t00fcxen2e9986e2012-09-15 12:42:22 +0000659#endif
t00fcxen890e1a32012-09-14 14:30:39 +0000660#if !defined(SCTP_WITH_NO_CSUM)
661 int compute_crc = 1;
662#endif
tuexen07961c42011-12-23 15:39:36 +0000663#if !defined(__Userspace_os_Windows)
tuexen587a0a62011-12-15 17:32:38 +0000664 struct iovec iov[MAXLEN_MBUF_CHAIN];
665 struct msghdr msg;
tuexenbca1dae2011-11-01 23:02:02 +0000666 struct cmsghdr *cmsgptr;
tuexen587a0a62011-12-15 17:32:38 +0000667#else
668 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
669 LPFN_WSARECVMSG WSARecvMsg;
670 char ControlBuffer[1024];
671 WSABUF iov[MAXLEN_MBUF_CHAIN];
t00fcxen2e9986e2012-09-15 12:42:22 +0000672 WSAMSG msg;
tuexen587a0a62011-12-15 17:32:38 +0000673 int nResult, m_ErrorCode;
t00fcxen2e9986e2012-09-15 12:42:22 +0000674 WSACMSGHDR *cmsgptr;
tuexenbca1dae2011-11-01 23:02:02 +0000675#endif
tuexen587a0a62011-12-15 17:32:38 +0000676
677 udprecvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
678
tuexenbca1dae2011-11-01 23:02:02 +0000679 while (1) {
680 for (i = 0; i < to_fill; i++) {
681 /* Not getting the packet header. Tests with chain of one run
682 as usual without having the packet header.
683 Have tried both sending and receiving
684 */
t00fcxen218d5d02012-12-10 20:28:19 +0000685 udprecvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
tuexen07961c42011-12-23 15:39:36 +0000686#if !defined(__Userspace_os_Windows)
tuexenbca1dae2011-11-01 23:02:02 +0000687 iov[i].iov_base = (caddr_t)udprecvmbuf[i]->m_data;
688 iov[i].iov_len = iovlen;
tuexen587a0a62011-12-15 17:32:38 +0000689#else
690 iov[i].buf = (caddr_t)udprecvmbuf[i]->m_data;
691 iov[i].len = iovlen;
692#endif
tuexenbca1dae2011-11-01 23:02:02 +0000693 }
694 to_fill = 0;
tuexen07961c42011-12-23 15:39:36 +0000695#if !defined(__Userspace_os_Windows)
tuexenbca1dae2011-11-01 23:02:02 +0000696 bzero((void *)&msg, sizeof(struct msghdr));
tuexen587a0a62011-12-15 17:32:38 +0000697#else
t00fcxen2e9986e2012-09-15 12:42:22 +0000698 bzero((void *)&msg, sizeof(WSAMSG));
tuexen587a0a62011-12-15 17:32:38 +0000699#endif
tuexenbca1dae2011-11-01 23:02:02 +0000700 bzero((void *)&src, sizeof(struct sockaddr_in));
701 bzero((void *)&dst, sizeof(struct sockaddr_in));
t00fcxen2e9986e2012-09-15 12:42:22 +0000702 bzero((void *)cmsgbuf, sizeof(cmsgbuf));
tuexen587a0a62011-12-15 17:32:38 +0000703
tuexen07961c42011-12-23 15:39:36 +0000704#if !defined(__Userspace_os_Windows)
tuexenbca1dae2011-11-01 23:02:02 +0000705 msg.msg_name = (void *)&src;
706 msg.msg_namelen = sizeof(struct sockaddr_in);
707 msg.msg_iov = iov;
708 msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
709 msg.msg_control = (void *)cmsgbuf;
t00fcxen2e9986e2012-09-15 12:42:22 +0000710 msg.msg_controllen = sizeof(cmsgbuf);
tuexenbca1dae2011-11-01 23:02:02 +0000711 msg.msg_flags = 0;
712
tuexenb735c0f2012-04-28 16:43:56 +0000713 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, 0);
tuexen67a1a082012-01-20 11:09:46 +0000714 if (n < 0) {
tuexenb735c0f2012-04-28 16:43:56 +0000715 if (errno == EAGAIN) {
716 continue;
717 } else {
718 break;
719 }
tuexen67a1a082012-01-20 11:09:46 +0000720 }
tuexen587a0a62011-12-15 17:32:38 +0000721#else
tuexenb735c0f2012-04-28 16:43:56 +0000722 nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp), SIO_GET_EXTENSION_FUNCTION_POINTER,
tuexen587a0a62011-12-15 17:32:38 +0000723 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
724 &WSARecvMsg, sizeof WSARecvMsg,
725 &ncounter, NULL, NULL);
tuexenf83a7fa2012-05-18 05:44:04 +0000726 if (nResult == 0) {
t00fcxen2e9986e2012-09-15 12:42:22 +0000727 msg.name = (void *)&src;
728 msg.namelen = sizeof(struct sockaddr_in);
729 msg.lpBuffers = iov;
730 msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
731 msg.Control.len = sizeof ControlBuffer;
732 msg.Control.buf = ControlBuffer;
733 msg.dwFlags = 0;
734 nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, &ncounter, NULL, NULL);
tuexen587a0a62011-12-15 17:32:38 +0000735 }
tuexen587a0a62011-12-15 17:32:38 +0000736 if (nResult != 0) {
737 m_ErrorCode = WSAGetLastError();
tuexenf83a7fa2012-05-18 05:44:04 +0000738 if (m_ErrorCode == WSAETIMEDOUT) {
739 continue;
740 }
741 if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
742 break;
743 }
tuexen587a0a62011-12-15 17:32:38 +0000744 }
745 n = ncounter;
746#endif
tuexenbca1dae2011-11-01 23:02:02 +0000747 SCTP_HEADER_LEN(udprecvmbuf[0]) = n; /* length of total packet */
t00fcxen6b5474d2013-08-03 13:14:37 +0000748 SCTP_STAT_INCR(sctps_recvpackets);
749 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
tuexen587a0a62011-12-15 17:32:38 +0000750
tuexenbca1dae2011-11-01 23:02:02 +0000751 if (n <= iovlen) {
752 SCTP_BUF_LEN(udprecvmbuf[0]) = n;
753 (to_fill)++;
754 } else {
tuexenbca1dae2011-11-01 23:02:02 +0000755 i = 0;
756 SCTP_BUF_LEN(udprecvmbuf[0]) = iovlen;
757
758 ncounter -= iovlen;
759 (to_fill)++;
760 do {
761 udprecvmbuf[i]->m_next = udprecvmbuf[i+1];
762 SCTP_BUF_LEN(udprecvmbuf[i]->m_next) = min(ncounter, iovlen);
763 i++;
764 ncounter -= iovlen;
765 (to_fill)++;
766 } while (ncounter > 0);
767 }
tuexenbca1dae2011-11-01 23:02:02 +0000768
769 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
t00fcxen26dd10f2012-09-17 07:36:15 +0000770#if defined(IP_PKTINFO)
t00fcxen2e9986e2012-09-15 12:42:22 +0000771 if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_PKTINFO)) {
772 struct in_pktinfo *info;
773
tuexenbca1dae2011-11-01 23:02:02 +0000774 dst.sin_family = AF_INET;
775#ifdef HAVE_SIN_LEN
776 dst.sin_len = sizeof(struct sockaddr_in);
777#endif
t00fcxen2e9986e2012-09-15 12:42:22 +0000778 info = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
779 memcpy((void *)&dst.sin_addr, (const void *)&(info->ipi_addr), sizeof(struct in_addr));
780 break;
tuexenbca1dae2011-11-01 23:02:02 +0000781 }
t00fcxen33bf9a02012-09-17 08:13:14 +0000782#else
t00fcxen2e9986e2012-09-15 12:42:22 +0000783 if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_RECVDSTADDR)) {
784 struct in_addr *addr;
785
786 dst.sin_family = AF_INET;
787#ifdef HAVE_SIN_LEN
788 dst.sin_len = sizeof(struct sockaddr_in);
789#endif
790 addr = (struct in_addr *)CMSG_DATA(cmsgptr);
791 memcpy((void *)&dst.sin_addr, (const void *)addr, sizeof(struct in_addr));
792 break;
793 }
794#endif
795 }
tuexenbca1dae2011-11-01 23:02:02 +0000796
t00fcxen890e1a32012-09-14 14:30:39 +0000797 /* SCTP does not allow broadcasts or multicasts */
798 if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
t00fcxen90c82b72013-11-14 20:51:33 +0000799 return (NULL);
t00fcxen890e1a32012-09-14 14:30:39 +0000800 }
801 if (SCTP_IS_IT_BROADCAST(dst.sin_addr, udprecvmbuf[0])) {
t00fcxen90c82b72013-11-14 20:51:33 +0000802 return (NULL);
t00fcxen890e1a32012-09-14 14:30:39 +0000803 }
tuexenbca1dae2011-11-01 23:02:02 +0000804
ruengeler6fc7a712012-07-31 12:16:29 +0000805 /*offset = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);*/
806 sh = mtod(udprecvmbuf[0], struct sctphdr *);
807 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
808 offset = sizeof(struct sctphdr);
809 port = src.sin_port;
810 src.sin_port = sh->src_port;
811 dst.sin_port = sh->dest_port;
t00fcxena84e47f2013-10-29 21:06:25 +0000812#if defined(SCTP_WITH_NO_CSUM)
813 SCTP_STAT_INCR(sctps_recvnocrc);
814#else
t00fcxen890e1a32012-09-14 14:30:39 +0000815 if (src.sin_addr.s_addr == dst.sin_addr.s_addr) {
816 compute_crc = 0;
t00fcxena84e47f2013-10-29 21:06:25 +0000817 SCTP_STAT_INCR(sctps_recvnocrc);
818 } else {
819 SCTP_STAT_INCR(sctps_recvswcrc);
t00fcxen890e1a32012-09-14 14:30:39 +0000820 }
821#endif
tuexena1d7a852012-05-19 14:55:19 +0000822 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
t00fcxen2356c9c2012-09-04 20:21:12 +0000823 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
ruengeler6fc7a712012-07-31 12:16:29 +0000824 sctp_common_input_processing(&udprecvmbuf[0], 0, offset, n,
825 (struct sockaddr *)&src,
826 (struct sockaddr *)&dst,
827 sh, ch,
828#if !defined(SCTP_WITH_NO_CSUM)
t00fcxen890e1a32012-09-14 14:30:39 +0000829 compute_crc,
ruengeler6fc7a712012-07-31 12:16:29 +0000830#endif
831 0,
832 SCTP_DEFAULT_VRFID, port);
t00fcxenefdae362013-11-14 18:30:47 +0000833 if (udprecvmbuf[0]) {
834 m_freem(udprecvmbuf[0]);
835 }
tuexenbca1dae2011-11-01 23:02:02 +0000836 }
tuexenb735c0f2012-04-28 16:43:56 +0000837 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
838 m_free(udprecvmbuf[i]);
839 }
840 /* free the array itself */
841 free(udprecvmbuf);
t00fcxenf2c34c32013-02-10 20:35:51 +0000842 return (NULL);
tuexenbca1dae2011-11-01 23:02:02 +0000843}
tuexen656fe4c2012-06-28 16:54:10 +0000844#endif
tuexenbca1dae2011-11-01 23:02:02 +0000845
tuexen07961c42011-12-23 15:39:36 +0000846#if defined(INET6)
tuexen07961c42011-12-23 15:39:36 +0000847static void *
848recv_function_udp6(void *arg)
849{
tuexenb735c0f2012-04-28 16:43:56 +0000850 struct mbuf **udprecvmbuf6;
tuexen07961c42011-12-23 15:39:36 +0000851 /*Initially the entire set of mbufs is to be allocated.
852 to_fill indicates this amount. */
853 int to_fill = MAXLEN_MBUF_CHAIN;
854 /* iovlen is the size of each mbuf in the chain */
855 int i, n, ncounter, offset;
856 int iovlen = MCLBYTES;
857 int want_ext = (iovlen > MLEN)? 1 : 0;
858 int want_header = 0;
tuexen07961c42011-12-23 15:39:36 +0000859 struct sockaddr_in6 src, dst;
ruengeler6fc7a712012-07-31 12:16:29 +0000860 struct sctphdr *sh;
861 uint16_t port;
862 struct sctp_chunkhdr *ch;
tuexen07961c42011-12-23 15:39:36 +0000863 char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
t00fcxen890e1a32012-09-14 14:30:39 +0000864#if !defined(SCTP_WITH_NO_CSUM)
865 int compute_crc = 1;
866#endif
tuexen07961c42011-12-23 15:39:36 +0000867#if !defined(__Userspace_os_Windows)
868 struct iovec iov[MAXLEN_MBUF_CHAIN];
869 struct msghdr msg;
870 struct cmsghdr *cmsgptr;
871#else
872 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
873 LPFN_WSARECVMSG WSARecvMsg;
874 char ControlBuffer[1024];
875 WSABUF iov[MAXLEN_MBUF_CHAIN];
t00fcxen2e9986e2012-09-15 12:42:22 +0000876 WSAMSG msg;
tuexen07961c42011-12-23 15:39:36 +0000877 int nResult, m_ErrorCode;
t00fcxen2e9986e2012-09-15 12:42:22 +0000878 WSACMSGHDR *cmsgptr;
tuexen07961c42011-12-23 15:39:36 +0000879#endif
880
881 udprecvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
ruengeler6fc7a712012-07-31 12:16:29 +0000882 while (1) {
tuexen07961c42011-12-23 15:39:36 +0000883 for (i = 0; i < to_fill; i++) {
884 /* Not getting the packet header. Tests with chain of one run
885 as usual without having the packet header.
886 Have tried both sending and receiving
887 */
t00fcxen218d5d02012-12-10 20:28:19 +0000888 udprecvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
tuexen07961c42011-12-23 15:39:36 +0000889#if !defined(__Userspace_os_Windows)
890 iov[i].iov_base = (caddr_t)udprecvmbuf6[i]->m_data;
891 iov[i].iov_len = iovlen;
892#else
893 iov[i].buf = (caddr_t)udprecvmbuf6[i]->m_data;
tuexen59caa502012-01-08 10:27:02 +0000894 iov[i].len = iovlen;
tuexen07961c42011-12-23 15:39:36 +0000895#endif
896 }
897 to_fill = 0;
898
899#if !defined(__Userspace_os_Windows)
900 bzero((void *)&msg, sizeof(struct msghdr));
901#else
t00fcxen2e9986e2012-09-15 12:42:22 +0000902 bzero((void *)&msg, sizeof(WSAMSG));
tuexen07961c42011-12-23 15:39:36 +0000903#endif
904 bzero((void *)&src, sizeof(struct sockaddr_in6));
905 bzero((void *)&dst, sizeof(struct sockaddr_in6));
906 bzero((void *)cmsgbuf, CMSG_SPACE(sizeof (struct in6_pktinfo)));
907
908#if !defined(__Userspace_os_Windows)
909 msg.msg_name = (void *)&src;
910 msg.msg_namelen = sizeof(struct sockaddr_in6);
911 msg.msg_iov = iov;
912 msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
913 msg.msg_control = (void *)cmsgbuf;
914 msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof (struct in6_pktinfo));
915 msg.msg_flags = 0;
916
tuexenb735c0f2012-04-28 16:43:56 +0000917 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, 0);
tuexen67a1a082012-01-20 11:09:46 +0000918 if (n < 0) {
tuexenb735c0f2012-04-28 16:43:56 +0000919 if (errno == EAGAIN) {
920 continue;
921 } else {
922 break;
923 }
tuexen67a1a082012-01-20 11:09:46 +0000924 }
tuexen07961c42011-12-23 15:39:36 +0000925#else
tuexenb735c0f2012-04-28 16:43:56 +0000926 nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER,
tuexen07961c42011-12-23 15:39:36 +0000927 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
928 &WSARecvMsg, sizeof WSARecvMsg,
929 &ncounter, NULL, NULL);
ruengeler6fc7a712012-07-31 12:16:29 +0000930 if (nResult == SOCKET_ERROR) {
931 m_ErrorCode = WSAGetLastError();
932 WSARecvMsg = NULL;
933 }
tuexenf83a7fa2012-05-18 05:44:04 +0000934 if (nResult == 0) {
t00fcxen2e9986e2012-09-15 12:42:22 +0000935 msg.name = (void *)&src;
936 msg.namelen = sizeof(struct sockaddr_in6);
937 msg.lpBuffers = iov;
938 msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
939 msg.Control.len = sizeof ControlBuffer;
940 msg.Control.buf = ControlBuffer;
941 msg.dwFlags = 0;
942 nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, &ncounter, NULL, NULL);
tuexen07961c42011-12-23 15:39:36 +0000943 }
tuexen07961c42011-12-23 15:39:36 +0000944 if (nResult != 0) {
945 m_ErrorCode = WSAGetLastError();
tuexenf83a7fa2012-05-18 05:44:04 +0000946 if (m_ErrorCode == WSAETIMEDOUT) {
947 continue;
948 }
949 if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
950 break;
951 }
tuexen07961c42011-12-23 15:39:36 +0000952 }
953 n = ncounter;
954#endif
tuexen07961c42011-12-23 15:39:36 +0000955 SCTP_HEADER_LEN(udprecvmbuf6[0]) = n; /* length of total packet */
t00fcxen6b5474d2013-08-03 13:14:37 +0000956 SCTP_STAT_INCR(sctps_recvpackets);
957 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
tuexen07961c42011-12-23 15:39:36 +0000958
959 if (n <= iovlen) {
960 SCTP_BUF_LEN(udprecvmbuf6[0]) = n;
961 (to_fill)++;
962 } else {
963 i = 0;
964 SCTP_BUF_LEN(udprecvmbuf6[0]) = iovlen;
965
966 ncounter -= iovlen;
967 (to_fill)++;
968 do {
969 udprecvmbuf6[i]->m_next = udprecvmbuf6[i+1];
970 SCTP_BUF_LEN(udprecvmbuf6[i]->m_next) = min(ncounter, iovlen);
971 i++;
972 ncounter -= iovlen;
973 (to_fill)++;
974 } while (ncounter > 0);
975 }
tuexen07961c42011-12-23 15:39:36 +0000976
tuexen07961c42011-12-23 15:39:36 +0000977 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
978 if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) {
t00fcxen2e9986e2012-09-15 12:42:22 +0000979 struct in6_pktinfo *info;
980
tuexen07961c42011-12-23 15:39:36 +0000981 dst.sin6_family = AF_INET6;
t00fcxen7b0ab5c2012-09-04 16:41:39 +0000982#ifdef HAVE_SIN6_LEN
tuexen07961c42011-12-23 15:39:36 +0000983 dst.sin6_len = sizeof(struct sockaddr_in6);
984#endif
t00fcxen2e9986e2012-09-15 12:42:22 +0000985 info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
ruengeler6fc7a712012-07-31 12:16:29 +0000986 /*dst.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));*/
t00fcxen2e9986e2012-09-15 12:42:22 +0000987 memcpy((void *)&dst.sin6_addr, (const void *)&(info->ipi6_addr), sizeof(struct in6_addr));
tuexen07961c42011-12-23 15:39:36 +0000988 }
989 }
tuexen07961c42011-12-23 15:39:36 +0000990
t00fcxen890e1a32012-09-14 14:30:39 +0000991 /* SCTP does not allow broadcasts or multicasts */
992 if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) {
t00fcxen90c82b72013-11-14 20:51:33 +0000993 return (NULL);
t00fcxen890e1a32012-09-14 14:30:39 +0000994 }
ruengeler6fc7a712012-07-31 12:16:29 +0000995
996 sh = mtod(udprecvmbuf6[0], struct sctphdr *);
997 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
998 offset = sizeof(struct sctphdr);
999
1000 port = src.sin6_port;
1001 src.sin6_port = sh->src_port;
1002 dst.sin6_port = sh->dest_port;
t00fcxena84e47f2013-10-29 21:06:25 +00001003#if defined(SCTP_WITH_NO_CSUM)
1004 SCTP_STAT_INCR(sctps_recvnocrc);
1005#else
t00fcxen890e1a32012-09-14 14:30:39 +00001006 if ((memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0)) {
1007 compute_crc = 0;
t00fcxena84e47f2013-10-29 21:06:25 +00001008 SCTP_STAT_INCR(sctps_recvnocrc);
1009 } else {
1010 SCTP_STAT_INCR(sctps_recvswcrc);
t00fcxen890e1a32012-09-14 14:30:39 +00001011 }
1012#endif
tuexena1d7a852012-05-19 14:55:19 +00001013 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
t00fcxen2356c9c2012-09-04 20:21:12 +00001014 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", (int)sizeof(struct sctphdr));
1015 sctp_common_input_processing(&udprecvmbuf6[0], 0, offset, n,
ruengeler6fc7a712012-07-31 12:16:29 +00001016 (struct sockaddr *)&src,
1017 (struct sockaddr *)&dst,
1018 sh, ch,
1019#if !defined(SCTP_WITH_NO_CSUM)
t00fcxen890e1a32012-09-14 14:30:39 +00001020 compute_crc,
ruengeler6fc7a712012-07-31 12:16:29 +00001021#endif
1022 0,
1023 SCTP_DEFAULT_VRFID, port);
t00fcxenefdae362013-11-14 18:30:47 +00001024 if (udprecvmbuf6[0]) {
1025 m_freem(udprecvmbuf6[0]);
1026 }
tuexen07961c42011-12-23 15:39:36 +00001027 }
tuexenb735c0f2012-04-28 16:43:56 +00001028 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
1029 m_free(udprecvmbuf6[i]);
1030 }
1031 /* free the array itself */
1032 free(udprecvmbuf6);
t00fcxenf2c34c32013-02-10 20:35:51 +00001033 return (NULL);
tuexen07961c42011-12-23 15:39:36 +00001034}
1035#endif
tuexenbca1dae2011-11-01 23:02:02 +00001036
tuexen0622a9e2012-05-20 10:08:24 +00001037static void
tuexenbca1dae2011-11-01 23:02:02 +00001038setReceiveBufferSize(int sfd, int new_size)
1039{
1040 int ch = new_size;
tuexen0622a9e2012-05-20 10:08:24 +00001041
tuexenbca1dae2011-11-01 23:02:02 +00001042 if (setsockopt (sfd, SOL_SOCKET, SO_RCVBUF, (void*)&ch, sizeof(ch)) < 0) {
ruengeler6fc7a712012-07-31 12:16:29 +00001043#if defined (__Userspace_os_Windows)
1044 SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", WSAGetLastError());
1045#else
tuexen0622a9e2012-05-20 10:08:24 +00001046 SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", errno);
ruengeler6fc7a712012-07-31 12:16:29 +00001047#endif
tuexenbca1dae2011-11-01 23:02:02 +00001048 }
tuexen0622a9e2012-05-20 10:08:24 +00001049 return;
tuexenbca1dae2011-11-01 23:02:02 +00001050}
1051
tuexen0622a9e2012-05-20 10:08:24 +00001052static void
tuexenbca1dae2011-11-01 23:02:02 +00001053setSendBufferSize(int sfd, int new_size)
1054{
1055 int ch = new_size;
tuexenb735c0f2012-04-28 16:43:56 +00001056
tuexenbca1dae2011-11-01 23:02:02 +00001057 if (setsockopt (sfd, SOL_SOCKET, SO_SNDBUF, (void*)&ch, sizeof(ch)) < 0) {
ruengeler6fc7a712012-07-31 12:16:29 +00001058#if defined (__Userspace_os_Windows)
1059 SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", WSAGetLastError());
1060#else
1061 SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", errno);
1062#endif
tuexenbca1dae2011-11-01 23:02:02 +00001063 }
tuexen0622a9e2012-05-20 10:08:24 +00001064 return;
tuexenbca1dae2011-11-01 23:02:02 +00001065}
1066
tuexenf83a7fa2012-05-18 05:44:04 +00001067#define SOCKET_TIMEOUT 100 /* in ms */
tuexenb735c0f2012-04-28 16:43:56 +00001068void
tuexen3a33bc92012-01-15 12:10:06 +00001069recv_thread_init(void)
tuexenbca1dae2011-11-01 23:02:02 +00001070{
tuexenb735c0f2012-04-28 16:43:56 +00001071#if defined(INET)
tuexenbca1dae2011-11-01 23:02:02 +00001072 struct sockaddr_in addr_ipv4;
tuexenb735c0f2012-04-28 16:43:56 +00001073 const int hdrincl = 1;
1074#endif
tuexen07961c42011-12-23 15:39:36 +00001075#if defined(INET6)
tuexen07961c42011-12-23 15:39:36 +00001076 struct sockaddr_in6 addr_ipv6;
1077#endif
tuexenb735c0f2012-04-28 16:43:56 +00001078#if defined(INET) || defined(INET6)
1079 const int on = 1;
1080#endif
tuexen1b9c2d22012-05-06 18:48:47 +00001081#if !defined(__Userspace_os_Windows)
1082 struct timeval timeout;
tuexenbca1dae2011-11-01 23:02:02 +00001083
tuexenf83a7fa2012-05-18 05:44:04 +00001084 timeout.tv_sec = (SOCKET_TIMEOUT / 1000);
1085 timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
1086#else
1087 unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */
tuexen1b9c2d22012-05-06 18:48:47 +00001088#endif
t00fcxen22a33a12013-12-27 19:21:25 +00001089#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
tuexenb735c0f2012-04-28 16:43:56 +00001090 if (SCTP_BASE_VAR(userspace_route) == -1) {
tuexenb735c0f2012-04-28 16:43:56 +00001091 if ((SCTP_BASE_VAR(userspace_route) = socket(AF_ROUTE, SOCK_RAW, 0)) < 0) {
tuexen0622a9e2012-05-20 10:08:24 +00001092 SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d).\n", errno);
tuexen3a33bc92012-01-15 12:10:06 +00001093 }
t00fcxenc48387a2012-09-04 20:35:12 +00001094#if 0
tuexenb735c0f2012-04-28 16:43:56 +00001095 struct sockaddr_nl sanl;
1096
1097 if ((SCTP_BASE_VAR(userspace_route) = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
tuexen0622a9e2012-05-20 10:08:24 +00001098 SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d.\n", errno);
tuexenb735c0f2012-04-28 16:43:56 +00001099 }
1100 memset(&sanl, 0, sizeof(sanl));
1101 sanl.nl_family = AF_NETLINK;
1102 sanl.nl_groups = 0;
1103#ifdef INET
1104 sanl.nl_groups |= RTMGRP_IPV4_IFADDR;
1105#endif
1106#ifdef INET6
1107 sanl.nl_groups |= RTMGRP_IPV6_IFADDR;
1108#endif
1109 if (bind(SCTP_BASE_VAR(userspace_route), (struct sockaddr *) &sanl, sizeof(sanl)) < 0) {
tuexen0622a9e2012-05-20 10:08:24 +00001110 SCTPDBG(SCTP_DEBUG_USR, "Can't bind routing socket (errno = %d).\n", errno);
tuexenb735c0f2012-04-28 16:43:56 +00001111 close(SCTP_BASE_VAR(userspace_route));
1112 SCTP_BASE_VAR(userspace_route) = -1;
1113 }
1114#endif
tuexenba1ce002012-05-06 18:56:26 +00001115 if (SCTP_BASE_VAR(userspace_route) != -1) {
1116 if (setsockopt(SCTP_BASE_VAR(userspace_route), SOL_SOCKET, SO_RCVTIMEO,(const void*)&timeout, sizeof(struct timeval)) < 0) {
tuexen0622a9e2012-05-20 10:08:24 +00001117 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on routing socket (errno = %d).\n", errno);
tuexenba1ce002012-05-06 18:56:26 +00001118#if defined(__Userspace_os_Windows)
tuexenf83a7fa2012-05-18 05:44:04 +00001119 closesocket(SCTP_BASE_VAR(userspace_route));
tuexenba1ce002012-05-06 18:56:26 +00001120#else
1121 close(SCTP_BASE_VAR(userspace_route));
1122#endif
1123 SCTP_BASE_VAR(userspace_route) = -1;
1124 }
1125 }
tuexen3a33bc92012-01-15 12:10:06 +00001126 }
1127#endif
tuexenb735c0f2012-04-28 16:43:56 +00001128#if defined(INET)
1129 if (SCTP_BASE_VAR(userspace_rawsctp) == -1) {
1130 if ((SCTP_BASE_VAR(userspace_rawsctp) = socket(AF_INET, SOCK_RAW, IPPROTO_SCTP)) < 0) {
ruengeler6fc7a712012-07-31 12:16:29 +00001131#if defined(__Userspace_os_Windows)
1132 SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", WSAGetLastError());
1133#else
tuexen0622a9e2012-05-20 10:08:24 +00001134 SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", errno);
ruengeler6fc7a712012-07-31 12:16:29 +00001135#endif
tuexene2c40ae2011-11-20 09:30:37 +00001136 } else {
1137 /* complete setting up the raw SCTP socket */
tuexenb735c0f2012-04-28 16:43:56 +00001138 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), IPPROTO_IP, IP_HDRINCL,(const void*)&hdrincl, sizeof(int)) < 0) {
tuexenb735c0f2012-04-28 16:43:56 +00001139#if defined(__Userspace_os_Windows)
ruengeler6fc7a712012-07-31 12:16:29 +00001140 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", WSAGetLastError());
tuexenf83a7fa2012-05-18 05:44:04 +00001141 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
tuexenb735c0f2012-04-28 16:43:56 +00001142#else
ruengeler6fc7a712012-07-31 12:16:29 +00001143 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", errno);
tuexenb735c0f2012-04-28 16:43:56 +00001144 close(SCTP_BASE_VAR(userspace_rawsctp));
tuexen587a0a62011-12-15 17:32:38 +00001145#endif
tuexen1b9c2d22012-05-06 18:48:47 +00001146 SCTP_BASE_VAR(userspace_rawsctp) = -1;
tuexenf83a7fa2012-05-18 05:44:04 +00001147 } else if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
tuexen1b9c2d22012-05-06 18:48:47 +00001148#if defined(__Userspace_os_Windows)
ruengeler6fc7a712012-07-31 12:16:29 +00001149 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError());
tuexenf83a7fa2012-05-18 05:44:04 +00001150 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
tuexen1b9c2d22012-05-06 18:48:47 +00001151#else
ruengeler6fc7a712012-07-31 12:16:29 +00001152 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", errno);
tuexen1b9c2d22012-05-06 18:48:47 +00001153 close(SCTP_BASE_VAR(userspace_rawsctp));
1154#endif
tuexenb735c0f2012-04-28 16:43:56 +00001155 SCTP_BASE_VAR(userspace_rawsctp) = -1;
1156 } else {
1157 memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in));
1158#ifdef HAVE_SIN_LEN
1159 addr_ipv4.sin_len = sizeof(struct sockaddr_in);
1160#endif
1161 addr_ipv4.sin_family = AF_INET;
1162 addr_ipv4.sin_port = htons(0);
1163 addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
1164 if (bind(SCTP_BASE_VAR(userspace_rawsctp), (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) {
tuexenb735c0f2012-04-28 16:43:56 +00001165#if defined(__Userspace_os_Windows)
ruengeler6fc7a712012-07-31 12:16:29 +00001166 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError());
tuexenf83a7fa2012-05-18 05:44:04 +00001167 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
tuexenb735c0f2012-04-28 16:43:56 +00001168#else
ruengeler6fc7a712012-07-31 12:16:29 +00001169 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", errno);
tuexenb735c0f2012-04-28 16:43:56 +00001170 close(SCTP_BASE_VAR(userspace_rawsctp));
1171#endif
1172 SCTP_BASE_VAR(userspace_rawsctp) = -1;
1173 } else {
1174 setReceiveBufferSize(SCTP_BASE_VAR(userspace_rawsctp), SB_RAW); /* 128K */
1175 setSendBufferSize(SCTP_BASE_VAR(userspace_rawsctp), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
1176 }
1177 }
tuexene2c40ae2011-11-20 09:30:37 +00001178 }
tuexenbca1dae2011-11-01 23:02:02 +00001179 }
tuexenb735c0f2012-04-28 16:43:56 +00001180 if (SCTP_BASE_VAR(userspace_udpsctp) == -1) {
1181 if ((SCTP_BASE_VAR(userspace_udpsctp) = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
ruengeler6fc7a712012-07-31 12:16:29 +00001182#if defined(__Userspace_os_Windows)
1183 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
1184#else
tuexen0622a9e2012-05-20 10:08:24 +00001185 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
ruengeler6fc7a712012-07-31 12:16:29 +00001186#endif
tuexen67a1a082012-01-20 11:09:46 +00001187 } else {
t00fcxen26dd10f2012-09-17 07:36:15 +00001188#if defined(IP_PKTINFO)
t00fcxen2e9986e2012-09-15 12:42:22 +00001189 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
t00fcxen26dd10f2012-09-17 07:36:15 +00001190#else
1191 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_RECVDSTADDR, (const void *)&on, (int)sizeof(int)) < 0) {
t00fcxen2e9986e2012-09-15 12:42:22 +00001192#endif
tuexenb735c0f2012-04-28 16:43:56 +00001193#if defined(__Userspace_os_Windows)
t00fcxen26dd10f2012-09-17 07:36:15 +00001194#if defined(IP_PKTINFO)
t00fcxen2e9986e2012-09-15 12:42:22 +00001195 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
t00fcxen26dd10f2012-09-17 07:36:15 +00001196#else
1197 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
t00fcxen2e9986e2012-09-15 12:42:22 +00001198#endif
tuexenf83a7fa2012-05-18 05:44:04 +00001199 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
tuexenb735c0f2012-04-28 16:43:56 +00001200#else
t00fcxen26dd10f2012-09-17 07:36:15 +00001201#if defined(IP_PKTINFO)
t00fcxen2e9986e2012-09-15 12:42:22 +00001202 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
t00fcxen26dd10f2012-09-17 07:36:15 +00001203#else
1204 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
t00fcxen2e9986e2012-09-15 12:42:22 +00001205#endif
tuexenb735c0f2012-04-28 16:43:56 +00001206 close(SCTP_BASE_VAR(userspace_udpsctp));
1207#endif
1208 SCTP_BASE_VAR(userspace_udpsctp) = -1;
tuexenf83a7fa2012-05-18 05:44:04 +00001209 } else if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
tuexen1b9c2d22012-05-06 18:48:47 +00001210#if defined(__Userspace_os_Windows)
ruengeler6fc7a712012-07-31 12:16:29 +00001211 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
tuexenf83a7fa2012-05-18 05:44:04 +00001212 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
tuexen1b9c2d22012-05-06 18:48:47 +00001213#else
ruengeler6fc7a712012-07-31 12:16:29 +00001214 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
tuexen1b9c2d22012-05-06 18:48:47 +00001215 close(SCTP_BASE_VAR(userspace_udpsctp));
1216#endif
1217 SCTP_BASE_VAR(userspace_udpsctp) = -1;
tuexenb735c0f2012-04-28 16:43:56 +00001218 } else {
1219 memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in));
1220#ifdef HAVE_SIN_LEN
1221 addr_ipv4.sin_len = sizeof(struct sockaddr_in);
1222#endif
1223 addr_ipv4.sin_family = AF_INET;
1224 addr_ipv4.sin_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
1225 addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
1226 if (bind(SCTP_BASE_VAR(userspace_udpsctp), (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) {
tuexenb735c0f2012-04-28 16:43:56 +00001227#if defined(__Userspace_os_Windows)
ruengeler6fc7a712012-07-31 12:16:29 +00001228 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
tuexenf83a7fa2012-05-18 05:44:04 +00001229 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
tuexenb735c0f2012-04-28 16:43:56 +00001230#else
ruengeler6fc7a712012-07-31 12:16:29 +00001231 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
tuexenb735c0f2012-04-28 16:43:56 +00001232 close(SCTP_BASE_VAR(userspace_udpsctp));
1233#endif
1234 SCTP_BASE_VAR(userspace_udpsctp) = -1;
1235 } else {
1236 setReceiveBufferSize(SCTP_BASE_VAR(userspace_udpsctp), SB_RAW); /* 128K */
1237 setSendBufferSize(SCTP_BASE_VAR(userspace_udpsctp), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
1238 }
1239 }
tuexenbca1dae2011-11-01 23:02:02 +00001240 }
tuexenbca1dae2011-11-01 23:02:02 +00001241 }
tuexenb735c0f2012-04-28 16:43:56 +00001242#endif
tuexen07961c42011-12-23 15:39:36 +00001243#if defined(INET6)
tuexenb735c0f2012-04-28 16:43:56 +00001244 if (SCTP_BASE_VAR(userspace_rawsctp6) == -1) {
1245 if ((SCTP_BASE_VAR(userspace_rawsctp6) = socket(AF_INET6, SOCK_RAW, IPPROTO_SCTP)) < 0) {
ruengeler6fc7a712012-07-31 12:16:29 +00001246#if defined(__Userspace_os_Windows)
1247 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1248#else
tuexen0622a9e2012-05-20 10:08:24 +00001249 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", errno);
ruengeler6fc7a712012-07-31 12:16:29 +00001250#endif
tuexen07961c42011-12-23 15:39:36 +00001251 } else {
1252 /* complete setting up the raw SCTP socket */
tuexen9cf61ba2012-01-16 10:17:41 +00001253#if defined(IPV6_RECVPKTINFO)
ruengeler6fc7a712012-07-31 12:16:29 +00001254 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, sizeof(on)) < 0) {
tuexenb735c0f2012-04-28 16:43:56 +00001255#if defined(__Userspace_os_Windows)
ruengeler6fc7a712012-07-31 12:16:29 +00001256 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
tuexenf83a7fa2012-05-18 05:44:04 +00001257 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
tuexen07961c42011-12-23 15:39:36 +00001258#else
ruengeler6fc7a712012-07-31 12:16:29 +00001259 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno);
tuexenb735c0f2012-04-28 16:43:56 +00001260 close(SCTP_BASE_VAR(userspace_rawsctp6));
tuexen07961c42011-12-23 15:39:36 +00001261#endif
tuexenb735c0f2012-04-28 16:43:56 +00001262 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
1263 } else {
1264#else
1265 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_PKTINFO,(const void*)&on, sizeof(on)) < 0) {
tuexenb735c0f2012-04-28 16:43:56 +00001266#if defined(__Userspace_os_Windows)
ruengeler6fc7a712012-07-31 12:16:29 +00001267 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
tuexenf83a7fa2012-05-18 05:44:04 +00001268 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
tuexenb735c0f2012-04-28 16:43:56 +00001269#else
ruengeler6fc7a712012-07-31 12:16:29 +00001270 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno);
tuexenb735c0f2012-04-28 16:43:56 +00001271 close(SCTP_BASE_VAR(userspace_rawsctp6));
1272#endif
1273 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
1274 } else {
1275#endif
1276 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&on, (socklen_t)sizeof(on)) < 0) {
ruengeler6fc7a712012-07-31 12:16:29 +00001277#if defined(__Userspace_os_Windows)
1278 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1279#else
tuexen0622a9e2012-05-20 10:08:24 +00001280 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", errno);
ruengeler6fc7a712012-07-31 12:16:29 +00001281#endif
tuexenb735c0f2012-04-28 16:43:56 +00001282 }
tuexenf83a7fa2012-05-18 05:44:04 +00001283 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
tuexenb735c0f2012-04-28 16:43:56 +00001284#if defined(__Userspace_os_Windows)
ruengeler6fc7a712012-07-31 12:16:29 +00001285 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
tuexenf83a7fa2012-05-18 05:44:04 +00001286 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
tuexenb735c0f2012-04-28 16:43:56 +00001287#else
ruengeler6fc7a712012-07-31 12:16:29 +00001288 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", errno);
tuexenf83a7fa2012-05-18 05:44:04 +00001289 close(SCTP_BASE_VAR(userspace_rawsctp6));
tuexenb735c0f2012-04-28 16:43:56 +00001290#endif
tuexenf83a7fa2012-05-18 05:44:04 +00001291 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
tuexenb735c0f2012-04-28 16:43:56 +00001292 } else {
tuexenba1ce002012-05-06 18:56:26 +00001293 memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6));
t00fcxen7b0ab5c2012-09-04 16:41:39 +00001294#ifdef HAVE_SIN6_LEN
tuexenba1ce002012-05-06 18:56:26 +00001295 addr_ipv6.sin6_len = sizeof(struct sockaddr_in6);
1296#endif
1297 addr_ipv6.sin6_family = AF_INET6;
1298 addr_ipv6.sin6_port = htons(0);
1299 addr_ipv6.sin6_addr = in6addr_any;
1300 if (bind(SCTP_BASE_VAR(userspace_rawsctp6), (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) {
tuexenba1ce002012-05-06 18:56:26 +00001301#if defined(__Userspace_os_Windows)
ruengeler6fc7a712012-07-31 12:16:29 +00001302 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
tuexenf83a7fa2012-05-18 05:44:04 +00001303 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
tuexenba1ce002012-05-06 18:56:26 +00001304#else
ruengeler6fc7a712012-07-31 12:16:29 +00001305 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", errno);
tuexenba1ce002012-05-06 18:56:26 +00001306 close(SCTP_BASE_VAR(userspace_rawsctp6));
1307#endif
1308 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
1309 } else {
1310 setReceiveBufferSize(SCTP_BASE_VAR(userspace_rawsctp6), SB_RAW); /* 128K */
1311 setSendBufferSize(SCTP_BASE_VAR(userspace_rawsctp6), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
1312 }
tuexenb735c0f2012-04-28 16:43:56 +00001313 }
1314 }
1315 }
1316 }
1317 if (SCTP_BASE_VAR(userspace_udpsctp6) == -1) {
1318 if ((SCTP_BASE_VAR(userspace_udpsctp6) = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
ruengeler6fc7a712012-07-31 12:16:29 +00001319#if defined(__Userspace_os_Windows)
1320 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1321#else
tuexen0622a9e2012-05-20 10:08:24 +00001322 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
ruengeler6fc7a712012-07-31 12:16:29 +00001323#endif
tuexenb735c0f2012-04-28 16:43:56 +00001324 }
1325#if defined(IPV6_RECVPKTINFO)
1326 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
tuexenf83a7fa2012-05-18 05:44:04 +00001327#if defined(__Userspace_os_Windows)
ruengeler6fc7a712012-07-31 12:16:29 +00001328 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
tuexenf83a7fa2012-05-18 05:44:04 +00001329 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1330#else
ruengeler6fc7a712012-07-31 12:16:29 +00001331 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
tuexenb735c0f2012-04-28 16:43:56 +00001332 close(SCTP_BASE_VAR(userspace_udpsctp6));
tuexenf83a7fa2012-05-18 05:44:04 +00001333#endif
tuexenb735c0f2012-04-28 16:43:56 +00001334 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1335 } else {
1336#else
1337 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
tuexenf83a7fa2012-05-18 05:44:04 +00001338#if defined(__Userspace_os_Windows)
ruengeler6fc7a712012-07-31 12:16:29 +00001339 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
tuexenf83a7fa2012-05-18 05:44:04 +00001340 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1341#else
ruengeler6fc7a712012-07-31 12:16:29 +00001342 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
tuexenb735c0f2012-04-28 16:43:56 +00001343 close(SCTP_BASE_VAR(userspace_udpsctp6));
tuexenf83a7fa2012-05-18 05:44:04 +00001344#endif
tuexenb735c0f2012-04-28 16:43:56 +00001345 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1346 } else {
1347#endif
tuexenf83a7fa2012-05-18 05:44:04 +00001348 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&on, (socklen_t)sizeof(on)) < 0) {
ruengeler6fc7a712012-07-31 12:16:29 +00001349#if defined(__Userspace_os_Windows)
1350 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1351#else
tuexen0622a9e2012-05-20 10:08:24 +00001352 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
ruengeler6fc7a712012-07-31 12:16:29 +00001353#endif
tuexenb735c0f2012-04-28 16:43:56 +00001354 }
tuexenf83a7fa2012-05-18 05:44:04 +00001355 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
tuexenba1ce002012-05-06 18:56:26 +00001356#if defined(__Userspace_os_Windows)
ruengeler6fc7a712012-07-31 12:16:29 +00001357 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
tuexenf83a7fa2012-05-18 05:44:04 +00001358 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1359#else
ruengeler6fc7a712012-07-31 12:16:29 +00001360 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
tuexenf83a7fa2012-05-18 05:44:04 +00001361 close(SCTP_BASE_VAR(userspace_udpsctp6));
tuexen07961c42011-12-23 15:39:36 +00001362#endif
tuexenf83a7fa2012-05-18 05:44:04 +00001363 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
tuexenb735c0f2012-04-28 16:43:56 +00001364 } else {
tuexenba1ce002012-05-06 18:56:26 +00001365 memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6));
t00fcxen7b0ab5c2012-09-04 16:41:39 +00001366#ifdef HAVE_SIN6_LEN
tuexenba1ce002012-05-06 18:56:26 +00001367 addr_ipv6.sin6_len = sizeof(struct sockaddr_in6);
1368#endif
1369 addr_ipv6.sin6_family = AF_INET6;
1370 addr_ipv6.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
1371 addr_ipv6.sin6_addr = in6addr_any;
ruengeler6fc7a712012-07-31 12:16:29 +00001372 if (bind(SCTP_BASE_VAR(userspace_udpsctp6), (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) {
tuexenf83a7fa2012-05-18 05:44:04 +00001373#if defined(__Userspace_os_Windows)
ruengeler6fc7a712012-07-31 12:16:29 +00001374 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
tuexenf83a7fa2012-05-18 05:44:04 +00001375 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1376#else
ruengeler6fc7a712012-07-31 12:16:29 +00001377 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
tuexenba1ce002012-05-06 18:56:26 +00001378 close(SCTP_BASE_VAR(userspace_udpsctp6));
tuexenf83a7fa2012-05-18 05:44:04 +00001379#endif
tuexenba1ce002012-05-06 18:56:26 +00001380 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1381 } else {
1382 setReceiveBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K */
1383 setSendBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
1384 }
tuexen07961c42011-12-23 15:39:36 +00001385 }
tuexen07961c42011-12-23 15:39:36 +00001386 }
tuexen07961c42011-12-23 15:39:36 +00001387 }
1388#endif
tuexen07961c42011-12-23 15:39:36 +00001389#if !defined(__Userspace_os_Windows)
t00fcxen22a33a12013-12-27 19:21:25 +00001390#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
tuexenb735c0f2012-04-28 16:43:56 +00001391#if defined(INET) || defined(INET6)
1392 if (SCTP_BASE_VAR(userspace_route) != -1) {
tuexen3a33bc92012-01-15 12:10:06 +00001393 int rc;
1394
tuexenb735c0f2012-04-28 16:43:56 +00001395 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadroute), NULL, &recv_function_route, NULL))) {
tuexena1d7a852012-05-19 14:55:19 +00001396 SCTPDBG(SCTP_DEBUG_USR, "Can't start routing thread (%d).\n", rc);
tuexend93dfec2012-04-28 18:04:13 +00001397 close(SCTP_BASE_VAR(userspace_route));
1398 SCTP_BASE_VAR(userspace_route) = -1;
tuexen3a33bc92012-01-15 12:10:06 +00001399 }
1400 }
tuexenb735c0f2012-04-28 16:43:56 +00001401#endif
t00fcxen7943a5e2012-09-04 20:32:11 +00001402#endif
tuexen085a5052012-01-08 13:42:59 +00001403#if defined(INET)
tuexenb735c0f2012-04-28 16:43:56 +00001404 if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
tuexen587a0a62011-12-15 17:32:38 +00001405 int rc;
1406
tuexenb735c0f2012-04-28 16:43:56 +00001407 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw), NULL, &recv_function_raw, NULL))) {
tuexena1d7a852012-05-19 14:55:19 +00001408 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread (%d).\n", rc);
tuexend93dfec2012-04-28 18:04:13 +00001409 close(SCTP_BASE_VAR(userspace_rawsctp));
1410 SCTP_BASE_VAR(userspace_rawsctp) = -1;
tuexenbca1dae2011-11-01 23:02:02 +00001411 }
1412 }
tuexenb735c0f2012-04-28 16:43:56 +00001413 if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
tuexen587a0a62011-12-15 17:32:38 +00001414 int rc;
1415
tuexenb735c0f2012-04-28 16:43:56 +00001416 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp), NULL, &recv_function_udp, NULL))) {
tuexena1d7a852012-05-19 14:55:19 +00001417 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread (%d).\n", rc);
tuexend93dfec2012-04-28 18:04:13 +00001418 close(SCTP_BASE_VAR(userspace_udpsctp));
1419 SCTP_BASE_VAR(userspace_udpsctp) = -1;
tuexen07961c42011-12-23 15:39:36 +00001420 }
1421 }
tuexen085a5052012-01-08 13:42:59 +00001422#endif
1423#if defined(INET6)
tuexenb735c0f2012-04-28 16:43:56 +00001424 if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
tuexen07961c42011-12-23 15:39:36 +00001425 int rc;
1426
tuexenb735c0f2012-04-28 16:43:56 +00001427 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw6), NULL, &recv_function_raw6, NULL))) {
tuexena1d7a852012-05-19 14:55:19 +00001428 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread (%d).\n", rc);
tuexend93dfec2012-04-28 18:04:13 +00001429 close(SCTP_BASE_VAR(userspace_rawsctp6));
1430 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
tuexen07961c42011-12-23 15:39:36 +00001431 }
1432 }
tuexenb735c0f2012-04-28 16:43:56 +00001433 if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
tuexen07961c42011-12-23 15:39:36 +00001434 int rc;
1435
tuexenb735c0f2012-04-28 16:43:56 +00001436 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp6), NULL, &recv_function_udp6, NULL))) {
tuexena1d7a852012-05-19 14:55:19 +00001437 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread (%d).\n", rc);
tuexend93dfec2012-04-28 18:04:13 +00001438 close(SCTP_BASE_VAR(userspace_udpsctp6));
1439 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
tuexenbca1dae2011-11-01 23:02:02 +00001440 }
1441 }
tuexen085a5052012-01-08 13:42:59 +00001442#endif
tuexen587a0a62011-12-15 17:32:38 +00001443#else
tuexen085a5052012-01-08 13:42:59 +00001444#if defined(INET)
tuexenb735c0f2012-04-28 16:43:56 +00001445 if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
1446 if ((SCTP_BASE_VAR(recvthreadraw) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw, NULL, 0, NULL)) == NULL) {
tuexena1d7a852012-05-19 14:55:19 +00001447 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread.\n");
tuexenf83a7fa2012-05-18 05:44:04 +00001448 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
tuexend93dfec2012-04-28 18:04:13 +00001449 SCTP_BASE_VAR(userspace_rawsctp) = -1;
tuexen587a0a62011-12-15 17:32:38 +00001450 }
1451 }
tuexenb735c0f2012-04-28 16:43:56 +00001452 if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
tuexena1d7a852012-05-19 14:55:19 +00001453 if ((SCTP_BASE_VAR(recvthreadudp) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp, NULL, 0, NULL)) == NULL) {
1454 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread.\n");
tuexenf83a7fa2012-05-18 05:44:04 +00001455 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
tuexend93dfec2012-04-28 18:04:13 +00001456 SCTP_BASE_VAR(userspace_udpsctp) = -1;
tuexen587a0a62011-12-15 17:32:38 +00001457 }
1458 }
tuexen085a5052012-01-08 13:42:59 +00001459#endif
1460#if defined(INET6)
tuexenb735c0f2012-04-28 16:43:56 +00001461 if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
tuexena1d7a852012-05-19 14:55:19 +00001462 if ((SCTP_BASE_VAR(recvthreadraw6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw6, NULL, 0, NULL)) == NULL) {
1463 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread.\n");
tuexenf83a7fa2012-05-18 05:44:04 +00001464 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
tuexend93dfec2012-04-28 18:04:13 +00001465 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
tuexen59caa502012-01-08 10:27:02 +00001466 }
1467 }
tuexenb735c0f2012-04-28 16:43:56 +00001468 if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
tuexena1d7a852012-05-19 14:55:19 +00001469 if ((SCTP_BASE_VAR(recvthreadudp6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp6, NULL, 0, NULL)) == NULL) {
1470 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread.\n");
tuexenf83a7fa2012-05-18 05:44:04 +00001471 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
tuexend93dfec2012-04-28 18:04:13 +00001472 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
tuexen59caa502012-01-08 10:27:02 +00001473 }
1474 }
tuexen587a0a62011-12-15 17:32:38 +00001475#endif
tuexen085a5052012-01-08 13:42:59 +00001476#endif
tuexenbca1dae2011-11-01 23:02:02 +00001477}
1478
1479void
tuexen3a33bc92012-01-15 12:10:06 +00001480recv_thread_destroy(void)
tuexen587a0a62011-12-15 17:32:38 +00001481{
t00fcxen22a33a12013-12-27 19:21:25 +00001482#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
tuexenb735c0f2012-04-28 16:43:56 +00001483#if defined(INET) || defined(INET6)
1484 if (SCTP_BASE_VAR(userspace_route) != -1) {
tuexenb735c0f2012-04-28 16:43:56 +00001485 close(SCTP_BASE_VAR(userspace_route));
tuexen3a33bc92012-01-15 12:10:06 +00001486 }
tuexenc5fa57e2012-01-10 14:51:23 +00001487#endif
tuexen3a33bc92012-01-15 12:10:06 +00001488#endif
tuexenb735c0f2012-04-28 16:43:56 +00001489#if defined(INET)
1490 if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
1491#if defined(__Userspace_os_Windows)
1492 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
1493#else
1494 close(SCTP_BASE_VAR(userspace_rawsctp));
1495#endif
tuexen587a0a62011-12-15 17:32:38 +00001496 }
tuexenb735c0f2012-04-28 16:43:56 +00001497 if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
1498#if defined(__Userspace_os_Windows)
1499 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
1500#else
1501 close(SCTP_BASE_VAR(userspace_udpsctp));
1502#endif
1503 }
1504#endif
tuexen3a33bc92012-01-15 12:10:06 +00001505#if defined(INET6)
tuexenb735c0f2012-04-28 16:43:56 +00001506 if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
tuexen3a33bc92012-01-15 12:10:06 +00001507#if defined(__Userspace_os_Windows)
tuexenb735c0f2012-04-28 16:43:56 +00001508 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
tuexen3a33bc92012-01-15 12:10:06 +00001509#else
tuexenb735c0f2012-04-28 16:43:56 +00001510 close(SCTP_BASE_VAR(userspace_rawsctp6));
tuexen3a33bc92012-01-15 12:10:06 +00001511#endif
tuexen3a33bc92012-01-15 12:10:06 +00001512 }
tuexenb735c0f2012-04-28 16:43:56 +00001513 if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
tuexen3a33bc92012-01-15 12:10:06 +00001514#if defined(__Userspace_os_Windows)
tuexenb735c0f2012-04-28 16:43:56 +00001515 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
tuexen3a33bc92012-01-15 12:10:06 +00001516#else
tuexenb735c0f2012-04-28 16:43:56 +00001517 close(SCTP_BASE_VAR(userspace_udpsctp6));
tuexen3a33bc92012-01-15 12:10:06 +00001518#endif
tuexen3a33bc92012-01-15 12:10:06 +00001519 }
1520#endif
tuexenbca1dae2011-11-01 23:02:02 +00001521}
t00fcxen6b5474d2013-08-03 13:14:37 +00001522#else
1523int foo;
tuexen00e1eea2012-07-15 15:48:48 +00001524#endif