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