plugins: fix build on some glibc systems
[olsrd.git] / lib / bmf / src / Bmf.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       : Bmf.c
35  * Description: Multicast forwarding functions
36  * Created    : 29 Jun 2006
37  *
38  * ------------------------------------------------------------------------- */
39
40 #define _MULTI_THREADED
41
42 #include "Bmf.h"
43
44 /* System includes */
45 #include <stddef.h> /* NULL */
46 #include <sys/types.h> /* ssize_t */
47 #include <string.h> /* strerror() */
48 #include <stdarg.h> /* va_list, va_start, va_end */
49 #include <errno.h> /* errno */
50 #include <assert.h> /* assert() */
51 #include <linux/if_ether.h> /* ETH_P_IP */
52 #include <linux/if_packet.h> /* struct sockaddr_ll, PACKET_MULTICAST */
53 #include <signal.h> /* sigset_t, sigfillset(), sigdelset(), SIGINT */
54 #include <netinet/ip.h> /* struct ip */
55 #include <netinet/udp.h> /* struct udphdr */
56 #include <unistd.h> /* read(), write() */
57 #include <sys/poll.h> /* Daniele Lacamera: Added guard poll for sendto(), needs poll.h */
58
59 /* OLSRD includes */
60 #include "plugin_util.h" /* set_plugin_int */
61 #include "defs.h" /* olsr_cnf, OLSR_PRINTF */
62 #include "ipcalc.h"
63 #include "olsr.h" /* olsr_printf */
64 #include "mid_set.h" /* mid_lookup_main_addr() */
65 #include "mpr_selector_set.h" /* olsr_lookup_mprs_set() */
66 #include "link_set.h" /* get_best_link_to_neighbor() */
67 #include "net_olsr.h" /* ipequal */
68
69 /* BMF includes */
70 #include "NetworkInterfaces.h" /* TBmfInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */
71 #include "Address.h" /* IsMulticast() */
72 #include "Packet.h" /* ENCAP_HDR_LEN, BMF_ENCAP_TYPE, BMF_ENCAP_LEN etc. */
73 #include "PacketHistory.h" /* InitPacketHistory() */
74
75 /* unicast/broadcast fan out limit */
76 int FanOutLimit = 2;
77
78 int BroadcastRetransmitCount = 1;
79
80 /* -------------------------------------------------------------------------
81  * Function   : BmfPError
82  * Description: Prints an error message at OLSR debug level 1.
83  *              First the plug-in name is printed. Then (if format is not NULL
84  *              and *format is not empty) the arguments are printed, followed
85  *              by a colon and a blank. Then the message and a new-line.
86  * Input      : format, arguments
87  * Output     : none
88  * Return     : none
89  * Data Used  : none
90  * ------------------------------------------------------------------------- */
91 void BmfPError(const char* format, ...)
92 {
93 #define MAX_STR_DESC 255
94   char* strErr = strerror(errno);
95   char strDesc[MAX_STR_DESC];
96
97   /* Rely on short-circuit boolean evaluation */
98   if (format == NULL || *format == '\0')
99   {
100     olsr_printf(1, "%s: %s\n", PLUGIN_NAME, strErr);
101   }
102   else
103   {
104     va_list arglist;
105
106     olsr_printf(1, "%s: ", PLUGIN_NAME);
107
108     va_start(arglist, format);
109     vsnprintf(strDesc, MAX_STR_DESC, format, arglist);
110     va_end(arglist);
111
112     strDesc[MAX_STR_DESC - 1] = '\0'; /* Ensures null termination */
113
114     olsr_printf(1, "%s: %s\n", strDesc, strErr);
115   }
116 } /* BmfPError */
117
118 /* -------------------------------------------------------------------------
119  * Function   : MainAddressOf
120  * Description: Lookup the main address of a node
121  * Input      : ip - IP address of the node
122  * Output     : none
123  * Return     : The main IP address of the node
124  * Data Used  : none
125  * ------------------------------------------------------------------------- */
126 union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip)
127 {
128   union olsr_ip_addr* result;
129
130   result = mid_lookup_main_addr(ip);
131   if (result == NULL)
132   {
133     result = ip;
134   }
135   return result;
136 } /* MainAddressOf */
137
138 /* -------------------------------------------------------------------------
139  * Function   : ForwardPacket
140  * Description: Forward a raw IP packet
141  * Input      : intf - the network interface on which to forward the packet. The
142  *                packet will be forwarded on its 'capturing' socket.
143  *              ipPacket - the IP packet to be forwarded
144  *              ipPacketLen - the length of the IP packet to be forwarded
145  *              debugInfo - string to use printing debugging information
146  * Output     : none
147  * Return     : none
148  * Data Used  : none
149  * ------------------------------------------------------------------------- */
150 static void ForwardPacket(
151   struct TBmfInterface* intf,
152   unsigned char* ipPacket,
153   u_int16_t ipPacketLen,
154   const char* debugInfo)
155 {
156   int nBytesWritten;
157   struct sockaddr_ll dest;
158
159   int pollret;
160   struct pollfd guard;
161   guard.fd = intf->capturingSkfd;
162   guard.events = POLLOUT;
163
164   /* If the IP packet is a local broadcast packet,
165    * update its destination address to match the subnet of the network
166    * interface on which the packet is being sent. */
167   CheckAndUpdateLocalBroadcast(ipPacket, &intf->broadAddr);
168
169   memset(&dest, 0, sizeof(dest));
170   dest.sll_family = AF_PACKET;
171   dest.sll_protocol = htons(ETH_P_IP);
172   dest.sll_ifindex = if_nametoindex(intf->ifName);
173   dest.sll_halen = IFHWADDRLEN;
174
175   /* Use all-ones as destination MAC address. When the IP destination is
176    * a multicast address, the destination MAC address should normally also
177    * be a multicast address. E.g., when the destination IP is 224.0.0.1,
178    * the destination MAC should be 01:00:5e:00:00:01. However, it does not
179    * seem to matter when the destination MAC address is set to all-ones
180    * in that case. */
181   memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
182
183   /* Daniele Lacamera: poll guard to avoid locking in sendto().
184    * Wait at most 2 polling periods. Since we're running in the context of the main
185    * OLSR thread, we should not wait too long. 2 polling periods is considered a
186    * reasonable time. */
187   pollret = poll (&guard, 1, 2 * olsr_cnf->pollrate * MSEC_PER_SEC);
188   if (pollret <= 0)
189   {
190     BmfPError("sendto() on \"%s\": not ready to send pkt. pollret=%d\n", intf->ifName, pollret);
191
192     /* Apparently the network interface is jammed. Give up. */
193     return;
194   }
195
196   /* Forward the BMF packet via the capturing socket */
197   nBytesWritten = sendto(
198     intf->capturingSkfd,
199     ipPacket,
200     ipPacketLen,
201     0,
202     (struct sockaddr*) &dest,
203     sizeof(dest));
204   if (nBytesWritten != ipPacketLen)
205   {
206     BmfPError("sendto() error forwarding pkt on \"%s\"", intf->ifName);
207     return;
208   }
209
210   /* Increase counter */
211   intf->nBmfPacketsTx++;
212
213   OLSR_PRINTF(
214     8,
215     "%s: --> %s \"%s\"\n",
216     PLUGIN_NAME_SHORT,
217     debugInfo,
218     intf->ifName);
219 } /* ForwardPacket */
220
221 /* -------------------------------------------------------------------------
222  * Function   : EncapsulateAndForwardPacket
223  * Description: Encapsulate a captured raw IP packet and forward it
224  * Input      : intf - the network interface on which to forward the packet
225  *              encapsulationUdpData - The encapsulation header, followed by
226  *                the encapsulated IP packet
227  *              source - the source IP address of the BMF packet, or NULL if
228  *                unknown or not applicable
229  *              forwardedBy - the IP address of the node that forwarded the BMF
230  *                packet, or NULL if unknown or not applicable
231  *              forwardedTo - the IP address of the node to which the BMF packet
232  *                was directed, or NULL if unknown or not applicable
233  * Output     : none
234  * Return     : none
235  * Data Used  : none
236  * ------------------------------------------------------------------------- */
237 static void EncapsulateAndForwardPacket(
238   struct TBmfInterface* intf,
239   unsigned char* encapsulationUdpData,
240   union olsr_ip_addr* source,
241   union olsr_ip_addr* forwardedBy,
242   union olsr_ip_addr* forwardedTo)
243 {
244   /* Retrieve the number of bytes to be forwarded via the encapsulation socket */
245   u_int16_t udpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);
246
247   /* The next destination(s) */
248   struct TBestNeighbors bestNeighborLinks;
249   struct link_entry* bestNeighbor;
250
251   int nPossibleNeighbors = 0;
252   struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
253   int nPacketsToSend;
254   int sendUnicast; /* 0 = send broadcast; 1 = send unicast */
255
256   int i;
257
258   /* Find at most 'FanOutLimit' best neigbors to forward the packet to */
259   FindNeighbors(
260     &bestNeighborLinks,
261     &bestNeighbor,
262     intf,
263     source,
264     forwardedBy,
265     forwardedTo,
266     &nPossibleNeighbors);
267
268   if (nPossibleNeighbors <= 0)
269   {
270     OLSR_PRINTF(
271       8,
272       "%s: --> not encap-forwarding on \"%s\": there is no neighbor that needs my retransmission\n",
273       PLUGIN_NAME_SHORT,
274       intf->ifName);
275     return;
276   } /* if */
277
278   /* Compose destination of encapsulation packet */
279
280   memset(&forwardTo, 0, sizeof(forwardTo));
281   forwardTo.sin_family = AF_INET;
282   forwardTo.sin_port = htons(BMF_ENCAP_PORT);
283
284   /* Start by filling in the local broadcast address. This may be overwritten later. */
285   forwardTo.sin_addr = intf->broadAddr.v4;
286
287   /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
288    *   unicast packet (to the best neighbor).
289    * - But if the BMF mechanism is BM_BROADCAST,
290    *   - send 'nPossibleNeighbors' unicast packets if there are up to
291    *     'FanOutLimit' possible neighbors,
292    *   - if there are more than 'FanOutLimit' possible neighbors, then
293    *     send a (WLAN-air-expensive, less reliable) broadcast packet. */
294   if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
295   {
296     /* One unicast packet to the best neighbor */
297     nPacketsToSend = 1;
298     sendUnicast = 1;
299     bestNeighborLinks.links[0] = bestNeighbor;
300   }
301   else /* BmfMechanism == BM_BROADCAST */
302   {
303     if (nPossibleNeighbors <= FanOutLimit)
304     {
305       /* 'nPossibleNeighbors' unicast packets */
306       nPacketsToSend = nPossibleNeighbors;
307       sendUnicast = 1;
308     }
309     else /* nPossibleNeighbors > FanOutLimit */
310     {
311       /* One broadcast packet, possibly retransmitted as specified in the
312        * 'BroadcastRetransmitCount' plugin parameter */
313       nPacketsToSend = BroadcastRetransmitCount;
314       sendUnicast = 0;
315     } /* if */
316   } /* if */
317
318   for (i = 0; i < nPacketsToSend; i++)
319   {
320     int nBytesWritten;
321
322     int pollret;
323     struct pollfd guard;
324     guard.fd = intf->encapsulatingSkfd;
325     guard.events = POLLOUT;
326
327     if (sendUnicast == 1)
328     {
329       /* For unicast, overwrite the local broadcast address which was filled in above */
330       forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4;
331     }
332
333     /* Daniele Lacamera: poll guard to avoid locking in sendto().
334      * Wait at most 2 polling periods. Since we're running in the context of the main
335      * OLSR thread, we should not wait too long. 2 polling periods is considered a
336      * reasonable time. */
337     pollret = poll (&guard, 1, 2 * olsr_cnf->pollrate * MSEC_PER_SEC);
338     if (pollret <= 0)
339     {
340       BmfPError("sendto() on \"%s\": not ready to send pkt. pollret=%d\n", intf->ifName, pollret);
341
342       /* Apparently the network interface is jammed. Give up and return. */
343       return;
344     }
345
346     /* Forward the BMF packet via the encapsulation socket */
347     nBytesWritten = sendto(
348       intf->encapsulatingSkfd,
349       encapsulationUdpData,
350       udpDataLen,
351       MSG_DONTROUTE,
352       (struct sockaddr*) &forwardTo,
353       sizeof(forwardTo));                   
354
355     /* Evaluate and display result */
356     if (nBytesWritten != udpDataLen)
357     {
358       BmfPError("sendto() error forwarding encapsulated pkt on \"%s\"", intf->ifName);
359       return;
360     } /* if (nBytesWritten != udpDataLen) */
361
362     /* Increase counter */
363     intf->nBmfPacketsTx++;
364
365     OLSR_PRINTF(
366       8,
367       "%s: --> forwarded encapsulated packet on \"%s\" to %s\n",
368       PLUGIN_NAME_SHORT,
369       intf->ifName,
370       inet_ntoa(forwardTo.sin_addr));
371   } /* for */
372 } /* EncapsulateAndForwardPacket */
373
374 /* -------------------------------------------------------------------------
375  * Function   : BmfPacketCaptured
376  * Description: Handle a captured IP packet
377  * Input      : intf - the network interface on which the packet was captured
378  *              sllPkttype - the type of packet. Either PACKET_OUTGOING,
379  *                PACKET_BROADCAST or PACKET_MULTICAST.
380  *              encapsulationUdpData - space for the encapsulation header, followed by
381  *                the captured IP packet
382  * Output     : none
383  * Return     : none
384  * Data Used  : BmfInterfaces
385  * Notes      : The IP packet is assumed to be captured on a socket of family
386  *              PF_PACKET and type SOCK_DGRAM (cooked).
387  * ------------------------------------------------------------------------- */
388 static void BmfPacketCaptured(
389   struct TBmfInterface* intf,
390   unsigned char sllPkttype,
391   unsigned char* encapsulationUdpData)
392 {
393   union olsr_ip_addr src; /* Source IP address in captured packet */
394   union olsr_ip_addr dst; /* Destination IP address in captured packet */
395   union olsr_ip_addr* origIp; /* Main OLSR address of source of captured packet */
396   struct TBmfInterface* walker;
397   int isFromOlsrIntf;
398   int isFromOlsrNeighbor;
399   int iAmMpr;
400   unsigned char* ipPacket; /* The captured IP packet... */
401   u_int16_t ipPacketLen; /* ...and its length */
402   struct ip* ipHeader; /* The IP header inside the captured IP packet */
403   u_int32_t crc32;
404   struct TEncapHeader* encapHdr;
405 #ifndef NODEBUG
406   struct ipaddr_str srcBuf, dstBuf;
407 #endif /* NODEBUG */
408   ipHeader = GetIpHeader(encapsulationUdpData);
409
410   dst.v4 = ipHeader->ip_dst;
411
412   /* Only forward multicast packets. If configured, also forward local broadcast packets */
413   if (IsMulticast(&dst) ||
414       (EnableLocalBroadcast != 0 && ipequal(&dst, &intf->broadAddr)))
415   {
416     /* continue */
417   }
418   else
419   {
420     return;
421   }
422
423   ipPacket = GetIpPacket(encapsulationUdpData);
424
425   /* Don't forward fragments of IP packets: there is no way to distinguish fragments
426    * of BMF encapsulation packets from other fragments.
427    * Well yes, there is the IP-ID, which can be kept in a list to relate a fragment
428    * to earlier sent BMF packets, but... sometimes the second fragment comes in earlier
429    * than the first fragment, so that the list is not yet up to date and the second
430    * fragment is not recognized as a BMF packet.
431    * Also, don't forward OLSR packets (UDP port 698) and BMF encapsulated packets */
432   if (IsIpFragment(ipPacket) || IsOlsrOrBmfPacket(ipPacket))
433   {
434     return;
435   }
436
437   /* Increase counter */
438   intf->nBmfPacketsRx++;
439
440   /* Check if the frame is captured on an OLSR-enabled interface */
441   isFromOlsrIntf = (intf->olsrIntf != NULL);
442
443   /* Retrieve the length of the captured packet */
444   ipPacketLen = GetIpTotalLength(ipPacket);
445
446   src.v4 = ipHeader->ip_src;
447
448   OLSR_PRINTF(
449     8,
450     "%s: %s pkt of %ld bytes captured on %s interface \"%s\": %s->%s\n",
451     PLUGIN_NAME_SHORT,
452     sllPkttype == PACKET_OUTGOING ? "outgoing" : "incoming",
453     (long)ipPacketLen,
454     isFromOlsrIntf ? "OLSR" : "non-OLSR",
455     intf->ifName,
456     olsr_ip_to_string(&srcBuf, &src),
457     olsr_ip_to_string(&dstBuf, &dst));
458
459   /* Lookup main address of source in the MID table of OLSR */
460   origIp = MainAddressOf(&src);
461
462   /* Calculate packet fingerprint */
463   crc32 = PacketCrc32(ipPacket, ipPacketLen);
464
465   /* Check if this packet was seen recently */
466   if (CheckAndMarkRecentPacket(crc32))
467   {
468     /* Increase counter */
469     intf->nBmfPacketsRxDup++;
470
471     OLSR_PRINTF(
472       8,
473       "%s: --> discarding: packet is duplicate\n",
474       PLUGIN_NAME_SHORT);
475     return;
476   }
477
478   /* Compose encapsulation header */
479   encapHdr = (struct TEncapHeader*) encapsulationUdpData;
480   memset (encapHdr, 0, ENCAP_HDR_LEN);
481   encapHdr->type = BMF_ENCAP_TYPE;
482   encapHdr->len = BMF_ENCAP_LEN;
483   encapHdr->reserved = 0;
484   encapHdr->crc32 = htonl(crc32);
485
486   /* Check if the frame is captured on an OLSR interface from an OLSR neighbor.
487    * TODO: get_best_link_to_neighbor() may be very CPU-expensive, a simpler call
488    * would do here (something like 'get_any_link_to_neighbor()'). */
489   isFromOlsrNeighbor =
490     (isFromOlsrIntf /* The frame is captured on an OLSR interface... */
491     && get_best_link_to_neighbor(origIp) != NULL); /* ...from an OLSR neighbor */ 
492
493   /* Check with OLSR if I am MPR for that neighbor */
494   iAmMpr = olsr_lookup_mprs_set(origIp) != NULL;
495
496   /* Check with each network interface what needs to be done on it */
497   for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
498   {
499     /* Is the forwarding interface OLSR-enabled? */
500     int isToOlsrIntf = (walker->olsrIntf != NULL);
501
502     /* Depending on certain conditions, we decide whether or not to forward
503      * the packet, and if it is forwarded, in which form (encapsulated
504      * or not, TTL decreased or not). These conditions are:
505      * - is the packet is coming in on an OLSR interface or not? (isFromOlsrIntf)
506      * - is the packet going out on an OLSR interface or not? (isToOlsrIntf)
507      * - if the packet if coming in on an OLSR interface:
508      *   - is the node that forwarded the packet my OLSR-neighbor? (isFromOlsrNeighbor)
509      *   - has the node that forwarded the packet selected me as MPR? (iAmMpr)
510      *
511      * Based on these conditions, the following cases can be distinguished:
512      *
513      * - Case 1: Packet coming in on an OLSR interface. What to
514      *   do with it on an OLSR interface?
515      *   Answer:
516      *   - Case 1.1: If the forwarding node is an OLSR neighbor that has *not*
517      *     selected me as MPR: don't forward the packet.
518      *   - Case 1.2: If the forwarding node is an OLSR neighbor that has selected
519      *     me as MPR: encapsulate and forward the packet.
520      *   - Case 1.3: If the forwarding node is not an OLSR neighbor: encapsulate
521      *     and forward the packet.
522      *     NOTE: Case 1.3 is a special case. In the perfect world, we expect to
523      *     see only OLSR-neighbors on OLSR-enabled interfaces. Sometimes, however,
524      *     ignorant users will connect a host not running OLSR, to a LAN in
525      *     which there are hosts running OLSR. Of course these ignorant users,
526      *     expecting magic, want to see their multicast packets being forwarded
527      *     through the network.
528      *
529      * - Case 2: Packet coming in on an OLSR interface. What to do with it on a
530      *   non-OLSR interface?
531      *   Answer: Forward it.
532      *
533      * - Case 3: Packet coming in on a non-OLSR interface. What to
534      *   do with it on an OLSR interface?
535      *   Answer: Encapsulate and forward it.
536      *
537      * - Case 4: Packet coming in on non-OLSR interface. What to do with it on a
538      *   non-OLSR interface?
539      *   Answer 1: nothing. Multicast routing between non-OLSR interfaces
540      *   is to be done by other protocols (e.g. PIM, DVMRP).
541      *   Answer 2 (better): Forward it.
542      */
543
544     if (isFromOlsrIntf && isToOlsrIntf)
545     {
546       /* Case 1: Forward from an OLSR interface to an OLSR interface */
547
548       if (isFromOlsrNeighbor && !iAmMpr)
549       {
550         /* Case 1.1 */
551         {
552 #ifndef NODEBUG
553           struct ipaddr_str buf;
554 #endif /* NODEBUG */
555           OLSR_PRINTF(
556             8,
557             "%s: --> not encap-forwarding on \"%s\": I am not selected as MPR by neighbor %s\n",
558             PLUGIN_NAME_SHORT,
559             walker->ifName,
560             olsr_ip_to_string(&buf, &src));
561         }    
562       }
563       else if (sllPkttype == PACKET_OUTGOING && intf == walker)
564       {
565         OLSR_PRINTF(
566           8,
567           "%s: --> not encap-forwarding on \"%s\": pkt was captured on that interface\n",
568           PLUGIN_NAME_SHORT,
569           walker->ifName);
570       }
571       else
572       {
573         /* Case 1.2 and 1.3 */
574         EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL);
575       }
576     } /* if (isFromOlsrIntf && isToOlsrIntf) */
577
578     else if (isFromOlsrIntf && !isToOlsrIntf)
579     {
580       /* Case 2: Forward from OLSR interface to non-OLSR interface */
581       ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded to non-OLSR interface");
582     } /* else if (isFromOlsrIntf && !isToOlsrIntf) */
583
584     else if (!isFromOlsrIntf && isToOlsrIntf)
585     {
586       /* Case 3: Forward from a non-OLSR interface to an OLSR interface.
587        * Encapsulate and forward packet. */
588       EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL);
589     } /* else if (!isFromOlsrIntf && isToOlsrIntf) */
590
591     else
592     {
593       /* Case 4: Forward from non-OLSR interface to non-OLSR interface. */
594
595       /* Don't forward on interface on which packet was received */
596       if (intf == walker)
597       {
598         OLSR_PRINTF(
599           8,
600           "%s: --> not forwarding on \"%s\": pkt was captured on that interface\n",
601           PLUGIN_NAME_SHORT,
602           walker->ifName);
603       }
604
605       else
606       {
607         ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded from non-OLSR to non-OLSR interface");
608       } /* if (intf == walker) */
609     } /* if */
610   } /* for */
611 } /* BmfPacketCaptured */
612
613 /* -------------------------------------------------------------------------
614  * Function   : BmfEncapsulationPacketReceived
615  * Description: Handle a received BMF-encapsulation packet
616  * Input      : intf - the network interface on which the packet was received
617  *              forwardedBy - the IP node that forwarded the packet to me
618  *              forwardedTo - the destination IP address of the encapsulation
619  *                packet, in case the packet was received promiscuously.
620  *                Pass NULL if the packet is received normally (unicast or
621  *                broadcast).
622  *              encapsulationUdpData - the encapsulating IP UDP data, containting
623  *                the BMF encapsulation header, followed by the encapsulated
624  *                IP packet
625  * Output     : none
626  * Return     : none
627  * Data Used  : BmfInterfaces
628  * ------------------------------------------------------------------------- */
629 static void BmfEncapsulationPacketReceived(
630   struct TBmfInterface* intf,
631   union olsr_ip_addr* forwardedBy,
632   union olsr_ip_addr* forwardedTo,
633   unsigned char* encapsulationUdpData)
634 {
635   int iAmMpr; /* True (1) if I am selected as MPR by 'forwardedBy' */
636   unsigned char* ipPacket; /* The encapsulated IP packet */
637   u_int16_t ipPacketLen; /* Length of the encapsulated IP packet */
638   struct ip* ipHeader; /* IP header inside the encapsulated IP packet */
639   union olsr_ip_addr mcSrc; /* Original source of the encapsulated multicast packet */
640   union olsr_ip_addr mcDst; /* Multicast destination of the encapsulated packet */
641   struct TEncapHeader* encapsulationHdr;
642   struct TBmfInterface* walker;
643 #ifndef NODEBUG
644   struct ipaddr_str mcSrcBuf, mcDstBuf, forwardedByBuf, forwardedToBuf;
645 #endif /* NODEBUG */
646   /* Are we talking to ourselves? */
647   if (if_ifwithaddr(forwardedBy) != NULL)
648   {
649     return;
650   }
651
652   /* Discard encapsulated packets received on a non-OLSR interface */
653   if (intf->olsrIntf == NULL)
654   {
655     return;
656   }
657
658   /* Retrieve details about the encapsulated IP packet */
659   ipPacket = GetIpPacket(encapsulationUdpData);
660   ipPacketLen = GetIpTotalLength(ipPacket);
661   ipHeader = GetIpHeader(encapsulationUdpData);
662
663   mcSrc.v4 = ipHeader->ip_src;
664   mcDst.v4 = ipHeader->ip_dst;
665
666   /* Increase counter */
667   intf->nBmfPacketsRx++;
668
669   /* Beware: not possible to call olsr_ip_to_string more than 4 times in same printf */
670   OLSR_PRINTF(
671     8,
672     "%s: encapsulated pkt of %ld bytes incoming on \"%s\": %s->%s, forwarded by %s to %s\n",
673     PLUGIN_NAME_SHORT,
674     (long)ipPacketLen,
675     intf->ifName,
676     olsr_ip_to_string(&mcSrcBuf, &mcSrc),
677     olsr_ip_to_string(&mcDstBuf, &mcDst),
678     olsr_ip_to_string(&forwardedByBuf, forwardedBy),
679     forwardedTo != NULL ? olsr_ip_to_string(&forwardedToBuf, forwardedTo) : "me");
680
681   /* Get encapsulation header */
682   encapsulationHdr = (struct TEncapHeader*) encapsulationUdpData;
683
684   /* Verify correct format of BMF encapsulation header */
685   if (encapsulationHdr->type != BMF_ENCAP_TYPE ||
686       encapsulationHdr->len != BMF_ENCAP_LEN ||
687       ntohs(encapsulationHdr->reserved != 0))
688   {
689     OLSR_PRINTF(
690       8,
691       "%s: --> discarding: format of BMF encapsulation header not recognized\n",
692       PLUGIN_NAME_SHORT);
693     return;
694   }
695
696   /* Check if this packet was seen recently */
697   if (CheckAndMarkRecentPacket(ntohl(encapsulationHdr->crc32)))
698   {
699     /* Increase counter */
700     intf->nBmfPacketsRxDup++;
701
702     OLSR_PRINTF(
703       8,
704       "%s: --> discarding: packet is duplicate\n",
705       PLUGIN_NAME_SHORT);
706     return;
707   }
708
709   if (EtherTunTapFd >= 0)
710   {
711     /* Unpack the encapsulated IP packet and deliver it locally, by sending
712      * a copy into the local IP stack via the EtherTunTap interface */
713
714     union olsr_ip_addr broadAddr;
715     int nBytesToWrite, nBytesWritten;
716     unsigned char* bufferToWrite;
717
718     /* If the encapsulated IP packet is a local broadcast packet,
719      * update its destination address to match the subnet of the EtherTunTap
720      * interface */
721     broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);
722     CheckAndUpdateLocalBroadcast(ipPacket, &broadAddr);
723
724     bufferToWrite = ipPacket;
725     nBytesToWrite = ipPacketLen;
726
727     /* Write the packet into the EtherTunTap interface for local delivery */
728     nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite);
729     if (nBytesWritten != nBytesToWrite)
730     {
731       BmfPError("write() error forwarding encapsulated pkt on \"%s\"", EtherTunTapIfName);
732     }
733     else
734     {
735       OLSR_PRINTF(
736         8,
737         "%s: --> unpacked and delivered locally on \"%s\"\n",
738         PLUGIN_NAME_SHORT,
739         EtherTunTapIfName);
740     }
741   } /* if (EtherTunTapFd >= 0) */
742
743   /* Check if I am MPR for the forwarder */
744   iAmMpr = (olsr_lookup_mprs_set(MainAddressOf(forwardedBy)) != NULL);
745
746   /* Check with each network interface what needs to be done on it */
747   for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
748   {
749     /* What to do with the packet on a non-OLSR interface? Unpack
750      * encapsulated packet, and forward it.
751      *
752      * What to do with the packet on an OLSR interface? Forward it only
753      * if the forwarding node has selected us as MPR (iAmMpr).
754      *
755      * Note that the packet is always coming in on an OLSR interface, because
756      * it is an encapsulated BMF packet. */
757
758     /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */
759     if (walker->olsrIntf == NULL)
760     {
761       ForwardPacket (walker, ipPacket, ipPacketLen, "unpacked and forwarded to non-OLSR interface");
762     } /* if (walker->olsrIntf == NULL) */
763
764     /* To an OLSR interface: forward the packet, but only if this node is
765      * selected as MPR by the forwarding node */
766     else if (iAmMpr)
767     {
768       EncapsulateAndForwardPacket (
769         walker,
770         encapsulationUdpData,
771         &mcSrc,
772         forwardedBy,
773         forwardedTo);
774     }  /* else if (iAmMpr) */
775
776     else /* walker->olsrIntf != NULL && !iAmMpr */
777     {
778 #ifndef NODEBUG
779       struct ipaddr_str buf;
780 #endif /*NODEBUG */
781       /* 'walker' is an OLSR interface, but I am not selected as MPR. In that
782        * case, don't forward. */
783       OLSR_PRINTF(
784         8,
785         "%s: --> not forwarding on \"%s\": I am not selected as MPR by %s\n",
786         PLUGIN_NAME_SHORT,
787         walker->ifName,
788         olsr_ip_to_string(&buf, forwardedBy));
789     } /* else */
790   } /* for */
791 } /* BmfEncapsulationPacketReceived */
792
793 /* -------------------------------------------------------------------------
794  * Function   : BmfTunPacketCaptured
795  * Description: Handle an IP packet, captured outgoing on the tuntap interface
796  * Input      : encapsulationUdpData - space for the encapsulation header, followed by
797  *                the captured outgoing IP packet
798  * Output     : none
799  * Return     : none
800  * Data Used  : none
801  * Notes      : The packet is assumed to be captured on a socket of family
802  *              PF_PACKET and type SOCK_DGRAM (cooked).
803  * ------------------------------------------------------------------------- */
804 static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData)
805 {
806   union olsr_ip_addr srcIp;
807   union olsr_ip_addr dstIp;
808   union olsr_ip_addr broadAddr;
809   struct TBmfInterface* walker;
810   unsigned char* ipPacket;
811   u_int16_t ipPacketLen;
812   struct ip* ipHeader;
813   u_int32_t crc32;
814   struct TEncapHeader* encapHdr;
815 #ifndef NODEBUG
816   struct ipaddr_str srcIpBuf, dstIpBuf;
817 #endif /* NODEBUG */
818   ipPacket = GetIpPacket(encapsulationUdpData);
819   ipPacketLen = GetIpTotalLength(ipPacket);
820   ipHeader = GetIpHeader(encapsulationUdpData);
821
822   dstIp.v4 = ipHeader->ip_dst;
823   broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);
824
825   /* Only forward multicast packets. If configured, also forward local broadcast packets */
826   if (IsMulticast(&dstIp) ||
827       (EnableLocalBroadcast != 0 && ipequal(&dstIp, &broadAddr)))
828   {
829     /* continue */
830   }
831   else
832   {
833     return;
834   }
835
836   srcIp.v4 = ipHeader->ip_src;
837
838   OLSR_PRINTF(
839     8,
840     "%s: outgoing pkt of %ld bytes captured on tuntap interface \"%s\": %s->%s\n",
841     PLUGIN_NAME_SHORT,
842     (long)ipPacketLen,
843     EtherTunTapIfName,
844     olsr_ip_to_string(&srcIpBuf, &srcIp),
845     olsr_ip_to_string(&dstIpBuf, &dstIp));
846
847   /* Calculate packet fingerprint */
848   crc32 = PacketCrc32(ipPacket, ipPacketLen);
849
850   /* Check if this packet was seen recently */
851   if (CheckAndMarkRecentPacket(crc32))
852   {
853     OLSR_PRINTF(
854       8,
855       "%s: --> discarding: packet is duplicate\n",
856       PLUGIN_NAME_SHORT);
857     return;
858   }
859
860   /* Compose encapsulation header */
861   encapHdr = (struct TEncapHeader*) encapsulationUdpData;
862   memset (encapHdr, 0, ENCAP_HDR_LEN);
863   encapHdr->type = BMF_ENCAP_TYPE;
864   encapHdr->len = BMF_ENCAP_LEN;
865   encapHdr->reserved = 0;
866   encapHdr->crc32 = htonl(crc32);
867
868   /* Check with each network interface what needs to be done on it */
869   for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
870   {
871     /* Is the forwarding interface OLSR-enabled? */
872     if (walker->olsrIntf != NULL)
873     {
874       /* On an OLSR interface: encapsulate and forward packet. */
875       EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL);
876     }
877     else
878     {
879       /* On a non-OLSR interface: what to do?
880        * Answer 1: nothing. Multicast routing between non-OLSR interfaces
881        * is to be done by other protocols (e.g. PIM, DVMRP).
882        * Answer 2 (better): Forward it. */
883       ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded from non-OLSR to non-OLSR interface");
884     } /* if */
885   } /* for */
886 } /* BmfTunPacketCaptured */
887
888 /* -------------------------------------------------------------------------
889  * Function   : DoBmf
890  * Description: Wait (blocking) for IP packets, then call the handler for each
891  *              received packet
892  * Input      : none
893  * Output     : none
894  * Return     : none
895  * Data Used  : BmfInterfaces
896  * ------------------------------------------------------------------------- */
897 void
898 BMF_handle_captureFd(int skfd, void *data, unsigned int flags __attribute__ ((unused))) {
899   unsigned char rxBuffer[BMF_BUFFER_SIZE];
900   struct TBmfInterface* walker = data;
901   struct sockaddr_ll pktAddr;
902   socklen_t addrLen = sizeof(pktAddr);
903   int nBytes;
904   unsigned char* ipPacket;
905
906   /* Receive the captured Ethernet frame, leaving space for the BMF
907    * encapsulation header */
908   ipPacket = GetIpPacket(rxBuffer);
909   nBytes = recvfrom(
910     skfd,
911     ipPacket,
912     BMF_BUFFER_SIZE - ENCAP_HDR_LEN,
913     0,
914     (struct sockaddr*)&pktAddr,
915     &addrLen);
916   if (nBytes < 0)
917   {
918     BmfPError("recvfrom() error on \"%s\"", walker->ifName);
919     return;
920   } /* if (nBytes < 0) */
921
922   /* Check if the number of received bytes is large enough for an IP
923    * packet which contains at least a minimum-size IP header.
924    * Note: There is an apparent bug in the packet socket implementation in
925    * combination with VLAN interfaces. On a VLAN interface, the value returned
926    * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
927    * returned on a non-VLAN interface, for the same ethernet frame. */
928   if (nBytes < (int)sizeof(struct ip))
929   {
930     olsr_printf(
931       1,
932       "%s: captured frame too short (%d bytes) on \"%s\"\n",
933       PLUGIN_NAME,
934       nBytes,
935       walker->ifName);
936     return;
937   }
938
939   if (pktAddr.sll_pkttype == PACKET_OUTGOING ||
940       pktAddr.sll_pkttype == PACKET_MULTICAST ||
941       pktAddr.sll_pkttype == PACKET_BROADCAST)
942   {
943     /* A multicast or broadcast packet was captured */
944
945     BmfPacketCaptured(walker, pktAddr.sll_pkttype, rxBuffer);
946
947   } /* if (pktAddr.sll_pkttype == ...) */
948 }
949
950 void
951 BMF_handle_listeningFd(int skfd, void *data, unsigned int flags __attribute__ ((unused))) {
952   unsigned char rxBuffer[BMF_BUFFER_SIZE];
953   struct TBmfInterface* walker = data;
954   struct sockaddr_ll pktAddr;
955   socklen_t addrLen = sizeof(pktAddr);
956   int nBytes;
957   int minimumLength;
958   struct ip* ipHeader;
959   unsigned int headerLength;
960   struct udphdr* udpHeader;
961   u_int16_t destPort;
962   union olsr_ip_addr forwardedBy;
963   union olsr_ip_addr forwardedTo;
964
965   /* Heard a BMF packet */
966
967   nBytes = recvfrom(
968     skfd,
969     rxBuffer,
970     BMF_BUFFER_SIZE,
971     0,
972     (struct sockaddr*)&pktAddr,
973     &addrLen);
974   if (nBytes < 0)
975   {
976     BmfPError("recvfrom() error on \"%s\"", walker->ifName);
977     return;
978   } /* if (nBytes < 0) */
979
980   /* Check if the received packet is actually directed to another
981    * node on the LAN */
982   if (pktAddr.sll_pkttype != PACKET_OTHERHOST)
983   {
984     /* No, the packet is directed to this node. In that case it will
985      * be, or will already have been received, via the encapsulating
986      * socket. Discard it here. */
987     return;
988   } /* if (pktAddr.sll_pkttype ...) */
989
990   /* Check if the received packet is UDP - BMF port */
991   ipHeader = (struct ip*) ARM_NOWARN_ALIGN(rxBuffer);
992   if (ipHeader->ip_p != SOL_UDP)
993   {
994     /* Not UDP */
995     return;
996   }
997
998   /* Check if the number of received bytes is large enough for a minimal BMF
999    * encapsulation packet, at least:
1000    * - the IP header of the encapsulation IP packet
1001    * - the UDP header of the encapsulation IP packet
1002    * - the encapsulation header
1003    * - a minimum IP header inside the encapsulated packet
1004    * Note: on a VLAN interface, the value returned by 'recvfrom' may (but need
1005    * not) be 4 (bytes) larger than the value returned on a non-VLAN interface, for
1006    * the same ethernet frame. */
1007   headerLength = GetIpHeaderLength(rxBuffer);
1008   minimumLength =
1009     headerLength +
1010     sizeof(struct udphdr) +
1011     ENCAP_HDR_LEN +
1012     sizeof(struct ip);
1013   if (minimumLength > BMF_BUFFER_SIZE) {
1014     olsr_printf(1, "%s: IP header length %u is too large\n",
1015         PLUGIN_NAME, headerLength);
1016     return;
1017   }
1018   if (nBytes < minimumLength)
1019   {
1020     olsr_printf(
1021       1,
1022       "%s: captured a too short encapsulation packet (%d bytes) on \"%s\"\n",
1023       PLUGIN_NAME,
1024       nBytes,
1025       walker->ifName);
1026
1027     return;
1028   }
1029
1030   udpHeader = (struct udphdr*) ARM_NOWARN_ALIGN((rxBuffer + headerLength));
1031 #ifdef __GLIBC__
1032   destPort = ntohs(udpHeader->dest);
1033 #else
1034   destPort = ntohs(udpHeader->uh_dport);
1035 #endif
1036   if (destPort != BMF_ENCAP_PORT)
1037   {
1038     /* Not BMF */
1039     return;
1040   }
1041
1042   forwardedBy.v4 = ipHeader->ip_src;
1043   forwardedTo.v4 = ipHeader->ip_dst;
1044   BmfEncapsulationPacketReceived(
1045     walker,
1046     &forwardedBy,
1047     &forwardedTo,
1048     rxBuffer + headerLength + sizeof(struct udphdr));
1049
1050 }
1051
1052 void
1053 BMF_handle_encapsulatingFd(int skfd, void *data, unsigned int flags __attribute__ ((unused))) {
1054   unsigned char rxBuffer[BMF_BUFFER_SIZE];
1055   struct TBmfInterface* walker = data;
1056   struct sockaddr_in from;
1057   socklen_t fromLen = sizeof(from);
1058   int nBytes;
1059   int minimumLength;
1060   union olsr_ip_addr forwardedBy;
1061
1062   /* An encapsulated packet was received */
1063   nBytes = recvfrom(
1064     skfd,
1065     rxBuffer,
1066     BMF_BUFFER_SIZE,
1067     0,
1068     (struct sockaddr*)&from,
1069     &fromLen);
1070   if (nBytes < 0)
1071   {
1072     BmfPError("recvfrom() error on \"%s\"", walker->ifName);
1073
1074     return;
1075   } /* if (nBytes < 0) */
1076
1077   forwardedBy.v4 = from.sin_addr;
1078
1079   /* Check if the number of received bytes is large enough for a minimal BMF
1080    * encapsulation packet, at least:
1081    * - the encapsulation header
1082    * - a minimum IP header inside the encapsulated packet */
1083   minimumLength =
1084     ENCAP_HDR_LEN +
1085     sizeof(struct ip);
1086   if (nBytes < minimumLength)
1087   {
1088     struct ipaddr_str buf;
1089     olsr_printf(
1090       1,
1091       "%s: received a too short encapsulation packet (%d bytes) from %s on \"%s\"\n",
1092       PLUGIN_NAME,
1093       nBytes,
1094       olsr_ip_to_string(&buf, &forwardedBy),
1095       walker->ifName);
1096     return;
1097   }
1098
1099   /* Unfortunately, the recvfrom call does not return the destination
1100    * of the encapsulation packet (the destination may be either the
1101    * my unicast or my local broadcast address). Therefore we fill in 'NULL'
1102    * for the 'forwardedTo' parameter. */
1103   BmfEncapsulationPacketReceived(walker, &forwardedBy, NULL, rxBuffer);
1104 }
1105
1106 void
1107 BMF_handle_tuntapFd(int skfd __attribute__ ((unused)),
1108     void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused))) {
1109   unsigned char rxBuffer[BMF_BUFFER_SIZE];
1110   int nBytes;
1111   unsigned char* ipPacket;
1112   unsigned char* bufferToRead;
1113   size_t nBytesToRead;
1114
1115   /* Receive the packet, leaving space for the BMF encapsulation header */
1116   ipPacket = GetIpPacket(rxBuffer);
1117     
1118   bufferToRead = ipPacket;
1119   nBytesToRead = BMF_BUFFER_SIZE - ENCAP_HDR_LEN;
1120
1121   nBytes = read(EtherTunTapFd, bufferToRead, nBytesToRead);
1122   if (nBytes < 0)
1123   {
1124     BmfPError("recvfrom() error on \"%s\"", EtherTunTapIfName);
1125     return;
1126   }
1127
1128   /* Check if the number of received bytes is large enough for an IP
1129    * packet which contains at least a minimum-size IP header */
1130   if (nBytes < (int)sizeof(struct ip))
1131   {
1132     olsr_printf(
1133       1,
1134       "%s: captured packet too short (%d bytes) on \"%s\"\n",
1135       PLUGIN_NAME,
1136       nBytes,
1137       EtherTunTapIfName);
1138     return;
1139   }
1140
1141   BmfTunPacketCaptured(rxBuffer);
1142 }
1143
1144 /* -------------------------------------------------------------------------
1145  * Function   : InterfaceChange
1146  * Description: Callback function passed to OLSRD for it to call whenever a
1147  *              network interface has been added, removed or updated
1148  * Input      : if_index - index of the interface
1149  *              interf - the network interface to deal with
1150  *                       (might be NULL for non-OLSR interfaces)
1151  *              action - indicates if the specified network interface was
1152  *                added, removed or updated.
1153  * Output     : none
1154  * Data Used  : none
1155  * ------------------------------------------------------------------------- */
1156 void InterfaceChange(int if_index __attribute__((unused)), struct interface_olsr * interf,
1157     enum olsr_ifchg_flag action)
1158 {
1159   if (interf == NULL) {
1160     return;
1161   }
1162   switch (action)
1163   {
1164   case (IFCHG_IF_ADD):
1165     /* If the new interfaces is ready, completely restart BMF. In this way
1166      * the IP address for the BMF network interface is correctly re-evaluated,
1167      * and a default route for multicast traffic is (re)established. 
1168      * Thanks to Daniele Lacamera for finding and solving this bug. */
1169     CloseBmf();
1170     InitBmf(NULL);
1171     olsr_printf(1, "%s: interface %s added\n", PLUGIN_NAME, interf->int_name);
1172     break;
1173
1174   case (IFCHG_IF_REMOVE):
1175     /* We cannot just remove the interface, because the receive-thread is likely
1176      * to be waiting in select(...) for packets coming in via the interface.
1177      * Therefore we first close BMF (CloseBmf()), interrupting and kiling the
1178      * receive-thread so that it is safe to remove this (and all other)
1179      * interfaces. After that, BMF is re-started (InitBmf(interf)). */
1180     CloseBmf();
1181     InitBmf(interf);
1182     olsr_printf(1, "%s: interface %s removed\n", PLUGIN_NAME, interf->int_name);
1183     break;
1184
1185   case (IFCHG_IF_UPDATE):
1186     olsr_printf(1, "%s: interface %s updated\n", PLUGIN_NAME, interf->int_name);
1187     break;
1188       
1189   default:
1190     olsr_printf(
1191       1,
1192       "%s: interface %s: error - unknown action (%d)\n",
1193       PLUGIN_NAME,
1194       interf->int_name, action);
1195     break;
1196   }
1197 } /* InterfaceChange */
1198
1199
1200 /* -------------------------------------------------------------------------
1201  * Function   : SetFanOutLimit
1202  * Description: Overrule the default fan out limit value (2)
1203  * Input      : value - fan out limit value (0...MAX_UNICAST_NEIGHBORS)
1204  *              data - not used
1205  *              addon - not used
1206  * Output     : none
1207  * Return     : success (0) or fail (1)
1208  * Data Used  : FanOutLimit
1209  * ------------------------------------------------------------------------- */
1210 int SetFanOutLimit(
1211   const char* value,
1212   void* data __attribute__((unused)),
1213   set_plugin_parameter_addon addon __attribute__((unused)))
1214 {
1215   if (set_plugin_int(value, &FanOutLimit, addon) == 0)
1216   {
1217     /* Extra check if within range */
1218     if (FanOutLimit >= 0 && FanOutLimit <= MAX_UNICAST_NEIGHBORS)
1219     {
1220       return 0;
1221     }
1222   }
1223   return 1;
1224 }
1225
1226 /* -------------------------------------------------------------------------
1227  * Function   : InitBmf
1228  * Description: Initialize the BMF plugin
1229  * Input      : skipThisIntf - specifies which network interface should not
1230  *              be enabled for BMF. Pass NULL if not applicable.
1231  * Output     : none
1232  * Return     : fail (0) or success (1)
1233  * Data Used  : BmfThreadRunning, BmfThread
1234  * ------------------------------------------------------------------------- */
1235 int InitBmf(struct interface_olsr * skipThisIntf)
1236 {
1237   CreateBmfNetworkInterfaces(skipThisIntf);
1238
1239   if (EtherTunTapFd >= 0)
1240   {
1241     /* Deactivate IP spoof filter for EtherTunTap interface */
1242     DeactivateSpoofFilter();
1243
1244     /* If the BMF network interface has a sensible IP address, it is a good idea
1245      * to route all multicast traffic through that interface */
1246     if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP)
1247     {
1248       AddMulticastRoute();
1249     }
1250   }
1251
1252   return 1;
1253 } /* InitBmf */
1254
1255 /* -------------------------------------------------------------------------
1256  * Function   : CloseBmf
1257  * Description: Close the BMF plugin and clean up
1258  * Input      : none
1259  * Output     : none
1260  * Return     : none
1261  * Data Used  : BmfThread
1262  * ------------------------------------------------------------------------- */
1263 void CloseBmf(void)
1264 {
1265   if (EtherTunTapFd >= 0)
1266   {
1267     /* If there is a multicast route, try to delete it first */
1268     DeleteMulticastRoute();
1269
1270     /* Restore IP spoof filter for EtherTunTap interface */
1271     RestoreSpoofFilter();
1272   }
1273
1274   /* Clean up after the BmfThread has been killed */
1275   CloseBmfNetworkInterfaces();
1276 } /* CloseBmf */
1277