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