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