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