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