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