0b01616a4cc722cdf1b3de93e419536a38f232be
[olsrd.git] / lib / mdns / src / NetworkInterfaces.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in
14  *   the documentation and/or other materials provided with the
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its
17  *   contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  */
40
41
42 #include "NetworkInterfaces.h"
43
44 /* System includes */
45 #include <stddef.h>             /* NULL */
46 #include <syslog.h>             /* syslog() */
47 #include <string.h>             /* strerror(), strchr(), strcmp() */
48 #include <errno.h>              /* errno */
49 #include <unistd.h>             /* close() */
50 #include <sys/ioctl.h>          /* ioctl() */
51 #include <fcntl.h>              /* fcntl() */
52 #include <assert.h>             /* assert() */
53 #include <net/if.h>             /* socket(), ifreq, if_indextoname(), if_nametoindex() */
54 #include <netinet/in.h>         /* htons() */
55 #ifdef __linux__
56 #include <linux/if_ether.h>     /* ETH_P_IP */
57 #include <linux/if_packet.h>    /* packet_mreq, PACKET_MR_PROMISC, PACKET_ADD_MEMBERSHIP */
58 #include <linux/if_tun.h>       /* IFF_TAP */
59 #endif /* __linux__ */
60 #include <netinet/ip.h>         /* struct ip */
61 #include <netinet/udp.h>        /* SOL_UDP */
62 #include <stdlib.h>             /* atoi, malloc */
63 #include <strings.h>    /* strcasecmp */
64
65 /* OLSRD includes */
66 #include "olsr.h"               /* OLSR_PRINTF() */
67 #include "ipcalc.h"
68 #include "defs.h"               /* olsr_cnf */
69 #include "link_set.h"           /* get_link_set() */
70 #include "tc_set.h"             /* olsr_lookup_tc_entry(), olsr_lookup_tc_edge() */
71 #include "net_olsr.h"           /* ipequal */
72 #include "lq_plugin.h"
73 //#include "olsr_ip_prefix_list.h"
74
75 /* Plugin includes */
76 #include "Packet.h"             /* IFHWADDRLEN */
77 #include "mdns.h"               /* PLUGIN_NAME, MainAddressOf() */
78 #include "Address.h"            /* IsMulticast() */
79 #include "plugin_util.h"
80
81 int my_MDNS_TTL = 0;
82 int my_TTL_Check = 1;
83
84 /* List of network interface objects used by BMF plugin */
85 struct TBmfInterface *BmfInterfaces = NULL;
86 struct TBmfInterface *LastBmfInterface = NULL;
87
88 /* Highest-numbered open socket file descriptor. To be used as first
89  * parameter in calls to select(...). */
90 int HighestSkfd = -1;
91
92 /* Set of socket file descriptors */
93 fd_set InputSet;
94
95
96 /* -------------------------------------------------------------------------
97  * Function   : CreateCaptureSocket
98  * Description: Create socket for promiscuously capturing multicast IP traffic
99  * Input      : ifname - network interface (e.g. "eth0")
100  * Output     : none
101  * Return     : the socket descriptor ( >= 0), or -1 if an error occurred
102  * Data Used  : none
103  * Notes      : The socket is a cooked IP packet socket, bound to the specified
104  *              network interface
105  * ------------------------------------------------------------------------- */
106 static int
107 CreateCaptureSocket(const char *ifName)
108 {
109   int ifIndex = if_nametoindex(ifName);
110   struct packet_mreq mreq;
111   struct ifreq req;
112   struct sockaddr_ll bindTo;
113   int skfd = 0;
114   /* Open cooked IP packet socket */
115   if (olsr_cnf->ip_version == AF_INET) {
116     skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
117   } else {
118     skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
119   }
120   if (skfd < 0) {
121     BmfPError("socket(PF_PACKET) error");
122     return -1;
123   }
124
125   /* Set interface to promiscuous mode */
126   memset(&mreq, 0, sizeof(struct packet_mreq));
127   mreq.mr_ifindex = ifIndex;
128   mreq.mr_type = PACKET_MR_PROMISC;
129   if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
130     BmfPError("setsockopt(PACKET_MR_PROMISC) error");
131     close(skfd);
132     return -1;
133   }
134
135   /* Get hardware (MAC) address */
136   memset(&req, 0, sizeof(struct ifreq));
137   strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
138   req.ifr_name[IFNAMSIZ - 1] = '\0';    /* Ensures null termination */
139   if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0) {
140     BmfPError("error retrieving MAC address");
141     close(skfd);
142     return -1;
143   }
144
145   /* Bind the socket to the specified interface */
146   memset(&bindTo, 0, sizeof(bindTo));
147   bindTo.sll_family = AF_PACKET;
148   if (olsr_cnf->ip_version == AF_INET) {
149     bindTo.sll_protocol = htons(ETH_P_IP);
150   } else {
151     bindTo.sll_protocol = htons(ETH_P_IPV6);
152   }
153   bindTo.sll_ifindex = ifIndex;
154   memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
155   bindTo.sll_halen = IFHWADDRLEN;
156
157   if (bind(skfd, (struct sockaddr *)&bindTo, sizeof(bindTo)) < 0) {
158     BmfPError("bind() error");
159     close(skfd);
160     return -1;
161   }
162
163   /* Set socket to blocking operation */
164   if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0) {
165     BmfPError("fcntl() error");
166     close(skfd);
167     return -1;
168   }
169   //AddDescriptorToInputSet(skfd);
170   add_olsr_socket(skfd, &DoMDNS,NULL, NULL, SP_PR_READ);
171
172   return skfd;
173 }                               /* CreateCaptureSocket */
174
175
176 /* -------------------------------------------------------------------------
177  * Function   : CreateRouterElectionSocket
178  * Description: Create socket for capturing router election hello packets
179  * Input      : ifname - network interface (e.g. "eth0")
180  * Output     : none
181  * Return     : the socket descriptor ( >= 0), or -1 if an error occurred
182  * Data Used  : none
183  * Notes      : The socket is a cooked IP packet socket, bound to the specified
184  *              network interface
185  * ------------------------------------------------------------------------- */
186 static int
187 CreateRouterElectionSocket(const char *ifName)
188 {
189         int ipFamilySetting;
190         int ipProtoSetting;
191         int ipMcLoopSetting;
192         int ipAddMembershipSetting;
193         short int ipPort = htons(5354);
194         struct in_addr ipv4_addr;
195         struct ifreq req;
196         int ifIndex = if_nametoindex(ifName);
197
198         void * addr;
199         size_t addrSize;
200         union olsr_sockaddr address;
201
202         int rxSocket = -1;
203
204         int socketReuseFlagValue = 1;
205         int mcLoopValue = 1;
206
207
208         memset(&address, 0, sizeof(address));
209         if (olsr_cnf->ip_version == AF_INET) {
210                 ipFamilySetting = AF_INET;
211                 ipProtoSetting = IPPROTO_IP;
212                 ipMcLoopSetting = IP_MULTICAST_LOOP;
213                 ipAddMembershipSetting = IP_ADD_MEMBERSHIP;
214
215                 address.in4.sin_family = ipFamilySetting;
216                 address.in4.sin_addr.s_addr = INADDR_ANY;
217                 address.in4.sin_port = ipPort;
218                 addr = &address.in4;
219                 addrSize = sizeof(struct sockaddr_in);
220         } else {
221                 ipFamilySetting = AF_INET6;
222                 ipProtoSetting = IPPROTO_IPV6;
223                 ipMcLoopSetting = IPV6_MULTICAST_LOOP;
224                 ipAddMembershipSetting = IPV6_ADD_MEMBERSHIP;
225
226                 address.in6.sin6_family = ipFamilySetting;
227                 address.in6.sin6_addr = in6addr_any;
228                 address.in6.sin6_port = ipPort;
229                 addr = &address.in6;
230                 addrSize = sizeof(struct sockaddr_in6);
231         }
232
233         /* Create a datagram socket on which to receive. */
234         errno = 0;
235         rxSocket = socket(ipFamilySetting, SOCK_DGRAM, 0);
236         if (rxSocket < 0) {
237                 BmfPError("Could not create a receive socket for interface %s",
238                                 ifName);
239                 goto bail;
240         }
241
242         /* Enable SO_REUSEADDR to allow multiple applications to receive the same
243          * multicast messages */
244         errno = 0;
245         if (setsockopt(rxSocket, SOL_SOCKET, SO_REUSEADDR, &socketReuseFlagValue,
246                         sizeof(socketReuseFlagValue)) < 0) {
247                 BmfPError("Could not set the reuse flag on the receive socket for"
248                         " interface %s", ifName);
249                 goto bail;
250         }
251
252         /* Bind to the proper port number with the IP address INADDR_ANY
253          * (INADDR_ANY is really required here, do not change it) */
254         errno = 0;
255         if (bind(rxSocket, addr, addrSize) < 0) {
256                 BmfPError("Could not bind the receive socket for interface"
257                         " %s to port %u", ifName, ntohs(ipPort));
258                 goto bail;
259         }
260
261         /* Enable multicast local loopback */
262         errno = 0;
263         if (setsockopt(rxSocket, ipProtoSetting, ipMcLoopSetting, &mcLoopValue,
264                         sizeof(mcLoopValue)) < 0) {
265                 BmfPError("Could not enable multicast loopback on the"
266                         " receive socket for interface %s", ifName);
267                 goto bail;
268         }
269
270         /* Join the multicast group on the local interface. Note that this
271          * ADD_MEMBERSHIP option must be called for each local interface over
272          * which the multicast datagrams are to be received. */
273         if (ipFamilySetting == AF_INET) {
274                 static const char * mc4Addr = "224.0.0.2";
275                 struct ip_mreq mc_settings;
276                 (void) memset(&mc_settings, 0, sizeof(mc_settings));
277                 if (inet_pton(AF_INET, mc4Addr, &mc_settings.imr_multiaddr.s_addr) != 1) {
278                         BmfPError("Could not convert ipv4 multicast address %s", mc4Addr);
279                         goto bail;
280                 }
281                 (void) memset(&req, 0, sizeof(struct ifreq));
282                 strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
283                 req.ifr_name[IFNAMSIZ -1] = '\0';       /* Ensure null termination */
284                 if(ioctl(rxSocket, SIOCGIFADDR, &req)){
285                         BmfPError("Could not get ipv4 address of %s interface", ifName);
286                         goto bail;
287                 }
288                 {
289       struct sockaddr* ifra = &req.ifr_addr;
290                   ipv4_addr = ((struct sockaddr_in *)(void *) ifra)->sin_addr;
291                 }
292                 mc_settings.imr_interface = ipv4_addr;
293                 errno = 0;
294                 if (setsockopt(rxSocket, ipProtoSetting, ipAddMembershipSetting,
295                                 &mc_settings, sizeof(mc_settings)) < 0) {
296                         BmfPError("Could not subscribe interface %s to the configured"
297                                 " multicast group", ifName);
298                         goto bail;
299                 }
300         } else {
301                 static const char * mc6Addr = "ff02::2";
302                 struct ipv6_mreq mc6_settings;
303                 (void) memset(&mc6_settings, 0, sizeof(mc6_settings));
304                 if (inet_pton(AF_INET6, mc6Addr, &mc6_settings.ipv6mr_multiaddr.s6_addr) != 1) {
305                         BmfPError("Could not convert ipv6 multicast address %s", mc6Addr);
306                         goto bail;
307                 }
308                 mc6_settings.ipv6mr_interface = ifIndex;
309                 errno = 0;
310                 if (setsockopt(rxSocket, ipProtoSetting, ipAddMembershipSetting,
311                                 &mc6_settings, sizeof(mc6_settings)) < 0) {
312                         BmfPError("Could not subscribe interface %s to the configured"
313                                 " multicast group", ifName);
314                         goto bail;
315                 }
316         }
317
318         add_olsr_socket(rxSocket, DoElection, NULL, NULL,
319                         SP_PR_READ);
320
321         return rxSocket;
322
323         bail: if (rxSocket >= 0) {
324                 close(rxSocket);
325         }
326         return -1;
327 }                               /* CreateRouterElectionSocket */
328
329 static int CreateHelloSocket(const char *ifName) {
330         int ipFamilySetting;
331         int ipProtoSetting;
332         int ipMcLoopSetting;
333         int ipMcIfSetting;
334         int ipTtlSetting;
335         short int ipPort = htons(5354);
336         struct in_addr ipv4_addr;
337         struct ifreq req;
338         int ifIndex = if_nametoindex(ifName);
339
340         void * addr;
341         size_t addrSize;
342         union olsr_sockaddr address;
343
344         int txSocket = -1;
345
346         int mcLoopValue = 0;
347         int txTtl = 2;
348
349         memset(&address, 0, sizeof(address));
350         if (olsr_cnf->ip_version == AF_INET) {
351                 ipFamilySetting = AF_INET;
352                 ipProtoSetting = IPPROTO_IP;
353                 ipMcLoopSetting = IP_MULTICAST_LOOP;
354                 ipMcIfSetting = IP_MULTICAST_IF;
355                 ipTtlSetting = IP_MULTICAST_TTL;
356                 ifIndex = if_nametoindex(ifName);
357         } else {
358                 ipFamilySetting = AF_INET6;
359                 ipProtoSetting = IPPROTO_IPV6;
360                 ipMcLoopSetting = IPV6_MULTICAST_LOOP;
361                 ipMcIfSetting = IPV6_MULTICAST_IF;
362                 ipTtlSetting = IPV6_MULTICAST_HOPS;
363                 ifIndex = if_nametoindex(ifName);
364
365                 addr = &ifIndex;
366                 addrSize = sizeof(ifIndex);
367         }
368
369         /*  Create a datagram socket on which to transmit */
370         errno = 0;
371         txSocket = socket(ipFamilySetting, SOCK_DGRAM, 0);
372         if (txSocket < 0) {
373                 BmfPError("Could not create a transmit socket for interface %s",
374                                 ifName);
375                 goto bail;
376         }
377
378         if (olsr_cnf->ip_version == AF_INET) {
379                 (void) memset(&req, 0, sizeof(struct ifreq));
380                 strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
381                 req.ifr_name[IFNAMSIZ -1] = '\0';       /* Ensure null termination */
382                 if(ioctl(txSocket, SIOCGIFADDR, &req)){
383                         BmfPError("Could not get ipv4 address of %s interface", ifName);
384                         goto bail;
385                 }
386                 {
387       struct sockaddr * ifra = &req.ifr_addr;
388       ipv4_addr = ((struct sockaddr_in *)(void *) ifra)->sin_addr;
389                 }
390                 address.in4.sin_addr = ipv4_addr;
391                 address.in4.sin_family = ipFamilySetting;
392                 address.in4.sin_port = ipPort;
393                 addr = &address.in4;
394                 addrSize = sizeof(struct sockaddr_in);
395         }
396
397         /* Bind the socket to the desired interface */
398         errno = 0;
399         if (setsockopt(txSocket, ipProtoSetting, ipMcIfSetting, addr, addrSize) < 0) {
400                 BmfPError("Could not set the multicast interface on the"
401                         " transmit socket to interface %s", ifName);
402                 goto bail;
403         }
404
405         /* Disable multicast local loopback */
406         errno = 0;
407         if (setsockopt(txSocket, ipProtoSetting, ipMcLoopSetting, &mcLoopValue,
408                         sizeof(mcLoopValue)) < 0) {
409                 BmfPError("Could not disable multicast loopback on the"
410                         " transmit socket for interface %s", ifName);
411                 goto bail;
412         }
413
414         /* Set the TTL on the socket */
415         errno = 0;
416         if (setsockopt(txSocket, ipProtoSetting, ipTtlSetting, &txTtl,
417                         sizeof(txTtl)) < 0) {
418                 BmfPError("Could not set TTL on the transmit socket"
419                         " for interface %s", ifName);
420                 goto bail;
421         }
422
423         /* Set the no delay option on the socket */
424         errno = 0;
425         if (fcntl(txSocket, F_SETFL, O_NDELAY) < 0) {
426                 BmfPError("Could not set the no delay option on the"
427                         " transmit socket for interface %s", ifName);
428                 goto bail;
429         }
430
431         return txSocket;
432
433         bail: if (txSocket >= 0) {
434                 close(txSocket);
435         }
436         return -1;
437 }
438
439 /* -------------------------------------------------------------------------
440  * Function   : CreateInterface
441  * Description: Create a new TBmfInterface object and adds it to the global
442  *              BmfInterfaces list
443  * Input      : ifName - name of the network interface (e.g. "eth0")
444  *            : olsrIntf - OLSR interface object of the network interface, or
445  *                NULL if the network interface is not OLSR-enabled
446  * Output     : none
447  * Return     : the number of opened sockets
448  * Data Used  : BmfInterfaces, LastBmfInterface
449  * ------------------------------------------------------------------------- */
450
451 //FOR MDNS IS ALWAYS CALLED WITH NULL AS SECOND ARG
452
453 static int
454 CreateInterface(const char *ifName, struct interface_olsr *olsrIntf)
455 {
456   int capturingSkfd = -1;
457   int encapsulatingSkfd = -1;
458   int listeningSkfd = -1;
459   int electionSkfd = -1;
460   int helloSkfd = -1;
461   int ioctlSkfd;
462   struct ifreq ifr;
463   int nOpened = 0;
464   struct TBmfInterface *newIf = olsr_malloc(sizeof(struct TBmfInterface), "TBMFInterface (mdns)");
465
466   assert(ifName != NULL);
467
468   if (newIf == NULL) {
469     return 0;
470   }
471 //TODO: assert interface is not talking OLSR
472
473
474   /* Create socket for capturing and sending of multicast packets on
475    * non-OLSR interfaces, and on OLSR-interfaces if configured. */
476   if (!olsrIntf) {
477     capturingSkfd = CreateCaptureSocket(ifName);
478     electionSkfd = CreateRouterElectionSocket(ifName);
479     helloSkfd = CreateHelloSocket(ifName);
480     if (capturingSkfd < 0 || electionSkfd < 0 || helloSkfd < 0) {
481       if (capturingSkfd >= 0) {
482         close(capturingSkfd);
483       }
484       if (electionSkfd >= 0) {
485         close(electionSkfd);
486       }
487       if (helloSkfd >= 0) {
488         close(helloSkfd);
489       }
490       free(newIf);
491       return 0;
492     }
493
494     nOpened++;
495   }
496
497   /* For ioctl operations on the network interface, use either capturingSkfd
498    * or encapsulatingSkfd, whichever is available */
499   ioctlSkfd = (capturingSkfd >= 0) ? capturingSkfd : encapsulatingSkfd;
500
501   /* Retrieve the MAC address of the interface. */
502   memset(&ifr, 0, sizeof(struct ifreq));
503   strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
504   ifr.ifr_name[IFNAMSIZ - 1] = '\0';    /* Ensures null termination */
505   if (ioctl(ioctlSkfd, SIOCGIFHWADDR, &ifr) < 0) {
506     BmfPError("ioctl(SIOCGIFHWADDR) error for interface \"%s\"", ifName);
507     if (capturingSkfd >= 0) {
508       close(capturingSkfd);
509     }
510     if (electionSkfd >= 0) {
511       close(electionSkfd);
512     }
513     if (helloSkfd >= 0) {
514       close(helloSkfd);
515     }
516     free(newIf);
517     return 0;
518   }
519
520   /* Copy data into TBmfInterface object */
521   newIf->capturingSkfd = capturingSkfd;
522   newIf->encapsulatingSkfd = encapsulatingSkfd;
523   newIf->listeningSkfd = listeningSkfd;
524   newIf->electionSkfd = electionSkfd;
525   newIf->helloSkfd = helloSkfd;
526   memcpy(newIf->macAddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
527   memcpy(newIf->ifName, ifName, IFNAMSIZ);
528   newIf->olsrIntf = olsrIntf;
529   newIf->isActive = 1; //as default the interface is active
530   if (olsrIntf != NULL) {
531     /* For an OLSR-interface, copy the interface address and broadcast
532      * address from the OLSR interface object. Downcast to correct sockaddr
533      * subtype. */
534     newIf->intAddr.v4 = olsrIntf->int_addr.sin_addr;
535     newIf->broadAddr.v4 = olsrIntf->int_broadaddr.sin_addr;
536   } else {
537     /* For a non-OLSR interface, retrieve the IP address ourselves */
538     memset(&ifr, 0, sizeof(struct ifreq));
539     strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
540     ifr.ifr_name[IFNAMSIZ - 1] = '\0';  /* Ensures null termination */
541     if (ioctl(ioctlSkfd, SIOCGIFADDR, &ifr) < 0) {
542       BmfPError("ioctl(SIOCGIFADDR) error for interface \"%s\"", ifName);
543
544       newIf->intAddr.v4.s_addr = inet_addr("0.0.0.0");
545     } else {
546       /* Downcast to correct sockaddr subtype */
547       struct sockaddr* ifra = &ifr.ifr_addr;
548       newIf->intAddr.v4 = ((struct sockaddr_in *)ARM_NOWARN_ALIGN(ifra))->sin_addr;
549     }
550
551     /* For a non-OLSR interface, retrieve the IP broadcast address ourselves */
552     memset(&ifr, 0, sizeof(struct ifreq));
553     strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
554     ifr.ifr_name[IFNAMSIZ - 1] = '\0';  /* Ensures null termination */
555     if (ioctl(ioctlSkfd, SIOCGIFBRDADDR, &ifr) < 0) {
556       BmfPError("ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName);
557
558       newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0");
559     } else {
560       /* Downcast to correct sockaddr subtype */
561       struct sockaddr* ifrb = &ifr.ifr_broadaddr;
562       newIf->broadAddr.v4 = ((struct sockaddr_in *)ARM_NOWARN_ALIGN(ifrb))->sin_addr;
563     }
564   }
565
566   /* Initialize fragment history table */
567   //memset(&newIf->fragmentHistory, 0, sizeof(newIf->fragmentHistory));
568   //newIf->nextFragmentHistoryEntry = 0;
569
570   /* Reset counters */
571   //newIf->nBmfPacketsRx = 0;
572   //newIf->nBmfPacketsRxDup = 0;
573   //newIf->nBmfPacketsTx = 0;
574
575   /* Add new TBmfInterface object to global list. OLSR interfaces are
576    * added at the front of the list, non-OLSR interfaces at the back. */
577   if (BmfInterfaces == NULL) {
578     /* First TBmfInterface object in list */
579     newIf->next = NULL;
580     BmfInterfaces = newIf;
581     LastBmfInterface = newIf;
582   } else if (olsrIntf != NULL) {
583     /* Add new TBmfInterface object at front of list */
584     newIf->next = BmfInterfaces;
585     BmfInterfaces = newIf;
586   } else {
587     /* Add new TBmfInterface object at back of list */
588     newIf->next = NULL;
589     LastBmfInterface->next = newIf;
590     LastBmfInterface = newIf;
591   }
592
593   //OLSR_PRINTF(
594   //  8,
595   //  "%s: opened %d socket%s on %s interface \"%s\"\n",
596   //  PLUGIN_NAME_SHORT,
597   //  nOpened,
598   //  nOpened == 1 ? "" : "s",
599   //  olsrIntf != NULL ? "OLSR" : "non-OLSR",
600   //  ifName);
601
602   return nOpened;
603 }                               /* CreateInterface */
604
605 /* -------------------------------------------------------------------------
606  * Function   : CreateBmfNetworkInterfaces
607  * Description: Create a list of TBmfInterface objects, one for each network
608  *              interface on which BMF runs
609  * Input      : skipThisIntf - network interface to skip, if seen
610  * Output     : none
611  * Return     : fail (-1) or success (0)
612  * Data Used  : none
613  * ------------------------------------------------------------------------- */
614 int
615 CreateBmfNetworkInterfaces(struct interface_olsr *skipThisIntf)
616 {
617   int skfd;
618   struct ifconf ifc;
619   int numreqs = 30;
620   struct ifreq *ifr;
621   int n;
622   int nOpenedSockets = 0;
623
624   /* Clear input descriptor set */
625   FD_ZERO(&InputSet);
626
627   skfd = socket(PF_INET, SOCK_DGRAM, 0);
628   if (skfd < 0) {
629     BmfPError("no inet socket available to retrieve interface list");
630     return -1;
631   }
632
633   /* Retrieve the network interface configuration list */
634   ifc.ifc_buf = NULL;
635   for (;;) {
636     ifc.ifc_len = sizeof(struct ifreq) * numreqs;
637     ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
638
639     if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
640       BmfPError("ioctl(SIOCGIFCONF) error");
641
642       close(skfd);
643       free(ifc.ifc_buf);
644       return -1;
645     }
646     if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
647       /* Assume it overflowed; double the space and try again */
648       numreqs *= 2;
649       assert(numreqs < 1024);
650       continue;                 /* for (;;) */
651     }
652     break;                      /* for (;;) */
653   }                             /* for (;;) */
654
655   close(skfd);
656
657   /* For each item in the interface configuration list... */
658   ifr = ifc.ifc_req;
659   for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++) {
660     struct interface_olsr *olsrIntf;
661     union olsr_ip_addr ipAddr;
662
663     /* Skip the BMF network interface itself */
664     //if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0)
665     //{
666     //  continue; /* for (n = ...) */
667     //}
668
669     /* ...find the OLSR interface structure, if any */
670     {
671       struct sockaddr* ifra = &ifr->ifr_addr;
672       ipAddr.v4 = ((struct sockaddr_in *)ARM_NOWARN_ALIGN(ifra))->sin_addr;
673     }
674     olsrIntf = if_ifwithaddr(&ipAddr);
675
676     if (skipThisIntf != NULL && olsrIntf == skipThisIntf) {
677       continue;                 /* for (n = ...) */
678     }
679
680     if (olsrIntf == NULL && !IsNonOlsrBmfIf(ifr->ifr_name)) {
681       /* Interface is neither OLSR interface, nor specified as non-OLSR BMF
682        * interface in the BMF plugin parameter list */
683       continue;                 /* for (n = ...) */
684     }
685
686     if (!IsNonOlsrBmfIf(ifr->ifr_name)) {
687       //If the interface is not specified in the configuration file then go ahead
688       continue;                 /* for (n = ...) */
689     }
690     //TODO: asser if->ifr_name is not talking OLSR
691     //nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf);
692     nOpenedSockets += CreateInterface(ifr->ifr_name, NULL);
693
694   }                             /* for (n = ...) */
695
696   free(ifc.ifc_buf);
697
698   if (BmfInterfaces == NULL) {
699     //OLSR_PRINTF(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
700   } else {
701     //OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets);
702   }
703   return 0;
704 }                               /* CreateBmfNetworkInterfaces */
705
706 /* -------------------------------------------------------------------------
707  * Function   : AddInterface
708  * Description: Add an OLSR-enabled network interface to the list of BMF-enabled
709  *              network interfaces
710  * Input      : newIntf - network interface to add
711  * Output     : none
712  * Return     : none
713  * Data Used  : none
714  * ------------------------------------------------------------------------- */
715 void
716 AddInterface(struct interface_olsr *newIntf)
717 {
718   /* int nOpened; */
719
720   assert(newIntf != NULL);
721
722   /* nOpened = */ (void)CreateInterface(newIntf->int_name, newIntf);
723
724   //OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpened);
725 }                               /* AddInterface */
726
727 /* -------------------------------------------------------------------------
728  * Function   : CloseBmfNetworkInterfaces
729  * Description: Closes every socket on each network interface used by BMF
730  * Input      : none
731  * Output     : none
732  * Return     : none
733  * Data Used  : none
734  * Notes      : Closes
735  *              - the local EtherTunTap interface (e.g. "tun0" or "tap0")
736  *              - for each BMF-enabled interface, the socket used for
737  *                capturing multicast packets
738  *              - for each OLSR-enabled interface, the socket used for
739  *                encapsulating packets
740  *              Also restores the network state to the situation before BMF
741  *              was started.
742  * ------------------------------------------------------------------------- */
743 void
744 CloseBmfNetworkInterfaces(void)
745 {
746   int nClosed = 0;
747   u_int32_t totalOlsrBmfPacketsRx = 0;
748   u_int32_t totalOlsrBmfPacketsRxDup = 0;
749   u_int32_t totalOlsrBmfPacketsTx = 0;
750   u_int32_t totalNonOlsrBmfPacketsRx = 0;
751   u_int32_t totalNonOlsrBmfPacketsRxDup = 0;
752   u_int32_t totalNonOlsrBmfPacketsTx = 0;
753
754   /* Close all opened sockets */
755   struct TBmfInterface *nextBmfIf = BmfInterfaces;
756   while (nextBmfIf != NULL) {
757     struct TBmfInterface *bmfIf = nextBmfIf;
758     nextBmfIf = bmfIf->next;
759
760     if (bmfIf->capturingSkfd >= 0) {
761       close(bmfIf->capturingSkfd);
762       nClosed++;
763     }
764     if (bmfIf->encapsulatingSkfd >= 0) {
765       close(bmfIf->encapsulatingSkfd);
766       nClosed++;
767     }
768     if (bmfIf->electionSkfd >= 0) {
769       close(bmfIf->electionSkfd);
770       nClosed++;
771     }
772     if (bmfIf->helloSkfd >= 0) {
773       close(bmfIf->helloSkfd);
774       nClosed++;
775     }
776     //OLSR_PRINTF(
777     //  7,
778     //  "%s: %s interface \"%s\": RX pkts %u (%u dups); TX pkts %u\n",
779     //  PLUGIN_NAME_SHORT,
780     //  bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
781     //  bmfIf->ifName,
782     //  bmfIf->nBmfPacketsRx,
783     //  bmfIf->nBmfPacketsRxDup,
784     //  bmfIf->nBmfPacketsTx);
785
786     //OLSR_PRINTF(
787     //  1,
788     //  "%s: closed %s interface \"%s\"\n",
789     //  PLUGIN_NAME_SHORT,
790     //  bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
791     //  bmfIf->ifName);
792
793     /* Add totals */
794     if (bmfIf->olsrIntf != NULL) {
795       totalOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
796       totalOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
797       totalOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
798     } else {
799       totalNonOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
800       totalNonOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
801       totalNonOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
802     }
803
804     free(bmfIf);
805   }                             /* while */
806
807   BmfInterfaces = NULL;
808
809   //OLSR_PRINTF(1, "%s: closed %d sockets\n", PLUGIN_NAME_SHORT, nClosed);
810
811 }                               /* CloseBmfNetworkInterfaces */
812
813 #define MAX_NON_OLSR_IFS 32
814 static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
815 static int nNonOlsrIfs = 0;
816 /* -------------------------------------------------------------------------
817  * Function   : AddNonOlsrBmfIf
818  * Description: Add an non-OLSR enabled network interface to the list of BMF-enabled
819  *              network interfaces
820  * Input      : ifName - network interface (e.g. "eth0")
821  *              data - not used
822  *              addon - not used
823  * Output     : none
824  * Return     : success (0) or fail (1)
825  * Data Used  : NonOlsrIfNames
826  * ------------------------------------------------------------------------- */
827 int
828 AddNonOlsrBmfIf(const char *ifName, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
829 {
830   assert(ifName != NULL);
831
832   if (nNonOlsrIfs >= MAX_NON_OLSR_IFS) {
833     //OLSR_PRINTF(
834     //  1,
835     //  "%s: too many non-OLSR interfaces specified, maximum is %d\n",
836     //  PLUGIN_NAME,
837     //  MAX_NON_OLSR_IFS);
838     return 1;
839   }
840
841   strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ - 1);
842   NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0';     /* Ensures null termination */
843   nNonOlsrIfs++;
844   return 0;
845 }                               /* AddNonOlsrBmfIf */
846
847
848 int
849 set_TTL_Check(const char *TTL_Check, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
850 {
851 assert(TTL_Check!= NULL);
852 set_plugin_boolean(TTL_Check, &my_TTL_Check, addon);
853 return 0;
854 } /* Set TTL Check */
855
856 int
857 set_MDNS_TTL(const char *MDNS_TTL, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
858 {
859   assert(MDNS_TTL!= NULL);
860   my_MDNS_TTL = atoi(MDNS_TTL);
861   return 0;
862 }                               /* set_MDNS_TTL */
863 /* -------------------------------------------------------------------------
864  * Function   : IsNonOlsrBmfIf
865  * Description: Checks if a network interface is OLSR-enabled
866  * Input      : ifName - network interface (e.g. "eth0")
867  * Output     : none
868  * Return     : true (1) or false (0)
869  * Data Used  : NonOlsrIfNames
870  * ------------------------------------------------------------------------- */
871 int
872 IsNonOlsrBmfIf(const char *ifName)
873 {
874   int i;
875
876   assert(ifName != NULL);
877
878   for (i = 0; i < nNonOlsrIfs; i++) {
879     if (strncmp(NonOlsrIfNames[i], ifName, IFNAMSIZ) == 0)
880       return 1;
881   }
882   return 0;
883 }                               /* IsNonOlsrBmfIf */