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
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
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>
38 #if !defined(__Userspace_os_DragonFly) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_NetBSD)
41 #include <user_ip6_var.h>
44 #include <netinet/sctp_os.h>
45 #include <netinet/sctp_var.h>
46 #include <netinet/sctp_pcb.h>
47 #include <netinet/sctp_input.h>
49 #if defined(__Userspace_os_Linux)
50 #include <linux/netlink.h>
51 #ifdef HAVE_LINUX_IF_ADDR_H
52 #include <linux/if_addr.h>
54 #ifdef HAVE_LINUX_RTNETLINK_H
55 #include <linux/rtnetlink.h>
59 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
60 #include <net/route.h>
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"
67 void 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)))
75 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
77 sctp_get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
81 for (i = 0; i < RTAX_MAX; i++) {
82 if (addrs & (1 << i)) {
92 sctp_handle_ifamsg(unsigned char type, unsigned short index, struct sockaddr *sa)
95 struct ifaddrs *ifa, *found_ifa = NULL;
97 /* handle only the types we want */
98 if ((type != RTM_NEWADDR) && (type != RTM_DELADDR)) {
102 rc = getifaddrs(&g_interfaces);
106 for (ifa = g_interfaces; ifa; ifa = ifa->ifa_next) {
107 if (index == if_nametoindex(ifa->ifa_name)) {
112 if (found_ifa == NULL) {
116 switch (sa->sa_family) {
119 ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
120 memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in));
125 ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in6));
126 memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in6));
130 SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", sa->sa_family);
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),
143 sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
144 if_nametoindex(ifa->ifa_name),
150 recv_function_route(void *arg)
153 struct ifa_msghdr *ifa;
154 char rt_buffer[1024];
155 struct sockaddr *sa, *rti_info[RTAX_MAX];
158 bzero(rt_buffer, sizeof(rt_buffer));
159 ret = recv(SCTP_BASE_VAR(userspace_route), rt_buffer, sizeof(rt_buffer), 0);
162 ifa = (struct ifa_msghdr *) rt_buffer;
163 if (ifa->ifam_type != RTM_DELADDR && ifa->ifam_type != RTM_NEWADDR) {
166 sa = (struct sockaddr *) (ifa + 1);
167 sctp_get_rtaddrs(ifa->ifam_addrs, sa, rti_info);
168 switch (ifa->ifam_type) {
171 sctp_handle_ifamsg(ifa->ifam_type, ifa->ifam_index, rti_info[RTAX_IFA]);
174 /* ignore this routing event */
179 if (errno == EAGAIN) {
191 /* This does not yet work on Linux */
193 recv_function_route(void *arg)
197 struct iovec iov = { buf, sizeof(buf) };
200 struct ifaddrmsg *rtmsg;
201 struct rtattr *rtatp;
203 struct sockaddr_nl sanl;
205 struct sockaddr_in *sa;
208 struct sockaddr_in6 *sa6;
212 memset(&sanl, 0, sizeof(sanl));
213 sanl.nl_family = AF_NETLINK;
214 sanl.nl_groups = RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_IFADDR;
215 memset(&msg, 0, sizeof(struct msghdr));
216 msg.msg_name = (void *)&sanl;
217 msg.msg_namelen = sizeof(sanl);
220 msg.msg_control = NULL;
221 msg.msg_controllen = 0;
223 len = recvmsg(SCTP_BASE_VAR(userspace_route), &msg, 0);
226 if (errno == EAGAIN) {
232 for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len);
233 nh = NLMSG_NEXT (nh, len)) {
234 if (nh->nlmsg_type == NLMSG_DONE)
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) {
245 sa = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
246 sa->sin_family = rtmsg->ifa_family;
248 memcpy(&sa->sin_addr, inp, sizeof(struct in_addr));
249 sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa);
254 sa6 = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6));
255 sa6->sin6_family = rtmsg->ifa_family;
257 memcpy(&sa6->sin6_addr, inp, sizeof(struct in6_addr));
258 sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa6);
262 SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", rtmsg->ifa_family);
275 recv_function_raw(void *arg)
277 struct mbuf **recvmbuf;
282 #if !defined(SCTP_WITH_NO_CSUM)
285 struct sctp_chunkhdr *ch;
286 struct sockaddr_in src, dst;
287 #if !defined(__Userspace_os_Windows)
289 struct iovec recv_iovec[MAXLEN_MBUF_CHAIN];
291 WSABUF recv_iovec[MAXLEN_MBUF_CHAIN];
292 int nResult, m_ErrorCode;
294 struct sockaddr_in from;
298 /*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 */
302 int i, n, ncounter = 0;
303 int iovlen = MCLBYTES;
304 int want_ext = (iovlen > MLEN)? 1 : 0;
307 bzero((void *)&src, sizeof(struct sockaddr_in));
308 bzero((void *)&dst, sizeof(struct sockaddr_in));
310 recvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
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
318 recvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
319 #if !defined(__Userspace_os_Windows)
320 recv_iovec[i].iov_base = (caddr_t)recvmbuf[i]->m_data;
321 recv_iovec[i].iov_len = iovlen;
323 recv_iovec[i].buf = (caddr_t)recvmbuf[i]->m_data;
324 recv_iovec[i].len = iovlen;
328 #if defined(__Userspace_os_Windows)
331 fromlen = sizeof(struct sockaddr_in);
332 bzero((void *)&from, sizeof(struct sockaddr_in));
334 nResult = WSARecvFrom(SCTP_BASE_VAR(userspace_rawsctp), recv_iovec, MAXLEN_MBUF_CHAIN, (LPDWORD)&ncounter, (LPDWORD)&flags, (struct sockaddr*)&from, &fromlen, NULL, NULL);
336 m_ErrorCode = WSAGetLastError();
337 if (m_ErrorCode == WSAETIMEDOUT) {
340 if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
346 bzero((void *)&msg, sizeof(struct msghdr));
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);
355 if (errno == EAGAIN) {
362 SCTP_HEADER_LEN(recvmbuf[0]) = n; /* length of total packet */
363 SCTP_STAT_INCR(sctps_recvpackets);
364 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
367 SCTP_BUF_LEN(recvmbuf[0]) = n;
371 SCTP_BUF_LEN(recvmbuf[0]) = iovlen;
376 recvmbuf[i]->m_next = recvmbuf[i+1];
377 SCTP_BUF_LEN(recvmbuf[i]->m_next) = min(ncounter, iovlen);
381 } while (ncounter > 0);
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);
389 if (iphdr->ip_tos != 0) {
390 ecn = iphdr->ip_tos & 0x02;
393 dst.sin_family = AF_INET;
395 dst.sin_len = sizeof(struct sockaddr_in);
397 dst.sin_addr = iphdr->ip_dst;
398 dst.sin_port = sh->dest_port;
400 src.sin_family = AF_INET;
402 src.sin_len = sizeof(struct sockaddr_in);
404 src.sin_addr = iphdr->ip_src;
405 src.sin_port = sh->src_port;
407 /* SCTP does not allow broadcasts or multicasts */
408 if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
411 if (SCTP_IS_IT_BROADCAST(dst.sin_addr, recvmbuf[0])) {
417 #if defined(SCTP_WITH_NO_CSUM)
418 SCTP_STAT_INCR(sctps_recvnocrc);
420 if (src.sin_addr.s_addr == dst.sin_addr.s_addr) {
422 SCTP_STAT_INCR(sctps_recvnocrc);
424 SCTP_STAT_INCR(sctps_recvswcrc);
427 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
428 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
429 sctp_common_input_processing(&recvmbuf[0], sizeof(struct ip), offset, n,
430 (struct sockaddr *)&src,
431 (struct sockaddr *)&dst,
433 #if !defined(SCTP_WITH_NO_CSUM)
437 SCTP_DEFAULT_VRFID, port);
439 m_freem(recvmbuf[0]);
442 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
445 /* free the array itself */
453 recv_function_raw6(void *arg)
455 struct mbuf **recvmbuf6;
456 #if !defined(__Userspace_os_Windows)
457 struct iovec recv_iovec[MAXLEN_MBUF_CHAIN];
459 struct cmsghdr *cmsgptr;
460 char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
462 WSABUF recv_iovec[MAXLEN_MBUF_CHAIN];
463 int nResult, m_ErrorCode;
465 struct sockaddr_in6 from;
467 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
468 LPFN_WSARECVMSG WSARecvMsg;
471 char ControlBuffer[1024];
473 struct sockaddr_in6 src, dst;
476 struct sctp_chunkhdr *ch;
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 */
482 int i, n, ncounter = 0;
483 #if !defined(SCTP_WITH_NO_CSUM)
486 int iovlen = MCLBYTES;
487 int want_ext = (iovlen > MLEN)? 1 : 0;
490 recvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
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
498 recvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
499 #if !defined(__Userspace_os_Windows)
500 recv_iovec[i].iov_base = (caddr_t)recvmbuf6[i]->m_data;
501 recv_iovec[i].iov_len = iovlen;
503 recv_iovec[i].buf = (caddr_t)recvmbuf6[i]->m_data;
504 recv_iovec[i].len = iovlen;
508 #if defined(__Userspace_os_Windows)
511 fromlen = sizeof(struct sockaddr_in6);
512 bzero((void *)&from, sizeof(struct sockaddr_in6));
513 nResult = WSAIoctl(SCTP_BASE_VAR(userspace_rawsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER,
514 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
515 &WSARecvMsg, sizeof WSARecvMsg,
516 &ncounter, NULL, NULL);
518 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;
525 nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, &ncounter, NULL, NULL);
528 m_ErrorCode = WSAGetLastError();
529 if (m_ErrorCode == WSAETIMEDOUT)
531 if (m_ErrorCode == WSAENOTSOCK || m_ErrorCode == WSAEINTR)
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));
548 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, 0);
550 if (errno == EAGAIN) {
557 SCTP_HEADER_LEN(recvmbuf6[0]) = n; /* length of total packet */
558 SCTP_STAT_INCR(sctps_recvpackets);
559 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
562 SCTP_BUF_LEN(recvmbuf6[0]) = n;
566 SCTP_BUF_LEN(recvmbuf6[0]) = iovlen;
571 recvmbuf6[i]->m_next = recvmbuf6[i+1];
572 SCTP_BUF_LEN(recvmbuf6[i]->m_next) = min(ncounter, iovlen);
576 } while (ncounter > 0);
579 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
580 if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) {
581 struct in6_pktinfo * info;
583 info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
584 memcpy((void *)&dst.sin6_addr, (const void *) &(info->ipi6_addr), sizeof(struct in6_addr));
589 sh = mtod(recvmbuf6[0], struct sctphdr *);
590 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
591 offset = sizeof(struct sctphdr);
593 dst.sin6_family = AF_INET6;
595 dst.sin6_len = sizeof(struct sockaddr_in6);
597 dst.sin6_port = sh->dest_port;
599 src.sin6_family = AF_INET6;
601 src.sin6_len = sizeof(struct sockaddr_in6);
603 src.sin6_port = sh->src_port;
604 #if defined(SCTP_WITH_NO_CSUM)
605 SCTP_STAT_INCR(sctps_recvnocrc);
607 if (memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0) {
609 SCTP_STAT_INCR(sctps_recvnocrc);
611 SCTP_STAT_INCR(sctps_recvswcrc);
614 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
615 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
616 sctp_common_input_processing(&recvmbuf6[0], 0, offset, n,
617 (struct sockaddr *)&src,
618 (struct sockaddr *)&dst,
620 #if !defined(SCTP_WITH_NO_CSUM)
624 SCTP_DEFAULT_VRFID, 0);
626 m_freem(recvmbuf6[0]);
629 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
630 m_free(recvmbuf6[i]);
632 /* free the array itself */
640 recv_function_udp(void *arg)
642 struct mbuf **udprecvmbuf;
643 /*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 */
647 int i, n, ncounter, offset;
648 int iovlen = MCLBYTES;
649 int want_ext = (iovlen > MLEN)? 1 : 0;
653 struct sctp_chunkhdr *ch;
654 struct sockaddr_in src, dst;
655 #if defined(IP_PKTINFO)
656 char cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))];
658 char cmsgbuf[CMSG_SPACE(sizeof(struct in_addr))];
660 #if !defined(SCTP_WITH_NO_CSUM)
663 #if !defined(__Userspace_os_Windows)
664 struct iovec iov[MAXLEN_MBUF_CHAIN];
666 struct cmsghdr *cmsgptr;
668 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
669 LPFN_WSARECVMSG WSARecvMsg;
670 char ControlBuffer[1024];
671 WSABUF iov[MAXLEN_MBUF_CHAIN];
673 int nResult, m_ErrorCode;
677 udprecvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
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
685 udprecvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
686 #if !defined(__Userspace_os_Windows)
687 iov[i].iov_base = (caddr_t)udprecvmbuf[i]->m_data;
688 iov[i].iov_len = iovlen;
690 iov[i].buf = (caddr_t)udprecvmbuf[i]->m_data;
695 #if !defined(__Userspace_os_Windows)
696 bzero((void *)&msg, sizeof(struct msghdr));
698 bzero((void *)&msg, sizeof(WSAMSG));
700 bzero((void *)&src, sizeof(struct sockaddr_in));
701 bzero((void *)&dst, sizeof(struct sockaddr_in));
702 bzero((void *)cmsgbuf, sizeof(cmsgbuf));
704 #if !defined(__Userspace_os_Windows)
705 msg.msg_name = (void *)&src;
706 msg.msg_namelen = sizeof(struct sockaddr_in);
708 msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
709 msg.msg_control = (void *)cmsgbuf;
710 msg.msg_controllen = sizeof(cmsgbuf);
713 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, 0);
715 if (errno == EAGAIN) {
722 nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp), SIO_GET_EXTENSION_FUNCTION_POINTER,
723 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
724 &WSARecvMsg, sizeof WSARecvMsg,
725 &ncounter, NULL, NULL);
727 msg.name = (void *)&src;
728 msg.namelen = sizeof(struct sockaddr_in);
730 msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
731 msg.Control.len = sizeof ControlBuffer;
732 msg.Control.buf = ControlBuffer;
734 nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, &ncounter, NULL, NULL);
737 m_ErrorCode = WSAGetLastError();
738 if (m_ErrorCode == WSAETIMEDOUT) {
741 if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
747 SCTP_HEADER_LEN(udprecvmbuf[0]) = n; /* length of total packet */
748 SCTP_STAT_INCR(sctps_recvpackets);
749 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
752 SCTP_BUF_LEN(udprecvmbuf[0]) = n;
756 SCTP_BUF_LEN(udprecvmbuf[0]) = iovlen;
761 udprecvmbuf[i]->m_next = udprecvmbuf[i+1];
762 SCTP_BUF_LEN(udprecvmbuf[i]->m_next) = min(ncounter, iovlen);
766 } while (ncounter > 0);
769 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
770 #if defined(IP_PKTINFO)
771 if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_PKTINFO)) {
772 struct in_pktinfo *info;
774 dst.sin_family = AF_INET;
776 dst.sin_len = sizeof(struct sockaddr_in);
778 info = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
779 memcpy((void *)&dst.sin_addr, (const void *)&(info->ipi_addr), sizeof(struct in_addr));
783 if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_RECVDSTADDR)) {
784 struct in_addr *addr;
786 dst.sin_family = AF_INET;
788 dst.sin_len = sizeof(struct sockaddr_in);
790 addr = (struct in_addr *)CMSG_DATA(cmsgptr);
791 memcpy((void *)&dst.sin_addr, (const void *)addr, sizeof(struct in_addr));
797 /* SCTP does not allow broadcasts or multicasts */
798 if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
801 if (SCTP_IS_IT_BROADCAST(dst.sin_addr, udprecvmbuf[0])) {
805 /*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);
810 src.sin_port = sh->src_port;
811 dst.sin_port = sh->dest_port;
812 #if defined(SCTP_WITH_NO_CSUM)
813 SCTP_STAT_INCR(sctps_recvnocrc);
815 if (src.sin_addr.s_addr == dst.sin_addr.s_addr) {
817 SCTP_STAT_INCR(sctps_recvnocrc);
819 SCTP_STAT_INCR(sctps_recvswcrc);
822 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
823 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
824 sctp_common_input_processing(&udprecvmbuf[0], 0, offset, n,
825 (struct sockaddr *)&src,
826 (struct sockaddr *)&dst,
828 #if !defined(SCTP_WITH_NO_CSUM)
832 SCTP_DEFAULT_VRFID, port);
833 if (udprecvmbuf[0]) {
834 m_freem(udprecvmbuf[0]);
837 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
838 m_free(udprecvmbuf[i]);
840 /* free the array itself */
848 recv_function_udp6(void *arg)
850 struct mbuf **udprecvmbuf6;
851 /*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;
859 struct sockaddr_in6 src, dst;
862 struct sctp_chunkhdr *ch;
863 char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
864 #if !defined(SCTP_WITH_NO_CSUM)
867 #if !defined(__Userspace_os_Windows)
868 struct iovec iov[MAXLEN_MBUF_CHAIN];
870 struct cmsghdr *cmsgptr;
872 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
873 LPFN_WSARECVMSG WSARecvMsg;
874 char ControlBuffer[1024];
875 WSABUF iov[MAXLEN_MBUF_CHAIN];
877 int nResult, m_ErrorCode;
881 udprecvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
883 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
888 udprecvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
889 #if !defined(__Userspace_os_Windows)
890 iov[i].iov_base = (caddr_t)udprecvmbuf6[i]->m_data;
891 iov[i].iov_len = iovlen;
893 iov[i].buf = (caddr_t)udprecvmbuf6[i]->m_data;
899 #if !defined(__Userspace_os_Windows)
900 bzero((void *)&msg, sizeof(struct msghdr));
902 bzero((void *)&msg, sizeof(WSAMSG));
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)));
908 #if !defined(__Userspace_os_Windows)
909 msg.msg_name = (void *)&src;
910 msg.msg_namelen = sizeof(struct sockaddr_in6);
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));
917 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, 0);
919 if (errno == EAGAIN) {
926 nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER,
927 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
928 &WSARecvMsg, sizeof WSARecvMsg,
929 &ncounter, NULL, NULL);
930 if (nResult == SOCKET_ERROR) {
931 m_ErrorCode = WSAGetLastError();
935 msg.name = (void *)&src;
936 msg.namelen = sizeof(struct sockaddr_in6);
938 msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
939 msg.Control.len = sizeof ControlBuffer;
940 msg.Control.buf = ControlBuffer;
942 nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, &ncounter, NULL, NULL);
945 m_ErrorCode = WSAGetLastError();
946 if (m_ErrorCode == WSAETIMEDOUT) {
949 if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
955 SCTP_HEADER_LEN(udprecvmbuf6[0]) = n; /* length of total packet */
956 SCTP_STAT_INCR(sctps_recvpackets);
957 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
960 SCTP_BUF_LEN(udprecvmbuf6[0]) = n;
964 SCTP_BUF_LEN(udprecvmbuf6[0]) = iovlen;
969 udprecvmbuf6[i]->m_next = udprecvmbuf6[i+1];
970 SCTP_BUF_LEN(udprecvmbuf6[i]->m_next) = min(ncounter, iovlen);
974 } while (ncounter > 0);
977 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
978 if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) {
979 struct in6_pktinfo *info;
981 dst.sin6_family = AF_INET6;
983 dst.sin6_len = sizeof(struct sockaddr_in6);
985 info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
986 /*dst.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));*/
987 memcpy((void *)&dst.sin6_addr, (const void *)&(info->ipi6_addr), sizeof(struct in6_addr));
991 /* SCTP does not allow broadcasts or multicasts */
992 if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) {
996 sh = mtod(udprecvmbuf6[0], struct sctphdr *);
997 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
998 offset = sizeof(struct sctphdr);
1000 port = src.sin6_port;
1001 src.sin6_port = sh->src_port;
1002 dst.sin6_port = sh->dest_port;
1003 #if defined(SCTP_WITH_NO_CSUM)
1004 SCTP_STAT_INCR(sctps_recvnocrc);
1006 if ((memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0)) {
1008 SCTP_STAT_INCR(sctps_recvnocrc);
1010 SCTP_STAT_INCR(sctps_recvswcrc);
1013 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
1014 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,
1016 (struct sockaddr *)&src,
1017 (struct sockaddr *)&dst,
1019 #if !defined(SCTP_WITH_NO_CSUM)
1023 SCTP_DEFAULT_VRFID, port);
1024 if (udprecvmbuf6[0]) {
1025 m_freem(udprecvmbuf6[0]);
1028 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
1029 m_free(udprecvmbuf6[i]);
1031 /* free the array itself */
1038 setReceiveBufferSize(int sfd, int new_size)
1042 if (setsockopt (sfd, SOL_SOCKET, SO_RCVBUF, (void*)&ch, sizeof(ch)) < 0) {
1043 #if defined (__Userspace_os_Windows)
1044 SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", WSAGetLastError());
1046 SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", errno);
1053 setSendBufferSize(int sfd, int new_size)
1057 if (setsockopt (sfd, SOL_SOCKET, SO_SNDBUF, (void*)&ch, sizeof(ch)) < 0) {
1058 #if defined (__Userspace_os_Windows)
1059 SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", WSAGetLastError());
1061 SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", errno);
1067 #define SOCKET_TIMEOUT 100 /* in ms */
1069 recv_thread_init(void)
1072 struct sockaddr_in addr_ipv4;
1073 const int hdrincl = 1;
1076 struct sockaddr_in6 addr_ipv6;
1078 #if defined(INET) || defined(INET6)
1081 #if !defined(__Userspace_os_Windows)
1082 struct timeval timeout;
1084 timeout.tv_sec = (SOCKET_TIMEOUT / 1000);
1085 timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
1087 unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */
1089 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
1090 if (SCTP_BASE_VAR(userspace_route) == -1) {
1091 if ((SCTP_BASE_VAR(userspace_route) = socket(AF_ROUTE, SOCK_RAW, 0)) < 0) {
1092 SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d).\n", errno);
1095 struct sockaddr_nl sanl;
1097 if ((SCTP_BASE_VAR(userspace_route) = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
1098 SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d.\n", errno);
1100 memset(&sanl, 0, sizeof(sanl));
1101 sanl.nl_family = AF_NETLINK;
1104 sanl.nl_groups |= RTMGRP_IPV4_IFADDR;
1107 sanl.nl_groups |= RTMGRP_IPV6_IFADDR;
1109 if (bind(SCTP_BASE_VAR(userspace_route), (struct sockaddr *) &sanl, sizeof(sanl)) < 0) {
1110 SCTPDBG(SCTP_DEBUG_USR, "Can't bind routing socket (errno = %d).\n", errno);
1111 close(SCTP_BASE_VAR(userspace_route));
1112 SCTP_BASE_VAR(userspace_route) = -1;
1115 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) {
1117 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on routing socket (errno = %d).\n", errno);
1118 #if defined(__Userspace_os_Windows)
1119 closesocket(SCTP_BASE_VAR(userspace_route));
1121 close(SCTP_BASE_VAR(userspace_route));
1123 SCTP_BASE_VAR(userspace_route) = -1;
1129 if (SCTP_BASE_VAR(userspace_rawsctp) == -1) {
1130 if ((SCTP_BASE_VAR(userspace_rawsctp) = socket(AF_INET, SOCK_RAW, IPPROTO_SCTP)) < 0) {
1131 #if defined(__Userspace_os_Windows)
1132 SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", WSAGetLastError());
1134 SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", errno);
1137 /* complete setting up the raw SCTP socket */
1138 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), IPPROTO_IP, IP_HDRINCL,(const void*)&hdrincl, sizeof(int)) < 0) {
1139 #if defined(__Userspace_os_Windows)
1140 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", WSAGetLastError());
1141 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
1143 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", errno);
1144 close(SCTP_BASE_VAR(userspace_rawsctp));
1146 SCTP_BASE_VAR(userspace_rawsctp) = -1;
1147 } else if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
1148 #if defined(__Userspace_os_Windows)
1149 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError());
1150 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
1152 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", errno);
1153 close(SCTP_BASE_VAR(userspace_rawsctp));
1155 SCTP_BASE_VAR(userspace_rawsctp) = -1;
1157 memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in));
1159 addr_ipv4.sin_len = sizeof(struct sockaddr_in);
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) {
1165 #if defined(__Userspace_os_Windows)
1166 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError());
1167 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
1169 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", errno);
1170 close(SCTP_BASE_VAR(userspace_rawsctp));
1172 SCTP_BASE_VAR(userspace_rawsctp) = -1;
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? */
1180 if (SCTP_BASE_VAR(userspace_udpsctp) == -1) {
1181 if ((SCTP_BASE_VAR(userspace_udpsctp) = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
1182 #if defined(__Userspace_os_Windows)
1183 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
1185 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
1188 #if defined(IP_PKTINFO)
1189 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
1191 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_RECVDSTADDR, (const void *)&on, (int)sizeof(int)) < 0) {
1193 #if defined(__Userspace_os_Windows)
1194 #if defined(IP_PKTINFO)
1195 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
1197 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
1199 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
1201 #if defined(IP_PKTINFO)
1202 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
1204 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
1206 close(SCTP_BASE_VAR(userspace_udpsctp));
1208 SCTP_BASE_VAR(userspace_udpsctp) = -1;
1209 } else if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
1210 #if defined(__Userspace_os_Windows)
1211 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
1212 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
1214 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
1215 close(SCTP_BASE_VAR(userspace_udpsctp));
1217 SCTP_BASE_VAR(userspace_udpsctp) = -1;
1219 memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in));
1221 addr_ipv4.sin_len = sizeof(struct sockaddr_in);
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) {
1227 #if defined(__Userspace_os_Windows)
1228 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
1229 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
1231 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
1232 close(SCTP_BASE_VAR(userspace_udpsctp));
1234 SCTP_BASE_VAR(userspace_udpsctp) = -1;
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? */
1244 if (SCTP_BASE_VAR(userspace_rawsctp6) == -1) {
1245 if ((SCTP_BASE_VAR(userspace_rawsctp6) = socket(AF_INET6, SOCK_RAW, IPPROTO_SCTP)) < 0) {
1246 #if defined(__Userspace_os_Windows)
1247 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1249 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", errno);
1252 /* complete setting up the raw SCTP socket */
1253 #if defined(IPV6_RECVPKTINFO)
1254 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, sizeof(on)) < 0) {
1255 #if defined(__Userspace_os_Windows)
1256 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1257 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
1259 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno);
1260 close(SCTP_BASE_VAR(userspace_rawsctp6));
1262 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
1265 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_PKTINFO,(const void*)&on, sizeof(on)) < 0) {
1266 #if defined(__Userspace_os_Windows)
1267 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1268 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
1270 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno);
1271 close(SCTP_BASE_VAR(userspace_rawsctp6));
1273 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
1276 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&on, (socklen_t)sizeof(on)) < 0) {
1277 #if defined(__Userspace_os_Windows)
1278 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1280 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", errno);
1283 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
1284 #if defined(__Userspace_os_Windows)
1285 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1286 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
1288 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", errno);
1289 close(SCTP_BASE_VAR(userspace_rawsctp6));
1291 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
1293 memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6));
1294 #ifdef HAVE_SIN6_LEN
1295 addr_ipv6.sin6_len = sizeof(struct sockaddr_in6);
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) {
1301 #if defined(__Userspace_os_Windows)
1302 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
1303 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
1305 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", errno);
1306 close(SCTP_BASE_VAR(userspace_rawsctp6));
1308 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
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? */
1317 if (SCTP_BASE_VAR(userspace_udpsctp6) == -1) {
1318 if ((SCTP_BASE_VAR(userspace_udpsctp6) = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
1319 #if defined(__Userspace_os_Windows)
1320 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1322 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1325 #if defined(IPV6_RECVPKTINFO)
1326 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
1327 #if defined(__Userspace_os_Windows)
1328 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1329 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1331 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1332 close(SCTP_BASE_VAR(userspace_udpsctp6));
1334 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1337 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
1338 #if defined(__Userspace_os_Windows)
1339 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1340 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1342 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1343 close(SCTP_BASE_VAR(userspace_udpsctp6));
1345 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1348 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&on, (socklen_t)sizeof(on)) < 0) {
1349 #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());
1352 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1355 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
1356 #if defined(__Userspace_os_Windows)
1357 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1358 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1360 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1361 close(SCTP_BASE_VAR(userspace_udpsctp6));
1363 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1365 memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6));
1366 #ifdef HAVE_SIN6_LEN
1367 addr_ipv6.sin6_len = sizeof(struct sockaddr_in6);
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;
1372 if (bind(SCTP_BASE_VAR(userspace_udpsctp6), (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) {
1373 #if defined(__Userspace_os_Windows)
1374 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
1375 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1377 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
1378 close(SCTP_BASE_VAR(userspace_udpsctp6));
1380 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
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? */
1389 #if !defined(__Userspace_os_Windows)
1390 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
1391 #if defined(INET) || defined(INET6)
1392 if (SCTP_BASE_VAR(userspace_route) != -1) {
1395 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadroute), NULL, &recv_function_route, NULL))) {
1396 SCTPDBG(SCTP_DEBUG_USR, "Can't start routing thread (%d).\n", rc);
1397 close(SCTP_BASE_VAR(userspace_route));
1398 SCTP_BASE_VAR(userspace_route) = -1;
1404 if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
1407 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw), NULL, &recv_function_raw, NULL))) {
1408 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread (%d).\n", rc);
1409 close(SCTP_BASE_VAR(userspace_rawsctp));
1410 SCTP_BASE_VAR(userspace_rawsctp) = -1;
1413 if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
1416 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp), NULL, &recv_function_udp, NULL))) {
1417 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread (%d).\n", rc);
1418 close(SCTP_BASE_VAR(userspace_udpsctp));
1419 SCTP_BASE_VAR(userspace_udpsctp) = -1;
1424 if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
1427 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw6), NULL, &recv_function_raw6, NULL))) {
1428 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread (%d).\n", rc);
1429 close(SCTP_BASE_VAR(userspace_rawsctp6));
1430 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
1433 if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
1436 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp6), NULL, &recv_function_udp6, NULL))) {
1437 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread (%d).\n", rc);
1438 close(SCTP_BASE_VAR(userspace_udpsctp6));
1439 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1445 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) {
1447 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread.\n");
1448 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
1449 SCTP_BASE_VAR(userspace_rawsctp) = -1;
1452 if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
1453 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");
1455 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
1456 SCTP_BASE_VAR(userspace_udpsctp) = -1;
1461 if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
1462 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");
1464 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
1465 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
1468 if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
1469 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");
1471 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1472 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
1480 recv_thread_destroy(void)
1482 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
1483 #if defined(INET) || defined(INET6)
1484 if (SCTP_BASE_VAR(userspace_route) != -1) {
1485 close(SCTP_BASE_VAR(userspace_route));
1490 if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
1491 #if defined(__Userspace_os_Windows)
1492 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
1494 close(SCTP_BASE_VAR(userspace_rawsctp));
1497 if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
1498 #if defined(__Userspace_os_Windows)
1499 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
1501 close(SCTP_BASE_VAR(userspace_udpsctp));
1506 if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
1507 #if defined(__Userspace_os_Windows)
1508 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
1510 close(SCTP_BASE_VAR(userspace_rawsctp6));
1513 if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
1514 #if defined(__Userspace_os_Windows)
1515 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
1517 close(SCTP_BASE_VAR(userspace_udpsctp6));