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