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