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