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