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