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