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