1 /* $Id$
2 * --------------------------------------------------------------------------
3 *
4 * //===== //===== ===//=== //===// // // //===//
5 * // // // // // // // // //
6 * //====// // // //===// // // //===<<
7 * // // // // // // // //
8 * ======// //===== // // //===== // //===//
9 *
10 * -------------- An SCTP implementation according to RFC 4960 --------------
11 *
12 * Copyright (C) 2000 by Siemens AG, Munich, Germany.
13 * Copyright (C) 2001-2004 Andreas Jungmaier
14 * Copyright (C) 2004-2019 Thomas Dreibholz
15 *
16 * Acknowledgements:
17 * Realized in co-operation between Siemens AG and the University of
18 * Duisburg-Essen, Institute for Experimental Mathematics, Computer
19 * Networking Technology group.
20 * This work was partially funded by the Bundesministerium fuer Bildung und
21 * Forschung (BMBF) of the Federal Republic of Germany
22 * (Förderkennzeichen 01AK045).
23 * The authors alone are responsible for the contents.
24 *
25 * This library is free software: you can redistribute it and/or modify it
26 * under the terms of the GNU Lesser General Public License as published by
27 * the Free Software Foundation, either version 2.1 of the License, or
28 * (at your option) any later version.
29 *
30 * This library is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
34 *
35 * You should have received a copy of the GNU Lesser General Public License
36 * along with this program. If not, see <http://www.gnu.org/licenses/>.
37 *
38 * Contact: sctp-discussion@sctp.de
39 * dreibh@iem.uni-due.de
40 * tuexen@fh-muenster.de
41 * andreas.jungmaier@web.de
42 */
43
44 #include "adaptation.h"
45 #include "timer_list.h"
46
47 #include <stdio.h>
48 #include <string.h>
49 #include <errno.h>
50
51
52 #ifndef WIN32
53 #include <sys/time.h>
54 #include <netinet/in_systm.h>
55 #include <netinet/ip.h>
56 #include <netdb.h>
57 #include <arpa/inet.h> /* for inet_ntoa() under both SOLARIS/LINUX */
58 #include <sys/errno.h>
59 #include <sys/uio.h> /* for struct iovec */
60 #include <sys/param.h>
61 #include <sys/ioctl.h>
62 #include <netinet/tcp.h>
63 #include <net/if.h>
64 #ifdef SCTP_OVER_UDP
65 #include <netinet/udp.h>
66 #endif
67 #else
68 #include <winsock2.h>
69 #include <WS2tcpip.h>
70
71 #include <sys/timeb.h>
72 #define ADDRESS_LIST_BUFFER_SIZE 4096
73 struct ip
74 {
75 unsigned char ip_verlen;
76 unsigned char ip_tos; /* type of service */
77 u_short ip_len; /* total length */
78 u_short ip_id; /* identification */
79 u_short ip_off; /* fragment offset field */
80 unsigned char ip_ttl; /* time to live */
81 unsigned char ip_p; /* protocol */
82 u_short ip_sum; /* checksum */
83 struct in_addr ip_src, ip_dst; /* source and dest address */
84 };
85
86 #define IFNAMSIZ 64 /* Windows has no IFNAMSIZ. Just define it. */
87 #endif
88
89 #ifdef HAVE_IPV6
90 #if defined (LINUX)
91 #include <netinet/ip6.h>
92 #else
93 /* include files for IPv6 header structs */
94 #endif
95 #endif
96
97 #if defined (LINUX)
98 #define LINUX_PROC_IPV6_FILE "/proc/net/if_inet6"
99 #include <asm/types.h>
100 #include <linux/rtnetlink.h>
101 #else /* this may not be okay for SOLARIS !!! */
102 #ifndef WIN32
103 #define USES_BSD_4_4_SOCKET
104 #include <net/if.h>
105 #include <net/if_dl.h>
106 #include <net/if_types.h>
107 #include <net/route.h>
108 #ifndef SOLARIS
109 #include <net/if_var.h>
110 #include <machine/param.h>
111 #define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
112 #define NEXT_SA(ap) ap = (struct sockaddr *) \
113 ((caddr_t) ap + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof (u_long)) : sizeof(u_long)))
114 #else
115 #include <sys/sockio.h>
116 #define NEXT_SA(ap) ap = (struct sockaddr *) ((caddr_t) ap + sizeof(struct sockaddr))
117 #define RTAX_MAX RTA_NUMBITS
118 #define RTAX_IFA 5
119 #define _NO_SIOCGIFMTU_
120 #endif
121 #endif
122 #endif
123
124 #define IFA_BUFFER_LENGTH 1024
125
126 #ifndef IN_EXPERIMENTAL
127 #define IN_EXPERIMENTAL(a) ((((int) (a)) & 0xf0000000) == 0xf0000000)
128 #endif
129
130 #ifndef IN_BADCLASS
131 #define IN_BADCLASS(a) IN_EXPERIMENTAL((a))
132 #endif
133
134 #ifdef HAVE_SYS_POLL_H
135 #include <sys/poll.h>
136 #else
137 #define POLLIN 0x001
138 #define POLLPRI 0x002
139 #define POLLOUT 0x004
140 #define POLLERR 0x008
141 #endif
142
143 #ifdef LIBRARY_DEBUG
144 #define ENTER_TIMER_DISPATCHER printf("Entering timer dispatcher.\n"); fflush(stdout);
145 #define LEAVE_TIMER_DISPATCHER printf("Leaving timer dispatcher.\n"); fflush(stdout);
146 #define ENTER_EVENT_DISPATCHER printf("Entering event dispatcher.\n"); fflush(stdout);
147 #define LEAVE_EVENT_DISPATCHER printf("Leaving event dispatcher.\n"); fflush(stdout);
148 #else
149 #define ENTER_TIMER_DISPATCHER
150 #define LEAVE_TIMER_DISPATCHER
151 #define ENTER_EVENT_DISPATCHER
152 #define LEAVE_EVENT_DISPATCHER
153 #endif
154
155
156 #define POLL_FD_UNUSED -1
157 #define NUM_FDS 20
158
159 #define EVENTCB_TYPE_SCTP 1
160 #define EVENTCB_TYPE_UDP 2
161 #define EVENTCB_TYPE_USER 3
162 #define EVENTCB_TYPE_ROUTING 4
163
164
165 #ifdef SCTP_OVER_UDP
166 int dummy_sctp_udp;
167 int dummy_sctpv6_udp;
168
inet_checksum(const void * ptr,size_t count)169 guint32 inet_checksum(const void* ptr, size_t count)
170 {
171 guint16* addr = (guint16*)ptr;
172 guint32 sum = 0;
173
174 while(count > 1) {
175 sum += *(guint16*)addr++;
176 count -= 2;
177 }
178
179 if(count > 0) {
180 sum += *(unsigned char*)addr;
181 }
182
183 while(sum>>16) {
184 sum = (sum & 0xffff) + (sum >> 16);
185 }
186
187 return(~sum);
188 }
189 #endif
190
191
192 /**
193 * Structure for callback events. The function "action" is called by the event-handler,
194 * when an event occurs on the file-descriptor.
195 */
196 struct event_cb
197 {
198 int sfd;
199 int eventcb_type;
200 /* pointer to possible arguments, associations etc. */
201 void *arg1;
202 void *arg2;
203 void (*action) ();
204 void* userData;
205 };
206
207 struct data {
208 char* dat;
209 int len;
210 void (*cb)();
211 };
212
213 #ifdef HAVE_RANDOM
214 static long rstate[2];
215 #endif
216
217 #ifdef WIN32
218 struct input_data {
219 DWORD len;
220 char buffer[1024];
221 HANDLE event, eventback;
222 };
223
224
225
226 static int fds[NUM_FDS];
227 static int fdnum;
228 HANDLE hEvent, handles[2];
229 static HANDLE stdin_thread_handle;
230 WSAEVENT stdinevent;
231 static struct input_data idata;
232 #endif
233
234 unsigned int
adl_random(void)235 adl_random(void)
236 {
237 #ifdef HAVE_RANDOM
238 return (unsigned int) random();
239 #else
240 return (unsigned int)rand();
241 #endif
242 }
243
244 /*
245 * An extended poll() implementation based on select()
246 *
247 * During the select() call, another thread may change the FD list,
248 * a revision number keeps track that results are only reported
249 * when the FD has already been registered before select() has
250 * been called. Otherwise, the event will be reported during the
251 * next select() call.
252 * This solves the following problem:
253 * - Thread #1 registers user callback for socket n
254 * - Thread #2 starts select()
255 * - A read event on socket n occurs
256 * - extendedPoll() returns
257 * - Thread #2 sends a notification (e.g. using pthread_condition) to thread #1
258 * - Thread #2 again starts select()
259 * - Since Thread #1 has not yet read the data, there is a read event again
260 * - Now, the thread scheduler selects the next thread
261 * - Thread #1 now gets CPU time, deregisters the callback for socket n
262 * and completely reads the incoming data. There is no more data to read!
263 * - Thread #1 again registers user callback for socket n
264 * - Now, thread #2 gets the CPU again and can send a notification
265 * about the assumed incoming data to thread #1
266 * - Thread #1 gets the read notification and tries to read. There is no
267 * data, so the socket blocks (possibily forever!) or the read call
268 * fails.
269 */
270
271 static long revision = 0;
272
273 struct extendedpollfd {
274 int fd;
275 short int events;
276 short int revents;
277 long revision;
278 };
279
extendedPoll(struct extendedpollfd * fdlist,int * count,int time,void (* lock)(void * data),void (* unlock)(void * data),void * data)280 int extendedPoll(struct extendedpollfd* fdlist,
281 int* count,
282 int time,
283 void (*lock)(void* data),
284 void (*unlock)(void* data),
285 void* data)
286 {
287 struct timeval timeout;
288 struct timeval* to;
289 fd_set readfdset;
290 fd_set writefdset;
291 fd_set exceptfdset;
292 int fdcount;
293 int n;
294 int ret;
295 int i;
296
297 if(time < 0) {
298 to = NULL;
299 }
300 else {
301 to = &timeout;
302 timeout.tv_sec = time / 1000;
303 timeout.tv_usec = (time % 1000) * 1000;
304 }
305
306
307 /* Initialize structures for select() */
308 fdcount = 0;
309 n = 0;
310 FD_ZERO(&readfdset);
311 FD_ZERO(&writefdset);
312 FD_ZERO(&exceptfdset);
313
314 for(i = 0; i < *count; i++) {
315 if(fdlist[i].fd < 0) {
316 continue;
317 }
318 n = MAX(n,fdlist[i].fd);
319 if(fdlist[i].events & (POLLIN|POLLPRI)) {
320 FD_SET(fdlist[i].fd, &readfdset);
321 }
322 if(fdlist[i].events & POLLOUT) {
323 FD_SET(fdlist[i].fd, &writefdset);
324 }
325 if(fdlist[i].events & (POLLIN|POLLOUT)) {
326 FD_SET(fdlist[i].fd, &exceptfdset);
327 }
328 fdcount++;
329 }
330
331
332 if(fdcount == 0) {
333 ret = 0;
334 }
335 else {
336 /*
337 * Set the revision number of all entries to the current revision.
338 */
339 for(i = 0; i < *count; i++) {
340 fdlist[i].revision = revision;
341 }
342
343 /*
344 * Increment the revision number by one -> New entries made by
345 * another thread during select() call will get this new revision number.
346 */
347 revision++;
348
349
350 if(unlock) {
351 unlock(data);
352 }
353
354 ret = select(n + 1, &readfdset, &writefdset, &exceptfdset, to);
355
356 if(lock) {
357 lock(data);
358 }
359
360
361 for(i = 0; i < *count; i++) {
362 fdlist[i].revents = 0;
363 if(fdlist[i].revision >= revision) {
364 FD_CLR(fdlist[i].fd, &readfdset);
365 FD_CLR(fdlist[i].fd, &writefdset);
366 FD_CLR(fdlist[i].fd, &exceptfdset);
367 }
368 }
369
370 if(ret > 0) {
371 for(i = 0; i < *count; i++) {
372 fdlist[i].revents = 0;
373 /*
374 * If fdlist's revision is equal the current revision, then the fdlist entry
375 * has been added by another thread during the poll() call. If this is the
376 * case, skip the results here (they will be reported again when select()
377 * is called the next time).
378 */
379 if(fdlist[i].revision < revision) {
380 if((fdlist[i].events & POLLIN) && FD_ISSET(fdlist[i].fd, &readfdset)) {
381 fdlist[i].revents |= POLLIN;
382 }
383 if((fdlist[i].events & POLLOUT) && FD_ISSET(fdlist[i].fd, &writefdset)) {
384 fdlist[i].revents |= POLLOUT;
385 }
386 if((fdlist[i].events & (POLLIN|POLLOUT)) && FD_ISSET(fdlist[i].fd, &exceptfdset)) {
387 fdlist[i].revents |= POLLERR;
388 }
389 }
390 }
391 }
392 }
393
394 return(ret);
395 }
396
397
398
399 /* a static counter - for stats we should have more counters ! */
400 static unsigned int number_of_sendevents = 0;
401 /* a static receive buffer */
402 static unsigned char rbuf[MAX_MTU_SIZE + 20];
403 /* a static value that keeps currently treated timer id */
404 static unsigned int current_tid = 0;
405
406
407 static struct extendedpollfd poll_fds[NUM_FDS];
408 static int num_of_fds = 0;
409
410 static int sctp_sfd = -1; /* socket fd for standard SCTP port.... */
411
412 #ifdef HAVE_IPV6
413 static int sctpv6_sfd = -1;
414 #endif
415
416 /* will be added back later....
417 static int icmp_sfd = -1; */ /* socket fd for ICMP messages */
418
419 static struct event_cb *event_callbacks[NUM_FDS];
420
421 /**
422 * converts address-string (hex for ipv6, dotted decimal for ipv4
423 * to a sockunion structure
424 * @return 0 for success, else -1.
425 */
adl_str2sockunion(guchar * str,union sockunion * su)426 int adl_str2sockunion(guchar * str, union sockunion *su)
427 {
428 int ret;
429
430 memset((void*)su, 0, sizeof(union sockunion));
431
432 #ifndef WIN32
433 ret = inet_aton((const char *)str, &su->sin.sin_addr);
434 #else
435 if ((su->sin.sin_addr.s_addr = inet_addr(str)) == INADDR_NONE)
436 ret=0;
437 else {
438 ret=1;
439 }
440 #endif
441 if (ret > 0) { /* Valid IPv4 address format. */
442 su->sin.sin_family = AF_INET;
443 #ifdef HAVE_SIN_LEN
444 su->sin.sin_len = sizeof(struct sockaddr_in);
445 #endif /* HAVE_SIN_LEN */
446 return 0;
447 }
448 #ifdef HAVE_IPV6
449 ret = inet_pton(AF_INET6, (const char *)str, &su->sin6.sin6_addr);
450 if (ret > 0) { /* Valid IPv6 address format. */
451 su->sin6.sin6_family = AF_INET6;
452 #ifdef SIN6_LEN
453 su->sin6.sin6_len = sizeof(struct sockaddr_in6);
454 #endif /* SIN6_LEN */
455 su->sin6.sin6_scope_id = 0;
456 return 0;
457 }
458 #endif /* HAVE_IPV6 */
459 return -1;
460 }
461
462
adl_sockunion2str(union sockunion * su,guchar * buf,size_t len)463 int adl_sockunion2str(union sockunion *su, guchar * buf, size_t len)
464 {
465 char ifnamebuffer[IFNAMSIZ];
466 const char* ifname;
467
468 if (su->sa.sa_family == AF_INET){
469 if (len > 16) len = 16;
470 strncpy((char *)buf, inet_ntoa(su->sin.sin_addr), len);
471 return(1);
472 }
473 #ifdef HAVE_IPV6
474 else if (su->sa.sa_family == AF_INET6) {
475 if (inet_ntop(AF_INET6, &su->sin6.sin6_addr, (char *)buf, len)==NULL) return 0;
476 if (IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr)) {
477 ifname = if_indextoname(su->sin6.sin6_scope_id, (char*)&ifnamebuffer);
478 if(ifname == NULL) {
479 /* printf("Bad scope: %s!\n", buf); */
480 return(0); /* Bad scope ID! */
481 }
482 if(strlen((const char*)buf) + strlen(ifname) + 2 >= len) {
483 return(0); /* Not enough space! */
484 }
485 strcat((char*)buf, "%");
486 strcat((char*)buf, ifname);
487 }
488 return (1);
489 }
490 #endif /* HAVE_IPV6 */
491 return 0;
492 }
493
adl_equal_address(union sockunion * a,union sockunion * b)494 boolean adl_equal_address(union sockunion * a, union sockunion * b)
495 {
496 #ifdef HAVE_IPV6
497 union sockunion my_a;
498 union sockunion my_b;
499 const union sockunion* one;
500 const union sockunion* two;
501 unsigned int count;
502
503 #if defined __APPLE__ || defined FreeBSD
504 #define s6_addr32 __u6_addr.__u6_addr32
505 #endif
506
507 if(a->sa.sa_family == AF_INET) {
508 my_a.sin6.sin6_family = AF_INET6;
509 my_a.sin6.sin6_port = a->sin.sin_port;
510 my_a.sin6.sin6_addr.s6_addr32[0] = 0x00000000;
511 my_a.sin6.sin6_addr.s6_addr32[1] = 0x00000000;
512 my_a.sin6.sin6_addr.s6_addr32[2] = 0x00000000;
513 my_a.sin6.sin6_addr.s6_addr32[3] = a->sin.sin_addr.s_addr;
514 one = &my_a;
515 }
516 else {
517 one = a;
518 }
519 if(b->sa.sa_family == AF_INET) {
520 my_b.sin6.sin6_family = AF_INET6;
521 my_b.sin6.sin6_port = b->sin.sin_port;
522 my_b.sin6.sin6_addr.s6_addr32[0] = 0x00000000;
523 my_b.sin6.sin6_addr.s6_addr32[1] = 0x00000000;
524 my_b.sin6.sin6_addr.s6_addr32[2] = 0x00000000;
525 my_b.sin6.sin6_addr.s6_addr32[3] = b->sin.sin_addr.s_addr;
526 two = &my_b;
527 }
528 else {
529 two = b;
530 }
531 #else
532 const union sockunion* one = a;
533 const union sockunion* two = b;
534 #endif
535
536 switch (sockunion_family(one)) {
537 case AF_INET:
538 if (sockunion_family(two) != AF_INET)
539 return FALSE;
540 return (sock2ip(one) == sock2ip(two));
541 break;
542 #ifdef HAVE_IPV6
543 case AF_INET6:
544 if (sockunion_family(two) != AF_INET6)
545 return FALSE;
546 for (count = 0; count < 16; count++)
547 if (sock2ip6(one)[count] != sock2ip6(two)[count])
548 return FALSE;
549 return TRUE;
550 break;
551 #endif
552 default:
553 error_logi(ERROR_MAJOR, "Address family %d not supported", sockunion_family(one));
554 return FALSE;
555 break;
556 }
557 }
558
559
adl_setReceiveBufferSize(int sfd,int new_size)560 int adl_setReceiveBufferSize(int sfd,int new_size)
561 {
562 int ch = new_size;
563 if (setsockopt (sfd, SOL_SOCKET, SO_RCVBUF, (void*)&ch, sizeof(ch)) < 0) {
564 error_log(ERROR_MAJOR, "setsockopt: SO_RCVBUF failed !");
565 return -1;
566 }
567 event_logi(INTERNAL_EVENT_0, "set receive buffer size to : %d bytes",ch);
568 return 0;
569 }
570
571
adl_open_sctp_socket(int af,int * myRwnd)572 gint adl_open_sctp_socket(int af, int* myRwnd)
573 {
574 int sfd, ch;
575 socklen_t opt_size;
576 #ifdef WIN32
577 struct sockaddr_in me;
578 #endif
579
580 #ifdef SCTP_OVER_UDP
581 if ((sfd = socket(af, SOCK_RAW, IPPROTO_UDP)) < 0) {
582 #else
583 if ((sfd = socket(af, SOCK_RAW, IPPROTO_SCTP)) < 0) {
584 #endif
585 return sfd;
586 }
587
588 #ifdef WIN32
589 /* binding to INADDR_ANY to make Windows happy... */
590 memset((void *)&me, 0, sizeof(me));
591 me.sin_family = AF_INET;
592 #ifdef HAVE_SIN_LEN
593 me.sin_len = sizeof(me);
594 #endif
595 me.sin_addr.s_addr = INADDR_ANY;
596 bind(sfd, (const struct sockaddr *)&me, sizeof(me));
597 #endif
598
599 switch (af) {
600 case AF_INET:
601 *myRwnd = 0;
602 opt_size=sizeof(*myRwnd);
603 if (getsockopt (sfd, SOL_SOCKET, SO_RCVBUF, (void*)myRwnd, &opt_size) < 0) {
604 error_log(ERROR_FATAL, "getsockopt: SO_RCVBUF failed !");
605 *myRwnd = -1;
606 }
607 event_logi(INTERNAL_EVENT_0, "receive buffer size initially is : %d", *myRwnd);
608
609 #if defined (LINUX)
610 adl_setReceiveBufferSize(sfd, 10*0xFFFF);
611
612 ch = IP_PMTUDISC_DO;
613 if (setsockopt(sfd, IPPROTO_IP, IP_MTU_DISCOVER, (char *) &ch, sizeof(ch)) < 0) {
614 error_log(ERROR_FATAL, "setsockopt: IP_PMTU_DISCOVER failed !");
615 }
616 opt_size=sizeof(*myRwnd);
617 if (getsockopt (sfd, SOL_SOCKET, SO_RCVBUF, (void*)myRwnd, &opt_size) < 0) {
618 error_log(ERROR_FATAL, "getsockopt: SO_RCVBUF failed !");
619 *myRwnd = -1;
620 }
621 event_logi(INTERNAL_EVENT_0, "receive buffer size finally is : %d", *myRwnd);
622 #endif
623 break;
624 #ifdef HAVE_IPV6
625 case AF_INET6:
626 *myRwnd = 0;
627 opt_size=sizeof(*myRwnd);
628 if (getsockopt (sfd, SOL_SOCKET, SO_RCVBUF, (void*)myRwnd, &opt_size) < 0) {
629 error_log(ERROR_FATAL, "getsockopt: SO_RCVBUF failed !");
630 *myRwnd = -1;
631 }
632 event_logi(INTERNAL_EVENT_0, "receive buffer size is : %d",*myRwnd);
633 /* also receive packetinfo on IPv6 sockets, for getting dest address */
634 ch = 1;
635 #ifdef HAVE_IPV6_RECVPKTINFO
636 /* IMPORTANT:
637 The new option name is now IPV6_RECVPKTINFO!
638 IPV6_PKTINFO expects an extended parameter structure now
639 and had to be replaced to provide the original functionality! */
640 if (setsockopt(sfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &ch, sizeof(ch)) < 0) {
641 error_log(ERROR_FATAL, "setsockopt: IPV6_RECVPKTINFO failed");
642 abort();
643 }
644 #else
645 if (setsockopt(sfd, IPPROTO_IPV6, IPV6_PKTINFO, &ch, sizeof(ch)) < 0) {
646 error_log(ERROR_FATAL, "setsockopt: IPV6_PKTINFO failed");
647 abort();
648 }
649 #endif
650 break;
651 #endif
652 default:
653 error_log(ERROR_MINOR, "Unknown address family.");
654 break;
655 }
656 event_logi(INTERNAL_EVENT_0, "Created raw socket %d with options\n", sfd);
657 return (sfd);
658 }
659
660
661 gint adl_get_sctpv4_socket(void)
662 {
663 /* this is a static variable ! */
664 return sctp_sfd;
665 }
666
667
668 #ifdef HAVE_IPV6
669 gint adl_get_sctpv6_socket(void)
670 {
671 /* this is a static variable ! */
672 return sctpv6_sfd;
673 }
674 #endif
675
676
677 /**
678 * This function creates a UDP socket bound to localhost, for asynchronous
679 * interprocess communication with an Upper Layer process.
680 * @return the socket file descriptor. Used to register a callback function
681 */
682 int adl_open_udp_socket(union sockunion* me)
683 {
684 guchar buf[1000];
685 int ch, sfd;
686
687 switch (sockunion_family(me)) {
688 case AF_INET:
689 if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
690 error_log(ERROR_FATAL, "SCTP: socket creation failed for UDP socket !");
691 }
692 ch = bind(sfd, (struct sockaddr *)me, sizeof(struct sockaddr_in));
693 adl_sockunion2str(me, buf, SCTP_MAX_IP_LEN);
694 event_logiii(VERBOSE,
695 " adl_open_udp_socket : Create socket %u, binding to address %s, result %d",sfd, buf, ch);
696 if (ch == 0)
697 return (sfd);
698 return -1;
699 break;
700 #ifdef HAVE_IPV6
701 case AF_INET6:
702 if ((sfd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
703 error_log(ERROR_FATAL, "SCTP: socket creation failed for UDPv6 socket");
704 }
705 ch = bind(sfd, (struct sockaddr *)me, sizeof(struct sockaddr_in6));
706 adl_sockunion2str(me, buf, SCTP_MAX_IP_LEN);
707 event_logiii(VERBOSE,
708 " adl_open_udp_socket : Create socket %u, binding to address %s, result %d",sfd, buf, ch);
709 if (ch == 0)
710 return (sfd);
711 return -1;
712 break;
713 #endif
714 default:
715 return -1;
716 break;
717 }
718
719 }
720
721 /**
722 * function to be called when we get a message from a peer sctp instance in the poll loop
723 * @param sfd the socket file descriptor where data can be read...
724 * @param buf pointer to a buffer, where we data is stored
725 * @param len number of bytes to be sent, including the ip header !
726 * @param address, where data goes from
727 * @param dest_len size of the address
728 * @return returns number of bytes actually sent, or error
729 */
730 int adl_sendUdpData(int sfd, unsigned char* buf, int length,
731 unsigned char destination[], unsigned short dest_port)
732 {
733 union sockunion dest_su;
734 int dest_len;
735 int result;
736
737 if (sfd < 0) {
738 error_log(ERROR_MAJOR, "You are trying to send UDP data on an invalid fd");
739 return -1;
740 }
741
742 if ((sfd == sctp_sfd)
743 #ifdef HAVE_IPV6
744 || (sfd == sctpv6_sfd)
745 #endif
746 ) {
747 error_log(ERROR_MAJOR, "You are trying to send UDP data on a SCTP socket");
748 return -1;
749 }
750 result = adl_str2sockunion(destination, &dest_su);
751
752 if (result != 0) {
753 error_logi(ERROR_MAJOR, "Invalid destination address in sctp_sendUdpData(%s)",destination);
754 return -1;
755 }
756 if (buf == NULL) {
757 error_log(ERROR_MAJOR, "Invalid buffer sctp_sendUdpData()");
758 return -1;
759 }
760 if (dest_port == 0) {
761 error_log(ERROR_MAJOR, "Invalid port in sctp_sendUdpData()");
762 return -1;
763 }
764 switch (sockunion_family(&dest_su)) {
765 case AF_INET:
766 dest_su.sin.sin_port = htons(dest_port);
767 dest_len = sizeof(struct sockaddr_in);
768 result = sendto(sfd, buf, length, 0, (struct sockaddr *) &(dest_su.sin), dest_len);
769 break;
770 #ifdef HAVE_IPV6
771 case AF_INET6:
772 dest_su.sin6.sin6_port = htons(dest_port);
773 dest_len = sizeof(struct sockaddr_in6);
774 result = sendto(sfd, buf, length, 0, (struct sockaddr *) &(dest_su.sin6), dest_len);
775 break;
776 #endif
777 default :
778 error_logi(ERROR_MAJOR, "Invalid address family in sctp_sendUdpData(%s)",destination);
779 result = -1;
780 break;
781 }
782 return result;
783 }
784
785
786
787 /**
788 * function to be called when library sends a message on an SCTP socket
789 * @param sfd the socket file descriptor where data will be sent
790 * @param buf pointer to a buffer, where data to be sent is stored
791 * @param len number of bytes to be sent
792 * @param destination address, where data is to be sent
793 * @param dest_len size of the address
794 * @return returns number of bytes actually sent, or error
795 */
796 int adl_send_message(int sfd, void *buf, int len, union sockunion *dest, unsigned char tos)
797 {
798 int txmt_len = 0;
799 unsigned char old_tos;
800 socklen_t opt_len;
801 int tmp;
802 #ifdef SCTP_OVER_UDP
803 guchar outBuffer[65536];
804 udp_header* udp;
805 #endif
806
807 #ifdef HAVE_IPV6
808 guchar hostname[MAX_MTU_SIZE];
809 #endif
810
811 switch (sockunion_family(dest)) {
812
813 case AF_INET:
814 number_of_sendevents++;
815 opt_len = sizeof(old_tos);
816 tmp = getsockopt(sfd, IPPROTO_IP, IP_TOS, &old_tos, &opt_len);
817 tmp = setsockopt(sfd, IPPROTO_IP, IP_TOS, &tos, sizeof(unsigned char));
818 event_logii(VVERBOSE, "adl_send_message: set IP_TOS %u, result=%d", tos,tmp);
819
820 event_logiiii(VERBOSE,
821 "AF_INET : adl_send_message : sfd : %d, len %d, destination : %s, send_events %u",
822 sfd, len, inet_ntoa(dest->sin.sin_addr), number_of_sendevents);
823
824 #ifdef SCTP_OVER_UDP
825 if(len + sizeof(udp_header) > sizeof(outBuffer)) {
826 error_log(ERROR_FATAL, "Data block too large ! bye !\n");
827 }
828 memcpy(&outBuffer[sizeof(udp_header)], buf, len);
829
830 udp = (udp_header*)&outBuffer;
831 udp->src_port = htons(SCTP_OVER_UDP_UDPPORT);
832 udp->dest_port = htons(SCTP_OVER_UDP_UDPPORT);
833 udp->length = htons(sizeof(udp_header) + len);
834 udp->checksum = 0x0000;
835
836 txmt_len = sendto(sfd, (char*)&outBuffer, sizeof(udp_header) + len,
837 0, (struct sockaddr *) &(dest->sin), sizeof(struct sockaddr_in));
838 if(txmt_len >= (int)sizeof(udp_header)) {
839 txmt_len -= (int)sizeof(udp_header);
840 }
841 #else
842 txmt_len = sendto(sfd, buf, len, 0, (struct sockaddr *) &(dest->sin), sizeof(struct sockaddr_in));
843 #endif
844
845 if (txmt_len < 0) {
846 error_logi(ERROR_MAJOR, "AF_INET : sendto()=%d !", txmt_len);
847 }
848 tmp = setsockopt(sfd, IPPROTO_IP, IP_TOS, &old_tos, sizeof(unsigned char));
849 break;
850 #ifdef HAVE_IPV6
851 case AF_INET6:
852 number_of_sendevents++;
853 inet_ntop(AF_INET6, sock2ip6(dest), (char *)hostname, MAX_MTU_SIZE);
854
855 event_logiiii(VVERBOSE,
856 "AF_INET6: adl_send_message : sfd : %d, len %d, destination : %s, send_events: %u",
857 sfd, len, hostname, number_of_sendevents);
858
859 #ifdef SCTP_OVER_UDP
860 if(len + sizeof(udp_header) > sizeof(outBuffer)) {
861 error_log(ERROR_FATAL, "Data block too large ! bye !\n");
862 }
863 memcpy(&outBuffer[sizeof(udp_header)], buf, len);
864
865 udp = (udp_header*)&outBuffer;
866 udp->src_port = htons(SCTP_OVER_UDP_UDPPORT);
867 udp->dest_port = htons(SCTP_OVER_UDP_UDPPORT);
868 udp->length = htons(sizeof(udp_header) + len);
869 udp->checksum = 0x0000;
870
871 txmt_len = sendto(sfd, (char*)&outBuffer, sizeof(udp_header) + len,
872 0, (struct sockaddr *) &(dest->sin6), sizeof(struct sockaddr_in6));
873 if(txmt_len >= (int)sizeof(udp_header)) {
874 txmt_len -= (int)sizeof(udp_header);
875 }
876 #else
877 txmt_len = sendto(sfd, buf, len, 0, (struct sockaddr *)&(dest->sin6), sizeof(struct sockaddr_in6));
878 #endif
879 break;
880 #endif
881 default:
882 error_logi(ERROR_MAJOR,
883 "adl_send_message : Adress Family %d not supported here",
884 sockunion_family(dest));
885 txmt_len = -1;
886 }
887 return txmt_len;
888 }
889
890 /**
891 * function to assign an event mask to a certain poll
892 */
893 void assign_poll_fd(int fd_index, int sfd, int event_mask)
894 {
895 if (fd_index > NUM_FDS)
896 error_log(ERROR_FATAL, "FD_Index bigger than NUM_FDS ! bye !\n");
897
898 poll_fds[fd_index].fd = sfd; /* file descriptor */
899 poll_fds[fd_index].events = event_mask;
900 /*
901 * Set the entry's revision to the current extendedPoll() revision.
902 * If another thread is currently inside extendedPoll(), extendedPoll()
903 * will notify that this entry is new and skip the possibly wrong results
904 * until the next invocation.
905 */
906 poll_fds[fd_index].revision = revision;
907 poll_fds[fd_index].revents = 0;
908 }
909
910
911 /**
912 * remove a sfd from the poll_list, and shift that list to the left
913 * @return number of sfd's removed...
914 */
915 int adl_remove_poll_fd(gint sfd)
916 {
917 int i, tmp, counter = 0;
918 for (i = 0, tmp = 0; i < NUM_FDS; i++, tmp++) {
919 if (tmp < NUM_FDS) {
920 poll_fds[i].fd = poll_fds[tmp].fd;
921 poll_fds[i].events = poll_fds[tmp].events;
922 poll_fds[i].revents = poll_fds[tmp].revents;
923 poll_fds[i].revision = poll_fds[tmp].revision;
924 event_callbacks[i] = event_callbacks[tmp];
925 } else {
926 poll_fds[i].fd = POLL_FD_UNUSED;
927 poll_fds[i].events = 0;
928 poll_fds[i].revents = 0;
929 poll_fds[i].revision = 0;
930 event_callbacks[i] = NULL;
931 }
932 if (poll_fds[i].fd == sfd) {
933 tmp = i + 1;
934 if (tmp < NUM_FDS) {
935 poll_fds[i].fd = poll_fds[tmp].fd;
936 poll_fds[i].events = poll_fds[tmp].events;
937 poll_fds[i].revents = poll_fds[tmp].revents;
938 poll_fds[i].revision = poll_fds[tmp].revision;
939 free(event_callbacks[i]);
940 event_callbacks[i] = event_callbacks[tmp];
941 } else {
942 poll_fds[i].fd = POLL_FD_UNUSED;
943 poll_fds[i].events = 0;
944 poll_fds[i].revents = 0;
945 poll_fds[i].revision = 0;
946 free(event_callbacks[i]);
947 event_callbacks[i] = NULL;
948 }
949 counter++;
950 num_of_fds -= 1;
951 }
952 #ifdef WIN32
953 for (i = 0; i < NUM_FDS; i++)
954 {
955 if (fds[i]==sfd)
956 {
957 fds[i]=-1;
958 fdnum--;
959 break;
960 }
961 }
962 #endif
963 }
964 return (counter);
965 }
966
967 /**
968 * function to register a file descriptor, that gets activated for certain read/write events
969 * when these occur, the specified callback funtion is activated and passed the parameters
970 * that are pointed to by the event_callback struct
971 */
972
973 int
974 adl_register_fd_cb(int sfd, int eventcb_type, int event_mask,
975 void (*action) (void *, void *) , void* userData)
976 {
977 #ifdef WIN32
978
979 int ret, i;
980 if (sfd!=0)
981 {
982
983 ret = WSAEventSelect(sfd, hEvent, FD_READ | FD_WRITE |
984 FD_ACCEPT | FD_CLOSE | FD_CONNECT);
985 if (ret == SOCKET_ERROR)
986 {
987 error_log(ERROR_FATAL, "WSAEventSelect() failed\n");
988 return (-1);
989 }
990 for (i=0; i<NUM_FDS;i++)
991 {
992 if (fds[i]==-1)
993 {
994 fds[i]=sfd;
995 fdnum++;
996 break;
997 }
998 }
999 }
1000 #endif
1001
1002 if (num_of_fds < NUM_FDS && sfd >= 0) {
1003 assign_poll_fd(num_of_fds, sfd, event_mask);
1004 event_callbacks[num_of_fds] = (struct event_cb*)malloc(sizeof(struct event_cb));
1005 if (!event_callbacks[num_of_fds])
1006 error_log(ERROR_FATAL, "Could not allocate memory in register_fd_cb \n");
1007 event_callbacks[num_of_fds]->sfd = sfd;
1008 event_callbacks[num_of_fds]->eventcb_type = eventcb_type;
1009
1010 event_callbacks[num_of_fds]->action = (void (*) (void))action;
1011 event_callbacks[num_of_fds]->userData = userData;
1012 num_of_fds++;
1013 return num_of_fds;
1014 } else
1015 return (-1);
1016 }
1017
1018 #ifndef CMSG_ALIGN
1019 #ifdef ALIGN
1020 #define CMSG_ALIGN ALIGN
1021 #else
1022 #define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) )
1023 #endif
1024 #endif
1025
1026 #ifndef CMSG_SPACE
1027 #define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len))
1028 #endif
1029
1030 #ifndef CMSG_LEN
1031 #define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
1032 #endif
1033
1034 /**
1035 * function to be called when we get an sctp message. This function gives also
1036 * the source and destination addresses.
1037 *
1038 * @param sfd the socket file descriptor where data can be read...
1039 * @param dest pointer to a buffer, where we can store the received data
1040 * @param maxlen maximum number of bytes that can be received with call
1041 * @param from address, where we got the data from
1042 * @param to destination address of that message
1043 * @return returns number of bytes received with this call
1044 */
1045 int adl_receive_message(int sfd, void *dest, int maxlen, union sockunion *from, union sockunion *to)
1046 {
1047 int len;
1048 #ifdef SCTP_OVER_UDP
1049 #ifdef LINUX
1050 udp_header* udp;
1051 #else
1052 struct udphdr * udp;
1053 #endif
1054 unsigned char* ptr;
1055 int i;
1056 #endif
1057 #ifdef HAVE_IPV6
1058 struct msghdr rmsghdr;
1059 struct cmsghdr *rcmsgp;
1060 struct iovec data_vec;
1061 #endif
1062 #ifdef LINUX
1063 struct iphdr *iph;
1064 #else
1065 struct ip *iph;
1066 #endif
1067
1068 #ifdef HAVE_IPV6
1069 unsigned char m6buf[(CMSG_SPACE(sizeof (struct in6_pktinfo)))];
1070 struct in6_pktinfo *pkt6info;
1071 #endif
1072
1073 len = -1;
1074 if ((dest == NULL) || (from == NULL) || (to == NULL)) return -1;
1075
1076 if (sfd == sctp_sfd) {
1077 len = recv (sfd, dest, maxlen, 0);
1078 #ifdef LINUX
1079 iph = (struct iphdr *)dest;
1080 #else
1081 iph = (struct ip *)dest;
1082 #endif
1083 to->sa.sa_family = AF_INET;
1084 to->sin.sin_port = htons(0);
1085 #ifdef LINUX
1086 to->sin.sin_addr.s_addr = iph->daddr;
1087 #else
1088 to->sin.sin_addr.s_addr = iph->ip_dst.s_addr;
1089 #endif
1090 from->sa.sa_family = AF_INET;
1091 from->sin.sin_port = htons(0);
1092 #ifdef LINUX
1093 from->sin.sin_addr.s_addr = iph->saddr;
1094 #else
1095 from->sin.sin_addr.s_addr = iph->ip_src.s_addr;
1096 #endif
1097
1098 #ifdef SCTP_OVER_UDP
1099 #ifdef LINUX
1100 if(len < (int)sizeof(struct iphdr) + (int)sizeof(udp_header)) {
1101 #else
1102 if(len < (int)sizeof(struct ip) + (int)sizeof(struct udphdr)) {
1103 #endif
1104 return -1;
1105 }
1106 #ifdef LINUX
1107 udp = (udp_header*)((long)dest + (long)sizeof(struct iphdr));
1108 #else
1109 udp = (struct udphdr *)((long)dest + (long)sizeof(struct ip));
1110 #endif
1111 #ifdef LINUX
1112 if(ntohs(udp->dest_port) != SCTP_OVER_UDP_UDPPORT) {
1113 #else
1114 if(ntohs(udp->uh_dport) != SCTP_OVER_UDP_UDPPORT) {
1115 #endif
1116 return -1;
1117 }
1118 ptr = (unsigned char*)udp;
1119 #ifdef LINUX
1120 for(i = 0;i < len - (int)(sizeof(struct iphdr) + sizeof(udp_header));i++) {
1121 *ptr = ptr[sizeof(udp_header)];
1122 #else
1123 for(i = 0;i < len - (int)(sizeof(struct ip) + sizeof(struct udphdr));i++) {
1124 *ptr = ptr[sizeof(struct udphdr)];
1125 #endif
1126 ptr++;
1127 }
1128 #ifdef LINUX
1129 len -= sizeof(udp_header);
1130 #else
1131 len -= sizeof(struct udphdr);
1132 #endif
1133 #endif
1134 }
1135 #ifdef HAVE_IPV6
1136 data_vec.iov_base = dest;
1137 data_vec.iov_len = maxlen;
1138 if (sfd == sctpv6_sfd) {
1139 rcmsgp = (struct cmsghdr *)m6buf;
1140 pkt6info = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));
1141
1142 /* receive control msg */
1143 rcmsgp->cmsg_level = IPPROTO_IPV6;
1144 rcmsgp->cmsg_type = IPV6_PKTINFO;
1145 rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
1146
1147 rmsghdr.msg_flags = 0;
1148 rmsghdr.msg_iov = &data_vec;
1149 rmsghdr.msg_iovlen = 1;
1150 rmsghdr.msg_name = (caddr_t) &(from->sin6);
1151 rmsghdr.msg_namelen = sizeof (struct sockaddr_in6);
1152 rmsghdr.msg_control = (caddr_t) m6buf;
1153 rmsghdr.msg_controllen = sizeof (m6buf);
1154 memset (from, 0, sizeof (struct sockaddr_in6));
1155 memset (to, 0, sizeof (struct sockaddr_in6));
1156
1157 len = recvmsg (sfd, &rmsghdr, 0);
1158
1159 /* Linux sets this, so we reset it, as we don't want to run into trouble if
1160 we have a port set on sending...then we would get INVALID ARGUMENT */
1161 from->sin6.sin6_port = htons(0);
1162
1163 to->sa.sa_family = AF_INET6;
1164 to->sin6.sin6_port = htons(0);
1165 to->sin6.sin6_flowinfo = htonl(0);
1166 memcpy(&(to->sin6.sin6_addr), &(pkt6info->ipi6_addr), sizeof(struct in6_addr));
1167
1168 #ifdef SCTP_OVER_UDP
1169 #ifdef LINUX
1170 if(len < (int)sizeof(udp_header)) {
1171 #else
1172 if(len < (int)sizeof(struct udphdr)) {
1173 #endif
1174 return -1;
1175 }
1176 #ifdef LINUX
1177 udp = (udp_header*)dest;
1178 #else
1179 udp = (struct udphdr *)dest;
1180 #endif
1181 #ifdef LINUX
1182 if(ntohs(udp->dest_port) != SCTP_OVER_UDP_UDPPORT) {
1183 #else
1184 if(ntohs(udp->uh_dport) != SCTP_OVER_UDP_UDPPORT) {
1185 #endif
1186 return -1;
1187 }
1188 ptr = (unsigned char*)udp;
1189 #ifdef LINUX
1190 for(i = 0;i < len - (int)sizeof(udp_header);i++) {
1191 *ptr = ptr[sizeof(udp_header)];
1192 #else
1193 for(i = 0;i < len - (int)sizeof(struct udphdr);i++) {
1194 *ptr = ptr[sizeof(struct udphdr)];
1195 #endif
1196 ptr++;
1197 }
1198 #ifdef LINUX
1199 len -= sizeof(udp_header);
1200 #else
1201 len -= sizeof(struct udphdr);
1202 #endif
1203 #endif
1204 }
1205 #endif
1206
1207 if (len < 0) error_log(ERROR_MAJOR, "recvmsg() failed in adl_receive_message() !");
1208
1209 return len;
1210 }
1211
1212
1213 /**
1214 * function to be called when we get a message from a peer sctp instance in the poll loop
1215 * @param sfd the socket file descriptor where data can be read...
1216 * @param dest pointer to a buffer, where we can store the received data
1217 * @param maxlen maximum number of bytes that can be received with call
1218 * @param address, where we got the data from
1219 * @param from_len size of the address
1220 * @return returns number of bytes received with this call
1221 */
1222 int adl_get_message(int sfd, void *dest, int maxlen, union sockunion *from, socklen_t *from_len)
1223 {
1224 int len;
1225
1226 len = recvfrom(sfd, dest, maxlen, 0, (struct sockaddr *) from, from_len);
1227 if (len < 0)
1228 error_log(ERROR_FATAL, "recvfrom failed in get_message(), aborting !");
1229
1230 return len;
1231 }
1232
1233 /**
1234 * this function is responsible for calling the callback functions belonging
1235 * to all of the file descriptors that have indicated an event !
1236 * TODO : check handling of POLLERR situation
1237 * @param num_of_events number of events indicated by poll()
1238 */
1239 void dispatch_event(int num_of_events)
1240 {
1241 int i = 0;
1242 int length=0;
1243 socklen_t src_len;
1244 union sockunion src, dest;
1245 struct sockaddr_in *src_in;
1246 guchar src_address[SCTP_MAX_IP_LEN];
1247 unsigned short portnum=0;
1248
1249 #if !defined (LINUX)
1250 struct ip *iph;
1251 #else
1252 struct iphdr *iph;
1253 #endif
1254 int hlen=0;
1255 ENTER_EVENT_DISPATCHER;
1256 for (i = 0; i < num_of_fds; i++) {
1257
1258 if (!poll_fds[i].revents) {
1259 continue;
1260 }
1261
1262 if (poll_fds[i].revents & POLLERR) {
1263 /* We must have specified this callback funtion for treating/logging the error */
1264 if (event_callbacks[i]->eventcb_type == EVENTCB_TYPE_USER) {
1265 event_logi(VERBOSE, "Poll Error Condition on user fd %d", poll_fds[i].fd);
1266 ((sctp_userCallback)*(event_callbacks[i]->action)) (poll_fds[i].fd, poll_fds[i].revents, &poll_fds[i].events, event_callbacks[i]->userData);
1267 } else {
1268 error_logi(ERROR_MINOR, "Poll Error Condition on fd %d", poll_fds[i].fd);
1269 ((sctp_socketCallback)*(event_callbacks[i]->action)) (poll_fds[i].fd, NULL, 0, NULL, 0);
1270 }
1271 }
1272
1273 if ((poll_fds[i].revents & POLLPRI) || (poll_fds[i].revents & POLLIN) || (poll_fds[i].revents & POLLOUT)) {
1274 if (event_callbacks[i]->eventcb_type == EVENTCB_TYPE_USER) {
1275 event_logi(VERBOSE, "Activity on user fd %d - Activating USER callback", poll_fds[i].fd);
1276 ((sctp_userCallback)*(event_callbacks[i]->action)) (poll_fds[i].fd, poll_fds[i].revents, &poll_fds[i].events, event_callbacks[i]->userData);
1277
1278 } else if (event_callbacks[i]->eventcb_type == EVENTCB_TYPE_UDP) {
1279 src_len = sizeof(src);
1280 length = adl_get_message(poll_fds[i].fd, rbuf, MAX_MTU_SIZE, &src, &src_len);
1281 event_logi(VERBOSE, "Message %d bytes - Activating UDP callback", length);
1282 adl_sockunion2str(&src, src_address, SCTP_MAX_IP_LEN);
1283
1284 switch (sockunion_family(&src)) {
1285 case AF_INET :
1286 portnum = ntohs(src.sin.sin_port);
1287 break;
1288 #ifdef HAVE_IPV6
1289 case AF_INET6:
1290 portnum = ntohs(src.sin6.sin6_port);
1291 break;
1292 #endif
1293 default:
1294 portnum = 0;
1295 break;
1296 }
1297 ((sctp_socketCallback)*(event_callbacks[i]->action)) (poll_fds[i].fd, rbuf, length, src_address, portnum);
1298
1299 } else if (event_callbacks[i]->eventcb_type == EVENTCB_TYPE_SCTP) {
1300 length = adl_receive_message(poll_fds[i].fd, rbuf, MAX_MTU_SIZE, &src, &dest);
1301
1302 if(length < 0) break;
1303
1304 event_logiiii(VERBOSE, "SCTP-Message on socket %u , len=%d, portnum=%d, sockunion family %u",
1305 poll_fds[i].fd, length, portnum, sockunion_family(&src));
1306
1307 switch (sockunion_family(&src)) {
1308 case AF_INET:
1309 src_in = (struct sockaddr_in *) &src;
1310 event_logi(VERBOSE, "IPv4/SCTP-Message from %s -> activating callback",
1311 inet_ntoa(src_in->sin_addr));
1312 #if defined (LINUX)
1313 iph = (struct iphdr *) rbuf;
1314 hlen = iph->ihl << 2;
1315 #elif defined (WIN32)
1316 iph = (struct ip *) rbuf;
1317 hlen = (iph->ip_verlen & 0x0F) << 2;
1318 #else
1319 iph = (struct ip *) rbuf;
1320 hlen = iph->ip_hl << 2;
1321 #endif
1322 if (length < hlen) {
1323 error_logii(ERROR_MINOR,
1324 "dispatch_event : packet too short (%d bytes) from %s",
1325 length, inet_ntoa(src_in->sin_addr));
1326 } else {
1327 length -= hlen;
1328 mdi_receiveMessage(poll_fds[i].fd, &rbuf[hlen], length, &src, &dest);
1329 }
1330 break;
1331 #ifdef HAVE_IPV6
1332 case AF_INET6:
1333 adl_sockunion2str(&src, src_address, SCTP_MAX_IP_LEN);
1334 /* if we have additional options, we must parse them, and deduct the sizes :-( */
1335 event_logii(VERBOSE, "IPv6/SCTP-Message from %s (%d bytes) -> activating callback",
1336 src_address, length);
1337
1338 mdi_receiveMessage(poll_fds[i].fd, &rbuf[hlen], length, &src, &dest);
1339 break;
1340
1341 #endif /* HAVE_IPV6 */
1342 default:
1343 error_logi(ERROR_MAJOR, "Unsupported Address Family Type %u ", sockunion_family(&src));
1344 break;
1345
1346 }
1347 }
1348 }
1349 poll_fds[i].revents = 0;
1350 } /* for(i = 0; i < num_of_fds; i++) */
1351 LEAVE_EVENT_DISPATCHER;
1352 }
1353
1354
1355 /**
1356 * function calls the respective callback funtion, that is to be executed as a timer
1357 * event, passing it two arguments
1358 */
1359 void dispatch_timer(void)
1360 {
1361 int tid, result;
1362 AlarmTimer* event;
1363
1364 ENTER_TIMER_DISPATCHER;
1365 if (timer_list_empty()) {
1366 LEAVE_TIMER_DISPATCHER;
1367 return;
1368 }
1369 result = get_msecs_to_nexttimer();
1370
1371 if (result == 0) { /* i.e. a timer expired */
1372 result = get_next_event(&event);
1373
1374 tid = event->timer_id;
1375 current_tid = tid;
1376
1377 (*(event->action)) (tid, event->arg1, event->arg2);
1378 current_tid = 0;
1379
1380 result = remove_timer(event);
1381 if (result) /* this can happen for a timeout that occurs on a deleted assoc ? */
1382 error_logi(ERROR_MAJOR, "remove_item returned %d", result);
1383 }
1384 LEAVE_TIMER_DISPATCHER;
1385 return;
1386 }
1387
1388
1389 void adl_add_msecs_totime(struct timeval *t, unsigned int msecs)
1390 {
1391 long seconds = 0, microseconds = 0;
1392 struct timeval tmp, res;
1393 seconds = msecs / 1000;
1394 microseconds = (msecs % 1000) * 1000;
1395 tmp.tv_sec = seconds;
1396 tmp.tv_usec = microseconds;
1397
1398 timeradd(t, &tmp, &res);
1399 memcpy(t, &res, sizeof(res));
1400 return;
1401 }
1402
1403 /**
1404 * helper function for the sake of a cleaner interface :-)
1405 */
1406 int adl_gettime(struct timeval *tv)
1407 {
1408 #ifdef WIN32
1409 struct timeb tb;
1410 ftime(&tb);
1411 tv->tv_sec=tb.time;
1412 tv->tv_usec=tb.millitm*1000;
1413 return 0;
1414 #else
1415 return (gettimeofday(tv, (struct timezone *) NULL));
1416 #endif
1417 }
1418
1419 /**
1420 * function is to return difference in msecs between time a and b (i.e. a-b)
1421 * @param a later time (e.g. current time)
1422 * @param b earlier time
1423 * @return -1 if a is earlier than b, else msecs that passed from b to a
1424 */
1425 int adl_timediff_to_msecs(struct timeval *a, struct timeval *b)
1426 {
1427 struct timeval result;
1428 int retval;
1429 /* result = a-b */
1430 timersub(a, b, &result);
1431 retval = result.tv_sec * 1000 + result.tv_usec / 1000;
1432 event_logi(VVERBOSE, "Computed Time Difference : %d msecs", retval);
1433 return ((retval < 0) ? -1 : retval);
1434 }
1435
1436 /**
1437 * function initializes the array of fds we want to use for listening to events
1438 * USE POLL_FD_UNUSED to differentiate between used/unused fds !
1439 */
1440 int init_poll_fds(void)
1441 {
1442 int i;
1443 for (i = 0; i < NUM_FDS; i++) {
1444 assign_poll_fd(i, POLL_FD_UNUSED, 0);
1445 #ifdef WIN32
1446 fds[i]=-1;
1447 #endif
1448 }
1449 num_of_fds = 0;
1450 #ifdef WIN32
1451 fdnum=0;
1452 #endif
1453 return (0);
1454 }
1455
1456
1457
1458
1459 /**
1460 * function to check for events on all poll fds (i.e. open sockets), or else
1461 * execute the next timer event. Executed timer events are removed from the list.
1462 * Wrapper to poll() -- returns after timeout or read event
1463 * @return number of events that where seen on the socket fds, 0 for timer event, -1 for error
1464 * @author ajung, dreibh
1465 */
1466 int adl_extendedEventLoop(void (*lock)(void* data), void (*unlock)(void* data), void* data)
1467 {
1468 int result;
1469 unsigned int u_res;
1470 int msecs;
1471
1472
1473
1474 if(lock != NULL) {
1475 lock(data);
1476 }
1477
1478 msecs = get_msecs_to_nexttimer();
1479
1480 /* returns -1 if no timer in list */
1481 /* if (msecs > GRANULARITY || msecs < 0) */
1482 if (msecs < 0)
1483 msecs = GRANULARITY;
1484 if (msecs == 0) {
1485 dispatch_timer();
1486 if(unlock != NULL) {
1487 unlock(data);
1488 }
1489 return (0);
1490 }
1491
1492 /* print_debug_list(INTERNAL_EVENT_0); */
1493 result = extendedPoll(poll_fds, &num_of_fds, msecs, lock, unlock, data);
1494 switch (result) {
1495 case -1:
1496 result = 0;
1497 break;
1498 case 0:
1499 dispatch_timer();
1500 break;
1501 default:
1502 u_res = (unsigned int) result;
1503 event_logi(INTERNAL_EVENT_0,
1504 "############### %d Read Event(s) occurred -> dispatch_event() #############",
1505 u_res);
1506 dispatch_event(result);
1507 break;
1508 }
1509
1510 if(unlock != NULL) {
1511 unlock(data);
1512 }
1513 return (result);
1514 }
1515
1516 /**
1517 * function to check for events on all poll fds (i.e. open sockets), or else
1518 * execute the next timer event. Executed timer events are removed from the list.
1519 * Wrapper to poll() -- returns after timeout or read event
1520 * @return number of events that where seen on the socket fds, 0 for timer event, -1 for error
1521 * @author ajung
1522 * @author dreibh
1523 */
1524 int adl_eventLoop()
1525 {
1526 #ifdef WIN32
1527
1528 int n, ret,i, j;
1529 WSANETWORKEVENTS ne;
1530 int length=0, hlen=0, msecs;
1531 union sockunion src, dest;
1532 struct ip *iph;
1533 struct sockaddr_in *src_in;
1534 unsigned short portnum;
1535
1536
1537 msecs = get_msecs_to_nexttimer();
1538
1539 /* returns -1 if no timer in list */
1540 if (msecs < 0)
1541 msecs = GRANULARITY;
1542 if (msecs == 0) {
1543 dispatch_timer();
1544 return (0);
1545 }
1546
1547 n = MsgWaitForMultipleObjects(2, handles, FALSE, msecs, QS_KEY);
1548 if (n==1 && idata.len>0)
1549 {
1550 for (i=0; i< NUM_FDS; i++)
1551 {
1552
1553 if (event_callbacks[i]->sfd==0)
1554 {
1555
1556 (*(event_callbacks[i]->action))(idata.buffer,idata.len);
1557 SetEvent(idata.eventback);
1558 memset(idata.buffer, 0, sizeof(idata.buffer));
1559 idata.len=0;
1560 break;
1561 }
1562 }
1563 }
1564 else if (n==0)
1565 {
1566 for (i=0; i<fdnum; i++)
1567 {
1568 ret = WSAEnumNetworkEvents(fds[i], hEvent, &ne);
1569 if (ret == SOCKET_ERROR)
1570 {
1571 error_log(ERROR_FATAL, "WSAEnumNetworkEvents() failed!");
1572 return (-1);
1573 }
1574 if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
1575 {
1576 for (j=0; j<NUM_FDS; j++)
1577 if (event_callbacks[i]->sfd==fds[i])
1578 {
1579 length = adl_receive_message(fds[i], rbuf, MAX_MTU_SIZE, &src, &dest);
1580 portnum = ntohs(src.sin.sin_port);
1581 if(length < 0) break;
1582 event_logiiii(VERBOSE, "SCTP-Message on socket %u , len=%d, portnum=%d, sockunion family %u",
1583 fds[i], length, portnum, sockunion_family(&src));
1584
1585 src_in = (struct sockaddr_in *) &src;
1586 event_logi(VERBOSE, "IPv4/SCTP-Message from %s -> activating callback",
1587 inet_ntoa(src_in->sin_addr));
1588 iph = (struct ip *) rbuf;
1589 hlen = (iph->ip_verlen & 0x0F) << 2;
1590 if (length < hlen)
1591 {
1592 error_logii(ERROR_MINOR,
1593 "dispatch_event : packet too short (%d bytes) from %s",
1594 length, inet_ntoa(src_in->sin_addr));
1595 } else
1596 {
1597 length -= hlen;
1598 mdi_receiveMessage(fds[i], &rbuf[hlen], length, &src, &dest);
1599 }
1600 break;
1601 }
1602
1603 }
1604 }
1605 }
1606 return 1;
1607 #else
1608
1609 return(adl_extendedEventLoop(NULL, NULL, NULL));
1610 #endif
1611 }
1612
1613
1614 int adl_extendedGetEvents(void (*lock)(void* data), void (*unlock)(void* data), void* data)
1615 {
1616 int result;
1617 unsigned int u_res;
1618
1619 if(lock != NULL) {
1620 lock(data);
1621 }
1622 result = extendedPoll(poll_fds, &num_of_fds, 0, lock, unlock, data);
1623 if(unlock != NULL) {
1624 unlock(data);
1625 }
1626
1627 switch (result) {
1628 case -1:
1629 result = 0;
1630 break;
1631 case 0:
1632 result = 0;
1633 break;
1634 default:
1635 u_res = (unsigned int) result;
1636 event_logi(INTERNAL_EVENT_0,
1637 "############### %d Read Event(s) occurred -> dispatch_event()#############",
1638 u_res);
1639 dispatch_event(result);
1640 result = 1;
1641 break;
1642 }
1643
1644 return (result);
1645 }
1646
1647
1648 /**
1649 * function to check for events on all poll fds (i.e. open sockets), or else
1650 * execute the next timer event. Executed timer events are removed from the list.
1651 * Wrapper to poll() -- returns at once or after a read event
1652 * @return 0 if no file descriptor event occurred, -1 for error
1653 * @author ajung
1654 */
1655 int adl_getEvents(void)
1656 {
1657 return(adl_extendedGetEvents(NULL, NULL, NULL));
1658 }
1659
1660
1661 #ifdef WIN32
1662
1663 static DWORD WINAPI stdin_read_thread(void *param)
1664 {
1665 struct input_data *indata = (struct input_data *) param;
1666
1667 HANDLE inhandle;
1668
1669 inhandle = GetStdHandle(STD_INPUT_HANDLE);
1670
1671 while (ReadFile(inhandle, indata->buffer, sizeof(indata->buffer),
1672 &indata->len, NULL) && indata->len > 0)
1673 {
1674 SetEvent(indata->event);
1675
1676 WaitForSingleObject(indata->eventback, INFINITE);
1677 memset(indata->buffer, 0, sizeof(indata->buffer));
1678 }
1679 indata->len = 0;
1680 memset(indata->buffer, 0, sizeof(indata->buffer));
1681 SetEvent(indata->event);
1682
1683 return 0;
1684 }
1685 #endif
1686
1687
1688 #ifdef SCTP_OVER_UDP
1689 int open_dummy_socket(int family)
1690 {
1691 struct sockaddr_in in;
1692 struct sockaddr_in6 in6;
1693 int sd;
1694 int on;
1695
1696 if(family == AF_INET6) {
1697 memset(&in6, 0, sizeof(in6));
1698 in6.sin6_family = AF_INET6;
1699 in6.sin6_port = htons(SCTP_OVER_UDP_UDPPORT);
1700 }
1701 else {
1702 memset(&in, 0, sizeof(in));
1703 in.sin_family = AF_INET;
1704 in.sin_port = htons(SCTP_OVER_UDP_UDPPORT);
1705 }
1706
1707 sd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
1708 if(sd < 0) {
1709 return -1;
1710 }
1711
1712 on = 1;
1713 if(setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) < 0) {
1714 close(sd);
1715 return -1;
1716 }
1717
1718 if(family == AF_INET6) {
1719 if(bind(sd, (struct sockaddr*)&in6, sizeof(in6)) < 0) {
1720 return -1;
1721 }
1722 }
1723 else {
1724 if(bind(sd, (struct sockaddr*)&in, sizeof(in)) < 0) {
1725 return -1;
1726 }
1727 }
1728
1729 return sd;
1730 }
1731 #endif
1732
1733
1734 int adl_init_adaptation_layer(int * myRwnd)
1735 {
1736 struct timeval curTime;
1737 #ifdef WIN32
1738 WSADATA wsaData;
1739 int Ret;
1740 #endif
1741 #ifdef HAVE_IPV6
1742 int myRwnd6 = 32767;
1743 #endif
1744
1745 #ifdef WIN32
1746 if ((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
1747 {
1748 error_log(ERROR_FATAL, "WSAStartup failed.");
1749 return SCTP_SPECIFIC_FUNCTION_ERROR;
1750 }
1751 hEvent = WSACreateEvent();
1752 if (hEvent == NULL)
1753 {
1754 error_log(ERROR_FATAL, "WSACreateEvent() of hEvent failed!");
1755 return -1;
1756 }
1757
1758 stdinevent = WSACreateEvent();
1759 if (stdinevent == NULL)
1760 {
1761 error_log(ERROR_FATAL, "WSACreateEvent() of stdinevent failed!");
1762 return -1;
1763 }
1764
1765 handles[0]=hEvent;
1766 handles[1]=stdinevent;
1767 #endif
1768
1769 /* initialize random number generator */
1770 adl_gettime(&curTime);
1771 #ifdef HAVE_RANDOM
1772 rstate[0] = curTime.tv_sec;
1773 rstate[1] = curTime.tv_usec;
1774 initstate(curTime.tv_sec, (char *) rstate, 8);
1775 setstate((char *) rstate);
1776 #else
1777 /* FIXME: this may be too weak (better than nothing however) */
1778 srand(curTime.tv_usec);
1779 #endif
1780
1781 init_poll_fds();
1782 init_timer_list();
1783 /* print_debug_list(INTERNAL_EVENT_0); */
1784 sctp_sfd = adl_open_sctp_socket(AF_INET, myRwnd);
1785 /* set a safe default */
1786 if (*myRwnd == -1) *myRwnd = 8192;
1787
1788 if (sctp_sfd < 0) return sctp_sfd;
1789
1790 #ifdef SCTP_OVER_UDP
1791 dummy_sctp_udp = open_dummy_socket(AF_INET);
1792 if(dummy_sctp_udp < 0) {
1793 error_log(ERROR_MAJOR, "Could not open UDP dummy socket !");
1794 return dummy_sctp_udp;
1795 }
1796 #endif
1797
1798 /* we should - in a later revision - add back the a function that opens
1799 appropriate ICMP sockets (IPv4 and/or IPv6) and registers these with
1800 callback functions that also set PATH MTU correctly */
1801 #ifdef HAVE_IPV6
1802 /* icmpv6_sfd = int adl_open_icmpv6_socket(); */
1803 sctpv6_sfd = adl_open_sctp_socket(AF_INET6, &myRwnd6);
1804 if (sctpv6_sfd < 0) {
1805 error_log(ERROR_MAJOR, "Could not open IPv6 socket - running IPv4 only !");
1806 sctpv6_sfd = -1;
1807 }
1808 else {
1809 #ifdef SCTP_OVER_UDP
1810 dummy_sctpv6_udp = open_dummy_socket(AF_INET6);
1811 if(dummy_sctpv6_udp < 0) {
1812 error_log(ERROR_MAJOR, "Could not open UDP/IPv6 dummy socket !");
1813 sctpv6_sfd = -1;
1814 }
1815 #endif
1816 }
1817
1818 /* adl_register_socket_cb(icmpv6_sfd, adl_icmpv6_cb); */
1819
1820 /* set a safe default */
1821 if (myRwnd6 == -1) *myRwnd = 8192;
1822 #endif
1823
1824 /* icmp_sfd = int adl_open_icmp_socket(); */
1825 /* adl_register_socket_cb(icmp_sfd, adl_icmp_cb); */
1826
1827 /* #if defined(HAVE_SETUID) && defined(HAVE_GETUID) */
1828 /* now we could drop privileges, if we did not use setsockopt() calls for IP_TOS etc. later */
1829 /* setuid(getuid()); */
1830 /* #endif */
1831 return 0;
1832 }
1833
1834
1835 /**
1836 * this function is supposed to open and bind a UDP socket listening on a port
1837 * to incoming udp pakets on a local interface (a local union sockunion address)
1838 * @param me pointer to a local address, that will trigger callback, if it receives UDP data
1839 * @param scf callback funtion that is called when data has arrived
1840 * @return new UDP socket file descriptor, or -1 if error ocurred
1841 */
1842 int adl_registerUdpCallback(unsigned char me[],
1843 unsigned short my_port,
1844 sctp_socketCallback scf)
1845 {
1846 int result, new_sfd;
1847 union sockunion my_address;
1848
1849 #ifdef WIN32
1850 error_log(ERROR_MAJOR, "WIN32: Registering ULP-Callbacks for UDP not installed !");
1851 return -1;
1852 #endif
1853 if (ntohs(my_port) == 0) {
1854 error_log(ERROR_MAJOR, "Port 0 is not allowed ! Fix your program !");
1855 return -1;
1856 }
1857 if (adl_str2sockunion(me, &my_address) < 0) {
1858 error_logi(ERROR_MAJOR, "Could not convert address string %s !", me);
1859 return -1;
1860 }
1861
1862 switch (sockunion_family(&my_address)) {
1863 case AF_INET:
1864 event_logi(VERBOSE, "Registering ULP-Callback for UDP socket on port %u",ntohs(my_port));
1865 my_address.sin.sin_port = htons(my_port);
1866 break;
1867 #ifdef HAVE_IPV6
1868 case AF_INET6:
1869 event_logi(VERBOSE, "Registering ULP-Callback for UDPv6 socket on port %u",ntohs(my_port));
1870 my_address.sin6.sin6_port = htons(my_port);
1871 break;
1872 #endif
1873 default:
1874 error_log(ERROR_MINOR, "UNKNOWN ADDRESS TYPE - CHECK YOUR PROGRAM !");
1875 break;
1876 }
1877
1878 new_sfd = adl_open_udp_socket(&my_address);
1879
1880 if (new_sfd != -1) {
1881 result = adl_register_fd_cb(new_sfd, EVENTCB_TYPE_UDP, POLLIN | POLLPRI, (void(*)(void *,void *))scf, NULL);
1882 event_logi(INTERNAL_EVENT_0, "Registered ULP-Callback: now %d registered callbacks !!!",result);
1883 return new_sfd;
1884 }
1885 return -1;
1886 }
1887
1888
1889
1890 int adl_unregisterUdpCallback(int udp_sfd)
1891 {
1892 if (udp_sfd <= 0) return -1;
1893 if (udp_sfd == sctp_sfd) return -1;
1894 #ifdef HAVE_IPV6
1895 if (udp_sfd == sctpv6_sfd) return -1;
1896 #endif
1897 return adl_remove_cb(udp_sfd);
1898 }
1899
1900
1901 /**
1902 * this function is supposed to register a callback function for catching
1903 * input from the Unix STDIN file descriptor. We expect this to be useful
1904 * in test programs mainly, so it is provided here for convenience.
1905 * @param scf callback funtion that is called (when return is hit)
1906 * @return 0, or -1 if error ocurred
1907 */
1908 int adl_registerUserCallback(int fd, sctp_userCallback sdf, void* userData, short int eventMask)
1909 {
1910 int result;
1911 #ifdef WIN32
1912 error_log(ERROR_MAJOR, "WIN32: Registering User Callbacks not installed !");
1913 return -1;
1914 #endif
1915 /* 0 is the standard input ! */
1916 result = adl_register_fd_cb(fd, EVENTCB_TYPE_USER, eventMask, (void (*) (void *,void *))sdf, userData);
1917 if (result != -1) {
1918 event_logii(EXTERNAL_EVENT,"----------> Registered User Callback: fd=%d result=%d -------\n", fd, result);
1919 }
1920 return result;
1921 }
1922
1923 #ifndef WIN32
1924 void readCallback(int fd, short int revents, short int* events, void* userData)
1925 {
1926 int n;
1927
1928 struct data *udata=(struct data *)userData;
1929
1930 n=read(0,(char *)udata->dat, udata->len);
1931 ((sctp_StdinCallback )udata->cb)(udata->dat, n);
1932 }
1933 #endif
1934
1935 int adl_registerStdinCallback(sctp_StdinCallback sdf, char* buffer, int length)
1936 {
1937 int result;
1938
1939
1940 #ifdef WIN32
1941 unsigned long in_threadid;
1942 idata.event = stdinevent;
1943 idata.eventback = CreateEvent(NULL, FALSE, FALSE, NULL);
1944
1945 if (!(stdin_thread_handle=CreateThread(NULL, 0, stdin_read_thread,
1946 &idata, 0, &in_threadid))) {
1947 fprintf(stderr, "Unable to create input thread\n");
1948 return -1;
1949 }
1950
1951 result = adl_register_fd_cb(0, EVENTCB_TYPE_USER, 0, (void (*) (void *,void *))sdf, NULL);
1952 #else
1953 struct data *userData;
1954 userData = (struct data*)malloc(sizeof (struct data));
1955 memset(userData, 0, sizeof(struct data));
1956 userData->dat=buffer;
1957 userData->len=length;
1958 userData->cb=(void (*) (void))sdf;
1959 result = adl_register_fd_cb(0, EVENTCB_TYPE_USER, POLLIN | POLLPRI, (void (*) (void *,void *))readCallback,userData);
1960 #endif
1961 if (result != -1) {
1962 event_logii(EXTERNAL_EVENT,"----------> Registered Stdin Callback: fd=%d result=%d -------\n", 0, result);
1963 }
1964 return result;
1965 }
1966
1967
1968 int adl_unregisterStdinCallback()
1969 {
1970 #ifdef WIN32
1971 TerminateThread(stdin_thread_handle,0);
1972 #endif
1973 adl_remove_poll_fd(0);
1974 return 0;
1975 }
1976
1977
1978
1979 int adl_unregisterUserCallback(int fd)
1980 {
1981 adl_remove_poll_fd(fd);
1982 return 0;
1983 }
1984
1985
1986 int
1987 adl_register_socket_cb(gint sfd, sctp_socketCallback scf)
1988 {
1989 return (adl_register_fd_cb(sfd, EVENTCB_TYPE_SCTP, POLLIN | POLLPRI, (void(*)(void *,void *))scf, NULL));
1990 }
1991
1992
1993 /**
1994 * This function adds a callback that is to be called some time from now. It realizes
1995 * the timer (in an ordered list).
1996 * @param milliseconds action is to be started in milliseconds ms from now
1997 * @param action pointer to a function to be executed, when timer goes off
1998 * @return returns an id value, that can be used to cancel a timer
1999 * @author ajung
2000 */
2001 unsigned int adl_startMicroTimer(unsigned int seconds, unsigned int microseconds,
2002 sctp_timerCallback timer_cb, int ttype, void *param1, void *param2)
2003 {
2004 unsigned int result = 0;
2005 AlarmTimer* item;
2006 struct timeval talarm, delta, now;
2007
2008 delta.tv_sec = seconds;
2009 /* make sure, user cannot confuse us :-) */
2010 delta.tv_sec += (microseconds / 1000000); /* usually 0 */
2011 delta.tv_usec = (microseconds % 1000000);
2012
2013 adl_gettime(&now);
2014 item = (AlarmTimer*)malloc(sizeof(AlarmTimer));
2015 if (item == NULL) return 0;
2016
2017 timeradd(&now, &delta, &talarm);
2018 item->timer_type = ttype;
2019 item->action_time = talarm;
2020 item->action = timer_cb;
2021 item->arg1 = param1;
2022 item->arg2 = param2;
2023 result = insert_item(item);
2024
2025 return (result);
2026 }
2027
2028 unsigned int
2029 adl_startTimer(unsigned int milliseconds, sctp_timerCallback timer_cb, int ttype,
2030 void *param1, void *param2)
2031 {
2032 unsigned int secs, usecs;
2033 unsigned int result = 0;
2034
2035 secs = milliseconds / 1000;
2036 usecs = (milliseconds - (secs * 1000))*1000;
2037 result = adl_startMicroTimer(secs, usecs, timer_cb, ttype, param1, param2);
2038 return result;
2039 }
2040
2041 /**
2042 * This function adds a callback that is to be called some time from now. It realizes
2043 * the timer (in an ordered list).
2044 * @param tid timer-id of timer to be removed
2045 * @return returns 0 on success, 1 if tid not in the list, -1 on error
2046 * @author ajung
2047 */
2048 int adl_stopTimer(unsigned int tid)
2049 {
2050 if (tid != current_tid)
2051 return (remove_item(tid));
2052 else
2053 return 0;
2054 }
2055
2056 /**
2057 * Restarts a timer currently running
2058 * @param timer_id the value returned by set_timer for a certain timer
2059 * @param milliseconds action is to be started in milliseconds ms from now
2060 * @return new timer id , zero when there is an error (i.e. no timer)
2061 * @author ajung
2062 */
2063 unsigned int adl_restartTimer(unsigned int timer_id, unsigned int milliseconds)
2064 {
2065 unsigned int result;
2066 result = update_item(timer_id, milliseconds);
2067 event_logiii(VVERBOSE,
2068 "Restarted Timer : timer_id = %u, msecs = %u, result = %u",
2069 timer_id, milliseconds, result);
2070 return result;
2071 }
2072
2073 unsigned int adl_restartMicroTimer(unsigned int timer_id, unsigned int seconds, unsigned int microseconds)
2074 {
2075 unsigned int result;
2076 result = micro_update_item(timer_id, seconds, microseconds);
2077 event_logiiii(VVERBOSE,
2078 "Restarted Micro-Timer : timer_id = %u, secs = %u, usecs=%u result = %u",
2079 timer_id, seconds, microseconds, result);
2080 return result;
2081
2082 }
2083
2084
2085 /**
2086 * function to close a bound socket from our list of socket descriptors
2087 * @param sfd socket file descriptor to be closed
2088 * @return 0 on success, -1 for error, 1 if socket was not bound
2089 * @author ajung
2090 */
2091 int adl_remove_cb(int sfd)
2092 {
2093 int result;
2094 #ifdef WIN32
2095 result = closesocket(sfd);
2096 #else
2097 result = close(sfd);
2098 #endif
2099 if (result < 0)
2100 error_log(ERROR_FATAL, "Close Socket resulted in an error");
2101 adl_remove_poll_fd(sfd);
2102 return result;
2103 }
2104
2105 /**
2106 * An address filtering function
2107 * @param newAddress a pointer to a sockunion address
2108 * @param flags bit mask hiding (i.e. filtering) address classes
2109 * returns TRUE if address is not filtered, else FALSE if address is filtered by mask
2110 */
2111 gboolean adl_filterInetAddress(union sockunion* newAddress, AddressScopingFlags flags)
2112 {
2113 switch (sockunion_family(newAddress)) {
2114 case AF_INET :
2115 event_log(VERBOSE, "Trying IPV4 address");
2116 if (
2117 (IN_MULTICAST(ntohl(newAddress->sin.sin_addr.s_addr)) && (flags & flag_HideMulticast)) ||
2118 (IN_EXPERIMENTAL(ntohl(newAddress->sin.sin_addr.s_addr)) && (flags & flag_HideReserved)) ||
2119 (IN_BADCLASS(ntohl(newAddress->sin.sin_addr.s_addr)) && (flags & flag_HideReserved)) ||
2120 ((INADDR_BROADCAST == ntohl(newAddress->sin.sin_addr.s_addr)) && (flags & flag_HideBroadcast))||
2121 ((INADDR_LOOPBACK == ntohl(newAddress->sin.sin_addr.s_addr)) && (flags & flag_HideLoopback)) ||
2122 ((INADDR_LOOPBACK != ntohl(newAddress->sin.sin_addr.s_addr)) && (flags & flag_HideAllExceptLoopback))||
2123 (ntohl(newAddress->sin.sin_addr.s_addr) == INADDR_ANY)
2124 ) {
2125 event_log(VERBOSE, "Filtering IPV4 address");
2126 return FALSE;
2127 }
2128 break;
2129 #ifdef HAVE_IPV6
2130 case AF_INET6 :
2131 #if defined (LINUX)
2132 if (
2133 (!IN6_IS_ADDR_LOOPBACK(&(newAddress->sin6.sin6_addr.s6_addr)) && (flags & flag_HideAllExceptLoopback)) ||
2134 (IN6_IS_ADDR_LOOPBACK(&(newAddress->sin6.sin6_addr.s6_addr)) && (flags & flag_HideLoopback)) ||
2135 (IN6_IS_ADDR_LINKLOCAL(&(newAddress->sin6.sin6_addr.s6_addr)) && (flags & flag_HideLinkLocal)) ||
2136 (!IN6_IS_ADDR_LINKLOCAL(&(newAddress->sin6.sin6_addr.s6_addr)) && (flags & flag_HideAllExceptLinkLocal)) ||
2137 (!IN6_IS_ADDR_SITELOCAL(&(newAddress->sin6.sin6_addr.s6_addr)) && (flags & flag_HideAllExceptSiteLocal)) ||
2138 (IN6_IS_ADDR_SITELOCAL(&(newAddress->sin6.sin6_addr.s6_addr)) && (flags & flag_HideSiteLocal)) ||
2139 (IN6_IS_ADDR_MULTICAST(&(newAddress->sin6.sin6_addr.s6_addr)) && (flags & flag_HideMulticast)) ||
2140 IN6_IS_ADDR_UNSPECIFIED(&(newAddress->sin6.sin6_addr.s6_addr))
2141 ) {
2142 event_log(VERBOSE, "Filtering IPV6 address");
2143 return FALSE;
2144 }
2145 #else
2146 if (
2147 (!IN6_IS_ADDR_LOOPBACK(&(newAddress->sin6.sin6_addr)) && (flags & flag_HideAllExceptLoopback)) ||
2148 (IN6_IS_ADDR_LOOPBACK(&(newAddress->sin6.sin6_addr)) && (flags & flag_HideLoopback)) ||
2149 (!IN6_IS_ADDR_LINKLOCAL(&(newAddress->sin6.sin6_addr)) && (flags & flag_HideAllExceptLinkLocal)) ||
2150 (!IN6_IS_ADDR_SITELOCAL(&(newAddress->sin6.sin6_addr)) && (flags & flag_HideAllExceptSiteLocal)) ||
2151 (IN6_IS_ADDR_LINKLOCAL(&(newAddress->sin6.sin6_addr)) && (flags & flag_HideLinkLocal)) ||
2152 (IN6_IS_ADDR_SITELOCAL(&(newAddress->sin6.sin6_addr)) && (flags & flag_HideSiteLocal)) ||
2153 (IN6_IS_ADDR_MULTICAST(&(newAddress->sin6.sin6_addr)) && (flags & flag_HideMulticast)) ||
2154 IN6_IS_ADDR_UNSPECIFIED(&(newAddress->sin6.sin6_addr))
2155 ) {
2156 event_log(VERBOSE, "Filtering IPV6 address");
2157 return FALSE;
2158 }
2159 #endif
2160 break;
2161 #endif
2162 default :
2163 event_log(VERBOSE, "Default : Filtering Address");
2164 return FALSE;
2165 break;
2166 }
2167 return TRUE;
2168 }
2169
2170
2171
2172
2173 /*
2174 * this is an ugly part to code, so it was taken an adapted from the
2175 * SCTP reference implementation by Randy Stewart
2176 * see http://www.sctp.org
2177 * returns TRUE is successful, else FALSE
2178 *
2179 * Changed by Stefan Jansen <stefan.jansen@gmx.de>, Aug 1st, 2002.
2180 * When going through the ifreq array, numAlocAddr was used as upper bound.
2181 * But at this time numAlocAddr counts also IPv6 addresses from
2182 * /proc/net/if_inet6 and is therefore too much. Thus I introduced a new
2183 * counter named numAlocIPv4Addr.
2184 * This error lead to a kernel error message because the kernel tried to load
2185 * a kernel module when the non-existing network devices were accessed on
2186 * SuSE Linux 7.3, kernel 2.4.16-4GB, GCC 2.95.3, glibc-2.2.4-64.
2187 *
2188 * Changed by Amedeo Bonfiglio <amedeo.bonfiglio@rcm.inet.it>, Dec 07 th, 2009.
2189 * When porting to Neutrino RTOS 6.4.1, ioctl(sctp_fd, SIOCGIFCONF) has been adapted
2190 * as shown in
2191 * http://www.qnx.com/developers/docs/6.4.0/io-pkt_en/user_guide/migrating.html#Coexistence
2192 * The modifications are controlled by #ifdef NEUTRINO_RTOS, but the modified code is applicable
2193 * to any OS.
2194 *
2195 */
2196 gboolean adl_gatherLocalAddresses(union sockunion **addresses,
2197 int *numberOfNets,
2198 int sctp_fd,
2199 gboolean with_ipv6,
2200 int *max_mtu,
2201 const AddressScopingFlags flags)
2202
2203 {
2204
2205 #ifdef WIN32
2206 union sockunion *localAddresses=NULL;
2207
2208 SOCKET s[MAXIMUM_WAIT_OBJECTS];
2209 WSAEVENT hEvent[MAXIMUM_WAIT_OBJECTS];
2210 WSAOVERLAPPED ol[MAXIMUM_WAIT_OBJECTS];
2211 struct addrinfo *local=NULL,hints,
2212 *ptr=NULL;
2213 SOCKET_ADDRESS_LIST *slist=NULL;
2214 DWORD bytes;
2215 char addrbuf[ADDRESS_LIST_BUFFER_SIZE],host[NI_MAXHOST],serv[NI_MAXSERV];
2216 int socketcount=0,
2217 addrbuflen=ADDRESS_LIST_BUFFER_SIZE,
2218 rc,i, j,hostlen = NI_MAXHOST,servlen = NI_MAXSERV;
2219 struct sockaddr_in Addr;
2220
2221
2222 /* Enumerate the local bind addresses - to wait for changes we only need
2223 one socket but to enumerate the addresses for a particular address
2224 family, we need a socket of that type */
2225
2226 memset(&hints, 0, sizeof(hints));
2227 hints.ai_flags = AI_PASSIVE;
2228 hints.ai_family = AF_INET;
2229 hints.ai_socktype = SOCK_DGRAM;
2230 hints.ai_protocol = IPPROTO_UDP;
2231
2232 if ((rc = getaddrinfo(NULL,"0",&hints,&local))!=0)
2233 {
2234 local=NULL;
2235 fprintf(stderr, "Unable to resolve the bind address!\n");
2236 return -1;
2237 }
2238
2239 /* Create a socket and event for each address returned*/
2240 ptr = local;
2241 while (ptr)
2242 {
2243 s[socketcount] = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
2244 if (s[socketcount] == INVALID_SOCKET)
2245 {
2246 fprintf(stderr, "socket failed: %d\n", WSAGetLastError());
2247 return -1;
2248 }
2249
2250 hEvent[socketcount] = WSACreateEvent();
2251 if (hEvent == NULL)
2252 {
2253 fprintf(stderr, "WSACreateEvent failed: %d\n", WSAGetLastError());
2254 return -1;
2255 }
2256
2257 socketcount++;
2258
2259 ptr = ptr->ai_next;
2260
2261 if (ptr && (socketcount > MAXIMUM_WAIT_OBJECTS))
2262 {
2263 printf("Too many address families returned!\n");
2264 break;
2265 }
2266 }
2267
2268 for(i=0; i < socketcount ;i++)
2269 {
2270 memset(&ol[i], 0, sizeof(WSAOVERLAPPED));
2271 ol[i].hEvent = hEvent[i];
2272 if ((rc = WSAIoctl(s[i],SIO_ADDRESS_LIST_QUERY,NULL,0,addrbuf,addrbuflen,
2273 &bytes,NULL, NULL))== SOCKET_ERROR)
2274 {
2275 fprintf(stderr, "WSAIoctl: SIO_ADDRESS_LIST_QUERY failed: %d\n", WSAGetLastError());
2276 return -1;
2277 }
2278
2279 slist = (SOCKET_ADDRESS_LIST *)addrbuf;
2280 localAddresses = calloc(slist->iAddressCount,sizeof(union sockunion));
2281 for(j=0; j < slist->iAddressCount ;j++)
2282 {
2283 if ((rc = getnameinfo(slist->Address[j].lpSockaddr, slist->Address[j].iSockaddrLength,
2284 host,hostlen,serv,servlen,NI_NUMERICHOST | NI_NUMERICSERV))!=0)
2285 fprintf(stderr, "%s: getnameinfo failed: %d\n", __FILE__, rc);
2286 Addr.sin_family=slist->Address[j].lpSockaddr->sa_family;
2287 Addr.sin_addr.s_addr=inet_addr(host);
2288 memcpy(&((localAddresses)[j]),&Addr,sizeof(Addr));
2289 }
2290
2291 /* Register for change notification*/
2292 if ((rc = WSAIoctl(s[i],SIO_ADDRESS_LIST_CHANGE,NULL,0,NULL,0,&bytes,&ol[i],NULL))== SOCKET_ERROR)
2293 {
2294 if (WSAGetLastError() != WSA_IO_PENDING)
2295 {
2296 fprintf(stderr, "WSAIoctl: SIO_ADDRESS_LIST_CHANGE failed: %d\n", WSAGetLastError());
2297 return -1;
2298 }
2299 }
2300 }
2301
2302 freeaddrinfo(local);
2303
2304 for(i=0; i < socketcount ;i++)
2305 closesocket(s[i]);
2306
2307 *addresses = localAddresses;
2308 *numberOfNets=slist->iAddressCount;
2309 *max_mtu=1500;
2310 return TRUE;
2311 #else
2312 #if defined (LINUX)
2313 int addedNets;
2314 char addrBuffer[256];
2315 FILE *v6list;
2316 struct sockaddr_in6 sin6;
2317 int numAlocIPv4Addr = 0;
2318 #endif
2319
2320 char addrBuffer2[64];
2321 /* unsigned short intf_flags; */
2322 struct ifconf cf;
2323 int pos=0,copSiz=0,numAlocAddr=0,ii;
2324 char buffer[8192];
2325 struct sockaddr *toUse;
2326 int saveMTU = 1500; /* default maximum MTU for now */
2327 #ifdef HAS_SIOCGLIFADDR
2328 struct if_laddrreq lifaddr;
2329 #endif
2330 struct ifreq local;
2331 struct ifreq *ifrequest,*nextif;
2332 int dup,xxx,tmp;
2333 union sockunion * localAddresses = NULL;
2334
2335 cf.ifc_buf = buffer;
2336 cf.ifc_len = 8192;
2337 *max_mtu = 0;
2338 *numberOfNets = 0;
2339
2340 /* Now gather the master address information */
2341 if(ioctl(sctp_fd, SIOCGIFCONF, (char *)&cf) == -1) {
2342 return(FALSE);
2343 }
2344
2345 #ifdef USES_BSD_4_4_SOCKET
2346 for (pos = 0; pos < cf.ifc_len; ) {
2347 ifrequest = (struct ifreq *)&buffer[pos];
2348 #ifdef SOLARIS
2349 pos += (sizeof(struct sockaddr) + sizeof(ifrequest->ifr_name));
2350 #else
2351 #ifdef NEUTRINO_RTOS
2352 if (ifrequest->ifr_addr.sa_len + IFNAMSIZ > sizeof(struct ifreq)) {
2353 pos += ifrequest->ifr_addr.sa_len + IFNAMSIZ;
2354 } else {
2355 pos += sizeof(struct ifreq);
2356 }
2357 #else
2358 pos += (ifrequest->ifr_addr.sa_len + sizeof(ifrequest->ifr_name));
2359
2360 if (ifrequest->ifr_addr.sa_len == 0) {
2361 /* if the interface has no address then you must
2362 * skip at a minium a sockaddr structure
2363 */
2364 pos += sizeof(struct sockaddr);
2365 }
2366 #endif // NEUTRINO_RTOS
2367 #endif
2368 numAlocAddr++;
2369 }
2370 #else
2371 numAlocAddr = cf.ifc_len / sizeof(struct ifreq);
2372 /* ???????????? numAlocAddr++; */
2373 ifrequest = cf.ifc_req;
2374 #endif
2375 #if defined (LINUX)
2376 numAlocIPv4Addr = numAlocAddr;
2377 addedNets = 0;
2378 v6list = fopen(LINUX_PROC_IPV6_FILE,"r");
2379 if (v6list != NULL) {
2380 while(fgets(addrBuffer,sizeof(addrBuffer),v6list) != NULL){
2381 addedNets++;
2382 }
2383 fclose(v6list);
2384 }
2385 numAlocAddr += addedNets;
2386 event_logii(VERBOSE, "Found additional %d v6 addresses, total now %d\n",addedNets,numAlocAddr);
2387 #endif
2388 /* now allocate the appropriate memory */
2389 localAddresses = (union sockunion*)calloc(numAlocAddr,sizeof(union sockunion));
2390
2391 if(localAddresses == NULL){
2392 error_log(ERROR_MAJOR, "Out of Memory in adl_gatherLocalAddresses() !");
2393 return(FALSE);
2394 }
2395
2396 pos = 0;
2397 /* Now we go through and pull each one */
2398
2399 #if defined (LINUX)
2400 v6list = fopen(LINUX_PROC_IPV6_FILE,"r");
2401 if(v6list != NULL){
2402 memset((char *)&sin6,0,sizeof(sin6));
2403 sin6.sin6_family = AF_INET6;
2404
2405 while(fgets(addrBuffer,sizeof(addrBuffer),v6list) != NULL){
2406 if(strncmp(addrBuffer,"00000000000000000000000000000001",32) == 0) {
2407 event_log(VVERBOSE, "At least I found the local IPV6 address !");
2408 if(inet_pton(AF_INET6,"::1",(void *)&sin6.sin6_addr) > 0){
2409 sin6.sin6_family = AF_INET6;
2410 memcpy(&((localAddresses)[*numberOfNets]),&sin6,sizeof(sin6));
2411 event_logiiiii(VVERBOSE, "copied the local IPV6 address %x:%x:%x:%x, family %x",
2412 sin6.sin6_addr.s6_addr32[3], sin6.sin6_addr.s6_addr32[2], sin6.sin6_addr.s6_addr32[1],
2413 sin6.sin6_addr.s6_addr32[0], sin6.sin6_family);
2414 (*numberOfNets)++;
2415 }
2416 continue;
2417 }
2418 memset(addrBuffer2,0,sizeof(addrBuffer2));
2419 strncpy(addrBuffer2,addrBuffer,4);
2420 addrBuffer2[4] = ':';
2421 strncpy(&addrBuffer2[5],&addrBuffer[4],4);
2422 addrBuffer2[9] = ':';
2423 strncpy(&addrBuffer2[10],&addrBuffer[8],4);
2424 addrBuffer2[14] = ':';
2425 strncpy(&addrBuffer2[15],&addrBuffer[12],4);
2426 addrBuffer2[19] = ':';
2427 strncpy(&addrBuffer2[20],&addrBuffer[16],4);
2428 addrBuffer2[24] = ':';
2429 strncpy(&addrBuffer2[25],&addrBuffer[20],4);
2430 addrBuffer2[29] = ':';
2431 strncpy(&addrBuffer2[30],&addrBuffer[24],4);
2432 addrBuffer2[34] = ':';
2433 strncpy(&addrBuffer2[35],&addrBuffer[28],4);
2434
2435 if(inet_pton(AF_INET6,addrBuffer2,(void *)&sin6.sin6_addr) > 0){
2436 if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr)) {
2437 sscanf((const char*)&addrBuffer[34], "%x", &sin6.sin6_scope_id);
2438 }
2439 memcpy(&((localAddresses)[*numberOfNets]),&sin6,sizeof(sin6));
2440
2441 }else{
2442 error_logi(ERROR_FATAL, "Could not translate string %s",addrBuffer2);
2443 }
2444 }
2445 fclose(v6list);
2446 }
2447 #endif
2448
2449 /* set to the start, i.e. buffer[0] */
2450 ifrequest = (struct ifreq *)&buffer[pos];
2451
2452 #if defined (LINUX)
2453 for(ii=0; ii < numAlocIPv4Addr; ii++,ifrequest=nextif){
2454 #else
2455 for(ii=0; ii < numAlocAddr; ii++,ifrequest=nextif){
2456 #endif
2457 #ifdef USES_BSD_4_4_SOCKET
2458 /* use the sa_len to calculate where the next one will be */
2459 #ifdef SOLARIS
2460 pos += (sizeof(struct sockaddr) + sizeof(ifrequest->ifr_name));
2461 #else
2462 #ifdef NEUTRINO_RTOS
2463 if (ifrequest->ifr_addr.sa_len + IFNAMSIZ > sizeof(struct ifreq)) {
2464 pos += ifrequest->ifr_addr.sa_len + IFNAMSIZ;
2465 } else {
2466 pos += sizeof(struct ifreq);
2467 }
2468 #else
2469 pos += (ifrequest->ifr_addr.sa_len + sizeof(ifrequest->ifr_name));
2470
2471 if (ifrequest->ifr_addr.sa_len == 0){
2472 /* if the interface has no address then you must
2473 * skip at a minium a sockaddr structure
2474 */
2475 pos += sizeof(struct sockaddr);
2476 }
2477 #endif // NEUTRINO_RTOS
2478 #endif
2479 nextif = (struct ifreq *)&buffer[pos];
2480 #else
2481 nextif = ifrequest + 1;
2482 #endif
2483
2484 #ifdef _NO_SIOCGIFMTU_
2485 *max_mtu = DEFAULT_MTU_CEILING;
2486 #else
2487 memset(&local, 0, sizeof(local));
2488 memcpy(local.ifr_name,ifrequest->ifr_name,IFNAMSIZ);
2489 event_logiii(VERBOSE, "Interface %d, NAME %s, Hex: %x",ii,local.ifr_name,local.ifr_name);
2490
2491 if (ioctl(sctp_fd, SIOCGIFMTU, (char *)&local) == -1) {
2492 /* cant get the flags? */
2493 continue;
2494 }
2495 saveMTU = local.ifr_mtu;
2496 event_logii(VERBOSE, "Interface %d, MTU %d",ii,saveMTU);
2497 #endif
2498 toUse = &ifrequest->ifr_addr;
2499
2500 adl_sockunion2str((union sockunion*)toUse, (guchar *)addrBuffer2, SCTP_MAX_IP_LEN);
2501 event_logi(VERBOSE, "we are talking about the address %s", addrBuffer2);
2502
2503
2504 memset(&local, 0, sizeof(local));
2505 memcpy(local.ifr_name, ifrequest->ifr_name, IFNAMSIZ);
2506
2507 if(ioctl(sctp_fd, SIOCGIFFLAGS, (char *)&local) == -1){
2508 /* can't get the flags, skip this guy */
2509 continue;
2510 }
2511 /* Ok get the address and save the flags */
2512 /* intf_flags = local.ifr_flags; */
2513
2514 if(!(local.ifr_flags & IFF_UP)) {
2515 /* Interface is down */
2516 continue;
2517 }
2518
2519
2520 if (flags & flag_HideLoopback){
2521 if (adl_filterInetAddress((union sockunion*)toUse, flag_HideLoopback) == FALSE){
2522 /* skip the loopback */
2523 event_logi(VERBOSE, "Interface %d, skipping loopback",ii);
2524 continue;
2525 }
2526 }
2527 if (adl_filterInetAddress((union sockunion*)toUse, flag_HideReserved) == FALSE) {
2528 /* skip reserved */
2529 event_logi(VERBOSE, "Interface %d, skipping reserved",ii);
2530 continue;
2531 }
2532
2533 if(toUse->sa_family== AF_INET){
2534 copSiz = sizeof(struct sockaddr_in);
2535 } else if (toUse->sa_family == AF_INET6){
2536 copSiz = sizeof(struct sockaddr_in6);
2537 }
2538 if (*max_mtu < saveMTU) *max_mtu = saveMTU;
2539
2540 /* Now, we may have already gathered this address, if so skip
2541 * it
2542 */
2543 event_logii(VERBOSE, "Starting checking for duplicates ! MTU = %d, nets: %d",saveMTU, *numberOfNets);
2544
2545 if(*numberOfNets) {
2546 tmp = *numberOfNets;
2547 dup = 0;
2548 /* scan for the dup */
2549 for(xxx=0; xxx < tmp; xxx++) {
2550 event_logi(VERBOSE, "duplicates loop xxx=%d",xxx);
2551 if(adl_equal_address(&localAddresses[xxx], (union sockunion*)toUse)) {
2552 #ifdef HAVE_IPV6
2553 if((localAddresses[xxx].sa.sa_family == AF_INET6) &&
2554 (toUse->sa_family == AF_INET) &&
2555 (IN6_IS_ADDR_V4MAPPED(&localAddresses[xxx].sin6.sin6_addr) ||
2556 IN6_IS_ADDR_V4COMPAT(&localAddresses[xxx].sin6.sin6_addr))) {
2557 /* There are multiple interfaces, one has ::ffff:a.b.c.d or
2558 ::a.b.c.d address. Use address which is IPv4 native instead. */
2559 memcpy(&localAddresses[xxx], toUse, sizeof(localAddresses[xxx]));
2560 }
2561 else {
2562 #endif
2563 event_log(VERBOSE, "Interface %d, found duplicate");
2564 dup = 1;
2565 #ifdef HAVE_IPV6
2566 }
2567 #endif
2568 }
2569 }
2570 if(dup) {
2571 /* skip the duplicate name/address we already have it*/
2572 continue;
2573 }
2574 }
2575
2576 /* copy address */
2577 event_logi(VVERBOSE, "Copying %d bytes",copSiz);
2578 memcpy(&localAddresses[*numberOfNets],(char *)toUse,copSiz);
2579 event_log(VVERBOSE, "Setting Family");
2580 /* set family */
2581 (&(localAddresses[*numberOfNets]))->sa.sa_family = toUse->sa_family;
2582
2583 #ifdef USES_BSD_4_4_SOCKET
2584 #ifndef SOLARIS
2585 /* copy the length */
2586 (&(localAddresses[*numberOfNets]))->sa.sa_len = toUse->sa_len;
2587 #endif
2588 #endif
2589 (*numberOfNets)++;
2590 event_logii(VERBOSE, "Interface %d, Number of Nets: %d",ii, *numberOfNets);
2591 }
2592
2593 event_logi(VERBOSE, "adl_gatherLocalAddresses: Found %d addresses", *numberOfNets);
2594 for(ii = 0; ii < (*numberOfNets); ii++) {
2595 adl_sockunion2str(&(localAddresses[ii]), (guchar *)addrBuffer2, SCTP_MAX_IP_LEN);
2596 event_logii(VERBOSE, "adl_gatherAddresses : Address %d: %s",ii, addrBuffer2);
2597
2598 }
2599 *addresses = localAddresses;
2600 return(TRUE);
2601 #endif
2602 }
2603
2604