netwerk/sctp/src/user_recv_thread.c

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rwxr-xr-x

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

michael@0 1 /*-
michael@0 2 * Copyright (c) 2009-2010 Brad Penoff
michael@0 3 * Copyright (c) 2009-2010 Humaira Kamal
michael@0 4 * Copyright (c) 2011-2012 Irene Ruengeler
michael@0 5 * Copyright (c) 2011-2012 Michael Tuexen
michael@0 6 * All rights reserved.
michael@0 7 *
michael@0 8 * Redistribution and use in source and binary forms, with or without
michael@0 9 * modification, are permitted provided that the following conditions
michael@0 10 * are met:
michael@0 11 * 1. Redistributions of source code must retain the above copyright
michael@0 12 * notice, this list of conditions and the following disclaimer.
michael@0 13 * 2. Redistributions in binary form must reproduce the above copyright
michael@0 14 * notice, this list of conditions and the following disclaimer in the
michael@0 15 * documentation and/or other materials provided with the distribution.
michael@0 16 *
michael@0 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
michael@0 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
michael@0 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
michael@0 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
michael@0 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
michael@0 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
michael@0 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
michael@0 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
michael@0 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
michael@0 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
michael@0 27 * SUCH DAMAGE.
michael@0 28 *
michael@0 29 */
michael@0 30
michael@0 31 #if defined(INET) || defined(INET6)
michael@0 32 #include <sys/types.h>
michael@0 33 #if !defined(__Userspace_os_Windows)
michael@0 34 #include <sys/socket.h>
michael@0 35 #include <netinet/in.h>
michael@0 36 #include <unistd.h>
michael@0 37 #include <pthread.h>
michael@0 38 #if !defined(__Userspace_os_DragonFly) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_NetBSD)
michael@0 39 #include <sys/uio.h>
michael@0 40 #else
michael@0 41 #include <user_ip6_var.h>
michael@0 42 #endif
michael@0 43 #endif
michael@0 44 #include <netinet/sctp_os.h>
michael@0 45 #include <netinet/sctp_var.h>
michael@0 46 #include <netinet/sctp_pcb.h>
michael@0 47 #include <netinet/sctp_input.h>
michael@0 48 #if 0
michael@0 49 #if defined(__Userspace_os_Linux)
michael@0 50 #include <linux/netlink.h>
michael@0 51 #ifdef HAVE_LINUX_IF_ADDR_H
michael@0 52 #include <linux/if_addr.h>
michael@0 53 #endif
michael@0 54 #ifdef HAVE_LINUX_RTNETLINK_H
michael@0 55 #include <linux/rtnetlink.h>
michael@0 56 #endif
michael@0 57 #endif
michael@0 58 #endif
michael@0 59 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
michael@0 60 #include <net/route.h>
michael@0 61 #endif
michael@0 62 /* local macros and datatypes used to get IP addresses system independently */
michael@0 63 #if !defined(IP_PKTINFO ) && ! defined(IP_RECVDSTADDR)
michael@0 64 # error "Can't determine socket option to use to get UDP IP"
michael@0 65 #endif
michael@0 66
michael@0 67 void recv_thread_destroy(void);
michael@0 68 #define MAXLEN_MBUF_CHAIN 32 /* What should this value be? */
michael@0 69 #define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
michael@0 70 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
michael@0 71 #define NEXT_SA(ap) ap = (struct sockaddr *) \
michael@0 72 ((caddr_t) ap + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof (uint32_t)) : sizeof(uint32_t)))
michael@0 73 #endif
michael@0 74
michael@0 75 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
michael@0 76 static void
michael@0 77 sctp_get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
michael@0 78 {
michael@0 79 int i;
michael@0 80
michael@0 81 for (i = 0; i < RTAX_MAX; i++) {
michael@0 82 if (addrs & (1 << i)) {
michael@0 83 rti_info[i] = sa;
michael@0 84 NEXT_SA(sa);
michael@0 85 } else {
michael@0 86 rti_info[i] = NULL;
michael@0 87 }
michael@0 88 }
michael@0 89 }
michael@0 90
michael@0 91 static void
michael@0 92 sctp_handle_ifamsg(unsigned char type, unsigned short index, struct sockaddr *sa)
michael@0 93 {
michael@0 94 int rc;
michael@0 95 struct ifaddrs *ifa, *found_ifa = NULL;
michael@0 96
michael@0 97 /* handle only the types we want */
michael@0 98 if ((type != RTM_NEWADDR) && (type != RTM_DELADDR)) {
michael@0 99 return;
michael@0 100 }
michael@0 101
michael@0 102 rc = getifaddrs(&g_interfaces);
michael@0 103 if (rc != 0) {
michael@0 104 return;
michael@0 105 }
michael@0 106 for (ifa = g_interfaces; ifa; ifa = ifa->ifa_next) {
michael@0 107 if (index == if_nametoindex(ifa->ifa_name)) {
michael@0 108 found_ifa = ifa;
michael@0 109 break;
michael@0 110 }
michael@0 111 }
michael@0 112 if (found_ifa == NULL) {
michael@0 113 return;
michael@0 114 }
michael@0 115
michael@0 116 switch (sa->sa_family) {
michael@0 117 #ifdef INET
michael@0 118 case AF_INET:
michael@0 119 ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
michael@0 120 memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in));
michael@0 121 break;
michael@0 122 #endif
michael@0 123 #ifdef INET6
michael@0 124 case AF_INET6:
michael@0 125 ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in6));
michael@0 126 memcpy(ifa->ifa_addr, sa, sizeof(struct sockaddr_in6));
michael@0 127 break;
michael@0 128 #endif
michael@0 129 default:
michael@0 130 SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", sa->sa_family);
michael@0 131 }
michael@0 132
michael@0 133 /* relay the appropriate address change to the base code */
michael@0 134 if (type == RTM_NEWADDR) {
michael@0 135 (void)sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, ifa, if_nametoindex(ifa->ifa_name),
michael@0 136 0,
michael@0 137 ifa->ifa_name,
michael@0 138 (void *)ifa,
michael@0 139 ifa->ifa_addr,
michael@0 140 0,
michael@0 141 1);
michael@0 142 } else {
michael@0 143 sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
michael@0 144 if_nametoindex(ifa->ifa_name),
michael@0 145 ifa->ifa_name);
michael@0 146 }
michael@0 147 }
michael@0 148
michael@0 149 static void *
michael@0 150 recv_function_route(void *arg)
michael@0 151 {
michael@0 152 ssize_t ret;
michael@0 153 struct ifa_msghdr *ifa;
michael@0 154 char rt_buffer[1024];
michael@0 155 struct sockaddr *sa, *rti_info[RTAX_MAX];
michael@0 156
michael@0 157 while (1) {
michael@0 158 bzero(rt_buffer, sizeof(rt_buffer));
michael@0 159 ret = recv(SCTP_BASE_VAR(userspace_route), rt_buffer, sizeof(rt_buffer), 0);
michael@0 160
michael@0 161 if (ret > 0) {
michael@0 162 ifa = (struct ifa_msghdr *) rt_buffer;
michael@0 163 if (ifa->ifam_type != RTM_DELADDR && ifa->ifam_type != RTM_NEWADDR) {
michael@0 164 continue;
michael@0 165 }
michael@0 166 sa = (struct sockaddr *) (ifa + 1);
michael@0 167 sctp_get_rtaddrs(ifa->ifam_addrs, sa, rti_info);
michael@0 168 switch (ifa->ifam_type) {
michael@0 169 case RTM_DELADDR:
michael@0 170 case RTM_NEWADDR:
michael@0 171 sctp_handle_ifamsg(ifa->ifam_type, ifa->ifam_index, rti_info[RTAX_IFA]);
michael@0 172 break;
michael@0 173 default:
michael@0 174 /* ignore this routing event */
michael@0 175 break;
michael@0 176 }
michael@0 177 }
michael@0 178 if (ret < 0) {
michael@0 179 if (errno == EAGAIN) {
michael@0 180 continue;
michael@0 181 } else {
michael@0 182 break;
michael@0 183 }
michael@0 184 }
michael@0 185 }
michael@0 186 return (NULL);
michael@0 187 }
michael@0 188 #endif
michael@0 189
michael@0 190 #if 0
michael@0 191 /* This does not yet work on Linux */
michael@0 192 static void *
michael@0 193 recv_function_route(void *arg)
michael@0 194 {
michael@0 195 int len;
michael@0 196 char buf[4096];
michael@0 197 struct iovec iov = { buf, sizeof(buf) };
michael@0 198 struct msghdr msg;
michael@0 199 struct nlmsghdr *nh;
michael@0 200 struct ifaddrmsg *rtmsg;
michael@0 201 struct rtattr *rtatp;
michael@0 202 struct in_addr *inp;
michael@0 203 struct sockaddr_nl sanl;
michael@0 204 #ifdef INET
michael@0 205 struct sockaddr_in *sa;
michael@0 206 #endif
michael@0 207 #ifdef INET6
michael@0 208 struct sockaddr_in6 *sa6;
michael@0 209 #endif
michael@0 210
michael@0 211 for (;;) {
michael@0 212 memset(&sanl, 0, sizeof(sanl));
michael@0 213 sanl.nl_family = AF_NETLINK;
michael@0 214 sanl.nl_groups = RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_IFADDR;
michael@0 215 memset(&msg, 0, sizeof(struct msghdr));
michael@0 216 msg.msg_name = (void *)&sanl;
michael@0 217 msg.msg_namelen = sizeof(sanl);
michael@0 218 msg.msg_iov = &iov;
michael@0 219 msg.msg_iovlen = 1;
michael@0 220 msg.msg_control = NULL;
michael@0 221 msg.msg_controllen = 0;
michael@0 222
michael@0 223 len = recvmsg(SCTP_BASE_VAR(userspace_route), &msg, 0);
michael@0 224
michael@0 225 if (len < 0) {
michael@0 226 if (errno == EAGAIN) {
michael@0 227 continue;
michael@0 228 } else {
michael@0 229 break;
michael@0 230 }
michael@0 231 }
michael@0 232 for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len);
michael@0 233 nh = NLMSG_NEXT (nh, len)) {
michael@0 234 if (nh->nlmsg_type == NLMSG_DONE)
michael@0 235 break;
michael@0 236
michael@0 237 if (nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR) {
michael@0 238 rtmsg = (struct ifaddrmsg *)NLMSG_DATA(nh);
michael@0 239 rtatp = (struct rtattr *)IFA_RTA(rtmsg);
michael@0 240 if(rtatp->rta_type == IFA_ADDRESS) {
michael@0 241 inp = (struct in_addr *)RTA_DATA(rtatp);
michael@0 242 switch (rtmsg->ifa_family) {
michael@0 243 #ifdef INET
michael@0 244 case AF_INET:
michael@0 245 sa = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
michael@0 246 sa->sin_family = rtmsg->ifa_family;
michael@0 247 sa->sin_port = 0;
michael@0 248 memcpy(&sa->sin_addr, inp, sizeof(struct in_addr));
michael@0 249 sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa);
michael@0 250 break;
michael@0 251 #endif
michael@0 252 #ifdef INET6
michael@0 253 case AF_INET6:
michael@0 254 sa6 = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6));
michael@0 255 sa6->sin6_family = rtmsg->ifa_family;
michael@0 256 sa6->sin6_port = 0;
michael@0 257 memcpy(&sa6->sin6_addr, inp, sizeof(struct in6_addr));
michael@0 258 sctp_handle_ifamsg(nh->nlmsg_type, rtmsg->ifa_index, (struct sockaddr *)sa6);
michael@0 259 break;
michael@0 260 #endif
michael@0 261 default:
michael@0 262 SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", rtmsg->ifa_family);
michael@0 263 break;
michael@0 264 }
michael@0 265 }
michael@0 266 }
michael@0 267 }
michael@0 268 }
michael@0 269 return (NULL);
michael@0 270 }
michael@0 271 #endif
michael@0 272
michael@0 273 #ifdef INET
michael@0 274 static void *
michael@0 275 recv_function_raw(void *arg)
michael@0 276 {
michael@0 277 struct mbuf **recvmbuf;
michael@0 278 struct ip *iphdr;
michael@0 279 struct sctphdr *sh;
michael@0 280 uint16_t port;
michael@0 281 int offset, ecn = 0;
michael@0 282 #if !defined(SCTP_WITH_NO_CSUM)
michael@0 283 int compute_crc = 1;
michael@0 284 #endif
michael@0 285 struct sctp_chunkhdr *ch;
michael@0 286 struct sockaddr_in src, dst;
michael@0 287 #if !defined(__Userspace_os_Windows)
michael@0 288 struct msghdr msg;
michael@0 289 struct iovec recv_iovec[MAXLEN_MBUF_CHAIN];
michael@0 290 #else
michael@0 291 WSABUF recv_iovec[MAXLEN_MBUF_CHAIN];
michael@0 292 int nResult, m_ErrorCode;
michael@0 293 DWORD flags;
michael@0 294 struct sockaddr_in from;
michael@0 295 int fromlen;
michael@0 296 #endif
michael@0 297
michael@0 298 /*Initially the entire set of mbufs is to be allocated.
michael@0 299 to_fill indicates this amount. */
michael@0 300 int to_fill = MAXLEN_MBUF_CHAIN;
michael@0 301 /* iovlen is the size of each mbuf in the chain */
michael@0 302 int i, n, ncounter = 0;
michael@0 303 int iovlen = MCLBYTES;
michael@0 304 int want_ext = (iovlen > MLEN)? 1 : 0;
michael@0 305 int want_header = 0;
michael@0 306
michael@0 307 bzero((void *)&src, sizeof(struct sockaddr_in));
michael@0 308 bzero((void *)&dst, sizeof(struct sockaddr_in));
michael@0 309
michael@0 310 recvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
michael@0 311
michael@0 312 while (1) {
michael@0 313 for (i = 0; i < to_fill; i++) {
michael@0 314 /* Not getting the packet header. Tests with chain of one run
michael@0 315 as usual without having the packet header.
michael@0 316 Have tried both sending and receiving
michael@0 317 */
michael@0 318 recvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
michael@0 319 #if !defined(__Userspace_os_Windows)
michael@0 320 recv_iovec[i].iov_base = (caddr_t)recvmbuf[i]->m_data;
michael@0 321 recv_iovec[i].iov_len = iovlen;
michael@0 322 #else
michael@0 323 recv_iovec[i].buf = (caddr_t)recvmbuf[i]->m_data;
michael@0 324 recv_iovec[i].len = iovlen;
michael@0 325 #endif
michael@0 326 }
michael@0 327 to_fill = 0;
michael@0 328 #if defined(__Userspace_os_Windows)
michael@0 329 flags = 0;
michael@0 330 ncounter = 0;
michael@0 331 fromlen = sizeof(struct sockaddr_in);
michael@0 332 bzero((void *)&from, sizeof(struct sockaddr_in));
michael@0 333
michael@0 334 nResult = WSARecvFrom(SCTP_BASE_VAR(userspace_rawsctp), recv_iovec, MAXLEN_MBUF_CHAIN, (LPDWORD)&ncounter, (LPDWORD)&flags, (struct sockaddr*)&from, &fromlen, NULL, NULL);
michael@0 335 if (nResult != 0) {
michael@0 336 m_ErrorCode = WSAGetLastError();
michael@0 337 if (m_ErrorCode == WSAETIMEDOUT) {
michael@0 338 continue;
michael@0 339 }
michael@0 340 if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
michael@0 341 break;
michael@0 342 }
michael@0 343 }
michael@0 344 n = ncounter;
michael@0 345 #else
michael@0 346 bzero((void *)&msg, sizeof(struct msghdr));
michael@0 347 msg.msg_name = NULL;
michael@0 348 msg.msg_namelen = 0;
michael@0 349 msg.msg_iov = recv_iovec;
michael@0 350 msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
michael@0 351 msg.msg_control = NULL;
michael@0 352 msg.msg_controllen = 0;
michael@0 353 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp), &msg, 0);
michael@0 354 if (n < 0) {
michael@0 355 if (errno == EAGAIN) {
michael@0 356 continue;
michael@0 357 } else {
michael@0 358 break;
michael@0 359 }
michael@0 360 }
michael@0 361 #endif
michael@0 362 SCTP_HEADER_LEN(recvmbuf[0]) = n; /* length of total packet */
michael@0 363 SCTP_STAT_INCR(sctps_recvpackets);
michael@0 364 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
michael@0 365
michael@0 366 if (n <= iovlen) {
michael@0 367 SCTP_BUF_LEN(recvmbuf[0]) = n;
michael@0 368 (to_fill)++;
michael@0 369 } else {
michael@0 370 i = 0;
michael@0 371 SCTP_BUF_LEN(recvmbuf[0]) = iovlen;
michael@0 372
michael@0 373 ncounter -= iovlen;
michael@0 374 (to_fill)++;
michael@0 375 do {
michael@0 376 recvmbuf[i]->m_next = recvmbuf[i+1];
michael@0 377 SCTP_BUF_LEN(recvmbuf[i]->m_next) = min(ncounter, iovlen);
michael@0 378 i++;
michael@0 379 ncounter -= iovlen;
michael@0 380 (to_fill)++;
michael@0 381 } while (ncounter > 0);
michael@0 382 }
michael@0 383
michael@0 384 iphdr = mtod(recvmbuf[0], struct ip *);
michael@0 385 sh = (struct sctphdr *)((caddr_t)iphdr + sizeof(struct ip));
michael@0 386 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
michael@0 387 offset = sizeof(struct ip) + sizeof(struct sctphdr);
michael@0 388
michael@0 389 if (iphdr->ip_tos != 0) {
michael@0 390 ecn = iphdr->ip_tos & 0x02;
michael@0 391 }
michael@0 392
michael@0 393 dst.sin_family = AF_INET;
michael@0 394 #ifdef HAVE_SIN_LEN
michael@0 395 dst.sin_len = sizeof(struct sockaddr_in);
michael@0 396 #endif
michael@0 397 dst.sin_addr = iphdr->ip_dst;
michael@0 398 dst.sin_port = sh->dest_port;
michael@0 399
michael@0 400 src.sin_family = AF_INET;
michael@0 401 #ifdef HAVE_SIN_LEN
michael@0 402 src.sin_len = sizeof(struct sockaddr_in);
michael@0 403 #endif
michael@0 404 src.sin_addr = iphdr->ip_src;
michael@0 405 src.sin_port = sh->src_port;
michael@0 406
michael@0 407 /* SCTP does not allow broadcasts or multicasts */
michael@0 408 if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
michael@0 409 return (NULL);
michael@0 410 }
michael@0 411 if (SCTP_IS_IT_BROADCAST(dst.sin_addr, recvmbuf[0])) {
michael@0 412 return (NULL);
michael@0 413 }
michael@0 414
michael@0 415 port = 0;
michael@0 416
michael@0 417 #if defined(SCTP_WITH_NO_CSUM)
michael@0 418 SCTP_STAT_INCR(sctps_recvnocrc);
michael@0 419 #else
michael@0 420 if (src.sin_addr.s_addr == dst.sin_addr.s_addr) {
michael@0 421 compute_crc = 0;
michael@0 422 SCTP_STAT_INCR(sctps_recvnocrc);
michael@0 423 } else {
michael@0 424 SCTP_STAT_INCR(sctps_recvswcrc);
michael@0 425 }
michael@0 426 #endif
michael@0 427 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
michael@0 428 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
michael@0 429 sctp_common_input_processing(&recvmbuf[0], sizeof(struct ip), offset, n,
michael@0 430 (struct sockaddr *)&src,
michael@0 431 (struct sockaddr *)&dst,
michael@0 432 sh, ch,
michael@0 433 #if !defined(SCTP_WITH_NO_CSUM)
michael@0 434 compute_crc,
michael@0 435 #endif
michael@0 436 ecn,
michael@0 437 SCTP_DEFAULT_VRFID, port);
michael@0 438 if (recvmbuf[0]) {
michael@0 439 m_freem(recvmbuf[0]);
michael@0 440 }
michael@0 441 }
michael@0 442 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
michael@0 443 m_free(recvmbuf[i]);
michael@0 444 }
michael@0 445 /* free the array itself */
michael@0 446 free(recvmbuf);
michael@0 447 return (NULL);
michael@0 448 }
michael@0 449 #endif
michael@0 450
michael@0 451 #if defined(INET6)
michael@0 452 static void *
michael@0 453 recv_function_raw6(void *arg)
michael@0 454 {
michael@0 455 struct mbuf **recvmbuf6;
michael@0 456 #if !defined(__Userspace_os_Windows)
michael@0 457 struct iovec recv_iovec[MAXLEN_MBUF_CHAIN];
michael@0 458 struct msghdr msg;
michael@0 459 struct cmsghdr *cmsgptr;
michael@0 460 char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
michael@0 461 #else
michael@0 462 WSABUF recv_iovec[MAXLEN_MBUF_CHAIN];
michael@0 463 int nResult, m_ErrorCode;
michael@0 464 DWORD flags;
michael@0 465 struct sockaddr_in6 from;
michael@0 466 int fromlen;
michael@0 467 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
michael@0 468 LPFN_WSARECVMSG WSARecvMsg;
michael@0 469 WSACMSGHDR *cmsgptr;
michael@0 470 WSAMSG msg;
michael@0 471 char ControlBuffer[1024];
michael@0 472 #endif
michael@0 473 struct sockaddr_in6 src, dst;
michael@0 474 struct sctphdr *sh;
michael@0 475 int offset;
michael@0 476 struct sctp_chunkhdr *ch;
michael@0 477
michael@0 478 /*Initially the entire set of mbufs is to be allocated.
michael@0 479 to_fill indicates this amount. */
michael@0 480 int to_fill = MAXLEN_MBUF_CHAIN;
michael@0 481 /* iovlen is the size of each mbuf in the chain */
michael@0 482 int i, n, ncounter = 0;
michael@0 483 #if !defined(SCTP_WITH_NO_CSUM)
michael@0 484 int compute_crc = 1;
michael@0 485 #endif
michael@0 486 int iovlen = MCLBYTES;
michael@0 487 int want_ext = (iovlen > MLEN)? 1 : 0;
michael@0 488 int want_header = 0;
michael@0 489
michael@0 490 recvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
michael@0 491
michael@0 492 for (;;) {
michael@0 493 for (i = 0; i < to_fill; i++) {
michael@0 494 /* Not getting the packet header. Tests with chain of one run
michael@0 495 as usual without having the packet header.
michael@0 496 Have tried both sending and receiving
michael@0 497 */
michael@0 498 recvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
michael@0 499 #if !defined(__Userspace_os_Windows)
michael@0 500 recv_iovec[i].iov_base = (caddr_t)recvmbuf6[i]->m_data;
michael@0 501 recv_iovec[i].iov_len = iovlen;
michael@0 502 #else
michael@0 503 recv_iovec[i].buf = (caddr_t)recvmbuf6[i]->m_data;
michael@0 504 recv_iovec[i].len = iovlen;
michael@0 505 #endif
michael@0 506 }
michael@0 507 to_fill = 0;
michael@0 508 #if defined(__Userspace_os_Windows)
michael@0 509 flags = 0;
michael@0 510 ncounter = 0;
michael@0 511 fromlen = sizeof(struct sockaddr_in6);
michael@0 512 bzero((void *)&from, sizeof(struct sockaddr_in6));
michael@0 513 nResult = WSAIoctl(SCTP_BASE_VAR(userspace_rawsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER,
michael@0 514 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
michael@0 515 &WSARecvMsg, sizeof WSARecvMsg,
michael@0 516 &ncounter, NULL, NULL);
michael@0 517 if (nResult == 0) {
michael@0 518 msg.name = (void *)&src;
michael@0 519 msg.namelen = sizeof(struct sockaddr_in6);
michael@0 520 msg.lpBuffers = recv_iovec;
michael@0 521 msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
michael@0 522 msg.Control.len = sizeof ControlBuffer;
michael@0 523 msg.Control.buf = ControlBuffer;
michael@0 524 msg.dwFlags = 0;
michael@0 525 nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, &ncounter, NULL, NULL);
michael@0 526 }
michael@0 527 if (nResult != 0) {
michael@0 528 m_ErrorCode = WSAGetLastError();
michael@0 529 if (m_ErrorCode == WSAETIMEDOUT)
michael@0 530 continue;
michael@0 531 if (m_ErrorCode == WSAENOTSOCK || m_ErrorCode == WSAEINTR)
michael@0 532 break;
michael@0 533 }
michael@0 534 n = ncounter;
michael@0 535 #else
michael@0 536 bzero((void *)&msg, sizeof(struct msghdr));
michael@0 537 bzero((void *)&src, sizeof(struct sockaddr_in6));
michael@0 538 bzero((void *)&dst, sizeof(struct sockaddr_in6));
michael@0 539 bzero((void *)cmsgbuf, CMSG_SPACE(sizeof (struct in6_pktinfo)));
michael@0 540 msg.msg_name = (void *)&src;
michael@0 541 msg.msg_namelen = sizeof(struct sockaddr_in6);
michael@0 542 msg.msg_iov = recv_iovec;
michael@0 543 msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
michael@0 544 msg.msg_control = (void *)cmsgbuf;
michael@0 545 msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof (struct in6_pktinfo));
michael@0 546 msg.msg_flags = 0;
michael@0 547
michael@0 548 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_rawsctp6), &msg, 0);
michael@0 549 if (n < 0) {
michael@0 550 if (errno == EAGAIN) {
michael@0 551 continue;
michael@0 552 } else {
michael@0 553 break;
michael@0 554 }
michael@0 555 }
michael@0 556 #endif
michael@0 557 SCTP_HEADER_LEN(recvmbuf6[0]) = n; /* length of total packet */
michael@0 558 SCTP_STAT_INCR(sctps_recvpackets);
michael@0 559 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
michael@0 560
michael@0 561 if (n <= iovlen) {
michael@0 562 SCTP_BUF_LEN(recvmbuf6[0]) = n;
michael@0 563 (to_fill)++;
michael@0 564 } else {
michael@0 565 i = 0;
michael@0 566 SCTP_BUF_LEN(recvmbuf6[0]) = iovlen;
michael@0 567
michael@0 568 ncounter -= iovlen;
michael@0 569 (to_fill)++;
michael@0 570 do {
michael@0 571 recvmbuf6[i]->m_next = recvmbuf6[i+1];
michael@0 572 SCTP_BUF_LEN(recvmbuf6[i]->m_next) = min(ncounter, iovlen);
michael@0 573 i++;
michael@0 574 ncounter -= iovlen;
michael@0 575 (to_fill)++;
michael@0 576 } while (ncounter > 0);
michael@0 577 }
michael@0 578
michael@0 579 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
michael@0 580 if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) {
michael@0 581 struct in6_pktinfo * info;
michael@0 582
michael@0 583 info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
michael@0 584 memcpy((void *)&dst.sin6_addr, (const void *) &(info->ipi6_addr), sizeof(struct in6_addr));
michael@0 585 break;
michael@0 586 }
michael@0 587 }
michael@0 588
michael@0 589 sh = mtod(recvmbuf6[0], struct sctphdr *);
michael@0 590 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
michael@0 591 offset = sizeof(struct sctphdr);
michael@0 592
michael@0 593 dst.sin6_family = AF_INET6;
michael@0 594 #ifdef HAVE_SIN6_LEN
michael@0 595 dst.sin6_len = sizeof(struct sockaddr_in6);
michael@0 596 #endif
michael@0 597 dst.sin6_port = sh->dest_port;
michael@0 598
michael@0 599 src.sin6_family = AF_INET6;
michael@0 600 #ifdef HAVE_SIN6_LEN
michael@0 601 src.sin6_len = sizeof(struct sockaddr_in6);
michael@0 602 #endif
michael@0 603 src.sin6_port = sh->src_port;
michael@0 604 #if defined(SCTP_WITH_NO_CSUM)
michael@0 605 SCTP_STAT_INCR(sctps_recvnocrc);
michael@0 606 #else
michael@0 607 if (memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0) {
michael@0 608 compute_crc = 0;
michael@0 609 SCTP_STAT_INCR(sctps_recvnocrc);
michael@0 610 } else {
michael@0 611 SCTP_STAT_INCR(sctps_recvswcrc);
michael@0 612 }
michael@0 613 #endif
michael@0 614 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
michael@0 615 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
michael@0 616 sctp_common_input_processing(&recvmbuf6[0], 0, offset, n,
michael@0 617 (struct sockaddr *)&src,
michael@0 618 (struct sockaddr *)&dst,
michael@0 619 sh, ch,
michael@0 620 #if !defined(SCTP_WITH_NO_CSUM)
michael@0 621 compute_crc,
michael@0 622 #endif
michael@0 623 0,
michael@0 624 SCTP_DEFAULT_VRFID, 0);
michael@0 625 if (recvmbuf6[0]) {
michael@0 626 m_freem(recvmbuf6[0]);
michael@0 627 }
michael@0 628 }
michael@0 629 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
michael@0 630 m_free(recvmbuf6[i]);
michael@0 631 }
michael@0 632 /* free the array itself */
michael@0 633 free(recvmbuf6);
michael@0 634 return (NULL);
michael@0 635 }
michael@0 636 #endif
michael@0 637
michael@0 638 #ifdef INET
michael@0 639 static void *
michael@0 640 recv_function_udp(void *arg)
michael@0 641 {
michael@0 642 struct mbuf **udprecvmbuf;
michael@0 643 /*Initially the entire set of mbufs is to be allocated.
michael@0 644 to_fill indicates this amount. */
michael@0 645 int to_fill = MAXLEN_MBUF_CHAIN;
michael@0 646 /* iovlen is the size of each mbuf in the chain */
michael@0 647 int i, n, ncounter, offset;
michael@0 648 int iovlen = MCLBYTES;
michael@0 649 int want_ext = (iovlen > MLEN)? 1 : 0;
michael@0 650 int want_header = 0;
michael@0 651 struct sctphdr *sh;
michael@0 652 uint16_t port;
michael@0 653 struct sctp_chunkhdr *ch;
michael@0 654 struct sockaddr_in src, dst;
michael@0 655 #if defined(IP_PKTINFO)
michael@0 656 char cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))];
michael@0 657 #else
michael@0 658 char cmsgbuf[CMSG_SPACE(sizeof(struct in_addr))];
michael@0 659 #endif
michael@0 660 #if !defined(SCTP_WITH_NO_CSUM)
michael@0 661 int compute_crc = 1;
michael@0 662 #endif
michael@0 663 #if !defined(__Userspace_os_Windows)
michael@0 664 struct iovec iov[MAXLEN_MBUF_CHAIN];
michael@0 665 struct msghdr msg;
michael@0 666 struct cmsghdr *cmsgptr;
michael@0 667 #else
michael@0 668 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
michael@0 669 LPFN_WSARECVMSG WSARecvMsg;
michael@0 670 char ControlBuffer[1024];
michael@0 671 WSABUF iov[MAXLEN_MBUF_CHAIN];
michael@0 672 WSAMSG msg;
michael@0 673 int nResult, m_ErrorCode;
michael@0 674 WSACMSGHDR *cmsgptr;
michael@0 675 #endif
michael@0 676
michael@0 677 udprecvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
michael@0 678
michael@0 679 while (1) {
michael@0 680 for (i = 0; i < to_fill; i++) {
michael@0 681 /* Not getting the packet header. Tests with chain of one run
michael@0 682 as usual without having the packet header.
michael@0 683 Have tried both sending and receiving
michael@0 684 */
michael@0 685 udprecvmbuf[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
michael@0 686 #if !defined(__Userspace_os_Windows)
michael@0 687 iov[i].iov_base = (caddr_t)udprecvmbuf[i]->m_data;
michael@0 688 iov[i].iov_len = iovlen;
michael@0 689 #else
michael@0 690 iov[i].buf = (caddr_t)udprecvmbuf[i]->m_data;
michael@0 691 iov[i].len = iovlen;
michael@0 692 #endif
michael@0 693 }
michael@0 694 to_fill = 0;
michael@0 695 #if !defined(__Userspace_os_Windows)
michael@0 696 bzero((void *)&msg, sizeof(struct msghdr));
michael@0 697 #else
michael@0 698 bzero((void *)&msg, sizeof(WSAMSG));
michael@0 699 #endif
michael@0 700 bzero((void *)&src, sizeof(struct sockaddr_in));
michael@0 701 bzero((void *)&dst, sizeof(struct sockaddr_in));
michael@0 702 bzero((void *)cmsgbuf, sizeof(cmsgbuf));
michael@0 703
michael@0 704 #if !defined(__Userspace_os_Windows)
michael@0 705 msg.msg_name = (void *)&src;
michael@0 706 msg.msg_namelen = sizeof(struct sockaddr_in);
michael@0 707 msg.msg_iov = iov;
michael@0 708 msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
michael@0 709 msg.msg_control = (void *)cmsgbuf;
michael@0 710 msg.msg_controllen = sizeof(cmsgbuf);
michael@0 711 msg.msg_flags = 0;
michael@0 712
michael@0 713 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, 0);
michael@0 714 if (n < 0) {
michael@0 715 if (errno == EAGAIN) {
michael@0 716 continue;
michael@0 717 } else {
michael@0 718 break;
michael@0 719 }
michael@0 720 }
michael@0 721 #else
michael@0 722 nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp), SIO_GET_EXTENSION_FUNCTION_POINTER,
michael@0 723 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
michael@0 724 &WSARecvMsg, sizeof WSARecvMsg,
michael@0 725 &ncounter, NULL, NULL);
michael@0 726 if (nResult == 0) {
michael@0 727 msg.name = (void *)&src;
michael@0 728 msg.namelen = sizeof(struct sockaddr_in);
michael@0 729 msg.lpBuffers = iov;
michael@0 730 msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
michael@0 731 msg.Control.len = sizeof ControlBuffer;
michael@0 732 msg.Control.buf = ControlBuffer;
michael@0 733 msg.dwFlags = 0;
michael@0 734 nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp), &msg, &ncounter, NULL, NULL);
michael@0 735 }
michael@0 736 if (nResult != 0) {
michael@0 737 m_ErrorCode = WSAGetLastError();
michael@0 738 if (m_ErrorCode == WSAETIMEDOUT) {
michael@0 739 continue;
michael@0 740 }
michael@0 741 if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
michael@0 742 break;
michael@0 743 }
michael@0 744 }
michael@0 745 n = ncounter;
michael@0 746 #endif
michael@0 747 SCTP_HEADER_LEN(udprecvmbuf[0]) = n; /* length of total packet */
michael@0 748 SCTP_STAT_INCR(sctps_recvpackets);
michael@0 749 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
michael@0 750
michael@0 751 if (n <= iovlen) {
michael@0 752 SCTP_BUF_LEN(udprecvmbuf[0]) = n;
michael@0 753 (to_fill)++;
michael@0 754 } else {
michael@0 755 i = 0;
michael@0 756 SCTP_BUF_LEN(udprecvmbuf[0]) = iovlen;
michael@0 757
michael@0 758 ncounter -= iovlen;
michael@0 759 (to_fill)++;
michael@0 760 do {
michael@0 761 udprecvmbuf[i]->m_next = udprecvmbuf[i+1];
michael@0 762 SCTP_BUF_LEN(udprecvmbuf[i]->m_next) = min(ncounter, iovlen);
michael@0 763 i++;
michael@0 764 ncounter -= iovlen;
michael@0 765 (to_fill)++;
michael@0 766 } while (ncounter > 0);
michael@0 767 }
michael@0 768
michael@0 769 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
michael@0 770 #if defined(IP_PKTINFO)
michael@0 771 if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_PKTINFO)) {
michael@0 772 struct in_pktinfo *info;
michael@0 773
michael@0 774 dst.sin_family = AF_INET;
michael@0 775 #ifdef HAVE_SIN_LEN
michael@0 776 dst.sin_len = sizeof(struct sockaddr_in);
michael@0 777 #endif
michael@0 778 info = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
michael@0 779 memcpy((void *)&dst.sin_addr, (const void *)&(info->ipi_addr), sizeof(struct in_addr));
michael@0 780 break;
michael@0 781 }
michael@0 782 #else
michael@0 783 if ((cmsgptr->cmsg_level == IPPROTO_IP) && (cmsgptr->cmsg_type == IP_RECVDSTADDR)) {
michael@0 784 struct in_addr *addr;
michael@0 785
michael@0 786 dst.sin_family = AF_INET;
michael@0 787 #ifdef HAVE_SIN_LEN
michael@0 788 dst.sin_len = sizeof(struct sockaddr_in);
michael@0 789 #endif
michael@0 790 addr = (struct in_addr *)CMSG_DATA(cmsgptr);
michael@0 791 memcpy((void *)&dst.sin_addr, (const void *)addr, sizeof(struct in_addr));
michael@0 792 break;
michael@0 793 }
michael@0 794 #endif
michael@0 795 }
michael@0 796
michael@0 797 /* SCTP does not allow broadcasts or multicasts */
michael@0 798 if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
michael@0 799 return (NULL);
michael@0 800 }
michael@0 801 if (SCTP_IS_IT_BROADCAST(dst.sin_addr, udprecvmbuf[0])) {
michael@0 802 return (NULL);
michael@0 803 }
michael@0 804
michael@0 805 /*offset = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);*/
michael@0 806 sh = mtod(udprecvmbuf[0], struct sctphdr *);
michael@0 807 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
michael@0 808 offset = sizeof(struct sctphdr);
michael@0 809 port = src.sin_port;
michael@0 810 src.sin_port = sh->src_port;
michael@0 811 dst.sin_port = sh->dest_port;
michael@0 812 #if defined(SCTP_WITH_NO_CSUM)
michael@0 813 SCTP_STAT_INCR(sctps_recvnocrc);
michael@0 814 #else
michael@0 815 if (src.sin_addr.s_addr == dst.sin_addr.s_addr) {
michael@0 816 compute_crc = 0;
michael@0 817 SCTP_STAT_INCR(sctps_recvnocrc);
michael@0 818 } else {
michael@0 819 SCTP_STAT_INCR(sctps_recvswcrc);
michael@0 820 }
michael@0 821 #endif
michael@0 822 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
michael@0 823 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset);
michael@0 824 sctp_common_input_processing(&udprecvmbuf[0], 0, offset, n,
michael@0 825 (struct sockaddr *)&src,
michael@0 826 (struct sockaddr *)&dst,
michael@0 827 sh, ch,
michael@0 828 #if !defined(SCTP_WITH_NO_CSUM)
michael@0 829 compute_crc,
michael@0 830 #endif
michael@0 831 0,
michael@0 832 SCTP_DEFAULT_VRFID, port);
michael@0 833 if (udprecvmbuf[0]) {
michael@0 834 m_freem(udprecvmbuf[0]);
michael@0 835 }
michael@0 836 }
michael@0 837 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
michael@0 838 m_free(udprecvmbuf[i]);
michael@0 839 }
michael@0 840 /* free the array itself */
michael@0 841 free(udprecvmbuf);
michael@0 842 return (NULL);
michael@0 843 }
michael@0 844 #endif
michael@0 845
michael@0 846 #if defined(INET6)
michael@0 847 static void *
michael@0 848 recv_function_udp6(void *arg)
michael@0 849 {
michael@0 850 struct mbuf **udprecvmbuf6;
michael@0 851 /*Initially the entire set of mbufs is to be allocated.
michael@0 852 to_fill indicates this amount. */
michael@0 853 int to_fill = MAXLEN_MBUF_CHAIN;
michael@0 854 /* iovlen is the size of each mbuf in the chain */
michael@0 855 int i, n, ncounter, offset;
michael@0 856 int iovlen = MCLBYTES;
michael@0 857 int want_ext = (iovlen > MLEN)? 1 : 0;
michael@0 858 int want_header = 0;
michael@0 859 struct sockaddr_in6 src, dst;
michael@0 860 struct sctphdr *sh;
michael@0 861 uint16_t port;
michael@0 862 struct sctp_chunkhdr *ch;
michael@0 863 char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
michael@0 864 #if !defined(SCTP_WITH_NO_CSUM)
michael@0 865 int compute_crc = 1;
michael@0 866 #endif
michael@0 867 #if !defined(__Userspace_os_Windows)
michael@0 868 struct iovec iov[MAXLEN_MBUF_CHAIN];
michael@0 869 struct msghdr msg;
michael@0 870 struct cmsghdr *cmsgptr;
michael@0 871 #else
michael@0 872 GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
michael@0 873 LPFN_WSARECVMSG WSARecvMsg;
michael@0 874 char ControlBuffer[1024];
michael@0 875 WSABUF iov[MAXLEN_MBUF_CHAIN];
michael@0 876 WSAMSG msg;
michael@0 877 int nResult, m_ErrorCode;
michael@0 878 WSACMSGHDR *cmsgptr;
michael@0 879 #endif
michael@0 880
michael@0 881 udprecvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN);
michael@0 882 while (1) {
michael@0 883 for (i = 0; i < to_fill; i++) {
michael@0 884 /* Not getting the packet header. Tests with chain of one run
michael@0 885 as usual without having the packet header.
michael@0 886 Have tried both sending and receiving
michael@0 887 */
michael@0 888 udprecvmbuf6[i] = sctp_get_mbuf_for_msg(iovlen, want_header, M_NOWAIT, want_ext, MT_DATA);
michael@0 889 #if !defined(__Userspace_os_Windows)
michael@0 890 iov[i].iov_base = (caddr_t)udprecvmbuf6[i]->m_data;
michael@0 891 iov[i].iov_len = iovlen;
michael@0 892 #else
michael@0 893 iov[i].buf = (caddr_t)udprecvmbuf6[i]->m_data;
michael@0 894 iov[i].len = iovlen;
michael@0 895 #endif
michael@0 896 }
michael@0 897 to_fill = 0;
michael@0 898
michael@0 899 #if !defined(__Userspace_os_Windows)
michael@0 900 bzero((void *)&msg, sizeof(struct msghdr));
michael@0 901 #else
michael@0 902 bzero((void *)&msg, sizeof(WSAMSG));
michael@0 903 #endif
michael@0 904 bzero((void *)&src, sizeof(struct sockaddr_in6));
michael@0 905 bzero((void *)&dst, sizeof(struct sockaddr_in6));
michael@0 906 bzero((void *)cmsgbuf, CMSG_SPACE(sizeof (struct in6_pktinfo)));
michael@0 907
michael@0 908 #if !defined(__Userspace_os_Windows)
michael@0 909 msg.msg_name = (void *)&src;
michael@0 910 msg.msg_namelen = sizeof(struct sockaddr_in6);
michael@0 911 msg.msg_iov = iov;
michael@0 912 msg.msg_iovlen = MAXLEN_MBUF_CHAIN;
michael@0 913 msg.msg_control = (void *)cmsgbuf;
michael@0 914 msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof (struct in6_pktinfo));
michael@0 915 msg.msg_flags = 0;
michael@0 916
michael@0 917 ncounter = n = recvmsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, 0);
michael@0 918 if (n < 0) {
michael@0 919 if (errno == EAGAIN) {
michael@0 920 continue;
michael@0 921 } else {
michael@0 922 break;
michael@0 923 }
michael@0 924 }
michael@0 925 #else
michael@0 926 nResult = WSAIoctl(SCTP_BASE_VAR(userspace_udpsctp6), SIO_GET_EXTENSION_FUNCTION_POINTER,
michael@0 927 &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
michael@0 928 &WSARecvMsg, sizeof WSARecvMsg,
michael@0 929 &ncounter, NULL, NULL);
michael@0 930 if (nResult == SOCKET_ERROR) {
michael@0 931 m_ErrorCode = WSAGetLastError();
michael@0 932 WSARecvMsg = NULL;
michael@0 933 }
michael@0 934 if (nResult == 0) {
michael@0 935 msg.name = (void *)&src;
michael@0 936 msg.namelen = sizeof(struct sockaddr_in6);
michael@0 937 msg.lpBuffers = iov;
michael@0 938 msg.dwBufferCount = MAXLEN_MBUF_CHAIN;
michael@0 939 msg.Control.len = sizeof ControlBuffer;
michael@0 940 msg.Control.buf = ControlBuffer;
michael@0 941 msg.dwFlags = 0;
michael@0 942 nResult = WSARecvMsg(SCTP_BASE_VAR(userspace_udpsctp6), &msg, &ncounter, NULL, NULL);
michael@0 943 }
michael@0 944 if (nResult != 0) {
michael@0 945 m_ErrorCode = WSAGetLastError();
michael@0 946 if (m_ErrorCode == WSAETIMEDOUT) {
michael@0 947 continue;
michael@0 948 }
michael@0 949 if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) {
michael@0 950 break;
michael@0 951 }
michael@0 952 }
michael@0 953 n = ncounter;
michael@0 954 #endif
michael@0 955 SCTP_HEADER_LEN(udprecvmbuf6[0]) = n; /* length of total packet */
michael@0 956 SCTP_STAT_INCR(sctps_recvpackets);
michael@0 957 SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
michael@0 958
michael@0 959 if (n <= iovlen) {
michael@0 960 SCTP_BUF_LEN(udprecvmbuf6[0]) = n;
michael@0 961 (to_fill)++;
michael@0 962 } else {
michael@0 963 i = 0;
michael@0 964 SCTP_BUF_LEN(udprecvmbuf6[0]) = iovlen;
michael@0 965
michael@0 966 ncounter -= iovlen;
michael@0 967 (to_fill)++;
michael@0 968 do {
michael@0 969 udprecvmbuf6[i]->m_next = udprecvmbuf6[i+1];
michael@0 970 SCTP_BUF_LEN(udprecvmbuf6[i]->m_next) = min(ncounter, iovlen);
michael@0 971 i++;
michael@0 972 ncounter -= iovlen;
michael@0 973 (to_fill)++;
michael@0 974 } while (ncounter > 0);
michael@0 975 }
michael@0 976
michael@0 977 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
michael@0 978 if ((cmsgptr->cmsg_level == IPPROTO_IPV6) && (cmsgptr->cmsg_type == IPV6_PKTINFO)) {
michael@0 979 struct in6_pktinfo *info;
michael@0 980
michael@0 981 dst.sin6_family = AF_INET6;
michael@0 982 #ifdef HAVE_SIN6_LEN
michael@0 983 dst.sin6_len = sizeof(struct sockaddr_in6);
michael@0 984 #endif
michael@0 985 info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
michael@0 986 /*dst.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));*/
michael@0 987 memcpy((void *)&dst.sin6_addr, (const void *)&(info->ipi6_addr), sizeof(struct in6_addr));
michael@0 988 }
michael@0 989 }
michael@0 990
michael@0 991 /* SCTP does not allow broadcasts or multicasts */
michael@0 992 if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) {
michael@0 993 return (NULL);
michael@0 994 }
michael@0 995
michael@0 996 sh = mtod(udprecvmbuf6[0], struct sctphdr *);
michael@0 997 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
michael@0 998 offset = sizeof(struct sctphdr);
michael@0 999
michael@0 1000 port = src.sin6_port;
michael@0 1001 src.sin6_port = sh->src_port;
michael@0 1002 dst.sin6_port = sh->dest_port;
michael@0 1003 #if defined(SCTP_WITH_NO_CSUM)
michael@0 1004 SCTP_STAT_INCR(sctps_recvnocrc);
michael@0 1005 #else
michael@0 1006 if ((memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0)) {
michael@0 1007 compute_crc = 0;
michael@0 1008 SCTP_STAT_INCR(sctps_recvnocrc);
michael@0 1009 } else {
michael@0 1010 SCTP_STAT_INCR(sctps_recvswcrc);
michael@0 1011 }
michael@0 1012 #endif
michael@0 1013 SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n);
michael@0 1014 SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", (int)sizeof(struct sctphdr));
michael@0 1015 sctp_common_input_processing(&udprecvmbuf6[0], 0, offset, n,
michael@0 1016 (struct sockaddr *)&src,
michael@0 1017 (struct sockaddr *)&dst,
michael@0 1018 sh, ch,
michael@0 1019 #if !defined(SCTP_WITH_NO_CSUM)
michael@0 1020 compute_crc,
michael@0 1021 #endif
michael@0 1022 0,
michael@0 1023 SCTP_DEFAULT_VRFID, port);
michael@0 1024 if (udprecvmbuf6[0]) {
michael@0 1025 m_freem(udprecvmbuf6[0]);
michael@0 1026 }
michael@0 1027 }
michael@0 1028 for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) {
michael@0 1029 m_free(udprecvmbuf6[i]);
michael@0 1030 }
michael@0 1031 /* free the array itself */
michael@0 1032 free(udprecvmbuf6);
michael@0 1033 return (NULL);
michael@0 1034 }
michael@0 1035 #endif
michael@0 1036
michael@0 1037 static void
michael@0 1038 setReceiveBufferSize(int sfd, int new_size)
michael@0 1039 {
michael@0 1040 int ch = new_size;
michael@0 1041
michael@0 1042 if (setsockopt (sfd, SOL_SOCKET, SO_RCVBUF, (void*)&ch, sizeof(ch)) < 0) {
michael@0 1043 #if defined (__Userspace_os_Windows)
michael@0 1044 SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", WSAGetLastError());
michael@0 1045 #else
michael@0 1046 SCTPDBG(SCTP_DEBUG_USR, "Can't set recv-buffers size (errno = %d).\n", errno);
michael@0 1047 #endif
michael@0 1048 }
michael@0 1049 return;
michael@0 1050 }
michael@0 1051
michael@0 1052 static void
michael@0 1053 setSendBufferSize(int sfd, int new_size)
michael@0 1054 {
michael@0 1055 int ch = new_size;
michael@0 1056
michael@0 1057 if (setsockopt (sfd, SOL_SOCKET, SO_SNDBUF, (void*)&ch, sizeof(ch)) < 0) {
michael@0 1058 #if defined (__Userspace_os_Windows)
michael@0 1059 SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", WSAGetLastError());
michael@0 1060 #else
michael@0 1061 SCTPDBG(SCTP_DEBUG_USR, "Can't set send-buffers size (errno = %d).\n", errno);
michael@0 1062 #endif
michael@0 1063 }
michael@0 1064 return;
michael@0 1065 }
michael@0 1066
michael@0 1067 #define SOCKET_TIMEOUT 100 /* in ms */
michael@0 1068 void
michael@0 1069 recv_thread_init(void)
michael@0 1070 {
michael@0 1071 #if defined(INET)
michael@0 1072 struct sockaddr_in addr_ipv4;
michael@0 1073 const int hdrincl = 1;
michael@0 1074 #endif
michael@0 1075 #if defined(INET6)
michael@0 1076 struct sockaddr_in6 addr_ipv6;
michael@0 1077 #endif
michael@0 1078 #if defined(INET) || defined(INET6)
michael@0 1079 const int on = 1;
michael@0 1080 #endif
michael@0 1081 #if !defined(__Userspace_os_Windows)
michael@0 1082 struct timeval timeout;
michael@0 1083
michael@0 1084 timeout.tv_sec = (SOCKET_TIMEOUT / 1000);
michael@0 1085 timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
michael@0 1086 #else
michael@0 1087 unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */
michael@0 1088 #endif
michael@0 1089 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
michael@0 1090 if (SCTP_BASE_VAR(userspace_route) == -1) {
michael@0 1091 if ((SCTP_BASE_VAR(userspace_route) = socket(AF_ROUTE, SOCK_RAW, 0)) < 0) {
michael@0 1092 SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d).\n", errno);
michael@0 1093 }
michael@0 1094 #if 0
michael@0 1095 struct sockaddr_nl sanl;
michael@0 1096
michael@0 1097 if ((SCTP_BASE_VAR(userspace_route) = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
michael@0 1098 SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d.\n", errno);
michael@0 1099 }
michael@0 1100 memset(&sanl, 0, sizeof(sanl));
michael@0 1101 sanl.nl_family = AF_NETLINK;
michael@0 1102 sanl.nl_groups = 0;
michael@0 1103 #ifdef INET
michael@0 1104 sanl.nl_groups |= RTMGRP_IPV4_IFADDR;
michael@0 1105 #endif
michael@0 1106 #ifdef INET6
michael@0 1107 sanl.nl_groups |= RTMGRP_IPV6_IFADDR;
michael@0 1108 #endif
michael@0 1109 if (bind(SCTP_BASE_VAR(userspace_route), (struct sockaddr *) &sanl, sizeof(sanl)) < 0) {
michael@0 1110 SCTPDBG(SCTP_DEBUG_USR, "Can't bind routing socket (errno = %d).\n", errno);
michael@0 1111 close(SCTP_BASE_VAR(userspace_route));
michael@0 1112 SCTP_BASE_VAR(userspace_route) = -1;
michael@0 1113 }
michael@0 1114 #endif
michael@0 1115 if (SCTP_BASE_VAR(userspace_route) != -1) {
michael@0 1116 if (setsockopt(SCTP_BASE_VAR(userspace_route), SOL_SOCKET, SO_RCVTIMEO,(const void*)&timeout, sizeof(struct timeval)) < 0) {
michael@0 1117 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on routing socket (errno = %d).\n", errno);
michael@0 1118 #if defined(__Userspace_os_Windows)
michael@0 1119 closesocket(SCTP_BASE_VAR(userspace_route));
michael@0 1120 #else
michael@0 1121 close(SCTP_BASE_VAR(userspace_route));
michael@0 1122 #endif
michael@0 1123 SCTP_BASE_VAR(userspace_route) = -1;
michael@0 1124 }
michael@0 1125 }
michael@0 1126 }
michael@0 1127 #endif
michael@0 1128 #if defined(INET)
michael@0 1129 if (SCTP_BASE_VAR(userspace_rawsctp) == -1) {
michael@0 1130 if ((SCTP_BASE_VAR(userspace_rawsctp) = socket(AF_INET, SOCK_RAW, IPPROTO_SCTP)) < 0) {
michael@0 1131 #if defined(__Userspace_os_Windows)
michael@0 1132 SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", WSAGetLastError());
michael@0 1133 #else
michael@0 1134 SCTPDBG(SCTP_DEBUG_USR, "Can't create raw socket for IPv4 (errno = %d).\n", errno);
michael@0 1135 #endif
michael@0 1136 } else {
michael@0 1137 /* complete setting up the raw SCTP socket */
michael@0 1138 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), IPPROTO_IP, IP_HDRINCL,(const void*)&hdrincl, sizeof(int)) < 0) {
michael@0 1139 #if defined(__Userspace_os_Windows)
michael@0 1140 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", WSAGetLastError());
michael@0 1141 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
michael@0 1142 #else
michael@0 1143 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_HDRINCL (errno = %d).\n", errno);
michael@0 1144 close(SCTP_BASE_VAR(userspace_rawsctp));
michael@0 1145 #endif
michael@0 1146 SCTP_BASE_VAR(userspace_rawsctp) = -1;
michael@0 1147 } else if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
michael@0 1148 #if defined(__Userspace_os_Windows)
michael@0 1149 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError());
michael@0 1150 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
michael@0 1151 #else
michael@0 1152 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv4 (errno = %d).\n", errno);
michael@0 1153 close(SCTP_BASE_VAR(userspace_rawsctp));
michael@0 1154 #endif
michael@0 1155 SCTP_BASE_VAR(userspace_rawsctp) = -1;
michael@0 1156 } else {
michael@0 1157 memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in));
michael@0 1158 #ifdef HAVE_SIN_LEN
michael@0 1159 addr_ipv4.sin_len = sizeof(struct sockaddr_in);
michael@0 1160 #endif
michael@0 1161 addr_ipv4.sin_family = AF_INET;
michael@0 1162 addr_ipv4.sin_port = htons(0);
michael@0 1163 addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
michael@0 1164 if (bind(SCTP_BASE_VAR(userspace_rawsctp), (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) {
michael@0 1165 #if defined(__Userspace_os_Windows)
michael@0 1166 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", WSAGetLastError());
michael@0 1167 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
michael@0 1168 #else
michael@0 1169 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv4 (errno = %d).\n", errno);
michael@0 1170 close(SCTP_BASE_VAR(userspace_rawsctp));
michael@0 1171 #endif
michael@0 1172 SCTP_BASE_VAR(userspace_rawsctp) = -1;
michael@0 1173 } else {
michael@0 1174 setReceiveBufferSize(SCTP_BASE_VAR(userspace_rawsctp), SB_RAW); /* 128K */
michael@0 1175 setSendBufferSize(SCTP_BASE_VAR(userspace_rawsctp), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
michael@0 1176 }
michael@0 1177 }
michael@0 1178 }
michael@0 1179 }
michael@0 1180 if (SCTP_BASE_VAR(userspace_udpsctp) == -1) {
michael@0 1181 if ((SCTP_BASE_VAR(userspace_udpsctp) = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
michael@0 1182 #if defined(__Userspace_os_Windows)
michael@0 1183 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
michael@0 1184 #else
michael@0 1185 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
michael@0 1186 #endif
michael@0 1187 } else {
michael@0 1188 #if defined(IP_PKTINFO)
michael@0 1189 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
michael@0 1190 #else
michael@0 1191 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), IPPROTO_IP, IP_RECVDSTADDR, (const void *)&on, (int)sizeof(int)) < 0) {
michael@0 1192 #endif
michael@0 1193 #if defined(__Userspace_os_Windows)
michael@0 1194 #if defined(IP_PKTINFO)
michael@0 1195 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
michael@0 1196 #else
michael@0 1197 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
michael@0 1198 #endif
michael@0 1199 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
michael@0 1200 #else
michael@0 1201 #if defined(IP_PKTINFO)
michael@0 1202 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_PKTINFO on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
michael@0 1203 #else
michael@0 1204 SCTPDBG(SCTP_DEBUG_USR, "Can't set IP_RECVDSTADDR on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
michael@0 1205 #endif
michael@0 1206 close(SCTP_BASE_VAR(userspace_udpsctp));
michael@0 1207 #endif
michael@0 1208 SCTP_BASE_VAR(userspace_udpsctp) = -1;
michael@0 1209 } else if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
michael@0 1210 #if defined(__Userspace_os_Windows)
michael@0 1211 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
michael@0 1212 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
michael@0 1213 #else
michael@0 1214 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
michael@0 1215 close(SCTP_BASE_VAR(userspace_udpsctp));
michael@0 1216 #endif
michael@0 1217 SCTP_BASE_VAR(userspace_udpsctp) = -1;
michael@0 1218 } else {
michael@0 1219 memset((void *)&addr_ipv4, 0, sizeof(struct sockaddr_in));
michael@0 1220 #ifdef HAVE_SIN_LEN
michael@0 1221 addr_ipv4.sin_len = sizeof(struct sockaddr_in);
michael@0 1222 #endif
michael@0 1223 addr_ipv4.sin_family = AF_INET;
michael@0 1224 addr_ipv4.sin_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
michael@0 1225 addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
michael@0 1226 if (bind(SCTP_BASE_VAR(userspace_udpsctp), (const struct sockaddr *)&addr_ipv4, sizeof(struct sockaddr_in)) < 0) {
michael@0 1227 #if defined(__Userspace_os_Windows)
michael@0 1228 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", WSAGetLastError());
michael@0 1229 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
michael@0 1230 #else
michael@0 1231 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv4 (errno = %d).\n", errno);
michael@0 1232 close(SCTP_BASE_VAR(userspace_udpsctp));
michael@0 1233 #endif
michael@0 1234 SCTP_BASE_VAR(userspace_udpsctp) = -1;
michael@0 1235 } else {
michael@0 1236 setReceiveBufferSize(SCTP_BASE_VAR(userspace_udpsctp), SB_RAW); /* 128K */
michael@0 1237 setSendBufferSize(SCTP_BASE_VAR(userspace_udpsctp), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
michael@0 1238 }
michael@0 1239 }
michael@0 1240 }
michael@0 1241 }
michael@0 1242 #endif
michael@0 1243 #if defined(INET6)
michael@0 1244 if (SCTP_BASE_VAR(userspace_rawsctp6) == -1) {
michael@0 1245 if ((SCTP_BASE_VAR(userspace_rawsctp6) = socket(AF_INET6, SOCK_RAW, IPPROTO_SCTP)) < 0) {
michael@0 1246 #if defined(__Userspace_os_Windows)
michael@0 1247 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
michael@0 1248 #else
michael@0 1249 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/IPv6 (errno = %d).\n", errno);
michael@0 1250 #endif
michael@0 1251 } else {
michael@0 1252 /* complete setting up the raw SCTP socket */
michael@0 1253 #if defined(IPV6_RECVPKTINFO)
michael@0 1254 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, sizeof(on)) < 0) {
michael@0 1255 #if defined(__Userspace_os_Windows)
michael@0 1256 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
michael@0 1257 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
michael@0 1258 #else
michael@0 1259 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno);
michael@0 1260 close(SCTP_BASE_VAR(userspace_rawsctp6));
michael@0 1261 #endif
michael@0 1262 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
michael@0 1263 } else {
michael@0 1264 #else
michael@0 1265 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_PKTINFO,(const void*)&on, sizeof(on)) < 0) {
michael@0 1266 #if defined(__Userspace_os_Windows)
michael@0 1267 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
michael@0 1268 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
michael@0 1269 #else
michael@0 1270 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/IPv6 (errno = %d).\n", errno);
michael@0 1271 close(SCTP_BASE_VAR(userspace_rawsctp6));
michael@0 1272 #endif
michael@0 1273 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
michael@0 1274 } else {
michael@0 1275 #endif
michael@0 1276 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&on, (socklen_t)sizeof(on)) < 0) {
michael@0 1277 #if defined(__Userspace_os_Windows)
michael@0 1278 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
michael@0 1279 #else
michael@0 1280 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/IPv6 (errno = %d).\n", errno);
michael@0 1281 #endif
michael@0 1282 }
michael@0 1283 if (setsockopt(SCTP_BASE_VAR(userspace_rawsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
michael@0 1284 #if defined(__Userspace_os_Windows)
michael@0 1285 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
michael@0 1286 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
michael@0 1287 #else
michael@0 1288 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/IPv6 (errno = %d).\n", errno);
michael@0 1289 close(SCTP_BASE_VAR(userspace_rawsctp6));
michael@0 1290 #endif
michael@0 1291 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
michael@0 1292 } else {
michael@0 1293 memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6));
michael@0 1294 #ifdef HAVE_SIN6_LEN
michael@0 1295 addr_ipv6.sin6_len = sizeof(struct sockaddr_in6);
michael@0 1296 #endif
michael@0 1297 addr_ipv6.sin6_family = AF_INET6;
michael@0 1298 addr_ipv6.sin6_port = htons(0);
michael@0 1299 addr_ipv6.sin6_addr = in6addr_any;
michael@0 1300 if (bind(SCTP_BASE_VAR(userspace_rawsctp6), (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) {
michael@0 1301 #if defined(__Userspace_os_Windows)
michael@0 1302 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", WSAGetLastError());
michael@0 1303 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
michael@0 1304 #else
michael@0 1305 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/IPv6 (errno = %d).\n", errno);
michael@0 1306 close(SCTP_BASE_VAR(userspace_rawsctp6));
michael@0 1307 #endif
michael@0 1308 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
michael@0 1309 } else {
michael@0 1310 setReceiveBufferSize(SCTP_BASE_VAR(userspace_rawsctp6), SB_RAW); /* 128K */
michael@0 1311 setSendBufferSize(SCTP_BASE_VAR(userspace_rawsctp6), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
michael@0 1312 }
michael@0 1313 }
michael@0 1314 }
michael@0 1315 }
michael@0 1316 }
michael@0 1317 if (SCTP_BASE_VAR(userspace_udpsctp6) == -1) {
michael@0 1318 if ((SCTP_BASE_VAR(userspace_udpsctp6) = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
michael@0 1319 #if defined(__Userspace_os_Windows)
michael@0 1320 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
michael@0 1321 #else
michael@0 1322 SCTPDBG(SCTP_DEBUG_USR, "Can't create socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
michael@0 1323 #endif
michael@0 1324 }
michael@0 1325 #if defined(IPV6_RECVPKTINFO)
michael@0 1326 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_RECVPKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
michael@0 1327 #if defined(__Userspace_os_Windows)
michael@0 1328 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
michael@0 1329 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
michael@0 1330 #else
michael@0 1331 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_RECVPKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
michael@0 1332 close(SCTP_BASE_VAR(userspace_udpsctp6));
michael@0 1333 #endif
michael@0 1334 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
michael@0 1335 } else {
michael@0 1336 #else
michael@0 1337 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_PKTINFO, (const void *)&on, (int)sizeof(int)) < 0) {
michael@0 1338 #if defined(__Userspace_os_Windows)
michael@0 1339 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
michael@0 1340 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
michael@0 1341 #else
michael@0 1342 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_PKTINFO on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
michael@0 1343 close(SCTP_BASE_VAR(userspace_udpsctp6));
michael@0 1344 #endif
michael@0 1345 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
michael@0 1346 } else {
michael@0 1347 #endif
michael@0 1348 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&on, (socklen_t)sizeof(on)) < 0) {
michael@0 1349 #if defined(__Userspace_os_Windows)
michael@0 1350 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
michael@0 1351 #else
michael@0 1352 SCTPDBG(SCTP_DEBUG_USR, "Can't set IPV6_V6ONLY on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
michael@0 1353 #endif
michael@0 1354 }
michael@0 1355 if (setsockopt(SCTP_BASE_VAR(userspace_udpsctp6), SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)) < 0) {
michael@0 1356 #if defined(__Userspace_os_Windows)
michael@0 1357 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
michael@0 1358 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
michael@0 1359 #else
michael@0 1360 SCTPDBG(SCTP_DEBUG_USR, "Can't set timeout on socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
michael@0 1361 close(SCTP_BASE_VAR(userspace_udpsctp6));
michael@0 1362 #endif
michael@0 1363 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
michael@0 1364 } else {
michael@0 1365 memset((void *)&addr_ipv6, 0, sizeof(struct sockaddr_in6));
michael@0 1366 #ifdef HAVE_SIN6_LEN
michael@0 1367 addr_ipv6.sin6_len = sizeof(struct sockaddr_in6);
michael@0 1368 #endif
michael@0 1369 addr_ipv6.sin6_family = AF_INET6;
michael@0 1370 addr_ipv6.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
michael@0 1371 addr_ipv6.sin6_addr = in6addr_any;
michael@0 1372 if (bind(SCTP_BASE_VAR(userspace_udpsctp6), (const struct sockaddr *)&addr_ipv6, sizeof(struct sockaddr_in6)) < 0) {
michael@0 1373 #if defined(__Userspace_os_Windows)
michael@0 1374 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", WSAGetLastError());
michael@0 1375 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
michael@0 1376 #else
michael@0 1377 SCTPDBG(SCTP_DEBUG_USR, "Can't bind socket for SCTP/UDP/IPv6 (errno = %d).\n", errno);
michael@0 1378 close(SCTP_BASE_VAR(userspace_udpsctp6));
michael@0 1379 #endif
michael@0 1380 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
michael@0 1381 } else {
michael@0 1382 setReceiveBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K */
michael@0 1383 setSendBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */
michael@0 1384 }
michael@0 1385 }
michael@0 1386 }
michael@0 1387 }
michael@0 1388 #endif
michael@0 1389 #if !defined(__Userspace_os_Windows)
michael@0 1390 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
michael@0 1391 #if defined(INET) || defined(INET6)
michael@0 1392 if (SCTP_BASE_VAR(userspace_route) != -1) {
michael@0 1393 int rc;
michael@0 1394
michael@0 1395 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadroute), NULL, &recv_function_route, NULL))) {
michael@0 1396 SCTPDBG(SCTP_DEBUG_USR, "Can't start routing thread (%d).\n", rc);
michael@0 1397 close(SCTP_BASE_VAR(userspace_route));
michael@0 1398 SCTP_BASE_VAR(userspace_route) = -1;
michael@0 1399 }
michael@0 1400 }
michael@0 1401 #endif
michael@0 1402 #endif
michael@0 1403 #if defined(INET)
michael@0 1404 if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
michael@0 1405 int rc;
michael@0 1406
michael@0 1407 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw), NULL, &recv_function_raw, NULL))) {
michael@0 1408 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread (%d).\n", rc);
michael@0 1409 close(SCTP_BASE_VAR(userspace_rawsctp));
michael@0 1410 SCTP_BASE_VAR(userspace_rawsctp) = -1;
michael@0 1411 }
michael@0 1412 }
michael@0 1413 if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
michael@0 1414 int rc;
michael@0 1415
michael@0 1416 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp), NULL, &recv_function_udp, NULL))) {
michael@0 1417 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread (%d).\n", rc);
michael@0 1418 close(SCTP_BASE_VAR(userspace_udpsctp));
michael@0 1419 SCTP_BASE_VAR(userspace_udpsctp) = -1;
michael@0 1420 }
michael@0 1421 }
michael@0 1422 #endif
michael@0 1423 #if defined(INET6)
michael@0 1424 if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
michael@0 1425 int rc;
michael@0 1426
michael@0 1427 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw6), NULL, &recv_function_raw6, NULL))) {
michael@0 1428 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread (%d).\n", rc);
michael@0 1429 close(SCTP_BASE_VAR(userspace_rawsctp6));
michael@0 1430 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
michael@0 1431 }
michael@0 1432 }
michael@0 1433 if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
michael@0 1434 int rc;
michael@0 1435
michael@0 1436 if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp6), NULL, &recv_function_udp6, NULL))) {
michael@0 1437 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread (%d).\n", rc);
michael@0 1438 close(SCTP_BASE_VAR(userspace_udpsctp6));
michael@0 1439 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
michael@0 1440 }
michael@0 1441 }
michael@0 1442 #endif
michael@0 1443 #else
michael@0 1444 #if defined(INET)
michael@0 1445 if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
michael@0 1446 if ((SCTP_BASE_VAR(recvthreadraw) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw, NULL, 0, NULL)) == NULL) {
michael@0 1447 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread.\n");
michael@0 1448 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
michael@0 1449 SCTP_BASE_VAR(userspace_rawsctp) = -1;
michael@0 1450 }
michael@0 1451 }
michael@0 1452 if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
michael@0 1453 if ((SCTP_BASE_VAR(recvthreadudp) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp, NULL, 0, NULL)) == NULL) {
michael@0 1454 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread.\n");
michael@0 1455 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
michael@0 1456 SCTP_BASE_VAR(userspace_udpsctp) = -1;
michael@0 1457 }
michael@0 1458 }
michael@0 1459 #endif
michael@0 1460 #if defined(INET6)
michael@0 1461 if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
michael@0 1462 if ((SCTP_BASE_VAR(recvthreadraw6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw6, NULL, 0, NULL)) == NULL) {
michael@0 1463 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread.\n");
michael@0 1464 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
michael@0 1465 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
michael@0 1466 }
michael@0 1467 }
michael@0 1468 if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
michael@0 1469 if ((SCTP_BASE_VAR(recvthreadudp6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp6, NULL, 0, NULL)) == NULL) {
michael@0 1470 SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread.\n");
michael@0 1471 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
michael@0 1472 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
michael@0 1473 }
michael@0 1474 }
michael@0 1475 #endif
michael@0 1476 #endif
michael@0 1477 }
michael@0 1478
michael@0 1479 void
michael@0 1480 recv_thread_destroy(void)
michael@0 1481 {
michael@0 1482 #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD)
michael@0 1483 #if defined(INET) || defined(INET6)
michael@0 1484 if (SCTP_BASE_VAR(userspace_route) != -1) {
michael@0 1485 close(SCTP_BASE_VAR(userspace_route));
michael@0 1486 }
michael@0 1487 #endif
michael@0 1488 #endif
michael@0 1489 #if defined(INET)
michael@0 1490 if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
michael@0 1491 #if defined(__Userspace_os_Windows)
michael@0 1492 closesocket(SCTP_BASE_VAR(userspace_rawsctp));
michael@0 1493 #else
michael@0 1494 close(SCTP_BASE_VAR(userspace_rawsctp));
michael@0 1495 #endif
michael@0 1496 }
michael@0 1497 if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
michael@0 1498 #if defined(__Userspace_os_Windows)
michael@0 1499 closesocket(SCTP_BASE_VAR(userspace_udpsctp));
michael@0 1500 #else
michael@0 1501 close(SCTP_BASE_VAR(userspace_udpsctp));
michael@0 1502 #endif
michael@0 1503 }
michael@0 1504 #endif
michael@0 1505 #if defined(INET6)
michael@0 1506 if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
michael@0 1507 #if defined(__Userspace_os_Windows)
michael@0 1508 closesocket(SCTP_BASE_VAR(userspace_rawsctp6));
michael@0 1509 #else
michael@0 1510 close(SCTP_BASE_VAR(userspace_rawsctp6));
michael@0 1511 #endif
michael@0 1512 }
michael@0 1513 if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
michael@0 1514 #if defined(__Userspace_os_Windows)
michael@0 1515 closesocket(SCTP_BASE_VAR(userspace_udpsctp6));
michael@0 1516 #else
michael@0 1517 close(SCTP_BASE_VAR(userspace_udpsctp6));
michael@0 1518 #endif
michael@0 1519 }
michael@0 1520 #endif
michael@0 1521 }
michael@0 1522 #else
michael@0 1523 int foo;
michael@0 1524 #endif

mercurial