Rename 'struct interface' to 'struct interface_olsr'
[olsrd.git] / lib / bmf / src / NetworkInterfaces.c
1 /*
2  * OLSR Basic Multicast Forwarding (BMF) plugin.
3  * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
4  * Written by Erik Tromp.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without 
8  * modification, are permitted provided that the following conditions 
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright 
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright 
14  *   notice, this list of conditions and the following disclaimer in 
15  *   the documentation and/or other materials provided with the 
16  *   distribution.
17  * * Neither the name of Thales, BMF nor the names of its 
18  *   contributors may be used to endorse or promote products derived 
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
24  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
28  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
29  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
30  * OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 /* -------------------------------------------------------------------------
34  * File       : NetworkInterfaces.c
35  * Description: Functions to open and close sockets
36  * Created    : 29 Jun 2006
37  *
38  * ------------------------------------------------------------------------- */
39
40 #include "NetworkInterfaces.h"
41
42 /* System includes */
43 #include <stddef.h> /* NULL */
44 #include <syslog.h> /* syslog() */
45 #include <string.h> /* strerror(), strchr(), strcmp() */
46 #include <errno.h> /* errno */
47 #include <unistd.h> /* close() */
48 #include <sys/ioctl.h> /* ioctl() */
49 #include <fcntl.h> /* fcntl() */
50 #include <assert.h> /* assert() */
51 #include <net/if.h> /* socket(), ifreq, if_indextoname(), if_nametoindex() */
52 #include <netinet/in.h> /* htons() */
53 #include <linux/if_ether.h> /* ETH_P_IP */
54 #include <linux/if_packet.h> /* packet_mreq, PACKET_MR_PROMISC, PACKET_ADD_MEMBERSHIP */
55 #include <linux/if_tun.h> /* IFF_TAP */
56 #include <netinet/ip.h> /* struct ip */
57 #include <netinet/udp.h> /* SOL_UDP */
58
59 /* OLSRD includes */
60 #include "olsr.h" /* olsr_printf() */
61 #include "ipcalc.h"
62 #include "defs.h" /* olsr_cnf */
63 #include "link_set.h" /* get_link_set() */
64 #include "tc_set.h" /* olsr_lookup_tc_entry(), olsr_lookup_tc_edge() */
65 #include "net_olsr.h" /* ipequal */
66 #include "lq_plugin.h"
67 #include "kernel_tunnel.h"
68
69 /* Plugin includes */
70 #include "Packet.h" /* IFHWADDRLEN */
71 #include "Bmf.h" /* PLUGIN_NAME, MainAddressOf() */
72 #include "Address.h" /* IsMulticast() */
73
74 /* List of network interface objects used by BMF plugin */
75 struct TBmfInterface* BmfInterfaces = NULL;
76 struct TBmfInterface* LastBmfInterface = NULL;
77
78 /* Highest-numbered open socket file descriptor. To be used as first
79  * parameter in calls to select(...). */
80 int HighestSkfd = -1;
81
82 /* Set of socket file descriptors */
83 fd_set InputSet;
84
85 /* File descriptor of EtherTunTap interface */
86 int EtherTunTapFd = -1;
87
88 /* Network interface name of EtherTunTap interface. May be overruled by
89  * setting the plugin parameter "BmfInterface". */
90 char EtherTunTapIfName[IFNAMSIZ] = "bmf0";
91
92 /* The underlying mechanism to forward multicast packets. Either:
93  * - BM_BROADCAST: BMF uses the IP local broadcast as destination address
94  * - BM_UNICAST_PROMISCUOUS: BMF uses the IP address of the best neighbor as
95  *   destination address. The other neighbors listen promiscuously. */
96 enum TBmfMechanism BmfMechanism = BM_BROADCAST;
97
98 #define ETHERTUNTAPIPNOTSET 0
99
100 /* The IP address of the BMF network interface in host byte order.
101  * May be overruled by setting the plugin parameter "BmfInterfaceIp". */
102 u_int32_t EtherTunTapIp = ETHERTUNTAPIPNOTSET;
103
104 /* 255.255.255.255 in host byte order. May be overruled by
105  * setting the plugin parameter "BmfInterfaceIp". */
106 u_int32_t EtherTunTapIpMask = 0xFFFFFFFF;
107
108 /* The IP broadcast address of the BMF network interface in host byte order.
109  * May be overruled by setting the plugin parameter "BmfinterfaceIp". */
110 u_int32_t EtherTunTapIpBroadcast = ETHERTUNTAPIPNOTSET;
111
112 /* Whether or not the BMF network interface must be marked as persistent */
113 int EtherTunTapPersistent = 1;
114
115 /* Whether or not the configuration has overruled the default IP
116  * configuration of the EtherTunTap interface */
117 int TunTapIpOverruled = 0;
118
119 /* Whether or not to capture packets on the OLSR-enabled
120  * interfaces (in promiscuous mode). May be overruled by setting the plugin
121  * parameter "CapturePacketsOnOlsrInterfaces" to "yes". */
122 int CapturePacketsOnOlsrInterfaces = 0;
123
124 /* -------------------------------------------------------------------------
125  * Function   : SetBmfInterfaceName
126  * Description: Overrule the default network interface name ("bmf0") of the
127  *              EtherTunTap interface
128  * Input      : ifname - network interface name (e.g. "mybmf0")
129  *              data - not used
130  *              addon - not used
131  * Output     : none
132  * Return     : success (0) or fail (1)
133  * Data Used  : EtherTunTapIfName
134  * ------------------------------------------------------------------------- */
135 int SetBmfInterfaceName(
136   const char* ifname,
137   void* data __attribute__((unused)),
138   set_plugin_parameter_addon addon __attribute__((unused)))
139 {
140   strncpy(EtherTunTapIfName, ifname, IFNAMSIZ - 1);
141   EtherTunTapIfName[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
142   return 0;
143 } /* SetBmfInterfaceName */
144
145 /* -------------------------------------------------------------------------
146  * Function   : SetBmfInterfaceIp
147  * Description: Overrule the default IP address and prefix length
148  *              ("10.255.255.253/30") of the EtherTunTap interface
149  * Input      : ip - IP address string, followed by '/' and prefix length
150  *              data - not used
151  *              addon - not used
152  * Output     : none
153  * Return     : success (0) or fail (1)
154  * Data Used  : EtherTunTapIp, EtherTunTapIpMask, EtherTunTapIpBroadcast,
155  *              TunTapIpOverruled
156  * ------------------------------------------------------------------------- */
157 int SetBmfInterfaceIp(
158   const char* ip,
159   void* data __attribute__((unused)),
160   set_plugin_parameter_addon addon __attribute__((unused)))
161 {
162 #define IPV4_MAX_ADDRLEN 16
163 #define IPV4_MAX_PREFIXLEN 32
164   char* slashAt;
165   char ipAddr[IPV4_MAX_ADDRLEN];
166   struct in_addr sinaddr;
167   int prefixLen;
168   int i;
169
170   /* Inspired by function str2prefix_ipv4 as found in Quagga source
171    * file lib/prefix.c */
172
173   /* Find slash inside string. */
174   slashAt = strchr(ip, '/');
175
176   /* String doesn't contain slash. */
177   if (slashAt == NULL || slashAt - ip >= IPV4_MAX_ADDRLEN)
178   {
179     /* No prefix length specified, or IP address too long */
180     return 1;
181   }
182
183   strncpy(ipAddr, ip, slashAt - ip);
184   *(ipAddr + (slashAt - ip)) = '\0';
185   if (inet_aton(ipAddr, &sinaddr) == 0)
186   {
187     /* Invalid address passed */
188     return 1;
189   }
190
191   EtherTunTapIp = ntohl(sinaddr.s_addr);
192
193   /* Get prefix length. */
194   prefixLen = atoi(++slashAt);
195   if (prefixLen <= 0 || prefixLen > IPV4_MAX_PREFIXLEN)
196   {
197     return 1;
198   }
199
200   /* Compose IP subnet mask in host byte order */
201   EtherTunTapIpMask = 0;
202   for (i = 0; i < prefixLen; i++)
203   {
204     EtherTunTapIpMask |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i));
205   }
206
207   /* Compose IP broadcast address in host byte order */
208   EtherTunTapIpBroadcast = EtherTunTapIp;
209   for (i = prefixLen; i < IPV4_MAX_PREFIXLEN; i++)
210   {
211     EtherTunTapIpBroadcast |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i));
212   }
213
214   TunTapIpOverruled = 1;
215
216   return 0;
217 } /* SetBmfInterfaceIp */
218
219 /* -------------------------------------------------------------------------
220  * Function   : SetBmfInterfacePersistent
221  * Description: Determine if the EtherTunTap interface must be marked
222  *              persistent or not
223  * Input      : value - yes/true/1  or no/false/0
224  *              data  - not used
225  *              addon - not used
226  * Output     : none
227  * Return     : success (0) or fail (1)
228  * Data Used  : EtherTunTapPersistent
229  * ------------------------------------------------------------------------- */
230 int SetBmfInterfacePersistent(
231   const char* value,
232   void* data __attribute__((unused)),
233   set_plugin_parameter_addon addon __attribute__((unused)))
234 {
235         if (strcasecmp(value, "yes") == 0 || strcasecmp(value, "true") == 0 || strcasecmp(value, "1") == 0) {
236                 EtherTunTapPersistent = 1;
237         } else if (strcasecmp(value, "no") == 0 || strcasecmp(value, "false") == 0 || strcasecmp(value, "0") == 0) {
238                 EtherTunTapPersistent = 0;
239         } else {
240                 return 1;
241         }
242         return 0;
243 } /* SetBmfInterfacePersistent */
244
245 /* -------------------------------------------------------------------------
246  * Function   : SetCapturePacketsOnOlsrInterfaces
247  * Description: Overrule the default setting, enabling or disabling the
248  *              capturing of packets on OLSR-enabled interfaces.
249  * Input      : enable - either "yes" or "no"
250  *              data - not used
251  *              addon - not used
252  * Output     : none
253  * Return     : success (0) or fail (1)
254  * Data Used  : none
255  * ------------------------------------------------------------------------- */
256 int SetCapturePacketsOnOlsrInterfaces(
257   const char* enable,
258   void* data __attribute__((unused)),
259   set_plugin_parameter_addon addon __attribute__((unused)))
260 {
261   if (strcmp(enable, "yes") == 0)
262   {
263     CapturePacketsOnOlsrInterfaces = 1;
264     return 0;
265   }
266   else if (strcmp(enable, "no") == 0)
267   {
268     CapturePacketsOnOlsrInterfaces = 0;
269     return 0;
270   }
271
272   /* Value not recognized */
273   return 1;
274 } /* SetCapturePacketsOnOlsrInterfaces */
275
276 /* -------------------------------------------------------------------------
277  * Function   : SetBmfMechanism
278  * Description: Overrule the default BMF mechanism to either BM_BROADCAST or
279  *              BM_UNICAST_PROMISCUOUS.
280  * Input      : mechanism - either "Broadcast" or "UnicastPromiscuous"
281  *              data - not used
282  *              addon - not used
283  * Output     : none
284  * Return     : success (0) or fail (1)
285  * Data Used  : none
286  * ------------------------------------------------------------------------- */
287 int SetBmfMechanism(
288   const char* mechanism,
289   void* data __attribute__((unused)),
290   set_plugin_parameter_addon addon __attribute__((unused)))
291 {
292   if (strcmp(mechanism, "Broadcast") == 0)
293   {
294     BmfMechanism = BM_BROADCAST;
295     return 0;
296   }
297   else if (strcmp(mechanism, "UnicastPromiscuous") == 0)
298   {
299     BmfMechanism = BM_UNICAST_PROMISCUOUS;
300     return 0;
301   }
302
303   /* Value not recognized */
304   return 1;
305 } /* SetBmfMechanism */
306
307 /* -------------------------------------------------------------------------
308  * Function   : AddDescriptorToInputSet
309  * Description: Add a socket descriptor to the global set of socket file descriptors
310  * Input      : skfd - socket file descriptor
311  * Output     : none
312  * Return     : none
313  * Data Used  : HighestSkfd, InputSet
314  * Notes      : Keeps track of the highest-numbered descriptor
315  * ------------------------------------------------------------------------- */
316 static void AddDescriptorToInputSet(int skfd)
317 {
318   /* Keep the highest-numbered descriptor */
319   if (skfd > HighestSkfd)
320   {
321     HighestSkfd = skfd;
322   }
323
324   /* Add descriptor to input set */
325   FD_SET(skfd, &InputSet);
326 } /* AddDescriptorToInputSet */
327
328 /* To save the state of the IP spoof filter for the EtherTunTap interface */
329 static char EthTapSpoofState = '1';
330
331 /* -------------------------------------------------------------------------
332  * Function   : DeactivateSpoofFilter
333  * Description: Deactivates the Linux anti-spoofing filter for the tuntap
334  *              interface
335  * Input      : none
336  * Output     : none
337  * Return     : fail (0) or success (1)
338  * Data Used  : EtherTunTapIfName, EthTapSpoofState
339  * Notes      : Saves the current filter state for later restoring
340  * ------------------------------------------------------------------------- */
341 int DeactivateSpoofFilter(void)
342 {
343   FILE* procSpoof;
344   char procFile[FILENAME_MAX];
345
346   /* Generate the procfile name */
347   sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", EtherTunTapIfName);
348
349   /* Open procfile for reading */
350   procSpoof = fopen(procFile, "r");
351   if (procSpoof == NULL)
352   {
353     fprintf(
354       stderr,
355       "WARNING! Could not open the %s file to check/disable the IP spoof filter!\n"
356       "Are you using the procfile filesystem?\n"
357       "Does your system support IPv4?\n"
358       "I will continue (in 3 sec) - but you should manually ensure that IP spoof\n"
359       "filtering is disabled!\n\n",
360       procFile);
361       
362     sleep(3);
363     return 0;
364   }
365
366   EthTapSpoofState = (char)fgetc(procSpoof);
367   fclose(procSpoof);
368
369   /* Open procfile for writing */
370   procSpoof = fopen(procFile, "w");
371   if (procSpoof == NULL)
372   {
373     fprintf(stderr, "Could not open %s for writing!\n", procFile);
374     fprintf(
375       stderr,
376       "I will continue (in 3 sec) - but you should manually ensure that IP"
377       " spoof filtering is disabled!\n\n");
378     sleep(3);
379     return 0;
380   }
381
382   syslog(LOG_INFO, "Writing \"0\" to %s", procFile);
383   fputs("0", procSpoof);
384
385   fclose(procSpoof);
386
387   return 1;
388 } /* DeactivateSpoofFilter */
389
390 /* -------------------------------------------------------------------------
391  * Function   : RestoreSpoofFilter
392  * Description: Restores the Linux anti-spoofing filter setting for the tuntap
393  *              interface
394  * Input      : none
395  * Output     : none
396  * Return     : none
397  * Data Used  : EtherTunTapIfName, EthTapSpoofState
398  * ------------------------------------------------------------------------- */
399 void RestoreSpoofFilter(void)
400 {
401   FILE* procSpoof;
402   char procFile[FILENAME_MAX];
403
404   /* Generate the procfile name */
405   sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", EtherTunTapIfName);
406
407   /* Open procfile for writing */
408   procSpoof = fopen(procFile, "w");
409   if (procSpoof == NULL)
410   {
411     fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procFile);
412   }
413   else
414   {
415     syslog(LOG_INFO, "Resetting %s to %c\n", procFile, EthTapSpoofState);
416
417     fputc(EthTapSpoofState, procSpoof);
418     fclose(procSpoof);
419   }
420 } /* RestoreSpoofFilter */
421
422 /* -------------------------------------------------------------------------
423  * Function   : FindNeighbors
424  * Description: Find the neighbors on a network interface to forward a BMF
425  *              packet to
426  * Input      : intf - the network interface
427  *              source - the source IP address of the BMF packet, or NULL if
428  *                unknown or not applicable
429  *              forwardedBy - the IP address of the node that forwarded the BMF
430  *                packet, or NULL if unknown or not applicable
431  *              forwardedTo - the IP address of the node to which the BMF packet
432  *                was directed, or NULL if unknown or not applicable
433  * Output     : neighbors - list of (up to a number of 'FanOutLimit') neighbors.
434  *              bestNeighbor - the best neighbor (in terms of lowest cost or ETX
435  *                value)
436  *              nPossibleNeighbors - number of found possible neighbors
437  * Data Used  : FanOutLimit
438  * ------------------------------------------------------------------------- */
439 void FindNeighbors(
440   struct TBestNeighbors* neighbors,
441   struct link_entry** bestNeighbor,
442   struct TBmfInterface* intf,
443   union olsr_ip_addr* source,
444   union olsr_ip_addr* forwardedBy,
445   union olsr_ip_addr* forwardedTo,
446   int* nPossibleNeighbors)
447 {
448 #ifndef NODEBUG
449   struct ipaddr_str buf;
450 #endif /* NODEBUG */
451   int i;
452
453   /* Initialize */
454   *bestNeighbor = NULL;
455   for (i = 0; i < MAX_UNICAST_NEIGHBORS; i++)
456   {
457     neighbors->links[i] = NULL;
458   }
459   *nPossibleNeighbors = 0;
460
461   /* handle the non-LQ case */
462
463   if (olsr_cnf->lq_level == 0)
464   {
465     struct link_entry* walker;
466
467     OLSR_FOR_ALL_LINK_ENTRIES(walker) {
468       union olsr_ip_addr* neighborMainIp;
469
470       /* Consider only links from the specified interface */
471       if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
472       {
473         continue; /* for */
474       }
475
476       OLSR_PRINTF(
477         8,
478         "%s: ----> considering forwarding pkt on \"%s\" to %s\n",
479         PLUGIN_NAME_SHORT,
480         intf->ifName,
481         olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
482
483       neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
484
485       /* Consider only neighbors with an IP address that differs from the
486        * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
487       if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
488       {
489         OLSR_PRINTF(
490           9,
491           "%s: ----> not forwarding to %s: is source of pkt\n",
492           PLUGIN_NAME_SHORT,
493           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
494
495         continue; /* for */
496       }
497
498       /* Rely on short-circuit boolean evaluation */
499       if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
500       {
501         OLSR_PRINTF(
502           9,
503           "%s: ----> not forwarding to %s: is the node that forwarded the pkt\n",
504           PLUGIN_NAME_SHORT,
505           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
506
507         continue; /* for */
508       }
509
510       /* Rely on short-circuit boolean evaluation */
511       if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
512       {
513         OLSR_PRINTF(
514           9,
515           "%s: ----> not forwarding to %s: is the node to which the pkt was forwarded\n",
516           PLUGIN_NAME_SHORT,
517           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
518
519         continue; /* for */
520       }
521
522       /* Found a candidate neighbor to direct our packet to */
523
524       /* In the non-LQ case, it is not possible to select neigbors
525        * by quality or cost. So just remember the first found link.
526        * TODO: come on, there must be something better than to simply
527        * select the first one found! */
528       if (*bestNeighbor == NULL)
529       {
530         *bestNeighbor = walker;
531       }
532
533       /* Fill the list with up to 'FanOutLimit' neighbors. If there
534        * are more neighbors, broadcast is used instead of unicast. In that
535        * case we do not need the list of neighbors. */
536       if (*nPossibleNeighbors < FanOutLimit)
537       {
538         neighbors->links[*nPossibleNeighbors] = walker;
539       }
540
541       *nPossibleNeighbors += 1;
542     } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
543
544   }
545   /* handle the LQ case */
546   else
547   {
548 #ifdef USING_THALES_LINK_COST_ROUTING
549
550     struct link_entry* walker;
551     float previousLinkCost = 2 * INFINITE_COST;
552     float bestLinkCost = 2 * INFINITE_COST;
553
554     if (forwardedBy != NULL)
555     {
556       /* Retrieve the cost of the link from 'forwardedBy' to myself */
557       struct link_entry* bestLinkFromForwarder = get_best_link_to_neighbor(forwardedBy);
558       if (bestLinkFromForwarder != NULL)
559       {
560         previousLinkCost = bestLinkFromForwarder->link_cost;
561       }
562     }
563
564     for (walker = get_link_set(); walker != NULL; walker = walker->next) 
565     {
566       union olsr_ip_addr* neighborMainIp;
567       struct link_entry* bestLinkToNeighbor;
568       struct tc_entry* tcLastHop;
569
570       /* Consider only links from the specified interface */
571       if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
572       {
573         continue; /* for */
574       }
575
576       OLSR_PRINTF(
577         9,
578         "%s: ----> considering forwarding pkt on \"%s\" to %s\n",
579         PLUGIN_NAME_SHORT,
580         intf->ifName,
581         olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
582
583       neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
584
585       /* Consider only neighbors with an IP address that differs from the
586        * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
587       if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
588       {
589         OLSR_PRINTF(
590           9,
591           "%s: ----> not forwarding to %s: is source of pkt\n",
592           PLUGIN_NAME_SHORT,
593           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
594
595         continue; /* for */
596       }
597
598       /* Rely on short-circuit boolean evaluation */
599       if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
600       {
601         OLSR_PRINTF(
602           9,
603           "%s: ----> not forwarding to %s: is the node that forwarded the pkt\n",
604           PLUGIN_NAME_SHORT,
605           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
606
607         continue; /* for */
608       }
609
610       /* Rely on short-circuit boolean evaluation */
611       if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
612       {
613         OLSR_PRINTF(
614           9,
615           "%s: ----> not forwarding to %s: is the node to which the pkt was forwarded\n",
616           PLUGIN_NAME_SHORT,
617           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
618
619         continue; /* for */
620       }
621
622       /* Found a candidate neighbor to direct our packet to */
623
624       if (walker->link_cost >= INFINITE_COST)
625       {
626         OLSR_PRINTF(
627           9,
628           "%s: ----> not forwarding to %s: link is timing out\n",
629           PLUGIN_NAME_SHORT,
630           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
631
632         continue; /* for */
633       }
634
635       /* Compare costs to check if the candidate neighbor is best reached via 'intf' */
636       OLSR_PRINTF(
637         9,
638         "%s: ----> forwarding pkt to %s will cost %5.2f\n",
639         PLUGIN_NAME_SHORT,
640         olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
641         walker->link_cost);
642
643       /* If the candidate neighbor is best reached via another interface, then skip 
644        * the candidate neighbor; the candidate neighbor has been / will be selected via that
645        * other interface. */
646       bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
647
648       if (walker != bestLinkToNeighbor)
649       {
650         if (bestLinkToNeighbor == NULL)
651         {
652           OLSR_PRINTF(
653             9,
654             "%s: ----> not forwarding to %s: no link found\n",
655             PLUGIN_NAME_SHORT,
656             olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
657         }
658         else
659         {
660           struct interface_olsr * bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr);
661
662           OLSR_PRINTF(
663             9,
664             "%s: ----> not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %5.2f\n",
665             PLUGIN_NAME_SHORT,
666             olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
667             bestIntf->int_name,
668             bestLinkToNeighbor->link_cost);
669         }
670
671         continue; /* for */
672       }
673
674       if (forwardedBy != NULL)
675       {
676         OLSR_PRINTF(
677           9,
678           "%s: ----> 2-hop path from %s via me to %s will cost %5.2f\n",
679           PLUGIN_NAME_SHORT,
680           olsr_ip_to_string(&forwardedByBuf, forwardedBy),
681           olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
682           previousLinkCost + walker->link_cost);
683       }
684
685       /* Check the topology table whether the 'forwardedBy' node is itself a direct
686        * neighbor of the candidate neighbor, at a lower cost than the 2-hop route
687        * via myself. If so, we do not need to forward the BMF packet to the candidate
688        * neighbor, because the 'forwardedBy' node will forward the packet. */
689       if (forwardedBy != NULL)
690       {
691         tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
692         if (tcLastHop != NULL)
693         {
694           struct tc_edge_entry* tc_edge;
695
696           tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
697           
698           /* We are not interested in dead-end or dying edges. */
699           if (tc_edge != NULL && (tc_edge->flags & OLSR_TC_EDGE_DOWN) == 0)
700           {
701             if (previousLinkCost + walker->link_cost > tc_edge->link_cost)
702             {
703 #ifndef NODEBUG
704               struct ipaddr_str neighbor_iface_buf, forw_buf;
705               olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
706 #endif /* NODEBUG */
707               OLSR_PRINTF(
708                 9,
709                 "%s: ----> not forwarding to %s: I am not an MPR between %s and %s, direct link costs %5.2f\n",
710                 PLUGIN_NAME_SHORT,
711                 neighbor_iface_buf.buf,
712                 olsr_ip_to_string(&forw_buf, forwardedBy),
713                 neighbor_iface_buf.buf,
714                 tc_edge->link_cost);
715
716               continue; /* for */
717             } /* if */
718           } /* if */
719         } /* if */
720       } /* if */
721
722       /* Remember the best neighbor. If all are very bad, remember none. */
723       if (walker->link_cost < bestLinkCost)
724       {
725         *bestNeighbor = walker;
726         bestLinkCost = walker->link_cost;
727       }
728
729       /* Fill the list with up to 'FanOutLimit' neighbors. If there
730        * are more neighbors, broadcast is used instead of unicast. In that
731        * case we do not need the list of neighbors. */
732       if (*nPossibleNeighbors < FanOutLimit)
733       {
734         neighbors->links[*nPossibleNeighbors] = walker;
735       }
736
737       *nPossibleNeighbors += 1;
738
739     } /* for */
740
741 #else /* USING_THALES_LINK_COST_ROUTING */
742         
743     struct link_entry* walker;
744     olsr_linkcost previousLinkEtx = LINK_COST_BROKEN;
745     olsr_linkcost bestEtx = LINK_COST_BROKEN;
746
747     if (forwardedBy != NULL)
748     {
749       /* Retrieve the cost of the link from 'forwardedBy' to myself */
750       struct link_entry* bestLinkFromForwarder = get_best_link_to_neighbor(forwardedBy);
751       if (bestLinkFromForwarder != NULL)
752       {
753         previousLinkEtx = bestLinkFromForwarder->linkcost;
754       }
755     }
756
757     OLSR_FOR_ALL_LINK_ENTRIES(walker) {
758       union olsr_ip_addr* neighborMainIp;
759       struct link_entry* bestLinkToNeighbor;
760       struct tc_entry* tcLastHop;
761       float currEtx;
762  
763       /* Consider only links from the specified interface */
764       if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
765       {
766         continue; /* for */
767       }
768
769       OLSR_PRINTF(
770         9,
771         "%s: ----> considering forwarding pkt on \"%s\" to %s\n",
772         PLUGIN_NAME_SHORT,
773         intf->ifName,
774         olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
775
776       neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
777
778       /* Consider only neighbors with an IP address that differs from the
779        * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
780       if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
781       {
782         OLSR_PRINTF(
783           9,
784           "%s: ----> not forwarding to %s: is source of pkt\n",
785           PLUGIN_NAME_SHORT,
786           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
787
788         continue; /* for */
789       }
790
791       /* Rely on short-circuit boolean evaluation */
792       if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
793       {
794         OLSR_PRINTF(
795           9,
796           "%s: ----> not forwarding to %s: is the node that forwarded the pkt\n",
797           PLUGIN_NAME_SHORT,
798           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
799
800         continue; /* for */
801       }
802
803       /* Rely on short-circuit boolean evaluation */
804       if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
805       {
806         OLSR_PRINTF(
807           9,
808           "%s: ----> not forwarding to %s: is the node to which the pkt was forwarded\n",
809           PLUGIN_NAME_SHORT,
810           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
811
812         continue; /* for */
813       }
814
815       /* Found a candidate neighbor to direct our packet to */
816
817       /* Calculate the link quality (ETX) of the link to the found neighbor */
818       currEtx = walker->linkcost;
819  
820       if (currEtx >= LINK_COST_BROKEN)
821       {
822         OLSR_PRINTF(
823           9,
824           "%s: ----> not forwarding to %s: link is timing out\n",
825           PLUGIN_NAME_SHORT,
826           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
827
828         continue; /* for */
829       }
830
831       /* Compare costs to check if the candidate neighbor is best reached via 'intf' */
832       OLSR_PRINTF(
833         9,
834         "%s: ----> forwarding pkt to %s will cost ETX %5.2f\n",
835         PLUGIN_NAME_SHORT,
836         olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
837         (double)currEtx);
838
839       /* If the candidate neighbor is best reached via another interface, then skip 
840        * the candidate neighbor; the candidate neighbor has been / will be selected via that
841        * other interface. */
842       bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
843
844       if (walker != bestLinkToNeighbor)
845       {
846         if (bestLinkToNeighbor == NULL)
847         {
848           OLSR_PRINTF(
849             9,
850             "%s: ----> not forwarding to %s: no link found\n",
851             PLUGIN_NAME_SHORT,
852             olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
853         }
854         else
855         {
856 #ifndef NODEBUG
857           struct interface_olsr * bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr);
858           struct lqtextbuffer lqbuffer;
859 #endif /* NODEBUG */
860           OLSR_PRINTF(
861             9,
862             "%s: ----> not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %s\n",
863             PLUGIN_NAME_SHORT,
864             olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
865             bestIntf ? bestIntf->int_name : "NULL",
866             get_linkcost_text(bestLinkToNeighbor->linkcost, false, &lqbuffer));
867         }
868
869         continue; /* for */
870       }
871
872       if (forwardedBy != NULL)
873       {
874 #ifndef NODEBUG
875         struct ipaddr_str forwardedByBuf, niaBuf;
876         struct lqtextbuffer lqbuffer;
877 #endif /* NODEBUG */
878         OLSR_PRINTF(
879           9,
880           "%s: ----> 2-hop path from %s via me to %s will cost ETX %s\n",
881           PLUGIN_NAME_SHORT,
882           olsr_ip_to_string(&forwardedByBuf, forwardedBy),
883           olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
884           get_linkcost_text(previousLinkEtx + currEtx, true, &lqbuffer));
885       }
886
887       /* Check the topology table whether the 'forwardedBy' node is itself a direct
888        * neighbor of the candidate neighbor, at a lower cost than the 2-hop route
889        * via myself. If so, we do not need to forward the BMF packet to the candidate
890        * neighbor, because the 'forwardedBy' node will forward the packet. */
891       if (forwardedBy != NULL)
892       {
893         tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
894         if (tcLastHop != NULL)
895         {
896           struct tc_edge_entry* tc_edge;
897
898           tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
899
900           /* We are not interested in dead-end edges. */
901           if (tc_edge) {
902             olsr_linkcost tcEtx = tc_edge->cost;
903
904             if (previousLinkEtx + currEtx > tcEtx)
905             {
906 #ifndef NODEBUG
907               struct ipaddr_str neighbor_iface_buf, forw_buf;
908               struct lqtextbuffer lqbuffer;
909               olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
910 #endif /* NODEBUG */
911               OLSR_PRINTF(
912                 9,
913                 "%s: ----> not forwarding to %s: I am not an MPR between %s and %s, direct link costs %s\n",
914                 PLUGIN_NAME_SHORT,
915                 neighbor_iface_buf.buf,
916                 olsr_ip_to_string(&forw_buf, forwardedBy),
917                 neighbor_iface_buf.buf,
918                 get_linkcost_text(tcEtx, false, &lqbuffer));
919
920               continue; /* for */
921             } /* if */
922           } /* if */
923         } /* if */
924       } /* if */
925
926       /* Remember the best neighbor. If all are very bad, remember none. */
927       if (currEtx < bestEtx)
928       {
929         *bestNeighbor = walker;
930         bestEtx = currEtx;
931       }
932
933       /* Fill the list with up to 'FanOutLimit' neighbors. If there
934        * are more neighbors, broadcast is used instead of unicast. In that
935        * case we do not need the list of neighbors. */
936       if (*nPossibleNeighbors < FanOutLimit)
937       {
938         neighbors->links[*nPossibleNeighbors] = walker;
939       }
940
941       *nPossibleNeighbors += 1;
942     } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
943
944 #endif /* USING_THALES_LINK_COST_ROUTING */
945
946   } /* if */
947
948   /* Display the result of the neighbor search */
949   if (*nPossibleNeighbors == 0)
950   {
951     OLSR_PRINTF(
952       9,
953       "%s: ----> no suitable neighbor found to forward to on \"%s\"\n",
954       PLUGIN_NAME_SHORT,
955       intf->ifName);
956   }
957   else
958   {
959     OLSR_PRINTF(
960       9,
961       "%s: ----> %d neighbors found on \"%s\"; best neighbor to forward to: %s\n",
962       PLUGIN_NAME_SHORT,
963       *nPossibleNeighbors,
964       intf->ifName,
965       olsr_ip_to_string(&buf, &(*bestNeighbor)->neighbor_iface_addr));
966   } /* if */
967
968 } /* FindNeighbors */
969
970 /* -------------------------------------------------------------------------
971  * Function   : CreateCaptureSocket
972  * Description: Create socket for promiscuously capturing multicast IP traffic
973  * Input      : ifname - network interface (e.g. "eth0")
974  * Output     : none
975  * Return     : the socket descriptor ( >= 0), or -1 if an error occurred
976  * Data Used  : none
977  * Notes      : The socket is a cooked IP packet socket, bound to the specified
978  *              network interface
979  * ------------------------------------------------------------------------- */
980 static int CreateCaptureSocket(const char* ifName)
981 {
982   int ifIndex = if_nametoindex(ifName);
983   struct packet_mreq mreq;
984   struct ifreq req;
985   struct sockaddr_ll bindTo;
986
987   /* Open cooked IP packet socket */
988   int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
989   if (skfd < 0)
990   {
991     BmfPError("socket(PF_PACKET) error");
992     return -1;
993   }
994
995   /* Set interface to promiscuous mode */
996   memset(&mreq, 0, sizeof(struct packet_mreq));
997   mreq.mr_ifindex = ifIndex;
998   mreq.mr_type = PACKET_MR_PROMISC;
999   if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
1000   {
1001     BmfPError("setsockopt(PACKET_MR_PROMISC) error");
1002     close(skfd);
1003     return -1;
1004   }
1005
1006   /* Get hardware (MAC) address */
1007   memset(&req, 0, sizeof(struct ifreq));
1008   strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
1009   req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */
1010   if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
1011   {
1012     BmfPError("error retrieving MAC address");
1013     close(skfd);
1014     return -1;
1015   }
1016    
1017   /* Bind the socket to the specified interface */
1018   memset(&bindTo, 0, sizeof(bindTo));
1019   bindTo.sll_family = AF_PACKET;
1020   bindTo.sll_protocol = htons(ETH_P_IP);
1021   bindTo.sll_ifindex = ifIndex;
1022   memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
1023   bindTo.sll_halen = IFHWADDRLEN;
1024     
1025   if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
1026   {
1027     BmfPError("bind() error");
1028     close(skfd);
1029     return -1;
1030   }
1031
1032   /* Set socket to blocking operation */
1033   if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
1034   {
1035     BmfPError("fcntl() error");
1036     close(skfd);
1037     return -1;
1038   }
1039
1040   AddDescriptorToInputSet(skfd);
1041
1042   return skfd;
1043 } /* CreateCaptureSocket */
1044
1045 /* -------------------------------------------------------------------------
1046  * Function   : CreateListeningSocket
1047  * Description: Create socket for promiscuously listening to BMF packets.
1048  *              Used only when 'BmfMechanism' is BM_UNICAST_PROMISCUOUS
1049  * Input      : ifname - network interface (e.g. "eth0")
1050  * Output     : none
1051  * Return     : the socket descriptor ( >= 0), or -1 if an error occurred
1052  * Data Used  : none
1053  * Notes      : The socket is a cooked IP packet socket, bound to the specified
1054  *              network interface
1055  * ------------------------------------------------------------------------- */
1056 static int CreateListeningSocket(const char* ifName)
1057 {
1058   int ifIndex = if_nametoindex(ifName);
1059   struct packet_mreq mreq;
1060   struct ifreq req;
1061   struct sockaddr_ll bindTo;
1062
1063   /* Open cooked IP packet socket */
1064   int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
1065   if (skfd < 0)
1066   {
1067     BmfPError("socket(PF_PACKET) error");
1068     return -1;
1069   }
1070
1071   /* Set interface to promiscuous mode */
1072   memset(&mreq, 0, sizeof(struct packet_mreq));
1073   mreq.mr_ifindex = ifIndex;
1074   mreq.mr_type = PACKET_MR_PROMISC;
1075   if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
1076   {
1077     BmfPError("setsockopt(PACKET_MR_PROMISC) error");
1078     close(skfd);
1079     return -1;
1080   }
1081
1082   /* Get hardware (MAC) address */
1083   memset(&req, 0, sizeof(struct ifreq));
1084   strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
1085   req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */
1086   if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
1087   {
1088     BmfPError("error retrieving MAC address");
1089     close(skfd);
1090     return -1;
1091   }
1092
1093   /* Bind the socket to the specified interface */
1094   memset(&bindTo, 0, sizeof(bindTo));
1095   bindTo.sll_family = AF_PACKET;
1096   bindTo.sll_protocol = htons(ETH_P_IP);
1097   bindTo.sll_ifindex = ifIndex;
1098   memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
1099   bindTo.sll_halen = IFHWADDRLEN;
1100     
1101   if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
1102   {
1103     BmfPError("bind() error");
1104     close(skfd);
1105     return -1;
1106   }
1107
1108   /* Set socket to blocking operation */
1109   if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
1110   {
1111     BmfPError("fcntl() error");
1112     close(skfd);
1113     return -1;
1114   }
1115
1116   AddDescriptorToInputSet(skfd);
1117
1118   return skfd;
1119 } /* CreateListeningSocket */
1120
1121 /* -------------------------------------------------------------------------
1122  * Function   : CreateEncapsulateSocket
1123  * Description: Create a socket for sending and receiving encapsulated
1124  *              multicast packets
1125  * Input      : ifname - network interface (e.g. "eth0")
1126  * Output     : none
1127  * Return     : the socket descriptor ( >= 0), or -1 if an error occurred
1128  * Data Used  : none
1129  * Notes      : The socket is an UDP (datagram) over IP socket, bound to the
1130  *              specified network interface
1131  * ------------------------------------------------------------------------- */
1132 static int CreateEncapsulateSocket(const char* ifName)
1133 {
1134   int on = 1;
1135   struct sockaddr_in bindTo;
1136
1137   /* Open UDP-IP socket */
1138   int skfd = socket(PF_INET, SOCK_DGRAM, 0);
1139   if (skfd < 0)
1140   {
1141     BmfPError("socket(PF_INET) error");
1142     return -1;
1143   }
1144
1145   /* Enable sending to broadcast addresses */
1146   if (setsockopt(skfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
1147   {
1148     BmfPError("setsockopt(SO_BROADCAST) error");
1149     close(skfd);
1150     return -1;
1151   }
1152         
1153   /* Bind to the specific network interfaces indicated by ifName. */
1154   /* When using Kernel 2.6 this must happer prior to the port binding! */
1155   if (setsockopt(skfd, SOL_SOCKET, SO_BINDTODEVICE, ifName, strlen(ifName) + 1) < 0)
1156   {
1157     BmfPError("setsockopt(SO_BINDTODEVICE) error");
1158     close(skfd);
1159     return -1;
1160   }
1161
1162   /* Bind to BMF port */
1163   memset(&bindTo, 0, sizeof(bindTo));
1164   bindTo.sin_family = AF_INET;
1165   bindTo.sin_port = htons(BMF_ENCAP_PORT);
1166   bindTo.sin_addr.s_addr = htonl(INADDR_ANY);
1167       
1168   if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0) 
1169   {
1170     BmfPError("bind() error");
1171     close(skfd);
1172     return -1;
1173   }
1174
1175   /* Set socket to blocking operation */
1176   if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
1177   {
1178     BmfPError("fcntl() error");
1179     close(skfd);
1180     return -1;
1181   }
1182
1183   AddDescriptorToInputSet(skfd);
1184
1185   return skfd;
1186 } /* CreateEncapsulateSocket */
1187
1188 /* -------------------------------------------------------------------------
1189  * Function   : CreateLocalEtherTunTap
1190  * Description: Creates and brings up an EtherTunTap interface
1191  * Input      : none
1192  * Output     : none
1193  * Return     : the socket file descriptor (>= 0), or -1 in case of failure
1194  * Data Used  : EtherTunTapIfName - name used for the tuntap interface (e.g.
1195  *                "bmf0")
1196  *              EtherTunTapIp
1197  *              EtherTunTapIpMask
1198  *              EtherTunTapIpBroadcast
1199  *              BmfInterfaces
1200  * Note       : Order dependency: call this function only if BmfInterfaces
1201  *              is filled with a list of network interfaces.
1202  * ------------------------------------------------------------------------- */
1203 static int CreateLocalEtherTunTap(void)
1204 {
1205   static const char * deviceName = OS_TUNNEL_PATH;
1206   struct ifreq ifreq;
1207   int etfd;
1208   int ioctlSkfd;
1209   int ioctlres;
1210
1211   etfd = open(deviceName, O_RDWR | O_NONBLOCK);
1212   if (etfd < 0)
1213   {
1214     BmfPError("error opening %s", deviceName);
1215     return -1;
1216   }
1217
1218   memset(&ifreq, 0, sizeof(ifreq));
1219   strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
1220   ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1221
1222   /* Specify the IFF_TUN flag for IP packets.
1223    * Specify IFF_NO_PI for not receiving extra meta packet information. */
1224   ifreq.ifr_flags = IFF_TUN;
1225   ifreq.ifr_flags |= IFF_NO_PI;
1226
1227   if (ioctl(etfd, TUNSETIFF, (void *)&ifreq) < 0)
1228   {
1229     BmfPError("ioctl(TUNSETIFF) error on %s", deviceName);
1230     close(etfd);
1231     return -1;
1232   }
1233
1234   memset(&ifreq, 0, sizeof(ifreq));
1235   strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
1236   ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1237   ifreq.ifr_addr.sa_family = AF_INET;
1238
1239   ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1240   if (ioctlSkfd < 0)
1241   {
1242     BmfPError("socket(PF_INET) error on %s", deviceName);
1243     close(etfd);
1244     return -1;
1245   }
1246
1247   /* Give the EtherTunTap interface an IP address.
1248    * The default IP address is the address of the first OLSR interface;
1249    * the default netmask is 255.255.255.255 . Having an all-ones netmask prevents
1250    * automatic entry of the BMF network interface in the routing table. */
1251   if (EtherTunTapIp == ETHERTUNTAPIPNOTSET)
1252   {
1253     struct TBmfInterface* nextBmfIf = BmfInterfaces;
1254     while (nextBmfIf != NULL)
1255     {
1256       struct TBmfInterface* bmfIf = nextBmfIf;
1257       nextBmfIf = bmfIf->next;
1258
1259       if (bmfIf->olsrIntf != NULL)
1260       {
1261         EtherTunTapIp = ntohl(bmfIf->intAddr.v4.s_addr);
1262         EtherTunTapIpBroadcast = EtherTunTapIp;
1263       }
1264     }
1265   }
1266
1267   if (EtherTunTapIp == ETHERTUNTAPIPNOTSET)
1268   {
1269     /* No IP address configured for BMF network interface, and no OLSR interface found to
1270      * copy IP address from. Fall back to default: 10.255.255.253 . */
1271     EtherTunTapIp = ETHERTUNTAPDEFAULTIP;
1272   }
1273
1274   ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifreq.ifr_addr))->sin_addr.s_addr = htonl(EtherTunTapIp);
1275   ioctlres = ioctl(ioctlSkfd, SIOCSIFADDR, &ifreq);
1276   if (ioctlres >= 0)
1277   {
1278     /* Set net mask */
1279     ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifreq.ifr_netmask))->sin_addr.s_addr = htonl(EtherTunTapIpMask);
1280     ioctlres = ioctl(ioctlSkfd, SIOCSIFNETMASK, &ifreq);
1281     if (ioctlres >= 0)
1282     {
1283       /* Set broadcast IP */
1284       ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifreq.ifr_broadaddr))->sin_addr.s_addr = htonl(EtherTunTapIpBroadcast);
1285       ioctlres = ioctl(ioctlSkfd, SIOCSIFBRDADDR, &ifreq);
1286       if (ioctlres >= 0)
1287       {
1288         /* Bring EtherTunTap interface up (if not already) */
1289         ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
1290         if (ioctlres >= 0)
1291         {
1292           ifreq.ifr_flags |= (IFF_UP | IFF_RUNNING | IFF_BROADCAST);
1293           ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
1294         }
1295       }
1296     }
1297   }
1298
1299   if (ioctlres < 0)
1300   {
1301     /* Any of the above ioctl() calls failed */
1302     BmfPError("error bringing up EtherTunTap interface \"%s\"", EtherTunTapIfName);
1303
1304     close(etfd);
1305     close(ioctlSkfd);
1306     return -1;
1307   } /* if (ioctlres < 0) */
1308
1309   /* Set the multicast flag on the interface */
1310   memset(&ifreq, 0, sizeof(ifreq));
1311   strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
1312   ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1313
1314   ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
1315   if (ioctlres >= 0)
1316   {
1317     ifreq.ifr_flags |= IFF_MULTICAST;
1318     ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
1319   }
1320   if (ioctlres < 0)
1321   {
1322     /* Any of the two above ioctl() calls failed */
1323     BmfPError("error setting multicast flag on EtherTunTap interface \"%s\"", EtherTunTapIfName);
1324
1325     /* Continue anyway */
1326   }
1327
1328   /* Use ioctl to make the tuntap persistent. Otherwise it will disappear
1329    * when this program exits. That is not desirable, since a multicast
1330    * daemon (e.g. mrouted) may be using the tuntap interface. */
1331   if (ioctl(etfd, TUNSETPERSIST, EtherTunTapPersistent ? (void *)&ifreq : NULL) < 0)
1332   {
1333     BmfPError("error making EtherTunTap interface \"%s\" %spersistent", EtherTunTapIfName, !EtherTunTapPersistent ? "non-" : "");
1334
1335     /* Continue anyway */
1336   }
1337
1338   OLSR_PRINTF(8, "%s: opened 1 socket on \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
1339
1340   AddDescriptorToInputSet(etfd);
1341
1342   /* If the user configured a specific IP address for the BMF network interface,
1343    * help the user and advertise the IP address of the BMF network interface
1344    * on the OLSR network via HNA */
1345   if (TunTapIpOverruled != 0)
1346   {
1347     union olsr_ip_addr temp_net;
1348
1349     temp_net.v4.s_addr = htonl(EtherTunTapIp);
1350     ip_prefix_list_add(&olsr_cnf->hna_entries, &temp_net, 32);
1351   }
1352
1353   close(ioctlSkfd);
1354
1355   return etfd;
1356 } /* CreateLocalEtherTunTap */
1357
1358 /* -------------------------------------------------------------------------
1359  * Function   : CreateInterface
1360  * Description: Create a new TBmfInterface object and adds it to the global
1361  *              BmfInterfaces list
1362  * Input      : ifName - name of the network interface (e.g. "eth0")
1363  *            : olsrIntf - OLSR interface object of the network interface, or
1364  *                NULL if the network interface is not OLSR-enabled
1365  * Output     : none
1366  * Return     : the number of opened sockets
1367  * Data Used  : BmfInterfaces, LastBmfInterface
1368  * ------------------------------------------------------------------------- */
1369 static int CreateInterface(
1370   const char* ifName,
1371   struct interface_olsr * olsrIntf)
1372 {
1373   int capturingSkfd = -1;
1374   int encapsulatingSkfd = -1;
1375   int listeningSkfd = -1;
1376   int ioctlSkfd;
1377   struct ifreq ifr;
1378   int nOpened = 0;
1379   struct TBmfInterface* newIf = malloc(sizeof(struct TBmfInterface));
1380
1381   assert(ifName != NULL);
1382
1383   if (newIf == NULL)
1384   {
1385     return 0;
1386   }
1387
1388   if (olsrIntf != NULL)
1389   {
1390     /* On OLSR-enabled interfaces, create socket for encapsulating and forwarding 
1391      * multicast packets */
1392     encapsulatingSkfd = CreateEncapsulateSocket(ifName);
1393     if (encapsulatingSkfd < 0)
1394     {
1395       free(newIf);
1396       return 0;
1397     }
1398     nOpened++;
1399   }
1400
1401   /* Create socket for capturing and sending of multicast packets on
1402    * non-OLSR interfaces, and on OLSR-interfaces if configured. */
1403   if ((olsrIntf == NULL) || (CapturePacketsOnOlsrInterfaces != 0))
1404   {
1405     capturingSkfd = CreateCaptureSocket(ifName);
1406     if (capturingSkfd < 0)
1407     {
1408       if (encapsulatingSkfd >= 0) {
1409         close(encapsulatingSkfd);
1410       }
1411       free(newIf);
1412       return 0;
1413     }
1414
1415     nOpened++;
1416   }
1417
1418   /* Create promiscuous mode listening interface if BMF uses IP unicast
1419    * as underlying forwarding mechanism */
1420   if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
1421   {
1422     listeningSkfd = CreateListeningSocket(ifName);
1423     if (listeningSkfd < 0)
1424     {
1425       if (encapsulatingSkfd >= 0) {
1426         close(encapsulatingSkfd); /* no problem if 'encapsulatingSkfd' is -1 */
1427       }
1428       free(newIf);
1429       return 0;
1430     }
1431
1432     nOpened++;
1433   }
1434
1435   /* For ioctl operations on the network interface, use either capturingSkfd
1436    * or encapsulatingSkfd, whichever is available */
1437   ioctlSkfd = (capturingSkfd >= 0) ? capturingSkfd : encapsulatingSkfd;
1438
1439   /* Retrieve the MAC address of the interface. */
1440   memset(&ifr, 0, sizeof(struct ifreq));
1441   strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1442   ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1443   if (ioctl(ioctlSkfd, SIOCGIFHWADDR, &ifr) < 0)
1444   {
1445     BmfPError("ioctl(SIOCGIFHWADDR) error for interface \"%s\"", ifName);
1446     if (capturingSkfd >= 0) {
1447       close(capturingSkfd);
1448     }
1449     if (encapsulatingSkfd >= 0) {
1450       close(encapsulatingSkfd);
1451     }
1452     free(newIf);
1453     return 0;
1454   }
1455
1456   /* add listeners to sockets */
1457   if (capturingSkfd != -1) {
1458     add_olsr_socket(capturingSkfd, NULL, BMF_handle_captureFd, newIf, SP_IMM_READ);
1459   }
1460   if (encapsulatingSkfd != -1) {
1461     add_olsr_socket(encapsulatingSkfd, NULL, BMF_handle_encapsulatingFd, newIf, SP_IMM_READ);
1462   }
1463   if (listeningSkfd != -1) {
1464     add_olsr_socket(listeningSkfd, NULL, BMF_handle_listeningFd, newIf, SP_IMM_READ);
1465   }
1466   /* Copy data into TBmfInterface object */
1467   newIf->capturingSkfd = capturingSkfd;
1468   newIf->encapsulatingSkfd = encapsulatingSkfd;
1469   newIf->listeningSkfd = listeningSkfd;
1470   memcpy(newIf->macAddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1471   memcpy(newIf->ifName, ifName, IFNAMSIZ);
1472   newIf->olsrIntf = olsrIntf;
1473   if (olsrIntf != NULL)
1474   {
1475     /* For an OLSR-interface, copy the interface address and broadcast
1476      * address from the OLSR interface object. Downcast to correct sockaddr
1477      * subtype. */
1478     newIf->intAddr.v4 = ((struct sockaddr_in *)&olsrIntf->int_addr)->sin_addr;
1479     newIf->broadAddr.v4 = ((struct sockaddr_in *)&olsrIntf->int_broadaddr)->sin_addr;
1480   }
1481   else
1482   {
1483     /* For a non-OLSR interface, retrieve the IP address ourselves */
1484     memset(&ifr, 0, sizeof(struct ifreq));
1485     strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1486     ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1487     if (ioctl(ioctlSkfd, SIOCGIFADDR, &ifr) < 0) 
1488     {
1489       BmfPError("ioctl(SIOCGIFADDR) error for interface \"%s\"", ifName);
1490
1491       newIf->intAddr.v4.s_addr = inet_addr("0.0.0.0");
1492     }
1493     else
1494     {
1495       /* Downcast to correct sockaddr subtype */
1496       newIf->intAddr.v4 = ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&ifr.ifr_addr))->sin_addr;
1497     }
1498
1499     /* For a non-OLSR interface, retrieve the IP broadcast address ourselves */
1500     memset(&ifr, 0, sizeof(struct ifreq));
1501     strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1502     ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1503     if (ioctl(ioctlSkfd, SIOCGIFBRDADDR, &ifr) < 0) 
1504     {
1505       BmfPError("ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName);
1506
1507       newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0");
1508     }
1509     else
1510     {
1511       /* Downcast to correct sockaddr subtype */
1512       newIf->broadAddr.v4 = ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&ifr.ifr_broadaddr))->sin_addr;
1513     }
1514   }
1515
1516   /* Reset counters */
1517   newIf->nBmfPacketsRx = 0;
1518   newIf->nBmfPacketsRxDup = 0;
1519   newIf->nBmfPacketsTx = 0;
1520
1521   /* Add new TBmfInterface object to global list. OLSR interfaces are
1522    * added at the front of the list, non-OLSR interfaces at the back. */
1523   if (BmfInterfaces == NULL)
1524   {
1525     /* First TBmfInterface object in list */
1526     newIf->next = NULL;
1527     BmfInterfaces = newIf;
1528     LastBmfInterface = newIf;
1529   }
1530   else if (olsrIntf != NULL)
1531   {
1532     /* Add new TBmfInterface object at front of list */
1533     newIf->next = BmfInterfaces;
1534     BmfInterfaces = newIf;
1535   }
1536   else
1537   {
1538     /* Add new TBmfInterface object at back of list */
1539     newIf->next = NULL;
1540     LastBmfInterface->next= newIf;
1541     LastBmfInterface = newIf;
1542   }
1543
1544   OLSR_PRINTF(
1545     8,
1546     "%s: opened %d socket%s on %s interface \"%s\"\n",
1547     PLUGIN_NAME_SHORT,
1548     nOpened,
1549     nOpened == 1 ? "" : "s",
1550     olsrIntf != NULL ? "OLSR" : "non-OLSR",
1551     ifName);
1552
1553   return nOpened;
1554 } /* CreateInterface */
1555
1556 /* -------------------------------------------------------------------------
1557  * Function   : CreateBmfNetworkInterfaces
1558  * Description: Create a list of TBmfInterface objects, one for each network
1559  *              interface on which BMF runs
1560  * Input      : skipThisIntf - network interface to skip, if seen
1561  * Output     : none
1562  * Return     : fail (-1) or success (0)
1563  * Data Used  : none
1564  * ------------------------------------------------------------------------- */
1565 int CreateBmfNetworkInterfaces(struct interface_olsr * skipThisIntf)
1566 {
1567   int skfd;
1568   struct ifconf ifc;
1569   int numreqs = 30;
1570   struct ifreq* ifr;
1571   int n;
1572   int nOpenedSockets = 0;
1573
1574   /* Clear input descriptor set */
1575   FD_ZERO(&InputSet);
1576
1577   skfd = socket(PF_INET, SOCK_DGRAM, 0);
1578   if (skfd < 0)
1579   {
1580     BmfPError("no inet socket available to retrieve interface list");
1581     return -1;
1582   }
1583
1584   /* Retrieve the network interface configuration list */
1585   ifc.ifc_buf = NULL;
1586   for (;;)
1587   {
1588     ifc.ifc_len = sizeof(struct ifreq) * numreqs;
1589     ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
1590
1591     if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
1592     {
1593       BmfPError("ioctl(SIOCGIFCONF) error");
1594
1595       close(skfd);
1596       free(ifc.ifc_buf);
1597       return -1;
1598     }
1599     if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs)
1600     {
1601       /* Assume it overflowed; double the space and try again */
1602       numreqs *= 2;
1603       assert(numreqs < 1024);
1604       continue; /* for (;;) */
1605     }
1606     break; /* for (;;) */
1607   } /* for (;;) */
1608
1609   close(skfd);
1610
1611   /* For each item in the interface configuration list... */
1612   ifr = ifc.ifc_req;
1613   for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++)
1614   {
1615     struct interface_olsr * olsrIntf;
1616     union olsr_ip_addr ipAddr;
1617
1618     /* Skip the BMF network interface itself */
1619     if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0)
1620     {
1621       continue; /* for (n = ...) */
1622     }
1623
1624     /* ...find the OLSR interface structure, if any */
1625     ipAddr.v4 =  ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifr->ifr_addr))->sin_addr;
1626     olsrIntf = if_ifwithaddr(&ipAddr);
1627
1628     if (skipThisIntf != NULL && olsrIntf == skipThisIntf)
1629     {
1630       continue; /* for (n = ...) */
1631     }
1632
1633     if (olsrIntf == NULL && ! IsNonOlsrBmfIf(ifr->ifr_name))
1634     {
1635       /* Interface is neither OLSR interface, nor specified as non-OLSR BMF
1636        * interface in the BMF plugin parameter list */
1637       continue; /* for (n = ...) */
1638     }
1639
1640     nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf);
1641
1642   } /* for (n = ...) */
1643
1644   free(ifc.ifc_buf);
1645   
1646   /* Create the BMF network interface */
1647   EtherTunTapFd = CreateLocalEtherTunTap();
1648   if (EtherTunTapFd >= 0)
1649   {
1650     add_olsr_socket(EtherTunTapFd, NULL, BMF_handle_tuntapFd, NULL, SP_IMM_READ);
1651     nOpenedSockets++;
1652   }
1653
1654   if (BmfInterfaces == NULL)
1655   {
1656     olsr_printf(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
1657   }
1658   else
1659   {
1660     olsr_printf(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets);
1661   }
1662   return 0;
1663 } /* CreateBmfNetworkInterfaces */
1664
1665 /* -------------------------------------------------------------------------
1666  * Function   : CloseBmfNetworkInterfaces
1667  * Description: Closes every socket on each network interface used by BMF
1668  * Input      : none
1669  * Output     : none
1670  * Return     : none
1671  * Data Used  : BmfInterfaces, LastBmfInterface
1672  * Notes      : Closes
1673  *              - the local EtherTunTap interface (e.g. "tun0" or "tap0")
1674  *              - for each BMF-enabled interface, the socket used for
1675  *                capturing multicast packets
1676  *              - for each OLSR-enabled interface, the socket used for
1677  *                encapsulating packets
1678  *              Also restores the network state to the situation before BMF
1679  *              was started.
1680  * ------------------------------------------------------------------------- */
1681 void CloseBmfNetworkInterfaces(void)
1682 {
1683   int nClosed = 0;
1684   u_int32_t totalOlsrBmfPacketsRx = 0;
1685   u_int32_t totalOlsrBmfPacketsRxDup = 0;
1686   u_int32_t totalOlsrBmfPacketsTx = 0;
1687   u_int32_t totalNonOlsrBmfPacketsRx = 0;
1688   u_int32_t totalNonOlsrBmfPacketsRxDup = 0;
1689   u_int32_t totalNonOlsrBmfPacketsTx = 0;
1690
1691   /* Close all opened sockets */
1692   struct TBmfInterface* nextBmfIf = BmfInterfaces;
1693   while (nextBmfIf != NULL) 
1694   {
1695     struct TBmfInterface* bmfIf = nextBmfIf;
1696     nextBmfIf = bmfIf->next;
1697
1698     if (bmfIf->capturingSkfd >= 0)
1699     {
1700       close(bmfIf->capturingSkfd);
1701       remove_olsr_socket(bmfIf->capturingSkfd, NULL, BMF_handle_captureFd);
1702       nClosed++;
1703     }
1704     if (bmfIf->encapsulatingSkfd >= 0) 
1705     {
1706       close(bmfIf->encapsulatingSkfd);
1707       remove_olsr_socket(bmfIf->encapsulatingSkfd, NULL, BMF_handle_encapsulatingFd);
1708       nClosed++;
1709     }
1710     if (bmfIf->listeningSkfd >= 0)
1711     {
1712       close(bmfIf->listeningSkfd);
1713       remove_olsr_socket(bmfIf->listeningSkfd, NULL, BMF_handle_listeningFd);
1714       nClosed++;
1715     }
1716
1717     OLSR_PRINTF(
1718       7,
1719       "%s: %s interface \"%s\": RX pkts %d (%d dups); TX pkts %d\n", 
1720       PLUGIN_NAME_SHORT,
1721       bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
1722       bmfIf->ifName,
1723       bmfIf->nBmfPacketsRx,
1724       bmfIf->nBmfPacketsRxDup,
1725       bmfIf->nBmfPacketsTx);
1726
1727     olsr_printf(
1728       1,
1729       "%s: closed %s interface \"%s\"\n", 
1730       PLUGIN_NAME_SHORT,
1731       bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
1732       bmfIf->ifName);
1733
1734     /* Add totals */
1735     if (bmfIf->olsrIntf != NULL)
1736     {
1737       totalOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
1738       totalOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
1739       totalOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
1740     }
1741     else
1742     {
1743       totalNonOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
1744       totalNonOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
1745       totalNonOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
1746     }
1747
1748     free(bmfIf);
1749   } /* while */
1750   
1751   if (EtherTunTapFd >= 0)
1752   {
1753     close(EtherTunTapFd);
1754     remove_olsr_socket(EtherTunTapFd, NULL, BMF_handle_tuntapFd);
1755     nClosed++;
1756
1757     OLSR_PRINTF(7, "%s: closed \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
1758   }
1759
1760   BmfInterfaces = NULL;
1761   LastBmfInterface = NULL;
1762
1763   /* Re-initialize the IP address for the BMF network interface. Thanks to
1764    * Daniele Lacamera for finding and solving this bug. */
1765   EtherTunTapIp = ETHERTUNTAPIPNOTSET;
1766
1767   olsr_printf(1, "%s: closed %d sockets\n", PLUGIN_NAME_SHORT, nClosed);
1768
1769   OLSR_PRINTF(
1770     7,
1771     "%s: total all OLSR interfaces    : RX pkts %d (%d dups); TX pkts %d\n",
1772     PLUGIN_NAME_SHORT,
1773     totalOlsrBmfPacketsRx,
1774     totalOlsrBmfPacketsRxDup,
1775     totalOlsrBmfPacketsTx);
1776   OLSR_PRINTF(
1777     7,
1778     "%s: total all non-OLSR interfaces: RX pkts %d (%d dups); TX pkts %d\n",
1779     PLUGIN_NAME_SHORT,
1780     totalNonOlsrBmfPacketsRx,
1781     totalNonOlsrBmfPacketsRxDup,
1782     totalNonOlsrBmfPacketsTx);
1783 } /* CloseBmfNetworkInterfaces */
1784
1785 #define MAX_NON_OLSR_IFS 32
1786 static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
1787 static int nNonOlsrIfs = 0;
1788
1789 /* -------------------------------------------------------------------------
1790  * Function   : AddNonOlsrBmfIf
1791  * Description: Add an non-OLSR enabled network interface to the list of BMF-enabled
1792  *              network interfaces
1793  * Input      : ifName - network interface (e.g. "eth0")
1794  *              data - not used
1795  *              addon - not used
1796  * Output     : none
1797  * Return     : success (0) or fail (1)
1798  * Data Used  : NonOlsrIfNames
1799  * ------------------------------------------------------------------------- */
1800 int AddNonOlsrBmfIf(
1801   const char* ifName,
1802   void* data __attribute__((unused)),
1803   set_plugin_parameter_addon addon __attribute__((unused)))
1804 {
1805   assert(ifName != NULL);
1806
1807   if (nNonOlsrIfs >= MAX_NON_OLSR_IFS)
1808   {
1809     olsr_printf(
1810       1,
1811       "%s: too many non-OLSR interfaces specified, maximum is %d\n",
1812       PLUGIN_NAME,
1813       MAX_NON_OLSR_IFS);
1814     return 1;
1815   }
1816
1817   strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ - 1);
1818   NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1819   nNonOlsrIfs++;
1820   return 0;
1821 } /* AddNonOlsrBmfIf */
1822
1823 /* -------------------------------------------------------------------------
1824  * Function   : IsNonOlsrBmfIf
1825  * Description: Checks if a network interface is OLSR-enabled
1826  * Input      : ifName - network interface (e.g. "eth0")
1827  * Output     : none
1828  * Return     : true (1) or false (0)
1829  * Data Used  : NonOlsrIfNames
1830  * ------------------------------------------------------------------------- */
1831 int IsNonOlsrBmfIf(const char* ifName)
1832 {
1833   int i;
1834
1835   assert(ifName != NULL);
1836
1837   for (i = 0; i < nNonOlsrIfs; i++)
1838   {
1839     if (strncmp(NonOlsrIfNames[i], ifName, IFNAMSIZ) == 0) return 1;
1840   }
1841   return 0;
1842 } /* IsNonOlsrBmfIf */
1843
1844 /* -------------------------------------------------------------------------
1845  * Function   : CheckAndUpdateLocalBroadcast
1846  * Description: For an IP packet, check if the destination address is not a
1847  *              multicast address. If it is not, the packet is assumed to be
1848  *              a local broadcast packet. In that case, set the destination
1849  *              address of the IP packet to the passed broadcast address.
1850  * Input      : ipPacket - the IP packet
1851  *              broadAddr - the broadcast address to fill in
1852  * Output     : none
1853  * Return     : none
1854  * Data Used  : none
1855  * Notes      : See also RFC1141
1856  * ------------------------------------------------------------------------- */
1857 void CheckAndUpdateLocalBroadcast(unsigned char* ipPacket, union olsr_ip_addr* broadAddr)
1858 {
1859   struct iphdr* iph;
1860   union olsr_ip_addr destIp;
1861
1862   assert(ipPacket != NULL && broadAddr != NULL);
1863
1864   iph = (struct iphdr*) ARM_NOWARN_ALIGN(ipPacket);
1865   destIp.v4.s_addr = iph->daddr;
1866   if (! IsMulticast(&destIp))
1867   {
1868     u_int32_t origDaddr, newDaddr;
1869     u_int32_t check;
1870
1871     origDaddr = ntohl(iph->daddr);
1872
1873     iph->daddr = broadAddr->v4.s_addr;
1874     newDaddr = ntohl(iph->daddr);
1875
1876     /* Re-calculate IP header checksum for new destination */
1877     check = ntohs(iph->check);
1878
1879     check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF));
1880     check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF));
1881
1882     /* Add carry */
1883     check = check + (check >> 16);
1884
1885     iph->check = htons(check);
1886
1887     if (iph->protocol == SOL_UDP)
1888     {
1889       /* Re-calculate UDP/IP checksum for new destination */
1890
1891       int ipHeaderLen = GetIpHeaderLength(ipPacket);
1892       struct udphdr* udph = (struct udphdr*) ARM_NOWARN_ALIGN((ipPacket + ipHeaderLen));
1893
1894       /* RFC 1624, Eq. 3: HC' = ~(~HC - m + m') */
1895
1896       check = ntohs(udph->check);
1897
1898       check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF));
1899       check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF));
1900
1901       /* Add carry */
1902       check = check + (check >> 16);
1903
1904       udph->check = htons(check);
1905      } /* if */
1906   } /* if */
1907 } /* CheckAndUpdateLocalBroadcast */
1908
1909 /* -------------------------------------------------------------------------
1910  * Function   : AddMulticastRoute
1911  * Description: Insert a route to all multicast addresses in the kernel
1912  *              routing table. The route will be via the BMF network interface.
1913  * Input      : none
1914  * Output     : none
1915  * Return     : none
1916  * Data Used  : none
1917  * ------------------------------------------------------------------------- */
1918 void AddMulticastRoute(void)
1919 {
1920   struct rtentry kernel_route;
1921   int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1922   if (ioctlSkfd < 0)
1923   {
1924     BmfPError("socket(PF_INET) error");
1925     return;
1926   }
1927
1928   memset(&kernel_route, 0, sizeof(struct rtentry));
1929
1930   ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sa_family = AF_INET;
1931   ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_gateway))->sa_family = AF_INET;
1932   ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sa_family = AF_INET;
1933
1934   /* 224.0.0.0/4 */
1935   ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sin_addr.s_addr = htonl(0xE0000000);
1936   ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sin_addr.s_addr = htonl(0xF0000000);
1937
1938   kernel_route.rt_metric = 0;
1939   kernel_route.rt_flags = RTF_UP;
1940
1941   kernel_route.rt_dev = EtherTunTapIfName;
1942
1943   if (ioctl(ioctlSkfd, SIOCADDRT, &kernel_route) < 0)
1944   {
1945     BmfPError("error setting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName);
1946
1947     /* Continue anyway */
1948   }
1949   close(ioctlSkfd);
1950 } /* AddMulticastRoute */
1951
1952 /* -------------------------------------------------------------------------
1953  * Function   : DeleteMulticastRoute
1954  * Description: Delete the route to all multicast addresses from the kernel
1955  *              routing table
1956  * Input      : none
1957  * Output     : none
1958  * Return     : none
1959  * Data Used  : none
1960  * ------------------------------------------------------------------------- */
1961 void DeleteMulticastRoute(void)
1962 {
1963   if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP)
1964   {
1965     struct rtentry kernel_route;
1966     int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1967     if (ioctlSkfd < 0)
1968     {
1969       BmfPError("socket(PF_INET) error");
1970       return;
1971     }
1972
1973     memset(&kernel_route, 0, sizeof(struct rtentry));
1974
1975     ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sa_family = AF_INET;
1976     ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_gateway))->sa_family = AF_INET;
1977     ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sa_family = AF_INET;
1978
1979     /* 224.0.0.0/4 */
1980     ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sin_addr.s_addr = htonl(0xE0000000);
1981     ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sin_addr.s_addr = htonl(0xF0000000);
1982
1983     kernel_route.rt_metric = 0;
1984     kernel_route.rt_flags = RTF_UP;
1985
1986     kernel_route.rt_dev = EtherTunTapIfName;
1987
1988     if (ioctl(ioctlSkfd, SIOCDELRT, &kernel_route) < 0)
1989     {
1990       BmfPError("error deleting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName);
1991
1992       /* Continue anyway */
1993     }
1994     close(ioctlSkfd);
1995   } /* if */
1996 } /* DeleteMulticastRoute */