d6ac28092dcdd6ccb3d46a25766099e314d8d641
[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                 struct ip_mreq mc_settings;
275                 (void) memset(&mc_settings, 0, sizeof(mc_settings));
276                 inet_pton(AF_INET, "224.0.0.2", &mc_settings.imr_multiaddr.s_addr);
277                 (void) memset(&req, 0, sizeof(struct ifreq));
278                 strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
279                 req.ifr_name[IFNAMSIZ -1] = '\0';       /* Ensure null termination */
280                 if(ioctl(rxSocket, SIOCGIFADDR, &req)){
281                         BmfPError("Could not get ipv4 address of %s interface", ifName);
282                         goto bail;
283                 }
284                 ipv4_addr = ((struct sockaddr_in *)&req.ifr_addr)->sin_addr;
285                 mc_settings.imr_interface = ipv4_addr;
286                 errno = 0;
287                 if (setsockopt(rxSocket, ipProtoSetting, ipAddMembershipSetting,
288                                 &mc_settings, sizeof(mc_settings)) < 0) {
289                         BmfPError("Could not subscribe interface %s to the configured"
290                                 " multicast group", ifName);
291                         goto bail;
292                 }
293         } else {
294                 struct ipv6_mreq mc6_settings;
295                 (void) memset(&mc6_settings, 0, sizeof(mc6_settings));
296                 inet_pton(AF_INET6, "ff02::2", &mc6_settings.ipv6mr_multiaddr.s6_addr);
297                 mc6_settings.ipv6mr_interface = ifIndex;
298                 errno = 0;
299                 if (setsockopt(rxSocket, ipProtoSetting, ipAddMembershipSetting,
300                                 &mc6_settings, sizeof(mc6_settings)) < 0) {
301                         BmfPError("Could not subscribe interface %s to the configured"
302                                 " multicast group", ifName);
303                         goto bail;
304                 }
305         }
306
307         add_olsr_socket(rxSocket, DoElection, NULL, NULL,
308                         SP_PR_READ);
309
310         return rxSocket;
311
312         bail: if (rxSocket >= 0) {
313                 close(rxSocket);
314         }
315         return -1;
316 }                               /* CreateRouterElectionSocket */
317
318 static int CreateHelloSocket(const char *ifName) {
319         int ipFamilySetting;
320         int ipProtoSetting;
321         int ipMcLoopSetting;
322         int ipMcIfSetting;
323         int ipTtlSetting;
324         short int ipPort = htons(5354);
325         struct in_addr ipv4_addr;
326         struct ifreq req;
327         int ifIndex = if_nametoindex(ifName);
328
329         void * addr;
330         size_t addrSize;
331         union olsr_sockaddr address;
332
333         int txSocket = -1;
334
335         int mcLoopValue = 0;
336         int txTtl = 2;
337
338         memset(&address, 0, sizeof(address));
339         if (olsr_cnf->ip_version == AF_INET) {
340                 ipFamilySetting = AF_INET;
341                 ipProtoSetting = IPPROTO_IP;
342                 ipMcLoopSetting = IP_MULTICAST_LOOP;
343                 ipMcIfSetting = IP_MULTICAST_IF;
344                 ipTtlSetting = IP_MULTICAST_TTL;
345                 ifIndex = if_nametoindex(ifName);
346         } else {
347                 ipFamilySetting = AF_INET6;
348                 ipProtoSetting = IPPROTO_IPV6;
349                 ipMcLoopSetting = IPV6_MULTICAST_LOOP;
350                 ipMcIfSetting = IPV6_MULTICAST_IF;
351                 ipTtlSetting = IPV6_MULTICAST_HOPS;
352                 ifIndex = if_nametoindex(ifName);
353
354                 addr = &ifIndex;
355                 addrSize = sizeof(ifIndex);
356         }
357
358         /*  Create a datagram socket on which to transmit */
359         errno = 0;
360         txSocket = socket(ipFamilySetting, SOCK_DGRAM, 0);
361         if (txSocket < 0) {
362                 BmfPError("Could not create a transmit socket for interface %s",
363                                 ifName);
364                 goto bail;
365         }
366
367         if (olsr_cnf->ip_version == AF_INET) {
368                 (void) memset(&req, 0, sizeof(struct ifreq));
369                 strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
370                 req.ifr_name[IFNAMSIZ -1] = '\0';       /* Ensure null termination */
371                 if(ioctl(txSocket, SIOCGIFADDR, &req)){
372                         BmfPError("Could not get ipv4 address of %s interface", ifName);
373                         goto bail;
374                 }
375                 ipv4_addr = ((struct sockaddr_in *)&req.ifr_addr)->sin_addr;
376                 address.in4.sin_addr = ipv4_addr;
377                 address.in4.sin_family = ipFamilySetting;
378                 address.in4.sin_port = ipPort;
379                 addr = &address.in4;
380                 addrSize = sizeof(struct sockaddr_in);
381         }
382
383         /* Bind the socket to the desired interface */
384         errno = 0;
385         if (setsockopt(txSocket, ipProtoSetting, ipMcIfSetting, addr, addrSize) < 0) {
386                 BmfPError("Could not set the multicast interface on the"
387                         " transmit socket to interface %s", ifName);
388                 goto bail;
389         }
390
391         /* Disable multicast local loopback */
392         errno = 0;
393         if (setsockopt(txSocket, ipProtoSetting, ipMcLoopSetting, &mcLoopValue,
394                         sizeof(mcLoopValue)) < 0) {
395                 BmfPError("Could not disable multicast loopback on the"
396                         " transmit socket for interface %s", ifName);
397                 goto bail;
398         }
399
400         /* Set the TTL on the socket */
401         errno = 0;
402         if (setsockopt(txSocket, ipProtoSetting, ipTtlSetting, &txTtl,
403                         sizeof(txTtl)) < 0) {
404                 BmfPError("Could not set TTL on the transmit socket"
405                         " for interface %s", ifName);
406                 goto bail;
407         }
408
409         /* Set the no delay option on the socket */
410         errno = 0;
411         if (fcntl(txSocket, F_SETFL, O_NDELAY) < 0) {
412                 BmfPError("Could not set the no delay option on the"
413                         " transmit socket for interface %s", ifName);
414                 goto bail;
415         }
416
417         return txSocket;
418
419         bail: if (txSocket >= 0) {
420                 close(txSocket);
421         }
422         return -1;
423 }
424
425 /* -------------------------------------------------------------------------
426  * Function   : CreateInterface
427  * Description: Create a new TBmfInterface object and adds it to the global
428  *              BmfInterfaces list
429  * Input      : ifName - name of the network interface (e.g. "eth0")
430  *            : olsrIntf - OLSR interface object of the network interface, or
431  *                NULL if the network interface is not OLSR-enabled
432  * Output     : none
433  * Return     : the number of opened sockets
434  * Data Used  : BmfInterfaces, LastBmfInterface
435  * ------------------------------------------------------------------------- */
436
437 //FOR MDNS IS ALWAYS CALLED WITH NULL AS SECOND ARG
438
439 static int
440 CreateInterface(const char *ifName, struct interface *olsrIntf)
441 {
442   int capturingSkfd = -1;
443   int encapsulatingSkfd = -1;
444   int listeningSkfd = -1;
445   int electionSkfd = -1;
446   int helloSkfd = -1;
447   int ioctlSkfd;
448   struct ifreq ifr;
449   int nOpened = 0;
450   struct TBmfInterface *newIf = olsr_malloc(sizeof(struct TBmfInterface), "TBMFInterface (mdns)");
451
452   assert(ifName != NULL);
453
454   if (newIf == NULL) {
455     return 0;
456   }
457 //TODO: assert interface is not talking OLSR
458
459
460   /* Create socket for capturing and sending of multicast packets on
461    * non-OLSR interfaces, and on OLSR-interfaces if configured. */
462   if ((olsrIntf == NULL)) {
463     capturingSkfd = CreateCaptureSocket(ifName);
464     electionSkfd = CreateRouterElectionSocket(ifName);
465     helloSkfd = CreateHelloSocket(ifName);
466     if (capturingSkfd < 0 || electionSkfd < 0 || helloSkfd < 0) {
467       if (capturingSkfd >= 0) {
468         close(capturingSkfd);
469       }
470       if (electionSkfd >= 0) {
471         close(electionSkfd);
472       }
473       if (helloSkfd >= 0) {
474         close(helloSkfd);
475       }
476       free(newIf);
477       return 0;
478     }
479
480     nOpened++;
481   }
482
483   /* For ioctl operations on the network interface, use either capturingSkfd
484    * or encapsulatingSkfd, whichever is available */
485   ioctlSkfd = (capturingSkfd >= 0) ? capturingSkfd : encapsulatingSkfd;
486
487   /* Retrieve the MAC address of the interface. */
488   memset(&ifr, 0, sizeof(struct ifreq));
489   strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
490   ifr.ifr_name[IFNAMSIZ - 1] = '\0';    /* Ensures null termination */
491   if (ioctl(ioctlSkfd, SIOCGIFHWADDR, &ifr) < 0) {
492     BmfPError("ioctl(SIOCGIFHWADDR) error for interface \"%s\"", ifName);
493     if (capturingSkfd >= 0) {
494       close(capturingSkfd);
495     }
496     if (electionSkfd >= 0) {
497       close(electionSkfd);
498     }
499     if (helloSkfd >= 0) {
500       close(helloSkfd);
501     }
502     free(newIf);
503     return 0;
504   }
505
506   /* Copy data into TBmfInterface object */
507   newIf->capturingSkfd = capturingSkfd;
508   newIf->encapsulatingSkfd = encapsulatingSkfd;
509   newIf->listeningSkfd = listeningSkfd;
510   newIf->electionSkfd = electionSkfd;
511   newIf->helloSkfd = helloSkfd;
512   memcpy(newIf->macAddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
513   memcpy(newIf->ifName, ifName, IFNAMSIZ);
514   newIf->olsrIntf = olsrIntf;
515   newIf->isActive = 1; //as default the interface is active
516   if (olsrIntf != NULL) {
517     /* For an OLSR-interface, copy the interface address and broadcast
518      * address from the OLSR interface object. Downcast to correct sockaddr
519      * subtype. */
520     newIf->intAddr.v4 = olsrIntf->int_addr.sin_addr;
521     newIf->broadAddr.v4 = olsrIntf->int_broadaddr.sin_addr;
522   } else {
523     /* For a non-OLSR interface, retrieve the IP address ourselves */
524     memset(&ifr, 0, sizeof(struct ifreq));
525     strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
526     ifr.ifr_name[IFNAMSIZ - 1] = '\0';  /* Ensures null termination */
527     if (ioctl(ioctlSkfd, SIOCGIFADDR, &ifr) < 0) {
528       BmfPError("ioctl(SIOCGIFADDR) error for interface \"%s\"", ifName);
529
530       newIf->intAddr.v4.s_addr = inet_addr("0.0.0.0");
531     } else {
532       /* Downcast to correct sockaddr subtype */
533       newIf->intAddr.v4 = ((struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr.ifr_addr))->sin_addr;
534     }
535
536     /* For a non-OLSR interface, retrieve the IP broadcast address ourselves */
537     memset(&ifr, 0, sizeof(struct ifreq));
538     strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
539     ifr.ifr_name[IFNAMSIZ - 1] = '\0';  /* Ensures null termination */
540     if (ioctl(ioctlSkfd, SIOCGIFBRDADDR, &ifr) < 0) {
541       BmfPError("ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName);
542
543       newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0");
544     } else {
545       /* Downcast to correct sockaddr subtype */
546       newIf->broadAddr.v4 = ((struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr.ifr_broadaddr))->sin_addr;
547     }
548   }
549
550   /* Initialize fragment history table */
551   //memset(&newIf->fragmentHistory, 0, sizeof(newIf->fragmentHistory));
552   //newIf->nextFragmentHistoryEntry = 0;
553
554   /* Reset counters */
555   //newIf->nBmfPacketsRx = 0;
556   //newIf->nBmfPacketsRxDup = 0;
557   //newIf->nBmfPacketsTx = 0;
558
559   /* Add new TBmfInterface object to global list. OLSR interfaces are
560    * added at the front of the list, non-OLSR interfaces at the back. */
561   if (BmfInterfaces == NULL) {
562     /* First TBmfInterface object in list */
563     newIf->next = NULL;
564     BmfInterfaces = newIf;
565     LastBmfInterface = newIf;
566   } else if (olsrIntf != NULL) {
567     /* Add new TBmfInterface object at front of list */
568     newIf->next = BmfInterfaces;
569     BmfInterfaces = newIf;
570   } else {
571     /* Add new TBmfInterface object at back of list */
572     newIf->next = NULL;
573     LastBmfInterface->next = newIf;
574     LastBmfInterface = newIf;
575   }
576
577   //OLSR_PRINTF(
578   //  8,
579   //  "%s: opened %d socket%s on %s interface \"%s\"\n",
580   //  PLUGIN_NAME_SHORT,
581   //  nOpened,
582   //  nOpened == 1 ? "" : "s",
583   //  olsrIntf != NULL ? "OLSR" : "non-OLSR",
584   //  ifName);
585
586   return nOpened;
587 }                               /* CreateInterface */
588
589 /* -------------------------------------------------------------------------
590  * Function   : CreateBmfNetworkInterfaces
591  * Description: Create a list of TBmfInterface objects, one for each network
592  *              interface on which BMF runs
593  * Input      : skipThisIntf - network interface to skip, if seen
594  * Output     : none
595  * Return     : fail (-1) or success (0)
596  * Data Used  : none
597  * ------------------------------------------------------------------------- */
598 int
599 CreateBmfNetworkInterfaces(struct interface *skipThisIntf)
600 {
601   int skfd;
602   struct ifconf ifc;
603   int numreqs = 30;
604   struct ifreq *ifr;
605   int n;
606   int nOpenedSockets = 0;
607
608   /* Clear input descriptor set */
609   FD_ZERO(&InputSet);
610
611   skfd = socket(PF_INET, SOCK_DGRAM, 0);
612   if (skfd < 0) {
613     BmfPError("no inet socket available to retrieve interface list");
614     return -1;
615   }
616
617   /* Retrieve the network interface configuration list */
618   ifc.ifc_buf = NULL;
619   for (;;) {
620     ifc.ifc_len = sizeof(struct ifreq) * numreqs;
621     ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
622
623     if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
624       BmfPError("ioctl(SIOCGIFCONF) error");
625
626       close(skfd);
627       free(ifc.ifc_buf);
628       return -1;
629     }
630     if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
631       /* Assume it overflowed; double the space and try again */
632       numreqs *= 2;
633       assert(numreqs < 1024);
634       continue;                 /* for (;;) */
635     }
636     break;                      /* for (;;) */
637   }                             /* for (;;) */
638
639   close(skfd);
640
641   /* For each item in the interface configuration list... */
642   ifr = ifc.ifc_req;
643   for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++) {
644     struct interface *olsrIntf;
645     union olsr_ip_addr ipAddr;
646
647     /* Skip the BMF network interface itself */
648     //if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0)
649     //{
650     //  continue; /* for (n = ...) */
651     //}
652
653     /* ...find the OLSR interface structure, if any */
654     ipAddr.v4 = ((struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr->ifr_addr))->sin_addr;
655     olsrIntf = if_ifwithaddr(&ipAddr);
656
657     if (skipThisIntf != NULL && olsrIntf == skipThisIntf) {
658       continue;                 /* for (n = ...) */
659     }
660
661     if (olsrIntf == NULL && !IsNonOlsrBmfIf(ifr->ifr_name)) {
662       /* Interface is neither OLSR interface, nor specified as non-OLSR BMF
663        * interface in the BMF plugin parameter list */
664       continue;                 /* for (n = ...) */
665     }
666
667     if (!IsNonOlsrBmfIf(ifr->ifr_name)) {
668       //If the interface is not specified in the configuration file then go ahead
669       continue;                 /* for (n = ...) */
670     }
671     //TODO: asser if->ifr_name is not talking OLSR
672     //nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf);
673     nOpenedSockets += CreateInterface(ifr->ifr_name, NULL);
674
675   }                             /* for (n = ...) */
676
677   free(ifc.ifc_buf);
678
679   if (BmfInterfaces == NULL) {
680     //OLSR_PRINTF(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
681   } else {
682     //OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets);
683   }
684   return 0;
685 }                               /* CreateBmfNetworkInterfaces */
686
687 /* -------------------------------------------------------------------------
688  * Function   : AddInterface
689  * Description: Add an OLSR-enabled network interface to the list of BMF-enabled
690  *              network interfaces
691  * Input      : newIntf - network interface to add
692  * Output     : none
693  * Return     : none
694  * Data Used  : none
695  * ------------------------------------------------------------------------- */
696 void
697 AddInterface(struct interface *newIntf)
698 {
699   /* int nOpened; */
700
701   assert(newIntf != NULL);
702
703   /* nOpened = */ (void)CreateInterface(newIntf->int_name, newIntf);
704
705   //OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpened);
706 }                               /* AddInterface */
707
708 /* -------------------------------------------------------------------------
709  * Function   : CloseBmfNetworkInterfaces
710  * Description: Closes every socket on each network interface used by BMF
711  * Input      : none
712  * Output     : none
713  * Return     : none
714  * Data Used  : none
715  * Notes      : Closes
716  *              - the local EtherTunTap interface (e.g. "tun0" or "tap0")
717  *              - for each BMF-enabled interface, the socket used for
718  *                capturing multicast packets
719  *              - for each OLSR-enabled interface, the socket used for
720  *                encapsulating packets
721  *              Also restores the network state to the situation before BMF
722  *              was started.
723  * ------------------------------------------------------------------------- */
724 void
725 CloseBmfNetworkInterfaces(void)
726 {
727   int nClosed = 0;
728   u_int32_t totalOlsrBmfPacketsRx = 0;
729   u_int32_t totalOlsrBmfPacketsRxDup = 0;
730   u_int32_t totalOlsrBmfPacketsTx = 0;
731   u_int32_t totalNonOlsrBmfPacketsRx = 0;
732   u_int32_t totalNonOlsrBmfPacketsRxDup = 0;
733   u_int32_t totalNonOlsrBmfPacketsTx = 0;
734
735   /* Close all opened sockets */
736   struct TBmfInterface *nextBmfIf = BmfInterfaces;
737   while (nextBmfIf != NULL) {
738     struct TBmfInterface *bmfIf = nextBmfIf;
739     nextBmfIf = bmfIf->next;
740
741     if (bmfIf->capturingSkfd >= 0) {
742       close(bmfIf->capturingSkfd);
743       nClosed++;
744     }
745     if (bmfIf->encapsulatingSkfd >= 0) {
746       close(bmfIf->encapsulatingSkfd);
747       nClosed++;
748     }
749     if (bmfIf->electionSkfd >= 0) {
750       close(bmfIf->electionSkfd);
751       nClosed++;
752     }
753     if (bmfIf->helloSkfd >= 0) {
754       close(bmfIf->helloSkfd);
755       nClosed++;
756     }
757     //OLSR_PRINTF(
758     //  7,
759     //  "%s: %s interface \"%s\": RX pkts %u (%u dups); TX pkts %u\n",
760     //  PLUGIN_NAME_SHORT,
761     //  bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
762     //  bmfIf->ifName,
763     //  bmfIf->nBmfPacketsRx,
764     //  bmfIf->nBmfPacketsRxDup,
765     //  bmfIf->nBmfPacketsTx);
766
767     //OLSR_PRINTF(
768     //  1,
769     //  "%s: closed %s interface \"%s\"\n",
770     //  PLUGIN_NAME_SHORT,
771     //  bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
772     //  bmfIf->ifName);
773
774     /* Add totals */
775     if (bmfIf->olsrIntf != NULL) {
776       totalOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
777       totalOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
778       totalOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
779     } else {
780       totalNonOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
781       totalNonOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
782       totalNonOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
783     }
784
785     free(bmfIf);
786   }                             /* while */
787
788   BmfInterfaces = NULL;
789
790   //OLSR_PRINTF(1, "%s: closed %d sockets\n", PLUGIN_NAME_SHORT, nClosed);
791
792 }                               /* CloseBmfNetworkInterfaces */
793
794 #define MAX_NON_OLSR_IFS 32
795 static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
796 static int nNonOlsrIfs = 0;
797 /* -------------------------------------------------------------------------
798  * Function   : AddNonOlsrBmfIf
799  * Description: Add an non-OLSR enabled network interface to the list of BMF-enabled
800  *              network interfaces
801  * Input      : ifName - network interface (e.g. "eth0")
802  *              data - not used
803  *              addon - not used
804  * Output     : none
805  * Return     : success (0) or fail (1)
806  * Data Used  : NonOlsrIfNames
807  * ------------------------------------------------------------------------- */
808 int
809 AddNonOlsrBmfIf(const char *ifName, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
810 {
811   assert(ifName != NULL);
812
813   if (nNonOlsrIfs >= MAX_NON_OLSR_IFS) {
814     //OLSR_PRINTF(
815     //  1,
816     //  "%s: too many non-OLSR interfaces specified, maximum is %d\n",
817     //  PLUGIN_NAME,
818     //  MAX_NON_OLSR_IFS);
819     return 1;
820   }
821
822   strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ - 1);
823   NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0';     /* Ensures null termination */
824   nNonOlsrIfs++;
825   return 0;
826 }                               /* AddNonOlsrBmfIf */
827
828
829 int
830 set_TTL_Check(const char *TTL_Check, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
831 {
832 assert(TTL_Check!= NULL);
833 set_plugin_boolean(TTL_Check, &my_TTL_Check, addon);
834 return 0;
835 } /* Set TTL Check */
836
837 int
838 set_MDNS_TTL(const char *MDNS_TTL, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
839 {
840   assert(MDNS_TTL!= NULL);
841   my_MDNS_TTL = atoi(MDNS_TTL);
842   return 0;
843 }                               /* set_MDNS_TTL */
844 /* -------------------------------------------------------------------------
845  * Function   : IsNonOlsrBmfIf
846  * Description: Checks if a network interface is OLSR-enabled
847  * Input      : ifName - network interface (e.g. "eth0")
848  * Output     : none
849  * Return     : true (1) or false (0)
850  * Data Used  : NonOlsrIfNames
851  * ------------------------------------------------------------------------- */
852 int
853 IsNonOlsrBmfIf(const char *ifName)
854 {
855   int i;
856
857   assert(ifName != NULL);
858
859   for (i = 0; i < nNonOlsrIfs; i++) {
860     if (strncmp(NonOlsrIfNames[i], ifName, IFNAMSIZ) == 0)
861       return 1;
862   }
863   return 0;
864 }                               /* IsNonOlsrBmfIf */