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