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