PUD: add downlink socket, no handling yet
[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  * Uplink interface
431  */
432
433 /** The socket fd, uplinking our NMEA sentences */
434 static int uplinkSocketFd = -1;
435
436 /**
437  @return
438  The socket fd, uplinking our NMEA sentences. -1 when not valid.
439  */
440 int getUplinkSocketFd(void) {
441         return uplinkSocketFd;
442 }
443
444 /**
445  Create an uplink socket
446
447  @return
448  - the socket descriptor (>= 0)
449  - -1 if an error occurred
450  */
451 static int createUplinkSocket(void) {
452         int uplinkSocket = -1;
453
454         /*  Create a datagram socket on which to transmit */
455         errno = 0;
456         uplinkSocket = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
457         if (uplinkSocket < 0) {
458                 pudError(true, "Could not create the uplink socket");
459                 goto bail;
460         }
461
462         /* Set the no delay option on the socket */
463         errno = 0;
464         if (fcntl(uplinkSocket, F_SETFL, O_NDELAY) < 0) {
465                 pudError(true, "Could not set the no delay option on the uplink socket");
466                 goto bail;
467         }
468
469         return uplinkSocket;
470
471         bail: if (uplinkSocket >= 0) {
472                 close(uplinkSocket);
473         }
474         return -1;
475 }
476
477 /*
478  * Downlink interface
479  */
480
481 /** The socket fd, receiving downlinked messages */
482 static int downlinkSocketFd = -1;
483
484 /** the downlink handler function */
485 static socket_handler_func downlinkHandler = NULL;
486
487 /**
488  Create an downlink socket
489
490  @return
491  - the socket descriptor (>= 0)
492  - -1 if an error occurred
493  */
494 static int createDownlinkSocket(socket_handler_func rxSocketHandlerFunction) {
495         int downlinkSocket = -1;
496         int reuse = 1;
497         struct sockaddr_in address;
498
499         /*  Create a datagram socket on which to receive */
500         errno = 0;
501         downlinkSocket = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
502         if (downlinkSocket < 0) {
503                 pudError(true, "Could not create the downlink socket");
504                 goto bail;
505         }
506
507         /* Enable SO_REUSEADDR to allow multiple applications to receive the same
508          * messages */
509         errno = 0;
510         if (setsockopt(downlinkSocket, SOL_SOCKET, SO_REUSEADDR, &reuse,
511                         sizeof(reuse)) < 0) {
512                 pudError(true, "Could not set REUSE option on the downlink socket");
513                 goto bail;
514         }
515
516         /* Bind to the proper port number with the IP address INADDR_ANY (required) */
517         memset(&address, 0, sizeof(address));
518         address.sin_family = AF_INET;
519         address.sin_addr.s_addr = INADDR_ANY;
520         address.sin_port = getDownlinkPort();
521
522         errno = 0;
523         if (bind(downlinkSocket, (struct sockaddr *) &address,
524                         sizeof(address))) {
525                 pudError(true, "Could not bind downlink socket to port %d", getDownlinkPort());
526                 goto bail;
527         }
528
529         add_olsr_socket(downlinkSocket, rxSocketHandlerFunction, NULL, NULL,
530                         SP_PR_READ);
531
532         downlinkHandler = rxSocketHandlerFunction;
533
534         return downlinkSocket;
535
536         bail: if (downlinkSocket >= 0) {
537                 close(downlinkSocket);
538         }
539         return -1;
540 }
541
542 /*
543  * OLSR interfaces
544  */
545
546 /** The list of OLSR network interface objects */
547 static TOLSRNetworkInterface *olsrNetworkInterfacesListHead = NULL;
548
549 /** Pointer to the last OLSR network interface object */
550 static TOLSRNetworkInterface *lastOlsrNetworkInterface = NULL;
551
552 /**
553  Get the OLSR interface structure for a certain OLSR interface. Note that
554  pointer comparison is performed to compare the OLSR interfaces.
555
556  @param olsrIntf
557  a pointer to an OLSR interface
558
559  @return
560  - a pointer to the OLSR interface structure
561  - NULL when not found
562  */
563 TOLSRNetworkInterface * getOlsrNetworkInterface(struct interface *olsrIntf) {
564         TOLSRNetworkInterface * retval = olsrNetworkInterfacesListHead;
565
566         while ((retval->olsrIntf != olsrIntf) && (retval != NULL)) {
567                 retval = retval->next;
568         }
569
570         return retval;
571 }
572
573 /**
574  Create an OLSR interface and add it to the list of OLSR network interface
575  objects
576
577  @param olsrIntf
578  a pointer to the OLSR interface
579
580  @return
581  - true on success
582  - false on failure
583  */
584 static int createOlsrInterface(struct interface *olsrIntf) {
585         TOLSRNetworkInterface * networkInterface = NULL;
586
587         networkInterface = olsr_malloc(sizeof(TOLSRNetworkInterface),
588                         "TOLSRNetworkInterface (PUD)");
589         if (networkInterface == NULL) {
590                 goto bail;
591         }
592
593         networkInterface->olsrIntf = olsrIntf;
594         networkInterface->next = NULL;
595
596         /* Add new object to the end of the global list. */
597         if (olsrNetworkInterfacesListHead == NULL) {
598                 olsrNetworkInterfacesListHead = networkInterface;
599                 lastOlsrNetworkInterface = networkInterface;
600         } else {
601                 lastOlsrNetworkInterface->next = networkInterface;
602                 lastOlsrNetworkInterface = networkInterface;
603         }
604
605         return true;
606
607         bail: if (networkInterface != NULL) {
608                 free(networkInterface);
609         }
610         return false;
611 }
612
613 /*
614  * Interface Functions
615  */
616
617 /**
618  Creates receive and transmit sockets and register the receive sockets with
619  the OLSR stack
620
621  @param rxSocketHandlerFunction
622  The function to call upon reception of data on a receive socket
623  @param rxSocketHandlerFunctionDownlink
624  The function to call upon reception of data on a downlink receive socket
625
626  @return
627  - true on success
628  - false on failure
629  */
630 bool createNetworkInterfaces(socket_handler_func rxSocketHandlerFunction,
631                 socket_handler_func rxSocketHandlerFunctionDownlink) {
632         int retval = false;
633         struct ifaddrs *ifAddrs = NULL;
634         struct ifaddrs *ifAddr = NULL;
635         struct ifreq ifr;
636         unsigned char * macInIfr;
637
638         struct interface *mainInterface = if_ifwithaddr(&olsr_cnf->main_addr);
639         if (!mainInterface) {
640                 pudError(true, "Could not get the main interface");
641                 return retval;
642         }
643         macInIfr = getHardwareAddress(mainInterface->int_name,olsr_cnf->ip_version,&ifr);
644         if (!macInIfr) {
645                 pudError(true, "Could not get the MAC address of the main interface");
646                 return retval;
647         }
648         memcpy(&mac[0], &macInIfr[0], PUD_NODEIDTYPE_MAC_BYTES);
649
650         errno = 0;
651         if (getifaddrs(&ifAddrs) != 0) {
652                 pudError(true, "Could not get list of interfaces and their addresses");
653                 return retval;
654         }
655
656         /* loop over all interfaces */
657         for (ifAddr = ifAddrs; ifAddr != NULL; ifAddr = ifAddr->ifa_next) {
658                 struct sockaddr * addr = ifAddr->ifa_addr;
659                 if (addr != NULL) {
660                         int addrFamily = addr->sa_family;
661                         if (addrFamily == olsr_cnf->ip_version) {
662                                 char * ifName = ifAddr->ifa_name;
663                                 union olsr_sockaddr ipAddr;
664
665                                 /* determine whether the iterated interface is an OLSR
666                                  * interface: returns NULL when the interface is not an
667                                  * OLSR interface */
668                                 struct interface *olsrIntf = if_ifwithname(ifName);
669                                 bool isOlsrIf = (olsrIntf != NULL);
670
671                                 /* determine whether the iterated interface is configured as a
672                                  * non-OLSR interface in the plugin parameter list */
673                                 bool isRxNonOlsrIf = isRxNonOlsrInterface(ifName);
674                                 bool isTxNonOlsrIf = isTxNonOlsrInterface(ifName);
675                                 bool isNonOlsrIf = isRxNonOlsrIf || isTxNonOlsrIf;
676
677                                 if (!isOlsrIf && !isNonOlsrIf) {
678                                         /* Interface is not an OLSR interface AND interface is not
679                                          * configured as non-OLSR interface: skip */
680                                         continue;
681                                 }
682
683                                 if (isOlsrIf && !createOlsrInterface(olsrIntf)) {
684                                         /* creating an OLSR interface failed */
685                                         goto end;
686                                 }
687
688                                 if (!isNonOlsrIf) {
689                                         /* interface is not configured as non-OLSR interface: skip */
690                                         continue;
691                                 }
692
693                                 if (addrFamily == AF_INET) {
694                                         memcpy(&ipAddr.in4, addr, sizeof(struct sockaddr_in));
695                                 } else {
696                                         memcpy(&ipAddr.in6, addr, sizeof(struct sockaddr_in6));
697                                 }
698
699                                 if (isRxNonOlsrIf && !createRxInterface(ifName, ipAddr,
700                                                 rxSocketHandlerFunction)) {
701                                         /* creating a receive interface failed */
702                                         goto end;
703                                 }
704
705                                 if (isTxNonOlsrIf && !createTxInterface(ifName, ipAddr)) {
706                                         /* creating a transmit interface failed */
707                                         goto end;
708                                 }
709                         }
710                 }
711         }
712
713         if (isUplinkAddrSet()) {
714                 uplinkSocketFd = createUplinkSocket();
715                 if (uplinkSocketFd == -1) {
716                         goto end;
717                 }
718
719                 downlinkSocketFd = createDownlinkSocket(rxSocketHandlerFunctionDownlink);
720                 if (downlinkSocketFd == -1) {
721                         goto end;
722                 }
723         } else {
724                 uplinkSocketFd = -1;
725         }
726
727         retval = true;
728
729         end: freeifaddrs(ifAddrs);
730         return retval;
731 }
732
733 /**
734  Cleanup the OLSR network interfaces in the given list
735
736  @param networkInterface
737  the list of network interface to close and clean up
738  */
739 static void cleanupOlsrInterfaces(TOLSRNetworkInterface * networkInterface) {
740         TOLSRNetworkInterface * nextNetworkInterface = networkInterface;
741         while (nextNetworkInterface != NULL) {
742                 TOLSRNetworkInterface * iteratedNetworkInterface = nextNetworkInterface;
743                 nextNetworkInterface = iteratedNetworkInterface->next;
744                 iteratedNetworkInterface->next = NULL;
745                 free(iteratedNetworkInterface);
746         }
747 }
748
749 /**
750  Close and cleanup the network interfaces in the given list
751
752  @param networkInterface
753  the list of network interface to close and clean up
754  */
755 static void closeInterfaces(TRxTxNetworkInterface * networkInterface) {
756         TRxTxNetworkInterface * nextNetworkInterface = networkInterface;
757         while (nextNetworkInterface != NULL) {
758                 TRxTxNetworkInterface * iteratedNetworkInterface = nextNetworkInterface;
759                 if (iteratedNetworkInterface->socketFd >= 0) {
760                         if (iteratedNetworkInterface->handler) {
761                                 remove_olsr_socket(iteratedNetworkInterface->socketFd,
762                                                 iteratedNetworkInterface->handler, NULL);
763                         }
764                         close(iteratedNetworkInterface->socketFd);
765                         iteratedNetworkInterface->socketFd = -1;
766                 }
767                 nextNetworkInterface = iteratedNetworkInterface->next;
768                 iteratedNetworkInterface->next = NULL;
769                 free(iteratedNetworkInterface);
770         }
771 }
772
773 /**
774  Close and cleanup all receive and transmit network interfaces
775  */
776 void closeNetworkInterfaces(void) {
777         if (rxNetworkInterfacesListHead != NULL) {
778                 closeInterfaces(rxNetworkInterfacesListHead);
779                 rxNetworkInterfacesListHead = NULL;
780         }
781
782         if (txNetworkInterfacesListHead != NULL) {
783                 closeInterfaces(txNetworkInterfacesListHead);
784                 txNetworkInterfacesListHead = NULL;
785         }
786
787         if (olsrNetworkInterfacesListHead != NULL) {
788                 cleanupOlsrInterfaces(olsrNetworkInterfacesListHead);
789                 olsrNetworkInterfacesListHead = NULL;
790         }
791
792         if (uplinkSocketFd != -1 ) {
793                 close(uplinkSocketFd);
794                 uplinkSocketFd = -1;
795         }
796
797         if (downlinkSocketFd != -1 ) {
798                 if (downlinkHandler) {
799                         remove_olsr_socket (downlinkSocketFd, downlinkHandler, NULL);
800                         downlinkHandler = NULL;
801                 }
802                 close(downlinkSocketFd);
803                 downlinkSocketFd = -1;
804         }
805 }