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