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