PUD: fix some includes
[olsrd.git] / lib / pud / src / networkInterfaces.c
1 #include "networkInterfaces.h"
2
3 /* Plugin includes */
4 #include "pud.h"
5 #include "configuration.h"
6 #include "netTools.h"
7
8 /* OLSRD includes */
9 #include "olsr_cfg.h"
10 #include "olsr.h"
11 #include "interfaces.h"
12
13 /* System includes */
14 #include <assert.h>
15 #include <string.h>
16 #include <sys/socket.h>
17 #include <errno.h>
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <stddef.h>
21 #include <fcntl.h>
22 #include <ifaddrs.h>
23
24 /*
25  * Main IP MAC address
26  */
27
28 /** the MAC address of the main IP address */
29 static unsigned char mac[PUD_NODEIDTYPE_MAC_BYTES] = { 0 };
30
31 /** true when the MAC address of the main IP address has been retrieved */
32 static bool macSet = false;
33
34 /**
35  * @return
36  * the MAC address of the main IP address
37  */
38 unsigned char * getMainIpMacAddress(void) {
39         if (!macSet) {
40                 struct ifreq ifr;
41                 unsigned char * macInIfr;
42
43                 struct interface *mainInterface = if_ifwithaddr(&olsr_cnf->main_addr);
44                 if (!mainInterface) {
45                         pudError(true, "Could not get the main interface");
46                         return NULL;
47                 }
48                 macInIfr = getHardwareAddress(mainInterface->int_name,olsr_cnf->ip_version,&ifr);
49                 if (!macInIfr) {
50                         pudError(true, "Could not get the MAC address of the main interface");
51                         return NULL;
52                 }
53                 memcpy(&mac[0], &macInIfr[0], PUD_NODEIDTYPE_MAC_BYTES);
54                 macSet = true;
55         }
56
57         return &mac[0];
58 }
59
60 /*
61  * RX interfaces
62  */
63
64 /** The list of network interface objects, receiving GPS NMEA sentences */
65 static TRxTxNetworkInterface *rxNetworkInterfacesListHead = NULL;
66
67 /** Pointer to the last network interface object, receiving GPS NMEA sentences */
68 static TRxTxNetworkInterface *lastRxNetworkInterface = NULL;
69
70 /**
71  @return
72  The list of network interface objects, receiving GPS NMEA sentences
73  */
74 TRxTxNetworkInterface *getRxNetworkInterfaces(void) {
75         return rxNetworkInterfacesListHead;
76 }
77
78 /**
79  Create a receive socket for a network interface
80
81  @param networkInterface
82  The network interface object. This function expects it to be filled with all
83  information, except for the socket descriptor.
84  @param rxSocketHandlerFunction
85  The function that handles reception of data on the network interface
86
87  @return
88  - the socket descriptor (>= 0)
89  - -1 if an error occurred
90  */
91 static int createRxSocket(TRxTxNetworkInterface * networkInterface,
92                 socket_handler_func rxSocketHandlerFunction) {
93         int ipFamilySetting;
94         int ipProtoSetting;
95         int ipMcLoopSetting;
96         int ipAddMembershipSetting;
97         int socketReuseFlagValue = 1;
98         int mcLoopValue = 1;
99         union olsr_sockaddr address;
100         int rxSocket = -1;
101
102         assert(networkInterface != NULL);
103         assert(rxSocketHandlerFunction != NULL);
104         assert(strncmp((char *) &networkInterface->name[0], "",
105                                         sizeof(networkInterface->name)) != 0);
106
107         memset(&address, 0, sizeof(address));
108         if (olsr_cnf->ip_version == AF_INET) {
109                 assert(networkInterface->ipAddress.in4.sin_addr.s_addr != INADDR_ANY);
110
111                 ipFamilySetting = AF_INET;
112                 ipProtoSetting = IPPROTO_IP;
113                 ipMcLoopSetting = IP_MULTICAST_LOOP;
114                 ipAddMembershipSetting = IP_ADD_MEMBERSHIP;
115
116                 address.in4.sin_family = ipFamilySetting;
117                 address.in4.sin_addr.s_addr = INADDR_ANY;
118                 address.in4.sin_port = getRxMcPort();
119         } else {
120                 assert(networkInterface->ipAddress.in6.sin6_addr.s6_addr != in6addr_any.s6_addr);
121
122                 ipFamilySetting = AF_INET6;
123                 ipProtoSetting = IPPROTO_IPV6;
124                 ipMcLoopSetting = IPV6_MULTICAST_LOOP;
125                 ipAddMembershipSetting = IPV6_ADD_MEMBERSHIP;
126
127                 address.in6.sin6_family = ipFamilySetting;
128                 address.in6.sin6_addr = in6addr_any;
129                 address.in6.sin6_port = getRxMcPort();
130         }
131
132         /* Create a datagram socket on which to receive. */
133         errno = 0;
134         rxSocket = socket(ipFamilySetting, SOCK_DGRAM, 0);
135         if (rxSocket < 0) {
136                 pudError(true, "Could not create a receive socket for interface %s",
137                                 networkInterface->name);
138                 goto bail;
139         }
140
141         /* Enable SO_REUSEADDR to allow multiple applications to receive the same
142          * multicast messages */
143         errno = 0;
144         if (setsockopt(rxSocket, SOL_SOCKET, SO_REUSEADDR, &socketReuseFlagValue,
145                         sizeof(socketReuseFlagValue)) < 0) {
146                 pudError(true, "Could not set the reuse flag on the receive socket for"
147                         " interface %s", networkInterface->name);
148                 goto bail;
149         }
150
151         /* Bind to the proper port number with the IP address INADDR_ANY
152          * (INADDR_ANY is really required here, do not change it) */
153         errno = 0;
154         if (bind(rxSocket, (struct sockaddr *) &address, sizeof(address)) < 0) {
155                 pudError(true, "Could not bind the receive socket for interface"
156                         " %s to port %u", networkInterface->name, ntohs(getRxMcPort()));
157                 goto bail;
158         }
159
160         /* Enable multicast local loopback */
161         errno = 0;
162         if (setsockopt(rxSocket, ipProtoSetting, ipMcLoopSetting, &mcLoopValue,
163                         sizeof(mcLoopValue)) < 0) {
164                 pudError(true, "Could not %s multicast loopback on the"
165                         " receive socket for interface %s", mcLoopValue ? "enable"
166                                 : "disable", networkInterface->name);
167                 goto bail;
168         }
169
170         /* Join the multicast group on the local interface. Note that this
171          * ADD_MEMBERSHIP option must be called for each local interface over
172          * which the multicast datagrams are to be received. */
173         if (ipFamilySetting == AF_INET) {
174                 struct ip_mreq mc_settings;
175                 (void) memset(&mc_settings, 0, sizeof(mc_settings));
176                 mc_settings.imr_multiaddr = getRxMcAddr()->in4.sin_addr;
177                 mc_settings.imr_interface = networkInterface->ipAddress.in4.sin_addr;
178                 errno = 0;
179                 if (setsockopt(rxSocket, ipProtoSetting, ipAddMembershipSetting,
180                                 &mc_settings, sizeof(mc_settings)) < 0) {
181                         pudError(true, "Could not subscribe interface %s to the configured"
182                                 " multicast group", networkInterface->name);
183                         goto bail;
184                 }
185         } else {
186                 struct ipv6_mreq mc6_settings;
187                 (void) memset(&mc6_settings, 0, sizeof(mc6_settings));
188                 mc6_settings.ipv6mr_multiaddr = getRxMcAddr()->in6.sin6_addr;
189                 mc6_settings.ipv6mr_interface = 0;
190                 errno = 0;
191                 if (setsockopt(rxSocket, ipProtoSetting, ipAddMembershipSetting,
192                                 &mc6_settings, sizeof(mc6_settings)) < 0) {
193                         pudError(true, "Could not subscribe interface %s to the configured"
194                                 " multicast group", networkInterface->name);
195                         goto bail;
196                 }
197         }
198
199         add_olsr_socket(rxSocket, rxSocketHandlerFunction, NULL, networkInterface,
200                         SP_PR_READ);
201
202         return rxSocket;
203
204         bail: if (rxSocket >= 0) {
205                 close(rxSocket);
206         }
207         return -1;
208
209 }
210
211 /**
212  Create a receive interface and add it to the list of receive network interface
213  objects
214
215  @param ifName
216  the network interface name
217  @param ipAddr
218  the IP address of the interface
219  @param rxSocketHandlerFunction
220  the function that handles reception of data on the network interface
221
222  @return
223  - true on success
224  - false on failure
225  */
226 static bool createRxInterface(const char * ifName, union olsr_sockaddr ipAddr,
227                 socket_handler_func rxSocketHandlerFunction) {
228         int socketFd = -1;
229         TRxTxNetworkInterface * networkInterface = NULL;
230
231         if (ifName == NULL) {
232                 goto bail;
233         }
234
235         networkInterface = olsr_malloc(sizeof(TRxTxNetworkInterface),
236                         "TRxTxNetworkInterface (PUD)");
237         if (networkInterface == NULL) {
238                 goto bail;
239         }
240
241         memcpy(networkInterface->name, ifName, sizeof(networkInterface->name));
242         networkInterface->name[IFNAMSIZ] = '\0';
243         networkInterface->ipAddress = ipAddr;
244         networkInterface->handler = NULL;
245         networkInterface->next = NULL;
246
247         /* networkInterface needs to be filled in when calling createRxSocket */
248         socketFd = createRxSocket(networkInterface, rxSocketHandlerFunction);
249         if (socketFd < 0) {
250                 goto bail;
251         }
252         networkInterface->socketFd = socketFd;
253         networkInterface->handler = rxSocketHandlerFunction;
254
255         /* Add new object to the end of the global list. */
256         if (rxNetworkInterfacesListHead == NULL) {
257                 rxNetworkInterfacesListHead = networkInterface;
258                 lastRxNetworkInterface = networkInterface;
259         } else {
260                 lastRxNetworkInterface->next = networkInterface;
261                 lastRxNetworkInterface = networkInterface;
262         }
263
264         return true;
265
266         bail: if (networkInterface != NULL) {
267                 free(networkInterface);
268         }
269         return false;
270
271 }
272
273 /*
274  * TX interfaces
275  */
276
277 /** The list of network interface objects, sending our NMEA sentences */
278 static TRxTxNetworkInterface *txNetworkInterfacesListHead = NULL;
279
280 /** Pointer to the last network interface object, sending our NMEA sentences */
281 static TRxTxNetworkInterface *lastTxNetworkInterface = NULL;
282
283 /**
284  @return
285  The list of network interface objects, sending our NMEA sentences
286  */
287 TRxTxNetworkInterface *getTxNetworkInterfaces(void) {
288         return txNetworkInterfacesListHead;
289 }
290
291 /**
292  Create a transmit socket for a network interface
293
294  @param networkInterface
295  The network interface object. This function expects it to be filled with all
296  information, except for the socket descriptor.
297
298  @return
299  - the socket descriptor (>= 0)
300  - -1 if an error occurred
301  */
302 static int createTxSocket(TRxTxNetworkInterface * networkInterface) {
303         int ipFamilySetting;
304         int ipProtoSetting;
305         int ipMcLoopSetting;
306         int ipMcIfSetting;
307         int mcLoopValue = 0;
308         unsigned char txTtl = getTxTtl();
309         union olsr_sockaddr address;
310         int txSocket = -1;
311
312         assert(networkInterface != NULL);
313         assert(strncmp((char *) &networkInterface->name[0], "",
314                                         sizeof(networkInterface->name)) != 0);
315
316         memset(&address, 0, sizeof(address));
317         if (olsr_cnf->ip_version == AF_INET) {
318                 assert(networkInterface->ipAddress.in4.sin_addr.s_addr != INADDR_ANY);
319
320                 ipFamilySetting = AF_INET;
321                 ipProtoSetting = IPPROTO_IP;
322                 ipMcLoopSetting = IP_MULTICAST_LOOP;
323                 ipMcIfSetting = IP_MULTICAST_IF;
324
325                 address.in4.sin_family = ipFamilySetting;
326                 address.in4.sin_addr = networkInterface->ipAddress.in4.sin_addr;
327                 address.in4.sin_port = getTxMcPort();
328         } else {
329                 assert(networkInterface->ipAddress.in6.sin6_addr.s6_addr != in6addr_any.s6_addr);
330
331                 ipFamilySetting = AF_INET6;
332                 ipProtoSetting = IPPROTO_IPV6;
333                 ipMcLoopSetting = IPV6_MULTICAST_LOOP;
334                 ipMcIfSetting = IPV6_MULTICAST_IF;
335
336                 address.in6.sin6_family = ipFamilySetting;
337                 address.in6.sin6_addr = networkInterface->ipAddress.in6.sin6_addr;
338                 address.in6.sin6_port = getTxMcPort();
339         }
340
341         /*  Create a datagram socket on which to transmit */
342         errno = 0;
343         txSocket = socket(ipFamilySetting, SOCK_DGRAM, 0);
344         if (txSocket < 0) {
345                 pudError(true, "Could not create a transmit socket for interface %s",
346                                 networkInterface->name);
347                 goto bail;
348         }
349
350         /* Bind the socket to the desired interface and port */
351         errno = 0;
352         if (setsockopt(txSocket, ipProtoSetting, ipMcIfSetting, &address,
353                         sizeof(address)) < 0) {
354                 pudError(true, "Could not set the multicast interface on the"
355                         " transmit socket to interface %s", networkInterface->name);
356                 goto bail;
357         }
358
359         /* Disable multicast local loopback */
360         errno = 0;
361         if (setsockopt(txSocket, ipProtoSetting, ipMcLoopSetting, &mcLoopValue,
362                         sizeof(mcLoopValue)) < 0) {
363                 pudError(true, "Could not %s multicast loopback on the"
364                         " transmit socket for interface %s", mcLoopValue ? "enable"
365                                 : "disable", networkInterface->name);
366                 goto bail;
367         }
368
369         /* Set the TTL on the socket */
370         errno = 0;
371         if (setsockopt(txSocket, ipProtoSetting, IP_MULTICAST_TTL, &txTtl,
372                         sizeof(txTtl)) < 0) {
373                 pudError(true, "Could not set TTL on the transmit socket"
374                         " for interface %s", networkInterface->name);
375                 goto bail;
376         }
377
378         /* Set the no delay option on the socket */
379         errno = 0;
380         if (fcntl(txSocket, F_SETFL, O_NDELAY) < 0) {
381                 pudError(true, "Could not set the no delay option on the"
382                         " transmit socket for interface %s", networkInterface->name);
383                 goto bail;
384         }
385
386         return txSocket;
387
388         bail: if (txSocket >= 0) {
389                 close(txSocket);
390         }
391         return -1;
392 }
393
394 /**
395  Create a transmit interface and add it to the list of transmit network
396  interface objects
397
398  @param ifName
399  the network interface name
400  @param ipAddr
401  the IP address of the interface
402
403  @return
404  - true on success
405  - false on failure
406  */
407 static bool createTxInterface(const char * ifName, union olsr_sockaddr ipAddr) {
408         int socketFd = -1;
409         TRxTxNetworkInterface * networkInterface = NULL;
410
411         if (ifName == NULL) {
412                 goto bail;
413         }
414
415         networkInterface = olsr_malloc(sizeof(TRxTxNetworkInterface),
416                         "TRxTxNetworkInterface (PUD)");
417         if (networkInterface == NULL) {
418                 goto bail;
419         }
420
421         memcpy(networkInterface->name, ifName, sizeof(networkInterface->name));
422         networkInterface->name[IFNAMSIZ] = '\0';
423         networkInterface->ipAddress = ipAddr;
424         networkInterface->handler = NULL;
425         networkInterface->next = NULL;
426
427         /* networkInterface needs to be filled in when calling createTxSocket */
428         socketFd = createTxSocket(networkInterface);
429         if (socketFd < 0) {
430                 goto bail;
431         }
432         networkInterface->socketFd = socketFd;
433
434         /* Add new object to the end of the global list. */
435         if (txNetworkInterfacesListHead == NULL) {
436                 txNetworkInterfacesListHead = networkInterface;
437                 lastTxNetworkInterface = networkInterface;
438         } else {
439                 lastTxNetworkInterface->next = networkInterface;
440                 lastTxNetworkInterface = networkInterface;
441         }
442
443         return true;
444
445         bail: if (networkInterface != NULL) {
446                 free(networkInterface);
447         }
448         return false;
449 }
450
451 /*
452  * Downlink interface
453  */
454
455 /** The socket fd, receiving downlinked messages */
456 static int downlinkSocketFd = -1;
457
458 /** the downlink handler function */
459 static socket_handler_func downlinkHandler = NULL;
460
461
462 /**
463  @return
464  The downlink socket fd. -1 when not valid.
465  */
466 int getDownlinkSocketFd(void) {
467         return downlinkSocketFd;
468 }
469
470 /**
471  Create an downlink socket
472
473  @return
474  - the socket descriptor (>= 0)
475  - -1 if an error occurred
476  */
477 static int createDownlinkSocket(socket_handler_func rxSocketHandlerFunction) {
478         int downlinkSocket = -1;
479         int socketReuseFlagValue = 1;
480         union olsr_sockaddr address;
481
482         memset(&address, 0, sizeof(address));
483         if (olsr_cnf->ip_version == AF_INET) {
484                 address.in4.sin_family = AF_INET;
485                 address.in4.sin_addr.s_addr = INADDR_ANY;
486                 address.in4.sin_port = getDownlinkPort();
487         } else {
488                 address.in6.sin6_family = AF_INET6;
489                 address.in6.sin6_addr = in6addr_any;
490                 address.in6.sin6_port = getDownlinkPort();
491         }
492
493         /*  Create a datagram socket on which to receive */
494         errno = 0;
495         downlinkSocket = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
496         if (downlinkSocket < 0) {
497                 pudError(true, "Could not create the downlink socket");
498                 goto bail;
499         }
500
501         /* Enable SO_REUSEADDR to allow multiple applications to receive the same
502          * messages */
503         errno = 0;
504         if (setsockopt(downlinkSocket, SOL_SOCKET, SO_REUSEADDR, &socketReuseFlagValue,
505                         sizeof(socketReuseFlagValue)) < 0) {
506                 pudError(true, "Could not set REUSE option on the downlink socket");
507                 goto bail;
508         }
509
510         /* Bind to the proper port number with the IP address INADDR_ANY
511          * (INADDR_ANY is really required here, do not change it) */
512         errno = 0;
513         if (bind(downlinkSocket, (struct sockaddr *) &address, sizeof(address))) {
514                 pudError(true, "Could not bind downlink socket to port %d",
515                                 getDownlinkPort());
516                 goto bail;
517         }
518
519         add_olsr_socket(downlinkSocket, rxSocketHandlerFunction, NULL, NULL,
520                         SP_PR_READ);
521
522         downlinkHandler = rxSocketHandlerFunction;
523
524         return downlinkSocket;
525
526         bail: if (downlinkSocket >= 0) {
527                 close(downlinkSocket);
528         }
529         return -1;
530 }
531
532 /*
533  * OLSR interfaces
534  */
535
536 /** The list of OLSR network interface objects */
537 static TOLSRNetworkInterface *olsrNetworkInterfacesListHead = NULL;
538
539 /** Pointer to the last OLSR network interface object */
540 static TOLSRNetworkInterface *lastOlsrNetworkInterface = NULL;
541
542 /**
543  Get the OLSR interface structure for a certain OLSR interface. Note that
544  pointer comparison is performed to compare the OLSR interfaces.
545
546  @param olsrIntf
547  a pointer to an OLSR interface
548
549  @return
550  - a pointer to the OLSR interface structure
551  - NULL when not found
552  */
553 TOLSRNetworkInterface * getOlsrNetworkInterface(struct interface *olsrIntf) {
554         TOLSRNetworkInterface * retval = olsrNetworkInterfacesListHead;
555
556         while ((retval->olsrIntf != olsrIntf) && (retval != NULL)) {
557                 retval = retval->next;
558         }
559
560         return retval;
561 }
562
563 /**
564  Create an OLSR interface and add it to the list of OLSR network interface
565  objects
566
567  @param olsrIntf
568  a pointer to the OLSR interface
569
570  @return
571  - true on success
572  - false on failure
573  */
574 static int createOlsrInterface(struct interface *olsrIntf) {
575         TOLSRNetworkInterface * networkInterface = NULL;
576
577         networkInterface = olsr_malloc(sizeof(TOLSRNetworkInterface),
578                         "TOLSRNetworkInterface (PUD)");
579         if (networkInterface == NULL) {
580                 goto bail;
581         }
582
583         networkInterface->olsrIntf = olsrIntf;
584         networkInterface->next = NULL;
585
586         /* Add new object to the end of the global list. */
587         if (olsrNetworkInterfacesListHead == NULL) {
588                 olsrNetworkInterfacesListHead = networkInterface;
589                 lastOlsrNetworkInterface = networkInterface;
590         } else {
591                 lastOlsrNetworkInterface->next = networkInterface;
592                 lastOlsrNetworkInterface = networkInterface;
593         }
594
595         return true;
596
597         bail: if (networkInterface != NULL) {
598                 free(networkInterface);
599         }
600         return false;
601 }
602
603 /*
604  * Interface Functions
605  */
606
607 /**
608  Creates receive and transmit sockets and register the receive sockets with
609  the OLSR stack
610
611  @param rxSocketHandlerFunction
612  The function to call upon reception of data on a receive socket
613  @param rxSocketHandlerFunctionDownlink
614  The function to call upon reception of data on a downlink receive socket
615
616  @return
617  - true on success
618  - false on failure
619  */
620 bool createNetworkInterfaces(socket_handler_func rxSocketHandlerFunction,
621                 socket_handler_func rxSocketHandlerFunctionDownlink) {
622         int retval = false;
623         struct ifaddrs *ifAddrs = NULL;
624         struct ifaddrs *ifAddr = NULL;
625
626         errno = 0;
627         if (getifaddrs(&ifAddrs) != 0) {
628                 pudError(true, "Could not get list of interfaces and their addresses");
629                 return retval;
630         }
631
632         /* loop over all interfaces */
633         for (ifAddr = ifAddrs; ifAddr != NULL; ifAddr = ifAddr->ifa_next) {
634                 struct sockaddr * addr = ifAddr->ifa_addr;
635                 if (addr != NULL) {
636                         int addrFamily = addr->sa_family;
637                         if (addrFamily == olsr_cnf->ip_version) {
638                                 char * ifName = ifAddr->ifa_name;
639                                 union olsr_sockaddr ipAddr;
640
641                                 /* determine whether the iterated interface is an OLSR
642                                  * interface: returns NULL when the interface is not an
643                                  * OLSR interface */
644                                 struct interface *olsrIntf = if_ifwithname(ifName);
645                                 bool isOlsrIf = (olsrIntf != NULL);
646
647                                 /* determine whether the iterated interface is configured as a
648                                  * non-OLSR interface in the plugin parameter list */
649                                 bool isRxNonOlsrIf = isRxNonOlsrInterface(ifName);
650                                 bool isTxNonOlsrIf = isTxNonOlsrInterface(ifName);
651                                 bool isNonOlsrIf = isRxNonOlsrIf || isTxNonOlsrIf;
652
653                                 if (!isOlsrIf && !isNonOlsrIf) {
654                                         /* Interface is not an OLSR interface AND interface is not
655                                          * configured as non-OLSR interface: skip */
656                                         continue;
657                                 }
658
659                                 if (isOlsrIf && !createOlsrInterface(olsrIntf)) {
660                                         /* creating an OLSR interface failed */
661                                         goto end;
662                                 }
663
664                                 if (!isNonOlsrIf) {
665                                         /* interface is not configured as non-OLSR interface: skip */
666                                         continue;
667                                 }
668
669                                 if (addrFamily == AF_INET) {
670                                         memcpy(&ipAddr.in4, addr, sizeof(struct sockaddr_in));
671                                 } else {
672                                         memcpy(&ipAddr.in6, addr, sizeof(struct sockaddr_in6));
673                                 }
674
675                                 if (isRxNonOlsrIf && !createRxInterface(ifName, ipAddr,
676                                                 rxSocketHandlerFunction)) {
677                                         /* creating a receive interface failed */
678                                         goto end;
679                                 }
680
681                                 if (isTxNonOlsrIf && !createTxInterface(ifName, ipAddr)) {
682                                         /* creating a transmit interface failed */
683                                         goto end;
684                                 }
685                         }
686                 }
687         }
688
689         if (isUplinkAddrSet()) {
690                 downlinkSocketFd = createDownlinkSocket(rxSocketHandlerFunctionDownlink);
691                 if (downlinkSocketFd == -1) {
692                         goto end;
693                 }
694         } else {
695                 downlinkSocketFd = -1;
696         }
697
698         retval = true;
699
700         end: freeifaddrs(ifAddrs);
701         return retval;
702 }
703
704 /**
705  Cleanup the OLSR network interfaces in the given list
706
707  @param networkInterface
708  the list of network interface to close and clean up
709  */
710 static void cleanupOlsrInterfaces(TOLSRNetworkInterface * networkInterface) {
711         TOLSRNetworkInterface * nextNetworkInterface = networkInterface;
712         while (nextNetworkInterface != NULL) {
713                 TOLSRNetworkInterface * iteratedNetworkInterface = nextNetworkInterface;
714                 nextNetworkInterface = iteratedNetworkInterface->next;
715                 iteratedNetworkInterface->next = NULL;
716                 free(iteratedNetworkInterface);
717         }
718 }
719
720 /**
721  Close and cleanup the network interfaces in the given list
722
723  @param networkInterface
724  the list of network interface to close and clean up
725  */
726 static void closeInterfaces(TRxTxNetworkInterface * networkInterface) {
727         TRxTxNetworkInterface * nextNetworkInterface = networkInterface;
728         while (nextNetworkInterface != NULL) {
729                 TRxTxNetworkInterface * iteratedNetworkInterface = nextNetworkInterface;
730                 if (iteratedNetworkInterface->socketFd >= 0) {
731                         if (iteratedNetworkInterface->handler) {
732                                 remove_olsr_socket(iteratedNetworkInterface->socketFd,
733                                                 iteratedNetworkInterface->handler, NULL);
734                         }
735                         close(iteratedNetworkInterface->socketFd);
736                         iteratedNetworkInterface->socketFd = -1;
737                 }
738                 nextNetworkInterface = iteratedNetworkInterface->next;
739                 iteratedNetworkInterface->next = NULL;
740                 free(iteratedNetworkInterface);
741         }
742 }
743
744 /**
745  Close and cleanup all receive and transmit network interfaces
746  */
747 void closeNetworkInterfaces(void) {
748         if (rxNetworkInterfacesListHead != NULL) {
749                 closeInterfaces(rxNetworkInterfacesListHead);
750                 rxNetworkInterfacesListHead = NULL;
751         }
752
753         if (txNetworkInterfacesListHead != NULL) {
754                 closeInterfaces(txNetworkInterfacesListHead);
755                 txNetworkInterfacesListHead = NULL;
756         }
757
758         if (olsrNetworkInterfacesListHead != NULL) {
759                 cleanupOlsrInterfaces(olsrNetworkInterfacesListHead);
760                 olsrNetworkInterfacesListHead = NULL;
761         }
762
763         if (downlinkSocketFd != -1 ) {
764                 if (downlinkHandler) {
765                         remove_olsr_socket (downlinkSocketFd, downlinkHandler, NULL);
766                         downlinkHandler = NULL;
767                 }
768                 close(downlinkSocketFd);
769                 downlinkSocketFd = -1;
770         }
771 }