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