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