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