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