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