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