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