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