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