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