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