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