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