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