* upgrade to olsr-bmf-1.5
[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 <pthread.h> /* pthread_t, pthread_create() */
54 #include <signal.h> /* sigset_t, sigfillset(), sigdelset(), SIGINT */
55 #include <netinet/ip.h> /* struct ip */
56 #include <netinet/udp.h> /* struct udphdr */
57
58 /* OLSRD includes */
59 #include "defs.h" /* olsr_cnf, OLSR_PRINTF */
60 #include "olsr.h" /* olsr_printf */
61 #include "scheduler.h" /* olsr_register_scheduler_event */
62 #include "mid_set.h" /* mid_lookup_main_addr() */
63 #include "mpr_selector_set.h" /* olsr_lookup_mprs_set() */
64 #include "link_set.h" /* get_best_link_to_neighbor() */
65
66 /* Plugin includes */
67 #include "NetworkInterfaces.h" /* TBmfInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */
68 #include "Address.h" /* IsMulticast() */
69 #include "Packet.h" /* ETH_TYPE_OFFSET, IFHWADDRLEN etc. */
70 #include "PacketHistory.h" /* InitPacketHistory() */
71
72 static pthread_t BmfThread;
73 static int BmfThreadRunning = 0;
74
75 /* -------------------------------------------------------------------------
76  * Function   : BmfPError
77  * Description: Prints an error message at OLSR debug level 1.
78  *              First the plug-in name is printed. Then (if format is not NULL
79  *              and *format is not empty) the arguments are printed, followed
80  *              by a colon and a blank. Then the message and a new-line.
81  * Input      : format, arguments
82  * Output     : none
83  * Return     : none
84  * Data Used  : none
85  * ------------------------------------------------------------------------- */
86 void BmfPError(char* format, ...)
87 {
88 #define MAX_STR_DESC 255
89   char* strErr = strerror(errno);
90   char strDesc[MAX_STR_DESC];
91
92   /* Rely on short-circuit boolean evaluation */
93   if (format == NULL || *format == '\0')
94   {
95     olsr_printf(1, "%s: %s\n", PLUGIN_NAME, strErr);
96   }
97   else
98   {
99     va_list arglist;
100
101     olsr_printf(1, "%s: ", PLUGIN_NAME);
102
103     va_start(arglist, format);
104     vsnprintf(strDesc, MAX_STR_DESC, format, arglist);
105     va_end(arglist);
106
107     strDesc[MAX_STR_DESC - 1] = '\0'; /* Ensures null termination */
108
109     olsr_printf(1, "%s: %s\n", strDesc, strErr);
110   }
111 } /* BmfPError */
112
113 /* -------------------------------------------------------------------------
114  * Function   : MainAddressOf
115  * Description: Lookup the main address of a node
116  * Input      : ip - IP address of the node
117  * Output     : none
118  * Return     : The main IP address of the node
119  * Data Used  : none
120  * ------------------------------------------------------------------------- */
121 union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip)
122 {
123   union olsr_ip_addr* result;
124
125   /* TODO: mid_lookup_main_addr() is not thread-safe! */
126   result = mid_lookup_main_addr(ip);
127   if (result == NULL)
128   {
129     result = ip;
130   }
131   return result;
132 } /* MainAddressOf */
133
134 /* -------------------------------------------------------------------------
135  * Function   : EncapsulateAndForwardPacket
136  * Description: Encapsulate a captured raw IP packet and forward it
137  * Input      : intf - the network interface on which to forward the packet
138  *              encapsulationUdpData - The encapsulation header, followed by
139  *                the encapsulated IP packet
140  * Output     : none
141  * Return     : none
142  * Data Used  : none
143  * ------------------------------------------------------------------------- */
144 static void EncapsulateAndForwardPacket(
145   struct TBmfInterface* intf,
146   unsigned char* encapsulationUdpData)
147 {
148   /* The packet */
149   u_int16_t udpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);
150
151   /* The next destination(s) */
152   struct TBestNeighbors bestNeighborLinks;
153   int nPossibleNeighbors;
154   struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
155
156   int nPacketsToSend;
157   int nBytesWritten;
158   int i;
159
160   /* Retrieve at most two best neigbors to forward the packet to */
161   bestNeighborLinks = GetBestTwoNeighbors(intf, NULL, NULL, NULL, &nPossibleNeighbors);
162
163   if (nPossibleNeighbors <= 0)
164   {
165     OLSR_PRINTF(
166       8,
167       "%s: --> not encap-forwarding on \"%s\": there is no neighbor that needs my retransmission\n",
168       PLUGIN_NAME_SHORT,
169       intf->ifName);
170     return;
171   }
172
173   /* Compose destination of encapsulation packet */
174
175   memset(&forwardTo, 0, sizeof(forwardTo));
176   forwardTo.sin_family = AF_INET;
177   forwardTo.sin_port = htons(BMF_ENCAP_PORT);
178
179   /* Start by filling in the local broadcast address */
180   COPY_IP(&forwardTo.sin_addr.s_addr, &intf->broadAddr);
181
182   /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
183    *   packet (to the best neighbor).
184    * - If the BMF mechanism is BM_BROADCAST,
185    *   - send one unicast packet if there is one possible neighbor,
186    *   - send two unicast packets if there are two possible neighbors, and
187    *   - only if there are more than two possible neighbors, then send an
188    *     (WLAN-air-expensive, less reliable) broadcast packet. */
189   if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors < 2)
190   {
191     nPacketsToSend = 1;
192   }
193   else /* BmfMechanism == BM_BROADCAST && nPossibleNeighbors >= 2 */
194   {
195     nPacketsToSend = 2;
196   }
197
198   for (i = 0; i < nPacketsToSend; i++)
199   {
200     if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors <= 2)
201     {
202       COPY_IP(&forwardTo.sin_addr.s_addr, &bestNeighborLinks.links[i]->neighbor_iface_addr);
203     }
204
205     /* Forward the BMF packet via the encapsulation socket */
206     nBytesWritten = sendto(
207       intf->encapsulatingSkfd,
208       encapsulationUdpData,
209       udpDataLen,
210       MSG_DONTROUTE,
211       (struct sockaddr*) &forwardTo,
212       sizeof(forwardTo));                   
213
214     /* Evaluate and display result */
215     if (nBytesWritten != udpDataLen)
216     {
217       BmfPError("sendto() error forwarding pkt on \"%s\"", intf->ifName);
218     }
219     else
220     {
221       /* Increase counter */
222       intf->nBmfPacketsTx++;
223
224       OLSR_PRINTF(
225         8,
226         "%s: --> encapsulated and forwarded on \"%s\" to %s\n",
227         PLUGIN_NAME_SHORT,
228         intf->ifName,
229         inet_ntoa(forwardTo.sin_addr));
230     } /* if (nBytesWritten != udpDataLen) */
231   } /* for */
232 } /* EncapsulateAndForwardPacket */
233
234 /* -------------------------------------------------------------------------
235  * Function   : BmfPacketCaptured
236  * Description: Handle a captured IP packet
237  * Input      : intf - the network interface on which the packet was captured
238  *              sllPkttype - the type of packet. Either PACKET_OUTGOING,
239  *                PACKET_BROADCAST or PACKET_MULTICAST.
240  *              encapsulationUdpData - space for the encapsulation header, followed by
241  *                the captured IP packet
242  * Output     : none
243  * Return     : none
244  * Data Used  : BmfInterfaces
245  * Notes      : The IP packet is assumed to be captured on a socket of family
246  *              PF_PACKET and type SOCK_DGRAM (cooked).
247  * ------------------------------------------------------------------------- */
248 static void BmfPacketCaptured(
249   struct TBmfInterface* intf,
250   unsigned char sllPkttype,
251   unsigned char* encapsulationUdpData)
252 {
253   union olsr_ip_addr src; /* Source IP address in captured packet */
254   union olsr_ip_addr dst; /* Destination IP address in captured packet */
255   union olsr_ip_addr* origIp; /* Main OLSR address of source of captured packet */
256   struct TBmfInterface* walker;
257   int isFromOlsrIntf;
258   int isFromOlsrNeighbor;
259   int iAmMpr;
260   unsigned char* ipPacket; /* The captured IP packet... */
261   u_int16_t ipPacketLen; /* ...and its length */
262   struct ip* ipHeader; /* The IP header inside the captured IP packet */
263   u_int32_t crc32;
264   struct TEncapHeader* encapHdr;
265
266   ipHeader = GetIpHeader(encapsulationUdpData);
267
268   COPY_IP(&dst, &ipHeader->ip_dst);
269
270   /* Only forward multicast packets. If configured, also forward local broadcast packets */
271   if (IsMulticast(&dst) ||
272       (EnableLocalBroadcast != 0 && COMP_IP(&dst, &intf->broadAddr)))
273   {
274     /* continue */
275   }
276   else
277   {
278     return;
279   }
280
281   ipPacket = GetIpPacket(encapsulationUdpData);
282
283   /* Don't forward fragments of IP packets. Also, don't forward OLSR packets (UDP
284    * port 698) and BMF encapsulated packets */
285   if (IsIpFragment(ipPacket) || IsOlsrOrBmfPacket(ipPacket))
286   {
287     return;
288   }
289
290   /* Increase counter */
291   intf->nBmfPacketsRx++;
292
293   /* Check if the frame is captured on an OLSR-enabled interface */
294   isFromOlsrIntf = (intf->olsrIntf != NULL);
295
296   /* Retrieve the length of the captured packet */
297   ipPacketLen = GetIpTotalLength(ipPacket);
298
299   COPY_IP(&src, &ipHeader->ip_src);
300   OLSR_PRINTF(
301     8,
302     "%s: %s pkt of %ld bytes captured on %s interface \"%s\": %s->%s\n",
303     PLUGIN_NAME_SHORT,
304     sllPkttype == PACKET_OUTGOING ? "outgoing" : "incoming",
305     (long)ipPacketLen,
306     isFromOlsrIntf ? "OLSR" : "non-OLSR",
307     intf->ifName,
308     olsr_ip_to_string(&src),
309     olsr_ip_to_string(&dst));
310
311   /* Lookup main address of source in the MID table of OLSR */
312   origIp = MainAddressOf(&src);
313
314   /* Calculate packet fingerprint */
315   crc32 = PacketCrc32(ipPacket, ipPacketLen);
316
317   /* Check if this packet was seen recently */
318   if (CheckAndMarkRecentPacket(crc32))
319   {
320     /* Increase counter */
321     intf->nBmfPacketsRxDup++;
322
323     OLSR_PRINTF(
324       8,
325       "%s: --> discarding: packet is duplicate\n",
326       PLUGIN_NAME_SHORT);
327     return;
328   }
329
330   /* Compose encapsulation header */
331   encapHdr = (struct TEncapHeader*) encapsulationUdpData;
332   memset (encapHdr, 0, ENCAP_HDR_LEN);
333   encapHdr->type = BMF_ENCAP_TYPE;
334   encapHdr->len = BMF_ENCAP_LEN;
335   encapHdr->reserved = 0;
336   encapHdr->crc32 = htonl(crc32);
337
338   /* Check if the frame is captured on an OLSR interface from an OLSR neighbor.
339    * TODO1: get_best_link_to_neighbor() is not thread-safe.
340    * TODO2: get_best_link_to_neighbor() may be very CPU-expensive, a simpler call
341    * would do here (something like 'get_any_link_to_neighbor()'). */
342   isFromOlsrNeighbor =
343     (isFromOlsrIntf /* The frame is captured on an OLSR interface... */
344     && get_best_link_to_neighbor(origIp) != NULL); /* ...from an OLSR neighbor */ 
345
346   /* Check with OLSR if I am MPR for that neighbor */
347   /* TODO: olsr_lookup_mprs_set() is not thread-safe! */
348   iAmMpr = olsr_lookup_mprs_set(origIp) != NULL;
349
350   /* Check with each network interface what needs to be done on it */
351   for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
352   {
353     /* Is the forwarding interface OLSR-enabled? */
354     int isToOlsrIntf = (walker->olsrIntf != NULL);
355
356     /* Depending on certain conditions, we decide whether or not to forward
357      * the packet, and if it is forwarded, in which form (encapsulated
358      * or not, TTL decreased or not). These conditions are:
359      * - is the packet is coming in on an OLSR interface or not? (isFromOlsrIntf)
360      * - is the packet going out on an OLSR interface or not? (isToOlsrIntf)
361      * - if the packet if coming in on an OLSR interface:
362      *   - is the node that forwarded the packet my OLSR-neighbor? (isFromOlsrNeighbor)
363      *   - has the node that forwarded the packet selected me as MPR? (iAmMpr)
364      *
365      * Based on these conditions, the following cases can be distinguished:
366      *
367      * - Case 1: Packet coming in on an OLSR interface. What to
368      *   do with it on an OLSR interface?
369      *   Answer:
370      *   - Case 1.1: If the forwarding node is an OLSR neighbor that has *not*
371      *     selected me as MPR: don't forward the packet.
372      *   - Case 1.2: If the forwarding node is an OLSR neighbor that has selected
373      *     me as MPR: encapsulate and forward the packet.
374      *   - Case 1.3: If the forwarding node is not an OLSR neighbor: encapsulate
375      *     and forward the packet.
376      *     NOTE: Case 1.3 is a special case. In the perfect world, we expect to
377      *     see only OLSR-neighbors on OLSR-enabled interfaces. Sometimes, however,
378      *     ignorant users will connect a host not running OLSR, to a LAN in
379      *     which there are hosts running OLSR. Of course these ignorant users,
380      *     expecting magic, want to see their multicast packets being forwarded
381      *     through the network.
382      *
383      * - Case 2: Packet coming in on an OLSR interface. What to do with it on a
384      *   non-OLSR interface?
385      *   Answer: Forward it.
386      *
387      * - Case 3: Packet coming in on a non-OLSR interface. What to
388      *   do with it on an OLSR interface?
389      *   Answer: Encapsulate and forward it.
390      *
391      * - Case 4: Packet coming in on non-OLSR interface. What to do with it on a
392      *   non-OLSR interface?
393      *   Answer 1: nothing. Multicast routing between non-OLSR interfaces
394      *   is to be done by other protocols (e.g. PIM, DVMRP).
395      *   Answer 2 (better): Forward it.
396      */
397
398     if (isFromOlsrIntf && isToOlsrIntf)
399     {
400       /* Case 1: Forward from an OLSR interface to an OLSR interface */
401
402       if (isFromOlsrNeighbor && !iAmMpr)
403       {
404         /* Case 1.1 */
405         {
406           OLSR_PRINTF(
407             8,
408             "%s: --> not encap-forwarding on \"%s\": I am not selected as MPR by neighbor %s\n",
409             PLUGIN_NAME_SHORT,
410             walker->ifName,
411             olsr_ip_to_string(&src));
412         }    
413       }
414       else if (sllPkttype == PACKET_OUTGOING && intf == walker)
415       {
416         OLSR_PRINTF(
417           8,
418           "%s: --> not encap-forwarding on \"%s\": pkt was captured on that interface\n",
419           PLUGIN_NAME_SHORT,
420           walker->ifName);
421       }
422       else
423       {
424         /* Case 1.2 and 1.3 */
425         EncapsulateAndForwardPacket(walker, encapsulationUdpData);
426       }
427     } /* if (isFromOlsrIntf && isToOlsrIntf) */
428
429     else if (isFromOlsrIntf && !isToOlsrIntf)
430     {
431       /* Case 2: Forward from OLSR interface to non-OLSR interface */
432
433       int nBytesWritten;
434       struct sockaddr_ll dest;
435
436       /* If the encapsulated IP packet is a local broadcast packet,
437        * update its destination address to match the subnet of the network
438        * interface on which the packet is being sent. */
439       CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
440
441       memset(&dest, 0, sizeof(dest));
442       dest.sll_family = AF_PACKET;
443       dest.sll_protocol = htons(ETH_P_IP);
444       dest.sll_ifindex = if_nametoindex(walker->ifName);
445       dest.sll_halen = IFHWADDRLEN;
446
447       /* Use all-ones as destination MAC address. When the IP destination is
448        * a multicast address, the destination MAC address should normally also
449        * be a multicast address. E.g., when the destination IP is 224.0.0.1,
450        * the destination MAC should be 01:00:5e:00:00:01. However, it does not
451        * seem to matter when the destination MAC address is set to all-ones
452        * in that case. */
453       memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
454
455       nBytesWritten = sendto(
456         walker->capturingSkfd,
457         ipPacket,
458         ipPacketLen,
459         0,
460         (struct sockaddr*) &dest,
461         sizeof(dest));
462       if (nBytesWritten != ipPacketLen)
463       {
464         BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
465       }
466       else
467       {
468         /* Increase counter */
469         walker->nBmfPacketsTx++;
470
471         OLSR_PRINTF(8, "%s: --> forwarded on \"%s\"\n", PLUGIN_NAME_SHORT, walker->ifName);
472       }
473     } /* else if (isFromOlsrIntf && !isToOlsrIntf) */
474
475     else if (!isFromOlsrIntf && isToOlsrIntf)
476     {
477       /* Case 3: Forward from a non-OLSR interface to an OLSR interface.
478        * Encapsulate and forward packet. */
479
480       EncapsulateAndForwardPacket(walker, encapsulationUdpData);
481     } /* else if (!isFromOlsrIntf && isToOlsrIntf) */
482
483     else
484     {
485       /* Case 4: Forward from non-OLSR interface to non-OLSR interface. */
486
487       /* Don't forward on interface on which packet was received */
488       if (intf == walker)
489       {
490         OLSR_PRINTF(
491           8,
492           "%s: --> not forwarding on \"%s\": pkt was captured on that interface\n",
493           PLUGIN_NAME_SHORT,
494           walker->ifName);
495       }
496
497       else
498       {
499         int nBytesWritten;
500         struct sockaddr_ll dest;
501
502         /* If the encapsulated IP packet is a local broadcast packet,
503          * update its destination address to match the subnet of the network
504          * interface on which the packet is being sent. */
505         CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
506
507         memset(&dest, 0, sizeof(dest));
508         dest.sll_family = AF_PACKET;
509         dest.sll_protocol = htons(ETH_P_IP);
510         dest.sll_ifindex = if_nametoindex(walker->ifName);
511         dest.sll_halen = IFHWADDRLEN;
512
513         /* Use all-ones as destination MAC address. When the IP destination is
514          * a multicast address, the destination MAC address should normally also
515          * be a multicast address. E.g., when the destination IP is 224.0.0.1,
516          * the destination MAC should be 01:00:5e:00:00:01. However, it does not
517          * seem to matter when the destination MAC address is set to all-ones
518          * in that case. */
519         memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
520
521         nBytesWritten = sendto(
522           walker->capturingSkfd,
523           ipPacket,
524           ipPacketLen,
525           0,
526           (struct sockaddr*) &dest,
527           sizeof(dest));
528         if (nBytesWritten != ipPacketLen)
529         {
530           BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
531         }
532         else
533         {
534           /* Increase counter */
535           walker->nBmfPacketsTx++;
536
537           OLSR_PRINTF(
538             8,
539             "%s: --> forwarded from non-OLSR on non-OLSR \"%s\"\n",
540             PLUGIN_NAME_SHORT,
541             walker->ifName);
542         }
543       } /* if (intf == walker) */
544     } /* if */
545   } /* for */
546 } /* BmfPacketCaptured */
547
548 /* -------------------------------------------------------------------------
549  * Function   : BmfEncapsulationPacketReceived
550  * Description: Handle a received BMF-encapsulation packet
551  * Input      : intf - the network interface on which the packet was received
552  *              forwardedBy - the IP node that forwarded the packet to me
553  *              forwardedTo - the destination IP address of the encapsulation
554  *                packet, in case the packet was received promiscuously.
555  *                Pass NULL if the packet is received normally (unicast or
556  *                broadcast).
557  *              encapsulationUdpData - the encapsulating IP UDP data, containting
558  *                the BMF encapsulation header, followed by the encapsulated
559  *                IP packet
560  * Output     : none
561  * Return     : none
562  * Data Used  : BmfInterfaces
563  * ------------------------------------------------------------------------- */
564 static void BmfEncapsulationPacketReceived(
565   struct TBmfInterface* intf,
566   union olsr_ip_addr* forwardedBy,
567   union olsr_ip_addr* forwardedTo,
568   unsigned char* encapsulationUdpData)
569 {
570   int iAmMpr; /* True (1) if I am selected as MPR by 'forwardedBy' */
571   struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
572   unsigned char* ipPacket; /* The encapsulated IP packet */
573   u_int16_t ipPacketLen; /* Length of the encapsulated IP packet */
574   struct ip* ipHeader; /* IP header inside the encapsulated IP packet */
575   union olsr_ip_addr mcSrc; /* Original source of the encapsulated multicast packet */
576   union olsr_ip_addr mcDst; /* Multicast destination of the encapsulated packet */
577   struct TEncapHeader* encapsulationHdr;
578   u_int16_t encapsulationUdpDataLen;
579   struct TBmfInterface* walker;
580
581   /* Are we talking to ourselves? */
582   if (if_ifwithaddr(forwardedBy) != NULL)
583   {
584     return;
585   }
586
587   /* Discard encapsulated packets received on a non-OLSR interface */
588   if (intf->olsrIntf == NULL)
589   {
590     return;
591   }
592
593   /* Retrieve details about the encapsulated IP packet */
594   ipPacket = GetIpPacket(encapsulationUdpData);
595   ipPacketLen = GetIpTotalLength(ipPacket);
596   ipHeader = GetIpHeader(encapsulationUdpData);
597
598   COPY_IP(&mcSrc, &ipHeader->ip_src);
599   COPY_IP(&mcDst, &ipHeader->ip_dst);
600
601   /* Increase counter */
602   intf->nBmfPacketsRx++;
603
604   /* Beware: not possible to call olsr_ip_to_string more than 4 times in same printf */
605   OLSR_PRINTF(
606     8,
607     "%s: encapsulated pkt of %ld bytes incoming on \"%s\": %s->%s, forwarded by %s to %s\n",
608     PLUGIN_NAME_SHORT,
609     (long)ipPacketLen,
610     intf->ifName,
611     olsr_ip_to_string(&mcSrc),
612     olsr_ip_to_string(&mcDst),
613     olsr_ip_to_string(forwardedBy),
614     forwardedTo != NULL ? olsr_ip_to_string(forwardedTo) : "me");
615
616   /* Get encapsulation header */
617   encapsulationHdr = (struct TEncapHeader*) encapsulationUdpData;
618
619   /* Verify correct format of BMF encapsulation header */
620   if (encapsulationHdr->type != BMF_ENCAP_TYPE ||
621       encapsulationHdr->len != BMF_ENCAP_LEN ||
622       ntohs(encapsulationHdr->reserved != 0))
623   {
624     OLSR_PRINTF(
625       8,
626       "%s: --> discarding: format of BMF encapsulation header not recognized\n",
627       PLUGIN_NAME_SHORT);
628     return;
629   }
630
631   /* Check if this packet was seen recently */
632   if (CheckAndMarkRecentPacket(ntohl(encapsulationHdr->crc32)))
633   {
634     /* Increase counter */
635     intf->nBmfPacketsRxDup++;
636
637     OLSR_PRINTF(
638       8,
639       "%s: --> discarding: packet is duplicate\n",
640       PLUGIN_NAME_SHORT);
641     return;
642   }
643
644   if (EtherTunTapFd >= 0)
645   {
646     /* Unpack the encapsulated IP packet and deliver it locally, by sending
647      * a copy into the local IP stack via the EtherTunTap interface */
648
649     union olsr_ip_addr broadAddr;
650     int nBytesToWrite, nBytesWritten;
651     unsigned char* bufferToWrite;
652
653     /* If the encapsulated IP packet is a local broadcast packet,
654      * update its destination address to match the subnet of the EtherTunTap
655      * interface */
656     broadAddr.v4 = htonl(EtherTunTapIpBroadcast);
657     CheckAndUpdateLocalBroadcast(ipPacket, &broadAddr);
658
659     bufferToWrite = ipPacket;
660     nBytesToWrite = ipPacketLen;
661
662     /* Write the packet into the EtherTunTap interface for local delivery */
663     nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite);
664     if (nBytesWritten != nBytesToWrite)
665     {
666       BmfPError("write() error forwarding encapsulated pkt on \"%s\"", EtherTunTapIfName);
667     }
668     else
669     {
670       OLSR_PRINTF(
671         8,
672         "%s: --> unpacked and delivered locally on \"%s\"\n",
673         PLUGIN_NAME_SHORT,
674         EtherTunTapIfName);
675     }
676   } /* if (EtherTunTapFd >= 0) */
677
678   /* Check if I am MPR for the forwarder */
679   /* TODO: olsr_lookup_mprs_set() is not thread-safe! */
680   iAmMpr = (olsr_lookup_mprs_set(MainAddressOf(forwardedBy)) != NULL);
681
682   /* Compose destination address for next hop */
683   memset(&forwardTo, 0, sizeof(forwardTo));
684   forwardTo.sin_family = AF_INET;
685   forwardTo.sin_port = htons(BMF_ENCAP_PORT);
686
687   /* Retrieve the number of bytes to be forwarded via the encapsulation socket */
688   encapsulationUdpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);
689
690   /* Check with each network interface what needs to be done on it */
691   for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
692   {
693     /* What to do with the packet on a non-OLSR interface? Unpack
694      * encapsulated packet, and forward it.
695      *
696      * What to do with the packet on an OLSR interface? Forward it only
697      * if the forwarding node has selected us as MPR (iAmMpr).
698      *
699      * Note that the packet is always coming in on an OLSR interface, because
700      * it is an encapsulated BMF packet. */
701
702     /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */
703     if (walker->olsrIntf == NULL)
704     {
705       int nBytesWritten;
706       struct sockaddr_ll dest;
707
708       /* If the encapsulated IP packet is a local broadcast packet,
709        * update its destination address to match the subnet of the network
710        * interface on which the packet is being sent. */
711       CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
712
713       memset(&dest, 0, sizeof(dest));
714       dest.sll_family = AF_PACKET;
715       dest.sll_protocol = htons(ETH_P_IP);
716       dest.sll_ifindex = if_nametoindex(walker->ifName);
717       dest.sll_halen = IFHWADDRLEN;
718
719       /* Use all-ones as destination MAC address. When the IP destination is
720        * a multicast address, the destination MAC address should normally also
721        * be a multicast address. E.g., when the destination IP is 224.0.0.1,
722        * the destination MAC should be 01:00:5e:00:00:01. However, it does not
723        * seem to matter when the destination MAC address is set to all-ones
724        * in that case. */
725       memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
726
727       nBytesWritten = sendto(
728         walker->capturingSkfd,
729         ipPacket,
730         ipPacketLen,
731         0,
732         (struct sockaddr*) &dest,
733         sizeof(dest));
734       if (nBytesWritten != ipPacketLen)
735       {
736         BmfPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName);
737       }
738       else
739       {
740         /* Increase counter */
741         walker->nBmfPacketsTx++;
742
743         OLSR_PRINTF(
744           8,
745           "%s: --> unpacked and forwarded on \"%s\"\n",
746           PLUGIN_NAME_SHORT,
747           walker->ifName);
748       }
749     } /* if (walker->olsrIntf == NULL) */
750
751     /* To an OLSR interface: forward the packet, but only if this node is
752      * selected as MPR by the forwarding node */
753     else if (iAmMpr)
754     {
755       struct TBestNeighbors bestNeighborLinks;
756       int nPossibleNeighbors;
757       int nBytesWritten;
758       int nPacketsToSend;
759       int i;
760
761       /* Retrieve at most two best neigbors to forward the packet to */
762       bestNeighborLinks =
763         GetBestTwoNeighbors(
764           walker,
765           &mcSrc,
766           forwardedBy,
767           forwardedTo,
768           &nPossibleNeighbors);
769
770       if (nPossibleNeighbors <= 0)
771       {
772         OLSR_PRINTF(
773           8,
774           "%s: --> not forwarding on \"%s\": there is no neighbor that needs my retransmission\n",
775           PLUGIN_NAME_SHORT,
776           walker->ifName);
777
778         continue; /* for */
779       }
780
781       /* Compose destination of encapsulation packet.
782        * Start by filling in the local broadcast address. */
783       COPY_IP(&forwardTo.sin_addr.s_addr, &walker->broadAddr);
784
785       /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
786        *   packet (to the best neighbor). Other neighbors listen promiscuously.
787        * - If the BMF mechanism is BM_BROADCAST,
788        *   - send one unicast packet if there is one possible neighbor,
789        *   - send two unicast packets if there are two possible neighbors, and
790        *   - only if there are more than two possible neighbors, then send an
791        *     (WLAN-air-expensive, less reliable) broadcast packet. */
792       if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors < 2)
793       {
794         nPacketsToSend = 1;
795       }
796       else /* BmfMechanism == BM_BROADCAST && nPossibleNeighbors >= 2 */
797       {
798         nPacketsToSend = 2;
799       }
800
801       for (i = 0; i < nPacketsToSend; i++)
802       {
803         if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors <= 2)
804         {
805           /* For unicast, overwrite the local broadcast address which was filled in
806            * above */
807           COPY_IP(&forwardTo.sin_addr.s_addr, &bestNeighborLinks.links[i]->neighbor_iface_addr);
808         }
809
810         /* Forward the BMF packet via the encapsulation socket */
811         nBytesWritten = sendto(
812           walker->encapsulatingSkfd,
813           encapsulationUdpData,
814           encapsulationUdpDataLen,
815           MSG_DONTROUTE,
816           (struct sockaddr*) &forwardTo,
817           sizeof(forwardTo));                   
818
819         /* Evaluate and display result */
820         if (nBytesWritten != encapsulationUdpDataLen)
821         {
822           BmfPError("sendto() error forwarding encapsulated pkt on \"%s\"", walker->ifName);
823         }
824         else
825         {
826           /* Increase counter */
827           walker->nBmfPacketsTx++;
828
829           OLSR_PRINTF(
830             8,
831             "%s: --> forwarded on \"%s\" to %s\n",
832             PLUGIN_NAME_SHORT,
833             walker->ifName,
834             inet_ntoa(forwardTo.sin_addr));
835         } /* if */
836       } /* for */
837     }  /* else if (iAmMpr) */
838
839     else /* walker->olsrIntf != NULL && !iAmMpr */
840     {
841       /* 'walker' is an OLSR interface, but I am not selected as MPR. In that
842        * case, don't forward. */
843       OLSR_PRINTF(
844         8,
845         "%s: --> not forwarding on \"%s\": I am not selected as MPR by %s\n",
846         PLUGIN_NAME_SHORT,
847         walker->ifName,
848         olsr_ip_to_string(forwardedBy));
849     } /* else */
850   } /* for */
851 } /* BmfEncapsulationPacketReceived */
852
853 /* -------------------------------------------------------------------------
854  * Function   : BmfTunPacketCaptured
855  * Description: Handle an IP packet, captured outgoing on the tuntap interface
856  * Input      : encapsulationUdpData - space for the encapsulation header, followed by
857  *                the captured outgoing IP packet
858  * Output     : none
859  * Return     : none
860  * Data Used  : none
861  * Notes      : The packet is assumed to be captured on a socket of family
862  *              PF_PACKET and type SOCK_DGRAM (cooked).
863  * ------------------------------------------------------------------------- */
864 static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData)
865 {
866   union olsr_ip_addr srcIp;
867   union olsr_ip_addr dstIp;
868   union olsr_ip_addr broadAddr;
869   struct TBmfInterface* walker;
870   unsigned char* ipPacket;
871   u_int16_t ipPacketLen;
872   struct ip* ipHeader;
873   u_int32_t crc32;
874   struct TEncapHeader* encapHdr;
875
876   ipPacket = GetIpPacket(encapsulationUdpData);
877   ipPacketLen = GetIpTotalLength(ipPacket);
878   ipHeader = GetIpHeader(encapsulationUdpData);
879
880   /* Only forward multicast packets. If configured, also forward local broadcast packets */
881   COPY_IP(&dstIp, &ipHeader->ip_dst);
882   broadAddr.v4 = htonl(EtherTunTapIpBroadcast);
883   if (IsMulticast(&dstIp) ||
884       (EnableLocalBroadcast != 0 && COMP_IP(&dstIp, &broadAddr)))
885   {
886     /* continue */
887   }
888   else
889   {
890     return;
891   }
892
893   COPY_IP(&srcIp, &ipHeader->ip_src);
894   OLSR_PRINTF(
895     8,
896     "%s: outgoing pkt of %ld bytes captured on tuntap interface \"%s\": %s->%s\n",
897     PLUGIN_NAME_SHORT,
898     (long)ipPacketLen,
899     EtherTunTapIfName,
900     olsr_ip_to_string(&srcIp),
901     olsr_ip_to_string(&dstIp));
902
903   /* Calculate packet fingerprint */
904   crc32 = PacketCrc32(ipPacket, ipPacketLen);
905
906   /* Check if this packet was seen recently */
907   if (CheckAndMarkRecentPacket(crc32))
908   {
909     OLSR_PRINTF(
910       8,
911       "%s: --> discarding: packet is duplicate\n",
912       PLUGIN_NAME_SHORT);
913     return;
914   }
915
916   /* Compose encapsulation header */
917   encapHdr = (struct TEncapHeader*) encapsulationUdpData;
918   memset (encapHdr, 0, ENCAP_HDR_LEN);
919   encapHdr->type = BMF_ENCAP_TYPE;
920   encapHdr->len = BMF_ENCAP_LEN;
921   encapHdr->reserved = 0;
922   encapHdr->crc32 = htonl(crc32);
923
924   /* Check with each network interface what needs to be done on it */
925   for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
926   {
927     /* Is the forwarding interface OLSR-enabled? */
928     if (walker->olsrIntf != NULL)
929     {
930       /* On an OLSR interface: encapsulate and forward packet. */
931
932       EncapsulateAndForwardPacket(walker, encapsulationUdpData);
933     }
934     else
935     {
936       /* On a non-OLSR interface: what to do?
937        * Answer 1: nothing. Multicast routing between non-OLSR interfaces
938        * is to be done by other protocols (e.g. PIM, DVMRP).
939        * Answer 2 (better): Forward it. */
940
941       int nBytesWritten;
942       struct sockaddr_ll dest;
943
944       /* If the encapsulated IP packet is a local broadcast packet,
945        * update its destination address to match the subnet of the network
946        * interface on which the packet is being sent. */
947       CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
948
949       memset(&dest, 0, sizeof(dest));
950       dest.sll_family = AF_PACKET;
951       dest.sll_protocol = htons(ETH_P_IP);
952       dest.sll_ifindex = if_nametoindex(walker->ifName);
953       dest.sll_halen = IFHWADDRLEN;
954
955       /* Use all-ones as destination MAC address. When the IP destination is
956        * a multicast address, the destination MAC address should normally also
957        * be a multicast address. E.g., when the destination IP is 224.0.0.1,
958        * the destination MAC should be 01:00:5e:00:00:01. However, it does not
959        * seem to matter when the destination MAC address is set to all-ones
960        * in that case. */
961       memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
962
963       nBytesWritten = sendto(
964         walker->capturingSkfd,
965         ipPacket,
966         ipPacketLen,
967         0,
968         (struct sockaddr*) &dest,
969         sizeof(dest));
970       if (nBytesWritten != ipPacketLen)
971       {
972         BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
973       }
974       else
975       {
976         /* Increase counter */
977         walker->nBmfPacketsTx++;
978
979         OLSR_PRINTF(
980           8,
981           "%s: --> forwarded from non-OLSR to non-OLSR \"%s\"\n",
982           PLUGIN_NAME_SHORT,
983           walker->ifName);
984       } /* if */
985     } /* if */
986   } /* for */
987 } /* BmfTunPacketCaptured */
988
989 /* -------------------------------------------------------------------------
990  * Function   : DoBmf
991  * Description: Wait (blocking) for IP packets, then call the handler for each
992  *              received packet
993  * Input      : none
994  * Output     : none
995  * Return     : none
996  * Data Used  : BmfInterfaces
997  * ------------------------------------------------------------------------- */
998 static void DoBmf(void)
999 {
1000   int nFdBitsSet;
1001   unsigned char rxBuffer[BMF_BUFFER_SIZE];
1002   fd_set rxFdSet;
1003
1004   assert(HighestSkfd >= 0);
1005
1006   /* Make a local copy of the set of file descriptors that select() can
1007    * modify to indicate which descriptors actually changed status */
1008   rxFdSet = InputSet;
1009
1010   /* Wait (blocking) for packets received on any of the sockets.
1011    * NOTE: don't use a timeout (last parameter). It causes a high system CPU load! */
1012   nFdBitsSet = select(HighestSkfd + 1, &rxFdSet, NULL, NULL, NULL);
1013   if (nFdBitsSet < 0)
1014   {
1015     if (errno != EINTR)
1016     {
1017       BmfPError("select() error");
1018     }
1019     return;
1020   }
1021
1022   while (nFdBitsSet > 0)
1023   {
1024     struct TBmfInterface* walker;
1025
1026     /* Check if a packet was received on the capturing socket (if any)
1027      * of each network interface */
1028     for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
1029     {
1030       int skfd = walker->capturingSkfd;
1031       if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
1032       {
1033         struct sockaddr_ll pktAddr;
1034         socklen_t addrLen = sizeof(pktAddr);
1035         int nBytes;
1036         unsigned char* ipPacket;
1037
1038         /* A packet was captured. */
1039
1040         nFdBitsSet--;
1041
1042         /* Receive the captured Ethernet frame, leaving space for the BMF
1043          * encapsulation header */
1044         ipPacket = GetIpPacket(rxBuffer);
1045         nBytes = recvfrom(
1046           skfd,
1047           ipPacket,
1048           BMF_BUFFER_SIZE - ENCAP_HDR_LEN,
1049           0,
1050           (struct sockaddr*)&pktAddr,
1051           &addrLen);
1052         if (nBytes < 0)
1053         {
1054           BmfPError("recvfrom() error on \"%s\"", walker->ifName);
1055
1056           continue; /* for */
1057         } /* if (nBytes < 0) */
1058
1059         /* Check if the number of received bytes is large enough for an IP
1060          * packet which contains at least a minimum-size IP header.
1061          * Note: There is an apparent bug in the packet socket implementation in
1062          * combination with VLAN interfaces. On a VLAN interface, the value returned
1063          * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
1064          * returned on a non-VLAN interface, for the same ethernet frame. */
1065         if (nBytes < (int)sizeof(struct ip))
1066         {
1067           olsr_printf(
1068             1,
1069             "%s: captured frame too short (%d bytes) on \"%s\"\n",
1070             PLUGIN_NAME,
1071             nBytes,
1072             walker->ifName);
1073
1074           continue; /* for */
1075         }
1076
1077         if (pktAddr.sll_pkttype == PACKET_OUTGOING ||
1078             pktAddr.sll_pkttype == PACKET_MULTICAST ||
1079             pktAddr.sll_pkttype == PACKET_BROADCAST)
1080         {
1081           /* A multicast or broadcast packet was captured */
1082
1083           BmfPacketCaptured(walker, pktAddr.sll_pkttype, rxBuffer);
1084
1085         } /* if (pktAddr.sll_pkttype == ...) */
1086       } /* if (skfd >= 0 && (FD_ISSET...)) */
1087     } /* for */
1088     
1089     /* Check if a BMF encapsulation packet was received on the listening
1090      * socket (if any) of each network interface */
1091     for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
1092     {
1093       int skfd = walker->listeningSkfd;
1094       if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
1095       {
1096         struct sockaddr_ll pktAddr;
1097         socklen_t addrLen = sizeof(pktAddr);
1098         int nBytes;
1099         int minimumLength;
1100         struct ip* ipHeader;
1101         struct udphdr* udpHeader;
1102         u_int16_t destPort;
1103         union olsr_ip_addr forwardedBy;
1104         union olsr_ip_addr forwardedTo;
1105
1106         /* Heard a BMF packet */
1107
1108         nFdBitsSet--;
1109
1110         nBytes = recvfrom(
1111           skfd,
1112           rxBuffer,
1113           BMF_BUFFER_SIZE,
1114           0,
1115           (struct sockaddr*)&pktAddr,
1116           &addrLen);
1117         if (nBytes < 0)
1118         {
1119           BmfPError("recvfrom() error on \"%s\"", walker->ifName);
1120
1121           continue; /* for */
1122         } /* if (nBytes < 0) */
1123
1124         /* Check if the received packet is actually directed to another
1125          * node on the LAN */
1126         if (pktAddr.sll_pkttype != PACKET_OTHERHOST)
1127         {
1128           /* No, the packet is directed to this node. In that case it will
1129            * be, or will already have been received, via the encapsulating
1130            * socket. Discard it here. */
1131           continue; /* for */
1132         } /* if (pktAddr.sll_pkttype ...) */
1133
1134         /* Check if the received packet is UDP - BMF port */
1135         ipHeader = (struct ip*)rxBuffer;
1136         if (ipHeader->ip_p != SOL_UDP)
1137         {
1138           /* Not UDP */
1139           continue; /* for */
1140         }
1141
1142         udpHeader = (struct udphdr*)(rxBuffer + GetIpHeaderLength(rxBuffer));
1143         destPort = ntohs(udpHeader->dest);
1144         if (destPort != BMF_ENCAP_PORT)
1145         {
1146           /* Not BMF */
1147           continue; /* for */
1148         }
1149
1150         /* Check if the number of received bytes is large enough for a minimal BMF
1151          * encapsulation packet, at least:
1152          * - the IP header of the encapsulation IP packet
1153          * - the UDP header of the encapsulation IP packet
1154          * - the encapsulation header
1155          * - the Ethernet header in the encapsulated Ethernet packet
1156          * - a minimum IP header inside the encapsulated packet
1157          * Note: on a VLAN interface, the value returned by 'recvfrom' may (but need
1158          * not) be 4 (bytes) larger than the value returned on a non-VLAN interface, for
1159          * the same ethernet frame. */
1160         minimumLength =
1161           GetIpHeaderLength(rxBuffer) +
1162           sizeof(struct udphdr) +
1163           ENCAP_HDR_LEN +
1164           IP_HDR_OFFSET +
1165           sizeof(struct ip);
1166         if (nBytes < minimumLength)
1167         {
1168           olsr_printf(
1169             1,
1170             "%s: captured a too short encapsulation packet (%d bytes) on \"%s\"\n",
1171             PLUGIN_NAME,
1172             nBytes,
1173             walker->ifName);
1174
1175           continue; /* for */
1176         }
1177
1178         COPY_IP(&forwardedBy, &ipHeader->ip_src);
1179         COPY_IP(&forwardedTo, &ipHeader->ip_dst);
1180         BmfEncapsulationPacketReceived(
1181           walker,
1182           &forwardedBy,
1183           &forwardedTo,
1184           rxBuffer + GetIpHeaderLength(rxBuffer) + sizeof(struct udphdr));
1185
1186       } /* if (skfd >= 0 && (FD_ISSET...)) */
1187     } /* for */
1188
1189     /* Check if a packet was received on the encapsulating socket (if any)
1190      * of each network interface */
1191     for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
1192     {
1193       int skfd = walker->encapsulatingSkfd;
1194       if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
1195       {
1196         struct sockaddr_in from;
1197         socklen_t fromLen = sizeof(from);
1198         int nBytes;
1199         union olsr_ip_addr forwardedBy;
1200
1201         /* An encapsulated packet was received */
1202
1203         nFdBitsSet--;
1204
1205         nBytes = recvfrom(
1206           skfd,
1207           rxBuffer,
1208           BMF_BUFFER_SIZE,
1209           0,
1210           (struct sockaddr*)&from,
1211           &fromLen);
1212         if (nBytes < 0)
1213         {
1214           BmfPError("recvfrom() error on \"%s\"", walker->ifName);
1215
1216           continue; /* for */
1217         } /* if (nBytes < 0) */
1218
1219         COPY_IP(&forwardedBy, &from.sin_addr.s_addr);
1220
1221         /* Check if the number of received bytes is large enough for a minimal BMF
1222          * encapsulation packet, at least:
1223          * - the encapsulation header
1224          * - the Ethernet header in the encapsulated Ethernet packet
1225          * - a minimum IP header inside the encapsulated packet */
1226         if (nBytes < ENCAP_HDR_LEN + IP_HDR_OFFSET + (int)sizeof(struct ip))
1227         {
1228           olsr_printf(
1229             1,
1230             "%s: received a too short encapsulation packet (%d bytes) from %s on \"%s\"\n",
1231             PLUGIN_NAME,
1232             nBytes,
1233             olsr_ip_to_string(&forwardedBy),
1234             walker->ifName);
1235
1236           continue; /* for */
1237         }
1238
1239         /* Unfortunately, the recvfrom call does not return the destination
1240          * of the encapsulation packet (the destination may be either the
1241          * my unicast or my local broadcast address). Therefore we fill in 'NULL'
1242          * for the 'forwardedTo' parameter. */
1243         BmfEncapsulationPacketReceived(walker, &forwardedBy, NULL, rxBuffer);
1244
1245       } /* if (skfd >= 0 && (FD_ISSET...)) */
1246     } /* for */
1247
1248     if (nFdBitsSet > 0 && FD_ISSET(EtherTunTapFd, &rxFdSet))
1249     {
1250       /* Check if an application has sent a packet out via the tuntap
1251        * network interface */
1252
1253       int nBytes;
1254       unsigned char* ipPacket;
1255       unsigned char* bufferToRead;
1256       size_t nBytesToRead;
1257
1258       nFdBitsSet--;
1259
1260       /* Receive the packet, leaving space for the BMF encapsulation header */
1261       ipPacket = GetIpPacket(rxBuffer);
1262     
1263       bufferToRead = ipPacket;
1264       nBytesToRead = BMF_BUFFER_SIZE - ENCAP_HDR_LEN;
1265
1266       nBytes = read(EtherTunTapFd, bufferToRead, nBytesToRead);
1267
1268       if (nBytes < 0)
1269       {
1270         BmfPError("recvfrom() error on \"%s\"", EtherTunTapIfName);
1271       }
1272       else
1273       {
1274         /* Check if the number of received bytes is large enough for an IP
1275          * packet which contains at least a minimum-size IP header */
1276         if (nBytes < (int)sizeof(struct ip))
1277         {
1278           olsr_printf(
1279             1,
1280             "%s: captured packet too short (%d bytes) on \"%s\"\n",
1281             PLUGIN_NAME,
1282             nBytes,
1283             EtherTunTapIfName);
1284         }
1285         else
1286         {
1287           /* An outbound packet was captured */
1288
1289           BmfTunPacketCaptured(rxBuffer);
1290
1291         } /* if (nBytes < ... */
1292       } /* if (nBytes < 0) */
1293     } /* if (nFdBitsSet > 0 && ... */
1294   } /* while (nFdBitsSet > 0) */
1295 } /* DoBmf */
1296
1297 /* -------------------------------------------------------------------------
1298  * Function   : BmfSignalHandler
1299  * Description: Signal handler function
1300  * Input      : signo - signal being handled
1301  * Output     : none
1302  * Return     : none
1303  * Data Used  : BmfThreadRunning
1304  * ------------------------------------------------------------------------- */
1305 static void BmfSignalHandler(int signo __attribute__((unused)))
1306 {
1307   BmfThreadRunning = 0;
1308 } /* BmfSignalHandler */
1309
1310 /* -------------------------------------------------------------------------
1311  * Function   : BmfRun
1312  * Description: Receiver thread function
1313  * Input      : useless - not used
1314  * Output     : none
1315  * Return     : not used
1316  * Data Used  : BmfThreadRunning
1317  * Notes      : Another thread can gracefully stop this thread by sending
1318  *              a SIGALRM signal.
1319  * ------------------------------------------------------------------------- */
1320 static void* BmfRun(void* useless __attribute__((unused)))
1321 {
1322   /* Mask all signals except SIGALRM */
1323   sigset_t blockedSigs;
1324   sigfillset(&blockedSigs);
1325   sigdelset(&blockedSigs, SIGALRM);
1326   if (pthread_sigmask(SIG_BLOCK, &blockedSigs, NULL) != 0)
1327   {
1328     BmfPError("pthread_sigmask() error");
1329   }
1330
1331   /* Set up the signal handler for the process: use SIGALRM to terminate
1332    * the BMF thread. Only if a signal handler is specified, does a blocking
1333    * system call return with errno set to EINTR; if a signal hander is not
1334    * specified, any system call in which the thread may be waiting will not
1335    * return. Note that the BMF thread is usually blocked in the select()
1336    * function (see DoBmf()). */
1337   if (signal(SIGALRM, BmfSignalHandler) == SIG_ERR)
1338   {
1339     BmfPError("signal() error");
1340   }
1341
1342   /* Call the thread function until flagged to exit */
1343   while (BmfThreadRunning != 0)
1344   {
1345     DoBmf();
1346   }
1347
1348   return NULL;
1349 } /* BmfRun */
1350
1351 /* -------------------------------------------------------------------------
1352  * Function   : InterfaceChange
1353  * Description: Callback function passed to OLSRD for it to call whenever a
1354  *              network interface has been added, removed or updated
1355  * Input      : interf - the network interface to deal with
1356  *              action - indicates if the specified network interface was
1357  *                added, removed or updated.
1358  * Output     : none
1359  * Return     : always 0
1360  * Data Used  : none
1361  * ------------------------------------------------------------------------- */
1362 int InterfaceChange(struct interface* interf, int action)
1363 {
1364   switch (action)
1365   {
1366   case (IFCHG_IF_ADD):
1367     AddInterface(interf);
1368     olsr_printf(1, "%s: interface %s added\n", PLUGIN_NAME, interf->int_name);
1369     break;
1370
1371   case (IFCHG_IF_REMOVE):
1372     /* We cannot just remove the interface, because the receive-thread is likely
1373      * to be waiting in select(...) for packets coming in via the interface.
1374      * Therefore we first close BMF (CloseBmf()), interrupting and kiling the
1375      * receive-thread so that it is safe to remove this (and all other)
1376      * interfaces. After that, BMF is re-started (InitBmf(interf)). */
1377     CloseBmf();
1378     InitBmf(interf);
1379     olsr_printf(1, "%s: interface %s removed\n", PLUGIN_NAME, interf->int_name);
1380     break;
1381
1382   case (IFCHG_IF_UPDATE):
1383     olsr_printf(1, "%s: interface %s updated\n", PLUGIN_NAME, interf->int_name);
1384     break;
1385       
1386   default:
1387     olsr_printf(
1388       1,
1389       "%s: interface %s: error - unknown action (%d)\n",
1390       PLUGIN_NAME,
1391       interf->int_name, action);
1392     break;
1393   }
1394
1395   return 0;
1396 } /* InterfaceChange */
1397
1398 /* -------------------------------------------------------------------------
1399  * Function   : InitBmf
1400  * Description: Initialize the BMF plugin
1401  * Input      : skipThisIntf - specifies which network interface should not
1402  *              be enabled for BMF. Pass NULL if not applicable.
1403  * Output     : none
1404  * Return     : fail (0) or success (1)
1405  * Data Used  : BmfThreadRunning, BmfThread
1406  * ------------------------------------------------------------------------- */
1407 int InitBmf(struct interface* skipThisIntf)
1408 {
1409   CreateBmfNetworkInterfaces(skipThisIntf);
1410
1411   /* Start running the multicast packet processing thread */
1412   BmfThreadRunning = 1;
1413   if (pthread_create(&BmfThread, NULL, BmfRun, NULL) != 0)
1414   {
1415     BmfPError("pthread_create() error");
1416     return 0;
1417   }
1418
1419   if (EtherTunTapFd >= 0)
1420   {
1421     /* Deactivate IP spoof filter for EtherTunTap interface */
1422     DeactivateSpoofFilter();
1423
1424     /* If the BMF network interface has a sensible IP address, it is a good idea
1425      * to route all multicast traffic through that interface */
1426     if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP)
1427     {
1428       AddMulticastRoute();
1429     }
1430   }
1431
1432   return 1;
1433 } /* InitBmf */
1434
1435 /* -------------------------------------------------------------------------
1436  * Function   : CloseBmf
1437  * Description: Close the BMF plugin and clean up
1438  * Input      : none
1439  * Output     : none
1440  * Return     : none
1441  * Data Used  : BmfThread
1442  * ------------------------------------------------------------------------- */
1443 void CloseBmf(void)
1444 {
1445   if (EtherTunTapFd >= 0)
1446   {
1447     /* If there is a multicast route, try to delete it first */
1448     DeleteMulticastRoute();
1449
1450     /* Restore IP spoof filter for EtherTunTap interface */
1451     RestoreSpoofFilter();
1452   }
1453
1454   /* Signal BmfThread to exit */
1455   /* Strangely enough, all running threads receive the SIGALRM signal. But only the
1456    * BMF thread is affected by this signal, having specified a handler for this
1457    * signal in its thread entry function BmfRun(...). */
1458   if (pthread_kill(BmfThread, SIGALRM) != 0)
1459   {
1460     BmfPError("pthread_kill() error");
1461   }
1462
1463   /* Wait for BmfThread to acknowledge */
1464   if (pthread_join(BmfThread, NULL) != 0)
1465   {
1466     BmfPError("pthread_join() error");
1467   }
1468
1469   /* Clean up after the BmfThread has been killed */
1470   CloseBmfNetworkInterfaces();
1471 } /* CloseBmf */
1472
1473 /* -------------------------------------------------------------------------
1474  * Function   : RegisterBmfParameter
1475  * Description: Register a configuration parameter with the BMF process
1476  * Input      : key - the parameter name, e.g. "DropMac" or "NonOlsrIf"
1477  *              value - the parameter value
1478  * Output     : none
1479  * Return     : fatal error (<0), minor error (0) or success (>0)
1480  * Data Used  : none
1481  * ------------------------------------------------------------------------- */
1482 int RegisterBmfParameter(char* key, char* value)
1483 {
1484   if (strcmp(key, "NonOlsrIf") == 0)
1485   {
1486     return AddNonOlsrBmfIf(value);
1487   }
1488   else if (strcmp(key, "DoLocalBroadcast") == 0)
1489   {
1490     return DoLocalBroadcast(value);
1491   }
1492   else if (strcmp(key, "BmfInterface") == 0)
1493   {
1494     return SetBmfInterfaceName(value);
1495   }
1496   else if (strcmp(key, "BmfInterfaceIp") == 0)
1497   {
1498     return SetBmfInterfaceIp(value);
1499   }
1500   else if (strcmp(key, "CapturePacketsOnOlsrInterfaces") == 0)
1501   {
1502     return SetCapturePacketsOnOlsrInterfaces(value);
1503   }
1504   else if (strcmp(key, "BmfMechanism") == 0)
1505   {
1506     return SetBmfMechanism(value);
1507   }
1508
1509   /* Key not recognized */
1510   return 0;
1511 } /* RegisterBmfParameter */
1512