blob: a7990b39c0b1349562ac39bc85412280b0cf4717 [file] [log] [blame]
James Kuszmaul4cb043c2021-01-17 11:25:51 -08001/*-
2 * 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
6 * 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
31#if defined(INET) || defined(INET6)
32#include <sys/types.h>
33#if !defined(__Userspace_os_Windows)
34#include <sys/socket.h>
35#include <netinet/in.h>
36#include <unistd.h>
37#include <pthread.h>
38#if !defined(__Userspace_os_DragonFly) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_NetBSD)
39#include <sys/uio.h>
40#else
41#include <user_ip6_var.h>
42#endif
43#endif
44#include <netinet/sctp_os.h>
45#include <netinet/sctp_var.h>
46#include <netinet/sctp_pcb.h>
47#include <netinet/sctp_input.h>
48#if 0
49#if defined(__Userspace_os_Linux)
50#include <linux/netlink.h>
51#ifdef HAVE_LINUX_IF_ADDR_H
52#include <linux/if_addr.h>
53#endif
54#ifdef HAVE_LINUX_RTNETLINK_H
55#include <linux/rtnetlink.h>
56#endif
57#endif
58#endif
59#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
60#include <net/route.h>
61#endif
62/* local macros and datatypes used to get IP addresses system independently */
63#if !defined(IP_PKTINFO ) && ! defined(IP_RECVDSTADDR)
64# error "Can't determine socket option to use to get UDP IP"
65#endif
66
67void recv_thread_destroy(void);
68#define MAXLEN_MBUF_CHAIN 32 /* What should this value be? */
69#define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
70#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
71#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
75#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
76static 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}
90
91static void
92sctp_handle_ifamsg(unsigned char type, unsigned short index, struct sockaddr *sa)
93{
94 int rc;
95 struct ifaddrs *ifa, *ifas;
96
97 /* handle only the types we want */
98 if ((type != RTM_NEWADDR) && (type != RTM_DELADDR)) {
99 return;
100 }
101
102 rc = getifaddrs(&ifas);
103 if (rc != 0) {
104 return;
105 }
106 for (ifa = ifas; ifa; ifa = ifa->ifa_next) {
107 if (index == if_nametoindex(ifa->ifa_name)) {
108 break;
109 }
110 }
111 if (ifa == NULL) {
112 freeifaddrs(ifas);
113 return;
114 }
115
116 /* relay the appropriate address change to the base code */
117 if (type == RTM_NEWADDR) {
118 (void)sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID,
119 NULL,
120 if_nametoindex(ifa->ifa_name),
121 0,
122 ifa->ifa_name,
123 NULL,
124 sa,
125 0,
126 1);
127 } else {
128 sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
129 if_nametoindex(ifa->ifa_name),
130 ifa->ifa_name);
131 }
132 freeifaddrs(ifas);
133}
134
135static void *
136recv_function_route(void *arg)
137{
138 ssize_t ret;
139 struct ifa_msghdr *ifa;
140 char rt_buffer[1024];
141 struct sockaddr *sa, *rti_info[RTAX_MAX];
142
143 sctp_userspace_set_threadname("SCTP addr mon");
144
145 while (1) {
146 bzero(rt_buffer, sizeof(rt_buffer));
147 ret = recv(SCTP_BASE_VAR(userspace_route), rt_buffer, sizeof(rt_buffer), 0);
148
149 if (ret > 0) {
150 ifa = (struct ifa_msghdr *) rt_buffer;
151 if (ifa->ifam_type != RTM_DELADDR && ifa->ifam_type != RTM_NEWADDR) {
152 continue;
153 }
154 sa = (struct sockaddr *) (ifa + 1);
155 sctp_get_rtaddrs(ifa->ifam_addrs, sa, rti_info);
156 switch (ifa->ifam_type) {
157 case RTM_DELADDR:
158 case RTM_NEWADDR:
159 sctp_handle_ifamsg(ifa->ifam_type, ifa->ifam_index, rti_info[RTAX_IFA]);
160 break;
161 default:
162 /* ignore this routing event */
163 break;
164 }
165 }
166 if (ret < 0) {
167 if (errno == EAGAIN) {
168 continue;
169 } else {
170 break;
171 }
172 }
173 }
174 return (NULL);
175}
176#endif
177
178#if 0
179/* This does not yet work on Linux */
180static void *
181recv_function_route(void *arg)
182{
183 int len;
184 char buf[4096];
185 struct iovec iov = { buf, sizeof(buf) };
186 struct msghdr msg;
187 struct nlmsghdr *nh;
188 struct ifaddrmsg *rtmsg;
189 struct rtattr *rtatp;
190 struct in_addr *inp;
191 struct sockaddr_nl sanl;
192#ifdef INET
193 struct sockaddr_in *sa;
194#endif
195#ifdef INET6
196 struct sockaddr_in6 *sa6;
197#endif
198
199 for (;;) {
200 memset(&sanl, 0, sizeof(sanl));
201 sanl.nl_family = AF_NETLINK;
202 sanl.nl_groups = RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_IFADDR;
203 memset(&msg, 0, sizeof(struct msghdr));
204 msg.msg_name = (void *)&sanl;
205 msg.msg_namelen = sizeof(sanl);
206 msg.msg_iov = &iov;
207 msg.msg_iovlen = 1;
208 msg.msg_control = NULL;
209 msg.msg_controllen = 0;
210
211 len = recvmsg(SCTP_BASE_VAR(userspace_route), &msg, 0);
212
213 if (len < 0) {
214 if (errno == EAGAIN) {
215 continue;
216 } else {
217 break;
218 }
219 }
220 for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len);
221 nh = NLMSG_NEXT (nh, len)) {
222 if (nh->nlmsg_type == NLMSG_DONE)
223 break;
224
225 if (nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR) {
226 rtmsg = (struct ifaddrmsg *)NLMSG_DATA(nh);
227 rtatp = (struct rtattr *)IFA_RTA(rtmsg);
228 if (rtatp->rta_type == IFA_ADDRESS) {
229 inp = (struct in_addr *)RTA_DATA(rtatp);
230 switch (rtmsg->ifa_family) {
231#ifdef INET
232 case AF_INET:
233 sa = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
234 sa->sin_family = rtmsg->ifa_family;
235 sa->sin_port = 0;
236 memcpy(&sa->sin_addr, inp, sizeof(struct in_addr));
237 sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa);
238 break;
239#endif
240#ifdef INET6
241 case AF_INET6:
242 sa6 = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6));
243 sa6->sin6_family = rtmsg->ifa_family;
244 sa6->sin6_port = 0;
245 memcpy(&sa6->sin6_addr, inp, sizeof(struct in6_addr));
246 sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa6);
247 break;
248#endif
249 default:
250 SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", rtmsg->ifa_family);
251 break;
252 }
253 }
254 }
255 }
256 }
257 return (NULL);
258}
259#endif
260
261#ifdef INET
262#if !defined(__Userspace_os_Windows)
263int
264recv_raw4(struct iovec *rcv_iovec, int len, struct mbuf **recvmbuf)
265#else
266int
267recv_raw4(WSABUF *rcv_iovec, int len, struct mbuf **recvmbuf)
268#endif
269{
270#if !defined(__Userspace_os_Windows)
271 struct msghdr msg;
272#else
273 int nResult, m_ErrorCode;
274 DWORD flags;
275 struct sockaddr_in from;
276 int fromlen;
277#endif
278 int filled = 0;
279 int i, n, ncounter = 0;
280 int iovlen = MCLBYTES;
281 struct ip *iphdr;
282 struct sctphdr *sh;
283 struct sctp_chunkhdr *ch;
284 uint16_t port;
285 int offset, ecn = 0;
286#if !defined(SCTP_WITH_NO_CSUM)
287 int compute_crc = 1;
288#endif
289 struct sockaddr_in src, dst;
290
291#if defined(__Userspace_os_Windows)
292 flags = 0;
293 ncounter = 0;
294 fromlen = sizeof(struct sockaddr_in);
295 bzero((void *)&from, sizeof(struct sockaddr_in));
296
297 nResult = WSARecvFrom(SCTP_BASE_VAR(userspace_rawsctp), rcv_iovec, len, (LPDWORD)&ncounter, (LPDWORD)&flags, (struct sockaddr*)&from, &fromlen, NULL, NULL);
298 if (nResult != 0) {
299 m_ErrorCode = WSAGetLastError();
300 if (m_ErrorCode == WSAETIMEDOUT) {
301 return 0;
302 }
303 if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
304 return 0;
305 }
306 }
307 n = ncounter;
308#else
309 bzero((void *)&msg, sizeof(struct msghdr));
310 msg.msg_name = NULL;
311 msg.msg_namelen = 0;
312 msg.msg_iov = rcv_iovec;
313 msg.msg_iovlen = len;
314 msg.msg_control = NULL;
315 msg.msg_controllen = 0;
316 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp), &msg, 0);
317 if (n < 0) {
318 if (errno == EAGAIN) {
319 return 0;
320 } else {
321 return -1;
322 }
323 }
324#endif
325
326 SCTP_HEADER_LEN(recvmbuf[0]) = n; /* length of total packet */
327 SCTP_STAT_INCR(sctps_recvpackets);
328 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
329
330 if (n <= iovlen) {
331 SCTP_BUF_LEN(recvmbuf[0]) = n;
332 filled++;
333 } else {
334 i = 0;
335 SCTP_BUF_LEN(recvmbuf[0]) = iovlen;
336
337 ncounter -= iovlen;
338 filled++;
339 do {
340 recvmbuf[i]->m_next = recvmbuf[i+1];
341 SCTP_BUF_LEN(recvmbuf[i]->m_next) = min(ncounter, iovlen);
342 i++;
343 ncounter -= iovlen;
344 filled++;
345 } while (ncounter > 0);
346 }
347
348 iphdr = mtod(recvmbuf[0], struct ip *);
349 sh = (struct sctphdr *)((caddr_t)iphdr + sizeof(struct ip));
350 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
351 offset = sizeof(struct ip) + sizeof(struct sctphdr);
352
353 if (iphdr->ip_tos != 0) {
354 ecn = iphdr->ip_tos & 0x02;
355 }
356
357 dst.sin_family = AF_INET;
358#ifdef HAVE_SIN_LEN
359 dst.sin_len = sizeof(struct sockaddr_in);
360#endif
361 dst.sin_addr = iphdr->ip_dst;
362 dst.sin_port = sh->dest_port;
363 src.sin_family = AF_INET;
364#ifdef HAVE_SIN_LEN
365 src.sin_len = sizeof(struct sockaddr_in);
366#endif
367 src.sin_addr = iphdr->ip_src;
368 src.sin_port = sh->src_port;
369
370 /* SCTP does not allow broadcasts or multicasts */
371 if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
372 m_freem(recvmbuf[0]);
373 return 0;
374 }
375 if (SCTP_IS_IT_BROADCAST(dst.sin_addr, rcvmbuf[0])) {
376 m_freem(recvmbuf[0]);
377 return 0;
378 }
379
380 port = 0;
381
382#if defined(SCTP_WITH_NO_CSUM)
383 SCTP_STAT_INCR(sctps_recvnocrc);
384#else
385 if (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
386 ((IN4_ISLOOPBACK_ADDRESS(&src.sin_addr) &&
387 IN4_ISLOOPBACK_ADDRESS(&dst.sin_addr)) ||
388 (src.sin_addr.s_addr == dst.sin_addr.s_addr))) {
389 compute_crc = 0;
390 SCTP_STAT_INCR(sctps_recvnocrc);
391 } else {
392 SCTP_STAT_INCR(sctps_recvswcrc);
393 }
394#endif
395 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
396 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
397 sctp_common_input_processing(&recvmbuf[0], sizeof(struct ip), offset, n,
398 (struct sockaddr *)&src,
399 (struct sockaddr *)&dst,
400 sh, ch,
401#if !defined(SCTP_WITH_NO_CSUM)
402 compute_crc,
403#endif
404 ecn,
405 SCTP_DEFAULT_VRFID, port);
406 if (recvmbuf[0]) {
407 m_freem(recvmbuf[0]);
408 }
409 return filled;
410}
411#endif
412
413#ifdef INET
414#if !defined(THREAD_SUPPORT)
415#if !defined(__Userspace_os_Windows)
416void
417usrsctp_recv_function_sctp4(void)
418#else
419void
420usrsctp_recv_function_sctp4(void)
421#endif
422{
423 struct sockaddr_in src, dst;
424 /* iovlen is the size of each mbuf in the chain */
425 int i;
426 int iovlen = MCLBYTES;
427 int want_ext = (iovlen > MLEN)? 1 : 0;
428 int want_header = 0;
429
430 bzero((void *)&src, sizeof(struct sockaddr_in));
431 bzero((void *)&dst, sizeof(struct sockaddr_in));
432
433 for (i = 0; i < SCTP_BASE_VAR(to_fill4); i++) {
434 /* Not getting the packet header. Tests with chain of one run
435 as usual without having the packet header.
436 Have tried both sending and receiving
437 */
438 SCTP_BASE_VAR(recvmbuf4[i]) = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
439#if !defined(__Userspace_os_Windows)
440 SCTP_BASE_VAR(recv_iovec4[i].iov_base) = (caddr_t)SCTP_BASE_VAR(recvmbuf4[i]->m_data);
441 SCTP_BASE_VAR(recv_iovec4[i].iov_len) = iovlen;
442#else
443 SCTP_BASE_VAR(recv_iovec[i].buf) = (caddr_t)SCTP_BASE_VAR(recvmbuf[i]->m_data);
444 SCTP_BASE_VAR(recv_iovec[i].len) = iovlen;
445#endif
446 }
447 SCTP_BASE_VAR(to_fill4) = recv_raw4(SCTP_BASE_VAR(recv_iovec4), MAXLEN_MBUF_CHAIN, SCTP_BASE_VAR(recvmbuf4));
448}
449#endif
450#endif
451
452#ifdef INET
453static void *
454recv_function_raw(void *arg)
455{
456 struct mbuf **recvmbuf;
457 struct sockaddr_in src, dst;
458#if !defined(__Userspace_os_Windows)
459 struct iovec recv_iovec[MAXLEN_MBUF_CHAIN];
460#else
461 WSABUF recv_iovec[MAXLEN_MBUF_CHAIN];
462#endif
463 /*Initially the entire set of mbufs is to be allocated.
464 to_fill indicates this amount. */
465 int to_fill = MAXLEN_MBUF_CHAIN;
466 /* iovlen is the size of each mbuf in the chain */
467 int i;
468 int iovlen = MCLBYTES;
469 int want_ext = (iovlen > MLEN)? 1 : 0;
470 int want_header = 0;
471
472 sctp_userspace_set_threadname("SCTP/IP4 rcv");
473
474 bzero((void *)&src, sizeof(struct sockaddr_in));
475 bzero((void *)&dst, sizeof(struct sockaddr_in));
476
477 recvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
478
479 while (1) {
480 for (i = 0; i < to_fill; i++) {
481 /* Not getting the packet header. Tests with chain of one run
482 as usual without having the packet header.
483 Have tried both sending and receiving
484 */
485 recvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
486#if !defined(__Userspace_os_Windows)
487 recv_iovec[i].iov_base = (caddr_t)recvmbuf[i]->m_data;
488 recv_iovec[i].iov_len = iovlen;
489#else
490 recv_iovec[i].buf = (caddr_t)recvmbuf[i]->m_data;
491 recv_iovec[i].len = iovlen;
492#endif
493 }
494 to_fill = recv_raw4(recv_iovec, MAXLEN_MBUF_CHAIN, recvmbuf);
495 if (to_fill < 0) {
496 break;
497 }
498 }
499 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
500 m_free(recvmbuf[i]);
501 }
502 /* free the array itself */
503 free(recvmbuf);
504 return (NULL);
505}
506#endif
507
508#if defined(INET6)
509#if !defined(__Userspace_os_Windows)
510int
511recv_raw6(struct iovec *recv_iovec, int len, struct mbuf **recvmbuf6)
512#else
513int
514recv_raw6(WSABUF *recv_iovec, int len, struct mbuf **recvmbuf6)
515#endif
516{
517#if !defined(__Userspace_os_Windows)
518 struct msghdr msg;
519 char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
520 struct cmsghdr *cmsgptr;
521#else
522 int nResult, m_ErrorCode;
523 DWORD flags;
524 struct sockaddr_in6 from;
525 WSACMSGHDR *cmsgptr;
526 int fromlen;
527#endif
528 int filled = 0;
529 int i, n, ncounter = 0;
530 int iovlen = MCLBYTES;
531 struct sctphdr *sh;
532 struct sctp_chunkhdr *ch;
533 int offset;
534#if !defined(SCTP_WITH_NO_CSUM)
535 int compute_crc = 1;
536#endif
537 struct sockaddr_in6 src, dst;
538
539#if defined(__Userspace_os_Windows)
540 flags = 0;
541 ncounter = 0;
542 fromlen = sizeof(struct sockaddr_in6);
543 bzero((void *)&from, sizeof(struct sockaddr_in6));
544 nResult = WSAIoctl(SCTP_BASE_VAR(userspace_rawsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER,
545 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
546 &WSARecvMsg, sizeof WSARecvMsg,
547 &ncounter, NULL, NULL);
548 if (nResult == 0) {
549 msg.name = (void *)&src;
550 msg.namelen = sizeof(struct sockaddr_in6);
551 msg.lpBuffers = recv_iovec;
552 msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
553 msg.Control.len = sizeof ControlBuffer;
554 msg.Control.buf = ControlBuffer;
555 msg.dwFlags = 0;
556 nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, &ncounter, NULL, NULL);
557 }
558 if (nResult != 0) {
559 m_ErrorCode = WSAGetLastError();
560 if (m_ErrorCode == WSAETIMEDOUT)
561 return 0;
562 if (m_ErrorCode == WSAENOTSOCK || m_ErrorCode == WSAEINTR)
563 return -1;
564 }
565 n = ncounter;
566#else
567 bzero((void *)&msg, sizeof(struct msghdr));
568 bzero((void *)&src, sizeof(struct sockaddr_in6));
569 bzero((void *)&dst, sizeof(struct sockaddr_in6));
570 bzero((void *)cmsgbuf, CMSG_SPACE(sizeof (struct in6_pktinfo)));
571 msg.msg_name = (void *)&src;
572 msg.msg_namelen = sizeof(struct sockaddr_in6);
573 msg.msg_iov = recv_iovec;
574 msg.msg_iovlen = len;
575 msg.msg_control = (void *)cmsgbuf;
576 msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof (struct in6_pktinfo));
577 msg.msg_flags = 0;
578
579 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, 0);
580 if (n < 0) {
581 if (errno == EAGAIN) {
582 return 0;
583 } else {
584 return -1;
585 }
586 }
587#endif
588 SCTP_HEADER_LEN(recvmbuf6[0]) = n; /* length of total packet */
589 SCTP_STAT_INCR(sctps_recvpackets);
590 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
591
592 if (n <= iovlen) {
593 SCTP_BUF_LEN(recvmbuf6[0]) = n;
594 filled++;
595 } else {
596 i = 0;
597 SCTP_BUF_LEN(recvmbuf6[0]) = iovlen;
598
599 ncounter -= iovlen;
600 filled++;
601 do {
602 recvmbuf6[i]->m_next = recvmbuf6[i+1];
603 SCTP_BUF_LEN(recvmbuf6[i]->m_next) = min(ncounter, iovlen);
604 i++;
605 ncounter -= iovlen;
606 filled++;
607 } while (ncounter > 0);
608 }
609
610 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
611 if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) {
612 struct in6_pktinfo * info;
613
614 info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
615 memcpy((void *)&dst.sin6_addr, (const void *) &(info->ipi6_addr), sizeof(struct in6_addr));
616 break;
617 }
618 }
619
620 /* SCTP does not allow broadcasts or multicasts */
621 if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) {
622 m_freem(recvmbuf6[0]);
623 return 0;
624 }
625
626 sh = mtod(recvmbuf6[0], struct sctphdr *);
627 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
628 offset = sizeof(struct sctphdr);
629
630 dst.sin6_family = AF_INET6;
631#ifdef HAVE_SIN6_LEN
632 dst.sin6_len = sizeof(struct sockaddr_in6);
633#endif
634 dst.sin6_port = sh->dest_port;
635
636 src.sin6_family = AF_INET6;
637#ifdef HAVE_SIN6_LEN
638 src.sin6_len = sizeof(struct sockaddr_in6);
639#endif
640 src.sin6_port = sh->src_port;
641#if defined(SCTP_WITH_NO_CSUM)
642 SCTP_STAT_INCR(sctps_recvnocrc);
643#else
644 if (memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0) {
645 compute_crc = 0;
646 SCTP_STAT_INCR(sctps_recvnocrc);
647 } else {
648 SCTP_STAT_INCR(sctps_recvswcrc);
649 }
650#endif
651 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
652 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
653 sctp_common_input_processing(&recvmbuf6[0], 0, offset, n,
654 (struct sockaddr *)&src,
655 (struct sockaddr *)&dst,
656 sh, ch,
657#if !defined(SCTP_WITH_NO_CSUM)
658 compute_crc,
659#endif
660 0,
661 SCTP_DEFAULT_VRFID, 0);
662 if (recvmbuf6[0]) {
663 m_freem(recvmbuf6[0]);
664 }
665 return filled;
666}
667#endif
668
669#if defined(INET6)
670#if !defined(THREAD_SUPPORT)
671#if !defined(__Userspace_os_Windows)
672void
673usrsctp_recv_function_sctp6(void)
674#else
675void
676usrsctp_recv_function_sctp6(void)
677#endif
678{
679 /* iovlen is the size of each mbuf in the chain */
680 int i;
681 int iovlen = MCLBYTES;
682 int want_ext = (iovlen > MLEN)? 1 : 0;
683 int want_header = 0;
684
685 for (i = 0; i < SCTP_BASE_VAR(to_fill6); i++) {
686 /* Not getting the packet header. Tests with chain of one run
687 as usual without having the packet header.
688 Have tried both sending and receiving
689 */
690 SCTP_BASE_VAR(recvmbuf6[i]) = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
691#if !defined(__Userspace_os_Windows)
692 SCTP_BASE_VAR(recv_iovec6[i].iov_base) = (caddr_t)SCTP_BASE_VAR(recvmbuf6[i]->m_data);
693 SCTP_BASE_VAR(recv_iovec6[i].iov_len) = iovlen;
694#else
695 SCTP_BASE_VAR(recv_iovec6[i].buf) = (caddr_t)SCTP_BASE_VAR(recvmbuf6[i]->m_data);
696 SCTP_BASE_VAR(recv_iovec6[i].len) = iovlen;
697#endif
698 }
699 SCTP_BASE_VAR(to_fill6) = recv_raw6(SCTP_BASE_VAR(recv_iovec6), MAXLEN_MBUF_CHAIN, SCTP_BASE_VAR(recvmbuf6));
700}
701#endif
702#endif
703
704#if defined(INET6)
705static void *
706recv_function_raw6(void *arg)
707{
708 struct mbuf **recvmbuf6;
709#if !defined(__Userspace_os_Windows)
710 struct iovec recv_iovec[MAXLEN_MBUF_CHAIN];
711#else
712 WSABUF recv_iovec[MAXLEN_MBUF_CHAIN];
713#endif
714 /*Initially the entire set of mbufs is to be allocated.
715 to_fill indicates this amount. */
716 int to_fill = MAXLEN_MBUF_CHAIN;
717 /* iovlen is the size of each mbuf in the chain */
718 int i;
719 int iovlen = MCLBYTES;
720 int want_ext = (iovlen > MLEN)? 1 : 0;
721 int want_header = 0;
722
723 sctp_userspace_set_threadname("SCTP/IP6 rcv");
724
725 recvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
726
727 for (;;) {
728 for (i = 0; i < to_fill; i++) {
729 /* Not getting the packet header. Tests with chain of one run
730 as usual without having the packet header.
731 Have tried both sending and receiving
732 */
733 recvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
734#if !defined(__Userspace_os_Windows)
735 recv_iovec[i].iov_base = (caddr_t)recvmbuf6[i]->m_data;
736 recv_iovec[i].iov_len = iovlen;
737#else
738 recv_iovec[i].buf = (caddr_t)recvmbuf6[i]->m_data;
739 recv_iovec[i].len = iovlen;
740#endif
741 }
742 to_fill = recv_raw6(recv_iovec, MAXLEN_MBUF_CHAIN, recvmbuf6);
743 if (to_fill < 0) {
744 break;
745 }
746 }
747 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
748 m_free(recvmbuf6[i]);
749 }
750 /* free the array itself */
751 free(recvmbuf6);
752 return (NULL);
753}
754#endif
755
756#ifdef INET
757#if !defined(__Userspace_os_Windows)
758int
759recv_udp4(struct iovec *rcv_iovec, int len, struct mbuf **udprcvmbuf)
760#else
761int
762recv_udp4(WSABUF *rcv_iovec, int len, struct mbuf **udprcvmbuf)
763#endif
764{
765 /*Initially the entire set of mbufs is to be allocated.
766 to_fill indicates this amount. */
767 int filled = 0;
768 /* iovlen is the size of each mbuf in the chain */
769 int i, n, ncounter, offset;
770 int iovlen = MCLBYTES;
771 struct sctphdr *sh;
772 uint16_t port;
773 struct sctp_chunkhdr *ch;
774 struct sockaddr_in src, dst;
775#if defined(IP_PKTINFO)
776 char cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))];
777#else
778 char cmsgbuf[CMSG_SPACE(sizeof(struct in_addr))];
779#endif
780#if !defined(SCTP_WITH_NO_CSUM)
781 int compute_crc = 1;
782#endif
783#if !defined(__Userspace_os_Windows)
784 struct msghdr msg;
785 struct cmsghdr *cmsgptr;
786#else
787 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
788 LPFN_WSARECVMSG WSARecvMsg;
789 char ControlBuffer[1024];
790 WSAMSG msg;
791 int nResult, m_ErrorCode;
792 WSACMSGHDR *cmsgptr;
793#endif
794
795#if !defined(__Userspace_os_Windows)
796 bzero((void *)&msg, sizeof(struct msghdr));
797#else
798 bzero((void *)&msg, sizeof(WSAMSG));
799#endif
800 bzero((void *)&src, sizeof(struct sockaddr_in));
801 bzero((void *)&dst, sizeof(struct sockaddr_in));
802 bzero((void *)cmsgbuf, sizeof(cmsgbuf));
803
804#if !defined(__Userspace_os_Windows)
805 msg.msg_name = (void *)&src;
806 msg.msg_namelen = sizeof(struct sockaddr_in);
807 msg.msg_iov = rcv_iovec;
808 msg.msg_iovlen = len;
809 msg.msg_control = (void *)cmsgbuf;
810 msg.msg_controllen = sizeof(cmsgbuf);
811 msg.msg_flags = 0;
812
813 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, 0);
814
815 if (n < 0) {
816 if (errno == EAGAIN) {
817 return 0;
818 } else {
819 return -1;
820 }
821 }
822#else
823 nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp), SIO_GET_EXTENSION_FUNCTION_POINTER,
824 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
825 &WSARecvMsg, sizeof WSARecvMsg,
826 &ncounter, NULL, NULL);
827 if (nResult == 0) {
828 msg.name = (void *)&src;
829 msg.namelen = sizeof(struct sockaddr_in);
830 msg.lpBuffers = rcv_iovec;
831 msg.dwBufferCount = len;
832 msg.Control.len = sizeof ControlBuffer;
833 msg.Control.buf = ControlBuffer;
834 msg.dwFlags = 0;
835 nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, &ncounter, NULL, NULL);
836 }
837 if (nResult != 0) {
838 m_ErrorCode = WSAGetLastError();
839 if (m_ErrorCode == WSAETIMEDOUT) {
840 return 0;
841 }
842 if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
843 return 0;
844 }
845 }
846 n = ncounter;
847#endif
848 SCTP_HEADER_LEN(udprcvmbuf[0]) = n; /* length of total packet */
849 SCTP_STAT_INCR(sctps_recvpackets);
850 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
851 if (n <= iovlen) {
852 SCTP_BUF_LEN(udprcvmbuf[0]) = n;
853 filled++;
854 } else {
855 i = 0;
856 SCTP_BUF_LEN(udprcvmbuf[0]) = iovlen;
857 ncounter -= iovlen;
858 filled++;
859 do {
860 udprcvmbuf[i]->m_next = udprcvmbuf[i+1];
861 SCTP_BUF_LEN(udprcvmbuf[i]->m_next) = min(ncounter, iovlen);
862 i++;
863 ncounter -= iovlen;
864 filled++;
865 } while (ncounter > 0);
866 }
867 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
868#if defined(IP_PKTINFO)
869 if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_PKTINFO)) {
870 struct in_pktinfo *info;
871
872 dst.sin_family = AF_INET;
873#ifdef HAVE_SIN_LEN
874 dst.sin_len = sizeof(struct sockaddr_in);
875#endif
876 info = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
877 memcpy((void *)&dst.sin_addr, (const void *)&(info->ipi_addr), sizeof(struct in_addr));
878 break;
879 }
880#else
881 if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_RECVDSTADDR)) {
882 struct in_addr *addr;
883
884 dst.sin_family = AF_INET;
885#ifdef HAVE_SIN_LEN
886 dst.sin_len = sizeof(struct sockaddr_in);
887#endif
888 addr = (struct in_addr *)CMSG_DATA(cmsgptr);
889 memcpy((void *)&dst.sin_addr, (const void *)addr, sizeof(struct in_addr));
890 break;
891 }
892#endif
893 }
894 /* SCTP does not allow broadcasts or multicasts */
895 if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
896 m_freem(udprcvmbuf[0]);
897 return 0;
898 }
899 if (SCTP_IS_IT_BROADCAST(dst.sin_addr, udprcvmbuf[0])) {
900 m_freem(udprcvmbuf[0]);
901 return 0;
902 }
903
904 /*offset = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);*/
905 sh = mtod(udprcvmbuf[0], struct sctphdr *);
906 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
907 offset = sizeof(struct sctphdr);
908 port = src.sin_port;
909 src.sin_port = sh->src_port;
910 dst.sin_port = sh->dest_port;
911#if defined(SCTP_WITH_NO_CSUM)
912 SCTP_STAT_INCR(sctps_recvnocrc);
913#else
914 if (src.sin_addr.s_addr == dst.sin_addr.s_addr) {
915 compute_crc = 0;
916 SCTP_STAT_INCR(sctps_recvnocrc);
917 } else {
918 SCTP_STAT_INCR(sctps_recvswcrc);
919 }
920#endif
921 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
922 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
923 sctp_common_input_processing(&udprcvmbuf[0], 0, offset, n,
924 (struct sockaddr *)&src,
925 (struct sockaddr *)&dst,
926 sh, ch,
927#if !defined(SCTP_WITH_NO_CSUM)
928 compute_crc,
929#endif
930 0,
931 SCTP_DEFAULT_VRFID, port);
932 if (udprcvmbuf[0]) {
933 m_freem(udprcvmbuf[0]);
934 }
935 return filled;
936}
937
938#ifdef INET
939#if !defined(THREAD_SUPPORT)
940#if !defined(__Userspace_os_Windows)
941void
942usrsctp_recv_function_udpsctp4(void)
943#else
944void
945usrsctp_recv_function_udpsctp4(void)
946#endif
947{
948 struct sockaddr_in src, dst;
949 /* iovlen is the size of each mbuf in the chain */
950 int i;
951 int iovlen = MCLBYTES;
952 int want_ext = (iovlen > MLEN)? 1 : 0;
953 int want_header = 0;
954
955 bzero((void *)&src, sizeof(struct sockaddr_in));
956 bzero((void *)&dst, sizeof(struct sockaddr_in));
957
958 for (i = 0; i < SCTP_BASE_VAR(udp_to_fill4); i++) {
959 /* Not getting the packet header. Tests with chain of one run
960 as usual without having the packet header.
961 Have tried both sending and receiving
962 */
963 SCTP_BASE_VAR(udp_recvmbuf4[i]) = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
964#if !defined(__Userspace_os_Windows)
965 SCTP_BASE_VAR(udp_recv_iovec4[i].iov_base) = (caddr_t)SCTP_BASE_VAR(udp_recvmbuf4[i]->m_data);
966 SCTP_BASE_VAR(udp_recv_iovec4[i].iov_len) = iovlen;
967#else
968 SCTP_BASE_VAR(udp_recv_iovec4[i].buf) = (caddr_t)SCTP_BASE_VAR(udp_recvmbuf4[i]->m_data);
969 SCTP_BASE_VAR(udp_recv_iovec4[i].len) = iovlen;
970#endif
971 }
972
973 SCTP_BASE_VAR(udp_to_fill4) = recv_udp4(SCTP_BASE_VAR(udp_recv_iovec4), MAXLEN_MBUF_CHAIN, SCTP_BASE_VAR(udp_recvmbuf4));
974}
975#endif
976#endif
977
978static void *
979recv_function_udp(void *arg)
980{
981 struct mbuf **udprecvmbuf;
982 /*Initially the entire set of mbufs is to be allocated.
983 to_fill indicates this amount. */
984 int to_fill = MAXLEN_MBUF_CHAIN;
985 /* iovlen is the size of each mbuf in the chain */
986 int i;
987 int iovlen = MCLBYTES;
988 int want_ext = (iovlen > MLEN)? 1 : 0;
989 int want_header = 0;
990#if !defined(__Userspace_os_Windows)
991 struct iovec iov[MAXLEN_MBUF_CHAIN];
992#else
993 WSABUF iov[MAXLEN_MBUF_CHAIN];
994#endif
995
996 sctp_userspace_set_threadname("SCTP/UDP/IP4 rcv");
997
998 udprecvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
999
1000 while (1) {
1001 for (i = 0; i < to_fill; i++) {
1002 /* Not getting the packet header. Tests with chain of one run
1003 as usual without having the packet header.
1004 Have tried both sending and receiving
1005 */
1006 udprecvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
1007#if !defined(__Userspace_os_Windows)
1008 iov[i].iov_base = (caddr_t)udprecvmbuf[i]->m_data;
1009 iov[i].iov_len = iovlen;
1010#else
1011 iov[i].buf = (caddr_t)udprecvmbuf[i]->m_data;
1012 iov[i].len = iovlen;
1013#endif
1014 }
1015
1016 to_fill = recv_udp4(iov, MAXLEN_MBUF_CHAIN, udprecvmbuf);
1017 if (to_fill < 0) {
1018 break;
1019 }
1020
1021 }
1022 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
1023 m_free(udprecvmbuf[i]);
1024 }
1025 /* free the array itself */
1026 free(udprecvmbuf);
1027 return (NULL);
1028}
1029#endif
1030
1031#if defined(INET6)
1032#if !defined(__Userspace_os_Windows)
1033int
1034recv_udp6(struct iovec *iov, int len, struct mbuf **udprecvmbuf6)
1035#else
1036int
1037recv_udp6(WSABUF *iov, int len, struct mbuf **udprecvmbuf6)
1038#endif
1039{
1040 /*Initially the entire set of mbufs is to be allocated.
1041 to_fill indicates this amount. */
1042 int to_fill = 0;
1043 /* iovlen is the size of each mbuf in the chain */
1044 int i, n, ncounter, offset;
1045 int iovlen = MCLBYTES;
1046 struct sockaddr_in6 src, dst;
1047 struct sctphdr *sh;
1048 uint16_t port;
1049 struct sctp_chunkhdr *ch;
1050 char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
1051#if !defined(SCTP_WITH_NO_CSUM)
1052 int compute_crc = 1;
1053#endif
1054#if !defined(__Userspace_os_Windows)
1055 struct msghdr msg;
1056 struct cmsghdr *cmsgptr;
1057#else
1058 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
1059 LPFN_WSARECVMSG WSARecvMsg;
1060 char ControlBuffer[1024];
1061 WSAMSG msg;
1062 int nResult, m_ErrorCode;
1063 WSACMSGHDR *cmsgptr;
1064#endif
1065#if !defined(__Userspace_os_Windows)
1066 bzero((void *)&msg, sizeof(struct msghdr));
1067#else
1068 bzero((void *)&msg, sizeof(WSAMSG));
1069#endif
1070 bzero((void *)&src, sizeof(struct sockaddr_in6));
1071 bzero((void *)&dst, sizeof(struct sockaddr_in6));
1072 bzero((void *)cmsgbuf, CMSG_SPACE(sizeof (struct in6_pktinfo)));
1073
1074#if !defined(__Userspace_os_Windows)
1075 msg.msg_name = (void *)&src;
1076 msg.msg_namelen = sizeof(struct sockaddr_in6);
1077 msg.msg_iov = iov;
1078 msg.msg_iovlen = len;
1079 msg.msg_control = (void *)cmsgbuf;
1080 msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof (struct in6_pktinfo));
1081 msg.msg_flags = 0;
1082
1083 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, 0);
1084 if (n < 0) {
1085 if (errno == EAGAIN) {
1086 return 0;
1087 } else {
1088 return -1;
1089 }
1090 }
1091#else
1092 nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER,
1093 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
1094 &WSARecvMsg, sizeof WSARecvMsg,
1095 &ncounter, NULL, NULL);
1096 if (nResult == SOCKET_ERROR) {
1097 m_ErrorCode = WSAGetLastError();
1098 WSARecvMsg = NULL;
1099 }
1100 if (nResult == 0) {
1101 msg.name = (void *)&src;
1102 msg.namelen = sizeof(struct sockaddr_in6);
1103 msg.lpBuffers = iov;
1104 msg.dwBufferCount = len;
1105 msg.Control.len = sizeof ControlBuffer;
1106 msg.Control.buf = ControlBuffer;
1107 msg.dwFlags = 0;
1108 nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, &ncounter, NULL, NULL);
1109 }
1110 if (nResult != 0) {
1111 m_ErrorCode = WSAGetLastError();
1112 if (m_ErrorCode == WSAETIMEDOUT) {
1113 return 0;
1114 }
1115 if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
1116 return -1;
1117 }
1118 }
1119 n = ncounter;
1120#endif
1121 SCTP_HEADER_LEN(udprecvmbuf6[0]) = n; /* length of total packet */
1122 SCTP_STAT_INCR(sctps_recvpackets);
1123 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
1124
1125 if (n <= iovlen) {
1126 SCTP_BUF_LEN(udprecvmbuf6[0]) = n;
1127 (to_fill)++;
1128 } else {
1129 i = 0;
1130 SCTP_BUF_LEN(udprecvmbuf6[0]) = iovlen;
1131
1132 ncounter -= iovlen;
1133 (to_fill)++;
1134 do {
1135 udprecvmbuf6[i]->m_next = udprecvmbuf6[i+1];
1136 SCTP_BUF_LEN(udprecvmbuf6[i]->m_next) = min(ncounter, iovlen);
1137 i++;
1138 ncounter -= iovlen;
1139 (to_fill)++;
1140 } while (ncounter > 0);
1141 }
1142
1143 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
1144 if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) {
1145 struct in6_pktinfo *info;
1146
1147 dst.sin6_family = AF_INET6;
1148#ifdef HAVE_SIN6_LEN
1149 dst.sin6_len = sizeof(struct sockaddr_in6);
1150#endif
1151 info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
1152 /*dst.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));*/
1153 memcpy((void *)&dst.sin6_addr, (const void *)&(info->ipi6_addr), sizeof(struct in6_addr));
1154 }
1155 }
1156
1157 /* SCTP does not allow broadcasts or multicasts */
1158 if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) {
1159 m_freem(udprecvmbuf6[0]);
1160 return 0;
1161 }
1162
1163 sh = mtod(udprecvmbuf6[0], struct sctphdr *);
1164 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
1165 offset = sizeof(struct sctphdr);
1166
1167 port = src.sin6_port;
1168 src.sin6_port = sh->src_port;
1169 dst.sin6_port = sh->dest_port;
1170#if defined(SCTP_WITH_NO_CSUM)
1171 SCTP_STAT_INCR(sctps_recvnocrc);
1172#else
1173 if ((memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0)) {
1174 compute_crc = 0;
1175 SCTP_STAT_INCR(sctps_recvnocrc);
1176 } else {
1177 SCTP_STAT_INCR(sctps_recvswcrc);
1178 }
1179#endif
1180 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
1181 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", (int)sizeof(struct sctphdr));
1182 sctp_common_input_processing(&udprecvmbuf6[0], 0, offset, n,
1183 (struct sockaddr *)&src,
1184 (struct sockaddr *)&dst,
1185 sh, ch,
1186#if !defined(SCTP_WITH_NO_CSUM)
1187 compute_crc,
1188#endif
1189 0,
1190 SCTP_DEFAULT_VRFID, port);
1191 if (udprecvmbuf6[0]) {
1192 m_freem(udprecvmbuf6[0]);
1193 }
1194 return to_fill;
1195}
1196#endif
1197
1198#ifdef INET6
1199#if !defined(THREAD_SUPPORT)
1200#if !defined(__Userspace_os_Windows)
1201void
1202usrsctp_recv_function_udpsctp6(void)
1203#else
1204void
1205usrsctp_recv_function_udpsctp6(void)
1206#endif
1207{
1208 /* iovlen is the size of each mbuf in the chain */
1209 int i;
1210 int iovlen = MCLBYTES;
1211 int want_ext = (iovlen > MLEN)? 1 : 0;
1212 int want_header = 0;
1213
1214 for (i = 0; i < SCTP_BASE_VAR(udp_to_fill6); i++) {
1215 /* Not getting the packet header. Tests with chain of one run
1216 as usual without having the packet header.
1217 Have tried both sending and receiving
1218 */
1219 SCTP_BASE_VAR(udp_recvmbuf6[i]) = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
1220#if !defined(__Userspace_os_Windows)
1221 SCTP_BASE_VAR(udp_recv_iovec6[i].iov_base) = (caddr_t)SCTP_BASE_VAR(udp_recvmbuf6[i]->m_data);
1222 SCTP_BASE_VAR(udp_recv_iovec6[i].iov_len) = iovlen;
1223#else
1224 SCTP_BASE_VAR(udp_recv_iovec6[i].buf) = (caddr_t)SCTP_BASE_VAR(udp_recvmbuf6[i]->m_data);
1225 SCTP_BASE_VAR(udp_recv_iovec6[i].len) = iovlen;
1226#endif
1227 }
1228 SCTP_BASE_VAR(udp_to_fill6) = recv_udp6(SCTP_BASE_VAR(udp_recv_iovec6), MAXLEN_MBUF_CHAIN, SCTP_BASE_VAR(udp_recvmbuf6));
1229}
1230#endif
1231#endif
1232
1233#if defined(INET6)
1234static void *
1235recv_function_udp6(void *arg)
1236{
1237 struct mbuf **udprecvmbuf6;
1238 /*Initially the entire set of mbufs is to be allocated.
1239 to_fill indicates this amount. */
1240 int to_fill = MAXLEN_MBUF_CHAIN;
1241 /* iovlen is the size of each mbuf in the chain */
1242 int i;
1243 int iovlen = MCLBYTES;
1244 int want_ext = (iovlen > MLEN)? 1 : 0;
1245 int want_header = 0;
1246#if !defined(__Userspace_os_Windows)
1247 struct iovec iov[MAXLEN_MBUF_CHAIN];
1248#else
1249 WSABUF iov[MAXLEN_MBUF_CHAIN];
1250#endif
1251
1252 sctp_userspace_set_threadname("SCTP/UDP/IP6 rcv");
1253
1254 udprecvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
1255 while (1) {
1256 for (i = 0; i < to_fill; i++) {
1257 /* Not getting the packet header. Tests with chain of one run
1258 as usual without having the packet header.
1259 Have tried both sending and receiving
1260 */
1261 udprecvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
1262#if !defined(__Userspace_os_Windows)
1263 iov[i].iov_base = (caddr_t)udprecvmbuf6[i]->m_data;
1264 iov[i].iov_len = iovlen;
1265#else
1266 iov[i].buf = (caddr_t)udprecvmbuf6[i]->m_data;
1267 iov[i].len = iovlen;
1268#endif
1269 }
1270 to_fill = recv_udp6(iov, MAXLEN_MBUF_CHAIN, udprecvmbuf6);
1271 if (to_fill < 0) {
1272 break;
1273 }
1274 }
1275 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
1276 m_free(udprecvmbuf6[i]);
1277 }
1278 /* free the array itself */
1279 free(udprecvmbuf6);
1280 return (NULL);
1281}
1282#endif
1283
1284#if defined (__Userspace_os_Windows)
1285static void
1286setReceiveBufferSize(SOCKET sfd, int new_size)
1287#else
1288static void
1289setReceiveBufferSize(int sfd, int new_size)
1290#endif
1291{
1292 int ch = new_size;
1293
1294 if (setsockopt (sfd, SOL_SOCKET, SO_RCVBUF, (void*)&ch, sizeof(ch)) < 0) {
1295#if defined (__Userspace_os_Windows)
1296 SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", WSAGetLastError());
1297#else
1298 SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", errno);
1299#endif
1300 }
1301 return;
1302}
1303
1304#if defined (__Userspace_os_Windows)
1305static void
1306setSendBufferSize(SOCKET sfd, int new_size)
1307#else
1308static void
1309setSendBufferSize(int sfd, int new_size)
1310#endif
1311{
1312 int ch = new_size;
1313
1314 if (setsockopt (sfd, SOL_SOCKET, SO_SNDBUF, (void*)&ch, sizeof(ch)) < 0) {
1315#if defined (__Userspace_os_Windows)
1316 SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", WSAGetLastError());
1317#else
1318 SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", errno);
1319#endif
1320 }
1321 return;
1322}
1323
1324#define SOCKET_TIMEOUT 100 /* in ms */
1325#if defined(INET)
1326int open_sctp4_socket(void)
1327{
1328 int sctp4_fd = -1;
1329 struct sockaddr_in addr_ipv4;
1330 const int hdrincl = 1;
1331
1332#if !defined(__Userspace_os_Windows)
1333 struct timeval timeout;
1334
1335 memset(&timeout, 0, sizeof(struct timeval));
1336 timeout.tv_sec = (SOCKET_TIMEOUT / 1000);
1337 timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
1338#else
1339 unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */
1340#endif
1341
1342 if ((sctp4_fd = socket(AF_INET, SOCK_RAW, IPPROTO_SCTP)) < 0) {
1343#if defined(__Userspace_os_Windows)
1344 SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", WSAGetLastError());
1345#else
1346 SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", errno);
1347#endif
1348 } else {
1349 /* complete setting up the raw SCTP socket */
1350 if (setsockopt(sctp4_fd, IPPROTO_IP, IP_HDRINCL,(const void*)&hdrincl, sizeof(int)) < 0) {
1351#if defined(__Userspace_os_Windows)
1352 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", WSAGetLastError());
1353 closesocket(sctp4_fd);
1354#else
1355 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", errno);
1356 close(sctp4_fd);
1357#endif
1358 sctp4_fd = -1;
1359 } else if (setsockopt(sctp4_fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
1360#if defined(__Userspace_os_Windows)
1361 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError());
1362 closesocket(sctp4_fd);
1363#else
1364 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", errno);
1365 close(sctp4_fd);
1366#endif
1367 sctp4_fd = -1;
1368 } else {
1369 memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in));
1370#ifdef HAVE_SIN_LEN
1371 addr_ipv4.sin_len = sizeof(struct sockaddr_in);
1372#endif
1373 addr_ipv4.sin_family = AF_INET;
1374 addr_ipv4.sin_port = htons(0);
1375 addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
1376 if (bind(sctp4_fd, (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) {
1377#if defined(__Userspace_os_Windows)
1378 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError());
1379 closesocket(sctp4_fd);
1380#else
1381 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", errno);
1382 close(sctp4_fd);
1383#endif
1384 sctp4_fd = -1;
1385 } else {
1386 setReceiveBufferSize(sctp4_fd, SB_RAW); /* 128K */
1387 setSendBufferSize(sctp4_fd, SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
1388 }
1389 }
1390 }
1391 return sctp4_fd;
1392}
1393#endif
1394
1395#if defined(INET)
1396int usrsctp_open_sctp4_socket(void)
1397{
1398 int sctp4_fd = -1;
1399 sctp4_fd = open_sctp4_socket();
1400 SCTP_BASE_VAR(userspace_rawsctp) = sctp4_fd;
1401 return sctp4_fd;
1402}
1403#endif
1404
1405
1406#if defined(INET)
1407int open_udpsctp4_socket(void)
1408{
1409 int udpsctp4_fd = -1;
1410 struct sockaddr_in addr_ipv4;
1411 const int on = 1;
1412#if !defined(__Userspace_os_Windows)
1413 struct timeval timeout;
1414
1415 memset(&timeout, 0, sizeof(struct timeval));
1416 timeout.tv_sec = (SOCKET_TIMEOUT / 1000);
1417 timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
1418#else
1419 unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */
1420#endif
1421
1422 if ((udpsctp4_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
1423#if defined(__Userspace_os_Windows)
1424 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
1425#else
1426 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
1427#endif
1428 } else {
1429#if defined(IP_PKTINFO)
1430 if (setsockopt(udpsctp4_fd, IPPROTO_IP, IP_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
1431#else
1432 if (setsockopt(udpsctp4_fd, IPPROTO_IP, IP_RECVDSTADDR, (const void *)&on, (int)sizeof(int)) < 0) {
1433#endif
1434#if defined(__Userspace_os_Windows)
1435#if defined(IP_PKTINFO)
1436 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
1437#else
1438 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
1439#endif
1440 closesocket(udpsctp4_fd);
1441#else
1442#if defined(IP_PKTINFO)
1443 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
1444#else
1445 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
1446#endif
1447 close(udpsctp4_fd);
1448#endif
1449 udpsctp4_fd = -1;
1450 } else if (setsockopt(udpsctp4_fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
1451#if defined(__Userspace_os_Windows)
1452 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
1453 closesocket(udpsctp4_fd);
1454#else
1455 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
1456 close(udpsctp4_fd);
1457#endif
1458 udpsctp4_fd = -1;
1459 } else {
1460 memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in));
1461#ifdef HAVE_SIN_LEN
1462 addr_ipv4.sin_len = sizeof(struct sockaddr_in);
1463#endif
1464 addr_ipv4.sin_family = AF_INET;
1465 addr_ipv4.sin_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
1466 addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
1467 if (bind(udpsctp4_fd, (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) {
1468#if defined(__Userspace_os_Windows)
1469 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
1470 closesocket(udpsctp4_fd);
1471#else
1472 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
1473 close(udpsctp4_fd);
1474#endif
1475 udpsctp4_fd = -1;
1476 } else {
1477 setReceiveBufferSize(udpsctp4_fd, SB_RAW); /* 128K */
1478 setSendBufferSize(udpsctp4_fd, SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
1479 }
1480 }
1481 }
1482 return udpsctp4_fd;
1483}
1484#endif
1485
1486#if defined(INET)
1487int usrsctp_open_udpsctp4_socket(void)
1488{
1489 int udpsctp4_fd = -1;
1490 udpsctp4_fd = open_udpsctp4_socket();
1491 SCTP_BASE_VAR(userspace_udpsctp) = udpsctp4_fd;
1492 return udpsctp4_fd;
1493}
1494#endif
1495
1496#if defined(INET6)
1497int
1498open_sctp6_socket(void)
1499{
1500 int sctp6_fd = -1;
1501 struct sockaddr_in6 addr_ipv6;
1502 const int on = 1;
1503#if !defined(__Userspace_os_Windows)
1504 struct timeval timeout;
1505
1506 memset(&timeout, 0, sizeof(struct timeval));
1507 timeout.tv_sec = (SOCKET_TIMEOUT / 1000);
1508 timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
1509#else
1510 unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */
1511#endif
1512
1513 if ((sctp6_fd = socket(AF_INET6, SOCK_RAW, IPPROTO_SCTP)) < 0) {
1514#if defined(__Userspace_os_Windows)
1515 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1516#else
1517 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", errno);
1518#endif
1519 } else {
1520 /* complete setting up the raw SCTP socket */
1521#if defined(IPV6_RECVPKTINFO)
1522 if (setsockopt(sctp6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, sizeof(on)) < 0) {
1523#if defined(__Userspace_os_Windows)
1524 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1525 closesocket(sctp6_fd);
1526#else
1527 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno);
1528 close(sctp6_fd);
1529#endif
1530 sctp6_fd = -1;
1531 } else {
1532#else
1533 if (setsockopt(sctp6_fd, IPPROTO_IPV6, IPV6_PKTINFO,(const void*)&on, sizeof(on)) < 0) {
1534#if defined(__Userspace_os_Windows)
1535 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1536 closesocket(sctp6_fd);
1537#else
1538 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno);
1539 close(sctp6_fd);
1540#endif
1541 sctp6_fd = -1;
1542 } else {
1543#endif
1544 if (setsockopt(sctp6_fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&on, (socklen_t)sizeof(on)) < 0) {
1545#if defined(__Userspace_os_Windows)
1546 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1547#else
1548 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", errno);
1549#endif
1550 }
1551 if (setsockopt(sctp6_fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
1552#if defined(__Userspace_os_Windows)
1553 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1554 closesocket(sctp6_fd);
1555#else
1556 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", errno);
1557 close(sctp6_fd);
1558#endif
1559 sctp6_fd = -1;
1560 } else {
1561 memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6));
1562#ifdef HAVE_SIN6_LEN
1563 addr_ipv6.sin6_len = sizeof(struct sockaddr_in6);
1564#endif
1565 addr_ipv6.sin6_family = AF_INET6;
1566 addr_ipv6.sin6_port = htons(0);
1567 addr_ipv6.sin6_addr = in6addr_any;
1568 if (bind(sctp6_fd, (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) {
1569#if defined(__Userspace_os_Windows)
1570 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1571 closesocket(sctp6_fd);
1572#else
1573 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", errno);
1574 close(sctp6_fd);
1575#endif
1576 sctp6_fd = -1;
1577 } else {
1578 setReceiveBufferSize(sctp6_fd, SB_RAW); /* 128K */
1579 setSendBufferSize(sctp6_fd, SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
1580 }
1581 }
1582 }
1583 }
1584 return sctp6_fd;
1585}
1586#endif
1587
1588#if defined(INET6)
1589int
1590usrsctp_open_sctp6_socket(void)
1591{
1592 int sctp6_fd = -1;
1593 sctp6_fd = open_sctp6_socket();
1594 SCTP_BASE_VAR(userspace_rawsctp6) = sctp6_fd;
1595 return sctp6_fd;
1596}
1597#endif
1598
1599#if defined(INET6)
1600int
1601open_udpsctp6_socket(void)
1602{
1603 int udpsctp6_fd = -1;
1604 struct sockaddr_in6 addr_ipv6;
1605 const int on = 1;
1606#if !defined(__Userspace_os_Windows)
1607 struct timeval timeout;
1608
1609 memset(&timeout, 0, sizeof(struct timeval));
1610 timeout.tv_sec = (SOCKET_TIMEOUT / 1000);
1611 timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
1612#else
1613 unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */
1614#endif
1615
1616 if ((udpsctp6_fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
1617#if defined(__Userspace_os_Windows)
1618 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1619#else
1620 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1621#endif
1622 }
1623#if defined(IPV6_RECVPKTINFO)
1624 if (setsockopt(udpsctp6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
1625#if defined(__Userspace_os_Windows)
1626 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1627 closesocket(udpsctp6_fd);
1628#else
1629 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1630 close(udpsctp6_fd);
1631#endif
1632 udpsctp6_fd = -1;
1633 } else {
1634#else
1635 if (setsockopt(udpsctp6_fd, IPPROTO_IPV6, IPV6_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
1636#if defined(__Userspace_os_Windows)
1637 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1638 closesocket(udpsctp6_fd);
1639#else
1640 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1641 close(udpsctp6_fd);
1642#endif
1643 udpsctp6_fd = -1;
1644 } else {
1645#endif
1646 if (setsockopt(udpsctp6_fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&on, (socklen_t)sizeof(on)) < 0) {
1647#if defined(__Userspace_os_Windows)
1648 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1649#else
1650 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1651#endif
1652 }
1653 if (setsockopt(udpsctp6_fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
1654#if defined(__Userspace_os_Windows)
1655 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1656 closesocket(udpsctp6_fd);
1657#else
1658 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1659 close(udpsctp6_fd);
1660#endif
1661 udpsctp6_fd = -1;
1662 } else {
1663 memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6));
1664#ifdef HAVE_SIN6_LEN
1665 addr_ipv6.sin6_len = sizeof(struct sockaddr_in6);
1666#endif
1667 addr_ipv6.sin6_family = AF_INET6;
1668 addr_ipv6.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
1669 addr_ipv6.sin6_addr = in6addr_any;
1670 if (bind(udpsctp6_fd, (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) {
1671#if defined(__Userspace_os_Windows)
1672 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1673 closesocket(udpsctp6_fd);
1674#else
1675 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1676 close(udpsctp6_fd);
1677#endif
1678 udpsctp6_fd = -1;
1679 } else {
1680 setReceiveBufferSize(udpsctp6_fd, SB_RAW); /* 128K */
1681 setSendBufferSize(udpsctp6_fd, SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
1682 }
1683 }
1684 }
1685 return udpsctp6_fd;
1686}
1687#endif
1688
1689#if defined(INET6)
1690int usrsctp_open_udpsctp6_socket(void)
1691{
1692 int udpsctp6_fd = -1;
1693 udpsctp6_fd = open_udpsctp6_socket();
1694 SCTP_BASE_VAR(userspace_udpsctp6) = udpsctp6_fd;
1695 return udpsctp6_fd;
1696}
1697#endif
1698
1699void
1700recv_thread_init(void)
1701{
1702#if !defined(__Userspace_os_Windows)
1703 struct timeval timeout;
1704
1705 memset(&timeout, 0, sizeof(struct timeval));
1706 timeout.tv_sec = (SOCKET_TIMEOUT / 1000);
1707 timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
1708#else
1709 unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */
1710#endif
1711#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
1712 if (SCTP_BASE_VAR(userspace_route) == -1) {
1713 if ((SCTP_BASE_VAR(userspace_route) = socket(AF_ROUTE, SOCK_RAW, 0)) < 0) {
1714 SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d).\n", errno);
1715 }
1716#if 0
1717 struct sockaddr_nl sanl;
1718
1719 if ((SCTP_BASE_VAR(userspace_route) = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
1720 SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d.\n", errno);
1721 }
1722 memset(&sanl, 0, sizeof(sanl));
1723 sanl.nl_family = AF_NETLINK;
1724 sanl.nl_groups = 0;
1725#ifdef INET
1726 sanl.nl_groups |= RTMGRP_IPV4_IFADDR;
1727#endif
1728#ifdef INET6
1729 sanl.nl_groups |= RTMGRP_IPV6_IFADDR;
1730#endif
1731 if (bind(SCTP_BASE_VAR(userspace_route), (struct sockaddr *) &sanl, sizeof(sanl)) < 0) {
1732 SCTPDBG(SCTP_DEBUG_USR, "Can't bind routing socket (errno = %d).\n", errno);
1733 close(SCTP_BASE_VAR(userspace_route));
1734 SCTP_BASE_VAR(userspace_route) = -1;
1735 }
1736#endif
1737 if (SCTP_BASE_VAR(userspace_route) != -1) {
1738 if (setsockopt(SCTP_BASE_VAR(userspace_route), SOL_SOCKET, SO_RCVTIMEO,(const void*)&timeout, sizeof(struct timeval)) < 0) {
1739 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on routing socket (errno = %d).\n", errno);
1740#if defined(__Userspace_os_Windows)
1741 closesocket(SCTP_BASE_VAR(userspace_route));
1742#else
1743 close(SCTP_BASE_VAR(userspace_route));
1744#endif
1745 SCTP_BASE_VAR(userspace_route) = -1;
1746 }
1747 }
1748 }
1749#endif
1750#if defined(INET)
1751 if (SCTP_BASE_VAR(userspace_rawsctp) == -1) {
1752 SCTP_BASE_VAR(userspace_rawsctp) = open_sctp4_socket();
1753 }
1754
1755 if (SCTP_BASE_VAR(userspace_udpsctp) == -1) {
1756 SCTP_BASE_VAR(userspace_udpsctp) = open_udpsctp4_socket();
1757 }
1758#endif
1759#if defined(INET6)
1760 if (SCTP_BASE_VAR(userspace_rawsctp6) == -1) {
1761 SCTP_BASE_VAR(userspace_rawsctp6) = open_sctp6_socket();
1762 }
1763 if (SCTP_BASE_VAR(userspace_udpsctp6) == -1) {
1764 SCTP_BASE_VAR(userspace_udpsctp6) = open_udpsctp6_socket();
1765 }
1766#endif
1767
1768#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
1769#if defined(INET) || defined(INET6)
1770 if (SCTP_BASE_VAR(userspace_route) != -1) {
1771 int rc;
1772
1773 if ((rc = sctp_userspace_thread_create(&SCTP_BASE_VAR(recvthreadroute), &recv_function_route))) {
1774 SCTPDBG(SCTP_DEBUG_USR, "Can't start routing thread (%d).\n", rc);
1775 close(SCTP_BASE_VAR(userspace_route));
1776 SCTP_BASE_VAR(userspace_route) = -1;
1777 }
1778 }
1779#endif
1780#endif
1781#if defined(INET)
1782 if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
1783 int rc;
1784
1785 if ((rc = sctp_userspace_thread_create(&SCTP_BASE_VAR(recvthreadraw), &recv_function_raw))) {
1786 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread (%d).\n", rc);
1787#if defined(__Userspace_os_Windows)
1788 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
1789#else
1790 close(SCTP_BASE_VAR(userspace_rawsctp));
1791#endif
1792 SCTP_BASE_VAR(userspace_rawsctp) = -1;
1793 }
1794 }
1795 if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
1796 int rc;
1797
1798 if ((rc = sctp_userspace_thread_create(&SCTP_BASE_VAR(recvthreadudp), &recv_function_udp))) {
1799 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread (%d).\n", rc);
1800#if defined(__Userspace_os_Windows)
1801 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
1802#else
1803 close(SCTP_BASE_VAR(userspace_udpsctp));
1804#endif
1805 SCTP_BASE_VAR(userspace_udpsctp) = -1;
1806 }
1807 }
1808#endif
1809#if defined(INET6)
1810 if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
1811 int rc;
1812
1813 if ((rc = sctp_userspace_thread_create(&SCTP_BASE_VAR(recvthreadraw6), &recv_function_raw6))) {
1814 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread (%d).\n", rc);
1815#if defined(__Userspace_os_Windows)
1816 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
1817#else
1818 close(SCTP_BASE_VAR(userspace_rawsctp6));
1819#endif
1820 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
1821 }
1822 }
1823 if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
1824 int rc;
1825
1826 if ((rc = sctp_userspace_thread_create(&SCTP_BASE_VAR(recvthreadudp6), &recv_function_udp6))) {
1827 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread (%d).\n", rc);
1828#if defined(__Userspace_os_Windows)
1829 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1830#else
1831 close(SCTP_BASE_VAR(userspace_udpsctp6));
1832#endif
1833 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1834 }
1835 }
1836#endif
1837}
1838
1839void
1840recv_thread_destroy(void)
1841{
1842#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
1843#if defined(INET) || defined(INET6)
1844 if (SCTP_BASE_VAR(userspace_route) != -1) {
1845 close(SCTP_BASE_VAR(userspace_route));
1846 }
1847#endif
1848#endif
1849#if defined(INET)
1850 if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
1851#if defined(__Userspace_os_Windows)
1852 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
1853#else
1854 close(SCTP_BASE_VAR(userspace_rawsctp));
1855#endif
1856 }
1857 if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
1858#if defined(__Userspace_os_Windows)
1859 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
1860#else
1861 close(SCTP_BASE_VAR(userspace_udpsctp));
1862#endif
1863 }
1864#endif
1865#if defined(INET6)
1866 if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
1867#if defined(__Userspace_os_Windows)
1868 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
1869#else
1870 close(SCTP_BASE_VAR(userspace_rawsctp6));
1871#endif
1872 }
1873 if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
1874#if defined(__Userspace_os_Windows)
1875 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1876#else
1877 close(SCTP_BASE_VAR(userspace_udpsctp6));
1878#endif
1879 }
1880#endif
1881}
1882#else
1883int foo;
1884#endif