Coverage Report

Created: 2025-08-28 06:37

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