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