diff -Nur olsrd-0.5.0.cvs/lib/bmf/Makefile olsrd-0.5.0/lib/bmf/Makefile
--- olsrd-0.5.0.cvs/lib/bmf/Makefile	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/Makefile	2007-05-21 11:00:46.000000000 +0200
@@ -34,7 +34,7 @@
 
 OLSRD_PLUGIN =	true
 PLUGIN_NAME =	olsrd_bmf
-PLUGIN_VER =	1.4
+PLUGIN_VER =	1.5
 
 TOPDIR = ../..
 include $(TOPDIR)/Makefile.inc
diff -Nur olsrd-0.5.0.cvs/lib/bmf/README_BMF.txt olsrd-0.5.0/lib/bmf/README_BMF.txt
--- olsrd-0.5.0.cvs/lib/bmf/README_BMF.txt	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/README_BMF.txt	2007-05-08 07:25:32.000000000 +0200
@@ -1,6 +1,6 @@
 BASIC MULTICAST FORWARDING PLUGIN FOR OLSRD
 by Erik Tromp (erik.tromp@nl.thalesgroup.com, erik_tromp@hotmail.com)
-Version 1.4
+Version 1.5
 
 1. Introduction
 ---------------
@@ -17,14 +17,14 @@
 2. How to build and install
 ---------------------------
 
-Download the olsr-bmf-v1.4.tar.gz file and save it into your OLSRD
+Download the olsr-bmf-v1.5.tar.gz file and save it into your OLSRD
 base install directory.
 
 Change directory (cd) to your OLSRD base install directory.
 
 At the command prompt, type:
 
-  tar -zxvf ./olsr-bmf-v1.4.tar.gz
+  tar -zxvf ./olsr-bmf-v1.5.tar.gz
 
 then type:
 
@@ -47,7 +47,7 @@
 To configure BMF in OLSR, you must edit the file /etc/olsrd.conf
 to load the BMF plugin. For example, add the following lines:
 
-  LoadPlugin "olsrd_bmf.so.1.4"
+  LoadPlugin "olsrd_bmf.so.1.5"
   {
     # No PlParam entries required for basic operation
   }
@@ -64,8 +64,8 @@
 Look at the output; it should list the BMF plugin, e.g.:
 
   ---------- Plugin loader ----------
-  Library: olsrd_bmf.so.1.4
-  OLSRD Basic Multicast Forwarding plugin 1.4 (Mar 30 2007 14:30:57)
+  Library: olsrd_bmf.so.1.5
+  OLSRD Basic Multicast Forwarding plugin 1.5 (May 16 2007 14:30:57)
     (C) Thales Communications Huizen, Netherlands
     Erik Tromp (erik.tromp@nl.thalesgroup.com)
   Checking plugin interface version...  4 - OK
@@ -149,7 +149,8 @@
 packets are transported in UDP, port 50698. The source address of the
 encapsulation packet is set to the address of the forwarder instead of
 the originator. Of course, the payload of the encapsulation packet is
-the original IP packet.
+the original IP packet. For an exact specification of the encapsulation
+format, refer to paragraph 10 below.
 
 For local reception, each received encapsulated packets is unpacked
 and passed into a tuntap interface which is specially created for
@@ -189,16 +190,12 @@
 The following gives an overview of all plugin parameters that can be
 configured:
 
-  LoadPlugin "olsrd_bmf.so.1.4"
+  LoadPlugin "olsrd_bmf.so.1.5"
   {
     # Specify the name of the BMF network interface.
     # Defaults to "bmf0".
     PlParam "BmfInterface" "mybmf0"
 
-    # Specify the type of the BMF network interface: either "tun" or
-    # "tap". Defaults to "tun".
-    PlParam "BmfInterfaceType" "tap"
-
     # Specify the IP address and mask for the BMF network interface.
     # By default, the IP address of the first OLSR interface is copied.
     # The default prefix length is 32.
@@ -334,7 +331,7 @@
 interfaces one by one as "NonOlsrIf" parameters in the BMF plugin section
 of /etc/olsrd.conf. For example:
 
-  LoadPlugin "olsrd_bmf.so.1.4"
+  LoadPlugin "olsrd_bmf.so.1.5"
   {
     # Non-OLSR interfaces to participate in the multicast flooding
     PlParam     "NonOlsrIf"  "eth2"
@@ -392,7 +389,7 @@
 the BMF network interface, by editing the /etc/olsrd.conf file.
 For example:
 
-  LoadPlugin "olsrd_bmf.so.1.4"
+  LoadPlugin "olsrd_bmf.so.1.5"
   {
       PlParam "BmfInterfaceIp" "10.10.10.4/24"
   }
@@ -454,43 +451,7 @@
 TTL is implicitly assumed to be 1).
 
 
-9. Testing in a lab environment
--------------------------------
-
-When using equipment like switches or hubs, usually all the hosts see each
-other. In an OLSR lab environment, we sometimes want to simulate the
-situation that some hosts in the network cannot directly see other hosts
-(as 1-hop neighbors) but only indirectly (as 2- or more-hop neighbors).
-To simulate that situation, the iptables tool is often used (see
-www.netfilter.org). For BMF, however, that is nog enough.
-
-For OLSR testing, setup iptables on each host to drop packets from
-all other hosts which are not direct (1-hop) neigbors. For example, to
-drop all packets from the hosts with MAC addresses 00:0C:29:51:32:88,
-00:0C:29:61:34:B7 and 00:0C:29:28:0E:CC, enter at the shell prompt:
-
-  iptables -A INPUT -m mac --mac-source 00:0C:29:51:32:88 -j DROP
-  iptables -A INPUT -m mac --mac-source 00:0C:29:61:34:B7 -j DROP
-  iptables -A INPUT -m mac --mac-source 00:0C:29:28:0E:CC -j DROP
-
-For BMF testing, edit the file /etc/olsrd.conf, and specify the MAC
-addresses of the hosts we do not want to see. (Even though packets from
-these hosts are dropped by iptables, they are still received on network
-interfaces if they are in promiscuous mode.) For example:
-
-  LoadPlugin "olsrd_bmf.so.1.4"
-  {
-    # Drop all packets received from the following MAC sources
-    PlParam     "DropMac"    "00:0C:29:51:32:88" # RemoteClient1
-    PlParam     "DropMac"    "00:0C:29:61:34:B7" # SimpleClient1
-    PlParam     "DropMac"    "00:0C:29:28:0E:CC" # SimpleClient2
-  }
-
-See also the notes in the 'packet' manpage ("Packet sockets are not
-subject to the input or output firewall chains").
-
-
-10. Common problems, FAQ
+9. Common problems, FAQ
 ------------------------
 
 ---------
@@ -561,9 +522,75 @@
 (e.g. "bmf0") or by specifying its IP address.
 
 
-11. Version history
+10. Version history
 -------------------
 
+16 May 2007: Version 1.5
+
+* Improved packet history list to take into account the full 32 bits
+  of the packet fingerprint.
+  Previous versions derived a 16-bits value from the 32-bits packet
+  fingerprint and used that 16-bits value to determine packet unicity. In
+  situations with high packet rates (e.g. multicast video), this leads to
+  packets being incorrectly seen as duplicates of other, previously received
+  packets.
+
+* New encapsulation format. In previous versions, a complete Ethernet
+  frame was encapsulated. This is unnecessary, and not very clean; e.g.
+  from packets coming in on non-Ethernet media such as PPP, the data in
+  the Ethernet header is bogus.
+  The new encapsulation format encapsulates only the IP packet. An
+  outer IP header [1], UDP header [2] and BMF Encapsulation Header are
+  inserted before the datagram's existing IP header, as follows:
+
+                                       +---------------------------+
+                                       |                           |
+                                       |      Outer IP Header      |
+                                       +---------------------------+
+                                       |                           |
+                                       |        UDP Header         |
+                                       +---------------------------+
+                                       |      BMF Encapsulation    |
+                                       |           Header          |
+   +---------------------------+       +---------------------------+
+   |                           |       |                           |
+   |         IP Header         |       |         IP Header         |
+   +---------------------------+ ====> +---------------------------+
+   |                           |       |                           |
+   |         IP Payload        |       |         IP Payload        |
+   |                           |       |                           |
+   |                           |       |                           |
+   +---------------------------+       +---------------------------+
+
+  The BMF encapsulation header has a typical type-length-value (TLV)
+  format:
+
+    0                   1                   2                   3
+    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     Type      |    Length     |            Reserved           |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                       Packet fingerprint                      |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+   Type                1
+
+   Length              6.  Length in bytes of this extension, not
+                       including the Type and Length bytes.
+
+   Reserved            Reserved for future use. MUST be set to 0 on
+                       sending, MUST be verified as 0 on receipt;
+                       otherwise the extension must be handled as not
+                       understood and silently skipped.
+
+   Packet fingerprint  32-bits unique fingerprint inserted by the
+                       encapsulator. MAY be used by the receiver to
+                       determine duplicate packet reception.
+
+  The new encapsulation format is incompatible with those of previous
+  BMF versions, implying that all network nodes need to be updated.
+
+
 31 Mar 2007: Version 1.4
 * Optimized the standard forwarding mechanism in such a way that
   retransmissions of packets are only done on those network interfaces
@@ -643,3 +670,12 @@
 27 Apr 2006: Version 1.0.1
 * First release.
 
+
+11. Normative References
+------------------------
+
+   [1]  Postel, J., "Internet Protocol", STD 5, RFC 791, September 1981.
+
+   [2]  Postel, J., "User Datagram Protocol", STD 6, RFC 768, August
+        1980.
+
diff -Nur olsrd-0.5.0.cvs/lib/bmf/src/Address.c olsrd-0.5.0/lib/bmf/src/Address.c
--- olsrd-0.5.0.cvs/lib/bmf/src/Address.c	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/src/Address.c	2007-05-08 10:33:08.000000000 +0200
@@ -1,6 +1,6 @@
 /*
  * OLSR Basic Multicast Forwarding (BMF) plugin.
- * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
+ * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
  * Written by Erik Tromp.
  * All rights reserved.
  *
@@ -128,8 +128,8 @@
   }
 
   /* The total length must be at least large enough to store the UDP header */
-  ipHeaderLen = GetHeaderLength(ipPacket);
-  if (GetTotalLength(ipPacket) < ipHeaderLen + sizeof(struct udphdr))
+  ipHeaderLen = GetIpHeaderLength(ipPacket);
+  if (GetIpTotalLength(ipPacket) < ipHeaderLen + sizeof(struct udphdr))
   {
     /* Not long enough */
     return 0;
diff -Nur olsrd-0.5.0.cvs/lib/bmf/src/Address.h olsrd-0.5.0/lib/bmf/src/Address.h
--- olsrd-0.5.0.cvs/lib/bmf/src/Address.h	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/src/Address.h	2007-05-08 10:33:08.000000000 +0200
@@ -3,7 +3,7 @@
 
 /*
  * OLSR Basic Multicast Forwarding (BMF) plugin.
- * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
+ * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
  * Written by Erik Tromp.
  * All rights reserved.
  *
diff -Nur olsrd-0.5.0.cvs/lib/bmf/src/Bmf.c olsrd-0.5.0/lib/bmf/src/Bmf.c
--- olsrd-0.5.0.cvs/lib/bmf/src/Bmf.c	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/src/Bmf.c	2007-05-13 04:28:38.000000000 +0200
@@ -1,6 +1,6 @@
 /*
  * OLSR Basic Multicast Forwarding (BMF) plugin.
- * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
+ * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
  * Written by Erik Tromp.
  * All rights reserved.
  *
@@ -48,6 +48,7 @@
 #include <stdarg.h> /* va_list, va_start, va_end */
 #include <errno.h> /* errno */
 #include <assert.h> /* assert() */
+#include <linux/if_ether.h> /* ETH_P_IP */
 #include <linux/if_packet.h> /* struct sockaddr_ll, PACKET_MULTICAST */
 #include <pthread.h> /* pthread_t, pthread_create() */
 #include <signal.h> /* sigset_t, sigfillset(), sigdelset(), SIGINT */
@@ -67,7 +68,6 @@
 #include "Address.h" /* IsMulticast() */
 #include "Packet.h" /* ETH_TYPE_OFFSET, IFHWADDRLEN etc. */
 #include "PacketHistory.h" /* InitPacketHistory() */
-#include "DropList.h" /* DropMac() */
 
 static pthread_t BmfThread;
 static int BmfThreadRunning = 0;
@@ -108,7 +108,7 @@
 
     olsr_printf(1, "%s: %s\n", strDesc, strErr);
   }
-}
+} /* BmfPError */
 
 /* -------------------------------------------------------------------------
  * Function   : MainAddressOf
@@ -129,69 +129,14 @@
     result = ip;
   }
   return result;
-}
-
-/* -------------------------------------------------------------------------
- * Function   : ComposeEnapsulationDestination
- * Description: Compose a next destination for an encapsulated packet
- * Input      : intf - the network interface on which to forward the
- *                encapsulation packet
- *              src - the IP source of the encapsulated packet. Pass NULL if
- *                not applicable.
- *              forwardedBy - the IP address of the last host that forwarded
- *                the packet. Pass NULL if not applicable.
- *              forwardedTo - the IP address to which the last host has
- *                forwarded the packet. Pass NULL if not applicable.
- * Output     : nextDest - the composed next destination
- * Return     : 1 if a valid next destination could be composed, or 0 if not
- * Data Used  : BmfMechanism
- * ------------------------------------------------------------------------- */
-static int ComposeEnapsulationDestination(
-  struct TBmfInterface* intf,
-  union olsr_ip_addr* src,
-  union olsr_ip_addr* forwardedBy,
-  union olsr_ip_addr* forwardedTo,
-  struct sockaddr_in* nextDest)
-{
-  struct link_entry* bestNeighborLink;
-  int nPossibleNeighbors;
-
-  memset(nextDest, 0, sizeof(nextDest));
-  nextDest->sin_family = AF_INET;
-  nextDest->sin_port = htons(BMF_ENCAP_PORT);
-
-  bestNeighborLink = GetBestNeighbor(intf, src, forwardedBy, forwardedTo, &nPossibleNeighbors);
-
-  if (bestNeighborLink != NULL)
-  {
-    /* Depending on the how many neighbors there are, and on the BMF mechanism... */
-    if (nPossibleNeighbors == 1 || BmfMechanism == BM_UNICAST_PROMISCUOUS)
-    {
-      /* ...destination IP address is address of best neighbor... */
-      COPY_IP(&nextDest->sin_addr.s_addr, &bestNeighborLink->neighbor_iface_addr);
-    }
-    else
-    {
-      /* ...or destination IP address is local broadcast. */
-      COPY_IP(&nextDest->sin_addr.s_addr, &intf->broadAddr);
-    }
-  }
-  else
-  {
-    /* No (good enough) neighbor on the specified interface: don't forward
-     * the packet */
-    return 0;
-  }
-
-  return 1;
-}
+} /* MainAddressOf */
 
 /* -------------------------------------------------------------------------
  * Function   : EncapsulateAndForwardPacket
  * Description: Encapsulate a captured raw IP packet and forward it
  * Input      : intf - the network interface on which to forward the packet
  *              encapsulationUdpData - The encapsulation header, followed by
- *                the encapsulated Ethernet frame
+ *                the encapsulated IP packet
  * Output     : none
  * Return     : none
  * Data Used  : none
@@ -200,16 +145,22 @@
   struct TBmfInterface* intf,
   unsigned char* encapsulationUdpData)
 {
-  unsigned char* ethernetFrame = GetEthernetFrame(encapsulationUdpData);
-  int nBytesWritten;
-  struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
+  /* The packet */
   u_int16_t udpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);
 
-  /* Change encapsulated source MAC address to that of sending interface */
-  SetFrameSourceMac(ethernetFrame, intf->macAddr);
+  /* The next destination(s) */
+  struct TBestNeighbors bestNeighborLinks;
+  int nPossibleNeighbors;
+  struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
 
-  /* Compose destination of encapsulation packet */
-  if (ComposeEnapsulationDestination(intf, NULL, NULL, NULL, &forwardTo) == 0)
+  int nPacketsToSend;
+  int nBytesWritten;
+  int i;
+
+  /* Retrieve at most two best neigbors to forward the packet to */
+  bestNeighborLinks = GetBestTwoNeighbors(intf, NULL, NULL, NULL, &nPossibleNeighbors);
+
+  if (nPossibleNeighbors <= 0)
   {
     OLSR_PRINTF(
       8,
@@ -219,74 +170,100 @@
     return;
   }
 
-  nBytesWritten = sendto(
-    intf->encapsulatingSkfd,
-    encapsulationUdpData,
-    udpDataLen,
-    MSG_DONTROUTE,
-    (struct sockaddr*) &forwardTo,
-    sizeof(forwardTo));                   
-  if (nBytesWritten != udpDataLen)
+  /* Compose destination of encapsulation packet */
+
+  memset(&forwardTo, 0, sizeof(forwardTo));
+  forwardTo.sin_family = AF_INET;
+  forwardTo.sin_port = htons(BMF_ENCAP_PORT);
+
+  /* Start by filling in the local broadcast address */
+  COPY_IP(&forwardTo.sin_addr.s_addr, &intf->broadAddr);
+
+  /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
+   *   packet (to the best neighbor).
+   * - If the BMF mechanism is BM_BROADCAST,
+   *   - send one unicast packet if there is one possible neighbor,
+   *   - send two unicast packets if there are two possible neighbors, and
+   *   - only if there are more than two possible neighbors, then send an
+   *     (WLAN-air-expensive, less reliable) broadcast packet. */
+  if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors < 2)
   {
-    BmfPError("sendto() error forwarding pkt on \"%s\"", intf->ifName);
+    nPacketsToSend = 1;
   }
-  else
+  else /* BmfMechanism == BM_BROADCAST && nPossibleNeighbors >= 2 */
   {
-    /* Increase counter */
-    intf->nBmfPacketsTx++;
+    nPacketsToSend = 2;
+  }
 
-    OLSR_PRINTF(
-      8,
-      "%s: --> encapsulated and forwarded on \"%s\" to %s\n",
-      PLUGIN_NAME_SHORT,
-      intf->ifName,
-      inet_ntoa(forwardTo.sin_addr));
-  } /* if (nBytesWritten != udpDataLen) */
-}
+  for (i = 0; i < nPacketsToSend; i++)
+  {
+    if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors <= 2)
+    {
+      COPY_IP(&forwardTo.sin_addr.s_addr, &bestNeighborLinks.links[i]->neighbor_iface_addr);
+    }
+
+    /* Forward the BMF packet via the encapsulation socket */
+    nBytesWritten = sendto(
+      intf->encapsulatingSkfd,
+      encapsulationUdpData,
+      udpDataLen,
+      MSG_DONTROUTE,
+      (struct sockaddr*) &forwardTo,
+      sizeof(forwardTo));                   
+
+    /* Evaluate and display result */
+    if (nBytesWritten != udpDataLen)
+    {
+      BmfPError("sendto() error forwarding pkt on \"%s\"", intf->ifName);
+    }
+    else
+    {
+      /* Increase counter */
+      intf->nBmfPacketsTx++;
+
+      OLSR_PRINTF(
+        8,
+        "%s: --> encapsulated and forwarded on \"%s\" to %s\n",
+        PLUGIN_NAME_SHORT,
+        intf->ifName,
+        inet_ntoa(forwardTo.sin_addr));
+    } /* if (nBytesWritten != udpDataLen) */
+  } /* for */
+} /* EncapsulateAndForwardPacket */
 
 /* -------------------------------------------------------------------------
  * Function   : BmfPacketCaptured
- * Description: Handle a captured raw Ethernet frame
+ * Description: Handle a captured IP packet
  * Input      : intf - the network interface on which the packet was captured
  *              sllPkttype - the type of packet. Either PACKET_OUTGOING,
  *                PACKET_BROADCAST or PACKET_MULTICAST.
  *              encapsulationUdpData - space for the encapsulation header, followed by
- *                the captured Ethernet frame
+ *                the captured IP packet
  * Output     : none
  * Return     : none
  * Data Used  : BmfInterfaces
- * Notes      : The Ethernet frame is assumed to be captured on a socket of family
- *              PF_PACKET and type SOCK_RAW.
+ * Notes      : The IP packet is assumed to be captured on a socket of family
+ *              PF_PACKET and type SOCK_DGRAM (cooked).
  * ------------------------------------------------------------------------- */
 static void BmfPacketCaptured(
   struct TBmfInterface* intf,
   unsigned char sllPkttype,
   unsigned char* encapsulationUdpData)
 {
-  unsigned char* srcMac;
-  union olsr_ip_addr src; /* Source IP address in captured frame */
-  union olsr_ip_addr dst; /* Destination IP address in captured frame */
-  union olsr_ip_addr* origIp; /* Main OLSR address of source of captured frame */
+  union olsr_ip_addr src; /* Source IP address in captured packet */
+  union olsr_ip_addr dst; /* Destination IP address in captured packet */
+  union olsr_ip_addr* origIp; /* Main OLSR address of source of captured packet */
   struct TBmfInterface* walker;
   int isFromOlsrIntf;
   int isFromOlsrNeighbor;
   int iAmMpr;
-  unsigned char* ethernetFrame; /* The captured Ethernet frame... */
-  u_int16_t ethernetFrameLen; /* ...and its length */
-  struct ip* ipHeader; /* The IP header inside the captured Ethernet frame */
-  unsigned char* ipPacket; /* The IP packet inside the captured Ethernet frame */
+  unsigned char* ipPacket; /* The captured IP packet... */
+  u_int16_t ipPacketLen; /* ...and its length */
+  struct ip* ipHeader; /* The IP header inside the captured IP packet */
   u_int32_t crc32;
   struct TEncapHeader* encapHdr;
 
-  ethernetFrame = GetEthernetFrame(encapsulationUdpData);
-
-  /* Only forward IPv4 packets */
-  if (GetEtherType(ethernetFrame) != IPV4_TYPE)
-  {
-    return;
-  }
-
-  ipHeader = GetIpHeader(ethernetFrame);
+  ipHeader = GetIpHeader(encapsulationUdpData);
 
   COPY_IP(&dst, &ipHeader->ip_dst);
 
@@ -301,7 +278,7 @@
     return;
   }
 
-  ipPacket = GetIpPacket(ethernetFrame);
+  ipPacket = GetIpPacket(encapsulationUdpData);
 
   /* Don't forward fragments of IP packets. Also, don't forward OLSR packets (UDP
    * port 698) and BMF encapsulated packets */
@@ -316,8 +293,8 @@
   /* Check if the frame is captured on an OLSR-enabled interface */
   isFromOlsrIntf = (intf->olsrIntf != NULL);
 
-  /* Retrieve the length of the captured frame */
-  ethernetFrameLen = GetFrameLength(ethernetFrame);
+  /* Retrieve the length of the captured packet */
+  ipPacketLen = GetIpTotalLength(ipPacket);
 
   COPY_IP(&src, &ipHeader->ip_src);
   OLSR_PRINTF(
@@ -325,30 +302,20 @@
     "%s: %s pkt of %ld bytes captured on %s interface \"%s\": %s->%s\n",
     PLUGIN_NAME_SHORT,
     sllPkttype == PACKET_OUTGOING ? "outgoing" : "incoming",
-    (long)ethernetFrameLen,
+    (long)ipPacketLen,
     isFromOlsrIntf ? "OLSR" : "non-OLSR",
     intf->ifName,
     olsr_ip_to_string(&src),
     olsr_ip_to_string(&dst));
 
-  /* Apply drop list for testing purposes. */
-  srcMac = ethernetFrame + IFHWADDRLEN;
-  if (IsInDropList(srcMac))
-  {
-    OLSR_PRINTF(
-      8,
-      "%s: --> discarding: source MAC (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) found in drop list\n",
-      PLUGIN_NAME_SHORT,
-      *srcMac, *(srcMac + 1), *(srcMac + 2), *(srcMac + 3), *(srcMac + 4), *(srcMac + 5));
-    return;
-  }
-
   /* Lookup main address of source in the MID table of OLSR */
   origIp = MainAddressOf(&src);
 
+  /* Calculate packet fingerprint */
+  crc32 = PacketCrc32(ipPacket, ipPacketLen);
+
   /* Check if this packet was seen recently */
-  crc32 = PacketCrc32(ethernetFrame, ethernetFrameLen);
-  if (CheckAndMarkRecentPacket(Hash16(crc32)))
+  if (CheckAndMarkRecentPacket(crc32))
   {
     /* Increase counter */
     intf->nBmfPacketsRxDup++;
@@ -363,6 +330,9 @@
   /* Compose encapsulation header */
   encapHdr = (struct TEncapHeader*) encapsulationUdpData;
   memset (encapHdr, 0, ENCAP_HDR_LEN);
+  encapHdr->type = BMF_ENCAP_TYPE;
+  encapHdr->len = BMF_ENCAP_LEN;
+  encapHdr->reserved = 0;
   encapHdr->crc32 = htonl(crc32);
 
   /* Check if the frame is captured on an OLSR interface from an OLSR neighbor.
@@ -461,19 +431,37 @@
       /* Case 2: Forward from OLSR interface to non-OLSR interface */
 
       int nBytesWritten;
+      struct sockaddr_ll dest;
 
-      /* Change source MAC address to that of sending interface */
-      SetFrameSourceMac(ethernetFrame, walker->macAddr);
-
-      /* If the encapsulated Ethernet frame is an IP local broadcast packet,
+      /* If the encapsulated IP packet is a local broadcast packet,
        * update its destination address to match the subnet of the network
        * interface on which the packet is being sent. */
-      CheckAndUpdateLocalBroadcast(GetIpPacket(ethernetFrame), &walker->broadAddr);
+      CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
+
+      memset(&dest, 0, sizeof(dest));
+      dest.sll_family = AF_PACKET;
+      dest.sll_protocol = htons(ETH_P_IP);
+      dest.sll_ifindex = if_nametoindex(walker->ifName);
+      dest.sll_halen = IFHWADDRLEN;
+
+      /* Use all-ones as destination MAC address. When the IP destination is
+       * a multicast address, the destination MAC address should normally also
+       * be a multicast address. E.g., when the destination IP is 224.0.0.1,
+       * the destination MAC should be 01:00:5e:00:00:01. However, it does not
+       * seem to matter when the destination MAC address is set to all-ones
+       * in that case. */
+      memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
 
-      nBytesWritten = write(walker->capturingSkfd, ethernetFrame, ethernetFrameLen);
-      if (nBytesWritten != ethernetFrameLen)
+      nBytesWritten = sendto(
+        walker->capturingSkfd,
+        ipPacket,
+        ipPacketLen,
+        0,
+        (struct sockaddr*) &dest,
+        sizeof(dest));
+      if (nBytesWritten != ipPacketLen)
       {
-        BmfPError("write() error forwarding pkt on \"%s\"", walker->ifName);
+        BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
       }
       else
       {
@@ -509,19 +497,37 @@
       else
       {
         int nBytesWritten;
+        struct sockaddr_ll dest;
 
-        /* Change source MAC address to that of sending interface */
-        SetFrameSourceMac(ethernetFrame, walker->macAddr);
-
-        /* If the encapsulated Ethernet frame is an IP local broadcast packet,
+        /* If the encapsulated IP packet is a local broadcast packet,
          * update its destination address to match the subnet of the network
          * interface on which the packet is being sent. */
-        CheckAndUpdateLocalBroadcast(GetIpPacket(ethernetFrame), &walker->broadAddr);
+        CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
+
+        memset(&dest, 0, sizeof(dest));
+        dest.sll_family = AF_PACKET;
+        dest.sll_protocol = htons(ETH_P_IP);
+        dest.sll_ifindex = if_nametoindex(walker->ifName);
+        dest.sll_halen = IFHWADDRLEN;
+
+        /* Use all-ones as destination MAC address. When the IP destination is
+         * a multicast address, the destination MAC address should normally also
+         * be a multicast address. E.g., when the destination IP is 224.0.0.1,
+         * the destination MAC should be 01:00:5e:00:00:01. However, it does not
+         * seem to matter when the destination MAC address is set to all-ones
+         * in that case. */
+        memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
 
-        nBytesWritten = write(walker->capturingSkfd, ethernetFrame, ethernetFrameLen);
-        if (nBytesWritten != ethernetFrameLen)
+        nBytesWritten = sendto(
+          walker->capturingSkfd,
+          ipPacket,
+          ipPacketLen,
+          0,
+          (struct sockaddr*) &dest,
+          sizeof(dest));
+        if (nBytesWritten != ipPacketLen)
         {
-          BmfPError("write() error forwarding pkt on \"%s\"", walker->ifName);
+          BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
         }
         else
         {
@@ -537,7 +543,7 @@
       } /* if (intf == walker) */
     } /* if */
   } /* for */
-}
+} /* BmfPacketCaptured */
 
 /* -------------------------------------------------------------------------
  * Function   : BmfEncapsulationPacketReceived
@@ -550,7 +556,7 @@
  *                broadcast).
  *              encapsulationUdpData - the encapsulating IP UDP data, containting
  *                the BMF encapsulation header, followed by the encapsulated
- *                Ethernet frame
+ *                IP packet
  * Output     : none
  * Return     : none
  * Data Used  : BmfInterfaces
@@ -563,14 +569,14 @@
 {
   int iAmMpr; /* True (1) if I am selected as MPR by 'forwardedBy' */
   struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
-  struct TBmfInterface* walker;
-  unsigned char* ethernetFrame; /* The encapsulated Ethernet packet */
-  u_int16_t ethernetFrameLen; /* Length of the encapsulated Ethernet packet */
-  struct ip* ipHeader; /* IP header inside the encapsulated Ethernet packet */
+  unsigned char* ipPacket; /* The encapsulated IP packet */
+  u_int16_t ipPacketLen; /* Length of the encapsulated IP packet */
+  struct ip* ipHeader; /* IP header inside the encapsulated IP packet */
   union olsr_ip_addr mcSrc; /* Original source of the encapsulated multicast packet */
   union olsr_ip_addr mcDst; /* Multicast destination of the encapsulated packet */
   struct TEncapHeader* encapsulationHdr;
   u_int16_t encapsulationUdpDataLen;
+  struct TBmfInterface* walker;
 
   /* Are we talking to ourselves? */
   if (if_ifwithaddr(forwardedBy) != NULL)
@@ -584,19 +590,14 @@
     return;
   }
 
-  ethernetFrame = GetEthernetFrame(encapsulationUdpData);
-  ethernetFrameLen = GetFrameLength(ethernetFrame);
-
-  ipHeader = GetIpHeader(ethernetFrame);
+  /* Retrieve details about the encapsulated IP packet */
+  ipPacket = GetIpPacket(encapsulationUdpData);
+  ipPacketLen = GetIpTotalLength(ipPacket);
+  ipHeader = GetIpHeader(encapsulationUdpData);
 
   COPY_IP(&mcSrc, &ipHeader->ip_src);
   COPY_IP(&mcDst, &ipHeader->ip_dst);
 
-  /* Apply drop list? No, not needed: encapsulation packets are IP-routed,
-   * so filtering should be done by adding a rule to the iptables FORWARD
-   * chain, e.g.:
-   * iptables -A FORWARD -m mac --mac-source 00:0C:29:28:0E:CC -j DROP */
-
   /* Increase counter */
   intf->nBmfPacketsRx++;
 
@@ -605,7 +606,7 @@
     8,
     "%s: encapsulated pkt of %ld bytes incoming on \"%s\": %s->%s, forwarded by %s to %s\n",
     PLUGIN_NAME_SHORT,
-    (long)ethernetFrameLen,
+    (long)ipPacketLen,
     intf->ifName,
     olsr_ip_to_string(&mcSrc),
     olsr_ip_to_string(&mcDst),
@@ -615,8 +616,20 @@
   /* Get encapsulation header */
   encapsulationHdr = (struct TEncapHeader*) encapsulationUdpData;
 
+  /* Verify correct format of BMF encapsulation header */
+  if (encapsulationHdr->type != BMF_ENCAP_TYPE ||
+      encapsulationHdr->len != BMF_ENCAP_LEN ||
+      ntohs(encapsulationHdr->reserved != 0))
+  {
+    OLSR_PRINTF(
+      8,
+      "%s: --> discarding: format of BMF encapsulation header not recognized\n",
+      PLUGIN_NAME_SHORT);
+    return;
+  }
+
   /* Check if this packet was seen recently */
-  if (CheckAndMarkRecentPacket(Hash16(ntohl(encapsulationHdr->crc32))))
+  if (CheckAndMarkRecentPacket(ntohl(encapsulationHdr->crc32)))
   {
     /* Increase counter */
     intf->nBmfPacketsRxDup++;
@@ -630,31 +643,23 @@
 
   if (EtherTunTapFd >= 0)
   {
-    /* Unpack the encapsulated Ethernet packet and send a copy to myself via
-     * the EtherTunTap interface */
+    /* Unpack the encapsulated IP packet and deliver it locally, by sending
+     * a copy into the local IP stack via the EtherTunTap interface */
 
     union olsr_ip_addr broadAddr;
     int nBytesToWrite, nBytesWritten;
     unsigned char* bufferToWrite;
 
-    /* If the encapsulated Ethernet frame is an IP local broadcast packet,
+    /* If the encapsulated IP packet is a local broadcast packet,
      * update its destination address to match the subnet of the EtherTunTap
      * interface */
     broadAddr.v4 = htonl(EtherTunTapIpBroadcast);
-    CheckAndUpdateLocalBroadcast(GetIpPacket(ethernetFrame), &broadAddr);
+    CheckAndUpdateLocalBroadcast(ipPacket, &broadAddr);
 
-    /* Start off by assuming a TAP device */
-    bufferToWrite = ethernetFrame;
-    nBytesToWrite = ethernetFrameLen;
-
-    /* If we're using the TUN device instead, we need to write an IP packet instead
-     * of an Ethernet packet */
-    if (TunOrTap == TT_TUN)
-    {
-      bufferToWrite += IP_HDR_OFFSET;
-      nBytesToWrite -= IP_HDR_OFFSET;
-    }
+    bufferToWrite = ipPacket;
+    nBytesToWrite = ipPacketLen;
 
+    /* Write the packet into the EtherTunTap interface for local delivery */
     nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite);
     if (nBytesWritten != nBytesToWrite)
     {
@@ -668,56 +673,67 @@
         PLUGIN_NAME_SHORT,
         EtherTunTapIfName);
     }
-  }
+  } /* if (EtherTunTapFd >= 0) */
 
   /* Check if I am MPR for the forwarder */
   /* TODO: olsr_lookup_mprs_set() is not thread-safe! */
   iAmMpr = (olsr_lookup_mprs_set(MainAddressOf(forwardedBy)) != NULL);
 
+  /* Compose destination address for next hop */
   memset(&forwardTo, 0, sizeof(forwardTo));
   forwardTo.sin_family = AF_INET;
   forwardTo.sin_port = htons(BMF_ENCAP_PORT);
 
+  /* Retrieve the number of bytes to be forwarded via the encapsulation socket */
   encapsulationUdpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);
 
   /* Check with each network interface what needs to be done on it */
   for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
   {
-    /* Depending on certain conditions, decide whether or not to forward
-     * the packet, and if it is forwarded, in which form (encapsulated
-     * or not). These conditions are:
-     * - is the packet going out on an OLSR interface or not? (isToOlsrIntf)
-     * - is this node selected as MPR by the node that forwarded the packet,
-     *   or not? (iAmMpr)
-     * Note that the packet is always coming in on an OLSR interface, because
-     * it is an encapsulated BMF packet.
+    /* What to do with the packet on a non-OLSR interface? Unpack
+     * encapsulated packet, and forward it.
      *
-     * Based on these conditions, 3 cases can be distinguished:
-     * - Case 1: What to do with the packet on a non-OLSR interface?
-     *   Answer: unpack encapsulated packet, [decrease its TTL and] forward it.
-     * - Case 2: The forwarding node has selected us as MPR. What to
-     *   do with the packet on an OLSR interface?
-     *   Answer: Forward it.
-     * - Case 3: The forwarding node has not selected us as MPR. What to
-     *   do with the packet on an OLSR interface?
-     *   Answer: nothing. Nodes not selected as MPR must not participate in
-     *   the flooding.
-     */
+     * What to do with the packet on an OLSR interface? Forward it only
+     * if the forwarding node has selected us as MPR (iAmMpr).
+     *
+     * Note that the packet is always coming in on an OLSR interface, because
+     * it is an encapsulated BMF packet. */
 
-    /* To a non-OLSR interface: unpack encapsulated packet and forward */
+    /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */
     if (walker->olsrIntf == NULL)
     {
       int nBytesWritten;
+      struct sockaddr_ll dest;
 
-      /* If the encapsulated Ethernet frame is an IP local broadcast packet,
+      /* If the encapsulated IP packet is a local broadcast packet,
        * update its destination address to match the subnet of the network
        * interface on which the packet is being sent. */
-      CheckAndUpdateLocalBroadcast(GetIpPacket(ethernetFrame), &walker->broadAddr);
+      CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
+
+      memset(&dest, 0, sizeof(dest));
+      dest.sll_family = AF_PACKET;
+      dest.sll_protocol = htons(ETH_P_IP);
+      dest.sll_ifindex = if_nametoindex(walker->ifName);
+      dest.sll_halen = IFHWADDRLEN;
+
+      /* Use all-ones as destination MAC address. When the IP destination is
+       * a multicast address, the destination MAC address should normally also
+       * be a multicast address. E.g., when the destination IP is 224.0.0.1,
+       * the destination MAC should be 01:00:5e:00:00:01. However, it does not
+       * seem to matter when the destination MAC address is set to all-ones
+       * in that case. */
+      memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
 
-      nBytesWritten = write(walker->capturingSkfd, ethernetFrame, ethernetFrameLen);
-      if (nBytesWritten != ethernetFrameLen)
+      nBytesWritten = sendto(
+        walker->capturingSkfd,
+        ipPacket,
+        ipPacketLen,
+        0,
+        (struct sockaddr*) &dest,
+        sizeof(dest));
+      if (nBytesWritten != ipPacketLen)
       {
-        BmfPError("write() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName);
+        BmfPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName);
       }
       else
       {
@@ -732,18 +748,26 @@
       }
     } /* if (walker->olsrIntf == NULL) */
 
-    /* To a OLSR interface: forward the packet if this node is selected as MPR by the forwarding node */
+    /* To an OLSR interface: forward the packet, but only if this node is
+     * selected as MPR by the forwarding node */
     else if (iAmMpr)
     {
+      struct TBestNeighbors bestNeighborLinks;
+      int nPossibleNeighbors;
       int nBytesWritten;
+      int nPacketsToSend;
+      int i;
 
-      /* Compose destination of encapsulation packet */
-      if (ComposeEnapsulationDestination(
-        walker,
-        &mcSrc,
-        forwardedBy,
-        forwardedTo,
-        &forwardTo) == 0)
+      /* Retrieve at most two best neigbors to forward the packet to */
+      bestNeighborLinks =
+        GetBestTwoNeighbors(
+          walker,
+          &mcSrc,
+          forwardedBy,
+          forwardedTo,
+          &nPossibleNeighbors);
+
+      if (nPossibleNeighbors <= 0)
       {
         OLSR_PRINTF(
           8,
@@ -754,54 +778,88 @@
         continue; /* for */
       }
 
-      nBytesWritten = sendto(
-        walker->encapsulatingSkfd,
-        encapsulationUdpData,
-        encapsulationUdpDataLen,
-        MSG_DONTROUTE,
-        (struct sockaddr*) &forwardTo,
-        sizeof(forwardTo));                   
-
-      if (nBytesWritten != encapsulationUdpDataLen)
+      /* Compose destination of encapsulation packet.
+       * Start by filling in the local broadcast address. */
+      COPY_IP(&forwardTo.sin_addr.s_addr, &walker->broadAddr);
+
+      /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
+       *   packet (to the best neighbor). Other neighbors listen promiscuously.
+       * - If the BMF mechanism is BM_BROADCAST,
+       *   - send one unicast packet if there is one possible neighbor,
+       *   - send two unicast packets if there are two possible neighbors, and
+       *   - only if there are more than two possible neighbors, then send an
+       *     (WLAN-air-expensive, less reliable) broadcast packet. */
+      if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors < 2)
       {
-        BmfPError("sendto() error forwarding encapsulated pkt on \"%s\"", walker->ifName);
+        nPacketsToSend = 1;
       }
-      else
+      else /* BmfMechanism == BM_BROADCAST && nPossibleNeighbors >= 2 */
       {
-        /* Increase counter */
-        walker->nBmfPacketsTx++;
-
-        OLSR_PRINTF(
-          8,
-          "%s: --> forwarded on \"%s\" to %s\n",
-          PLUGIN_NAME_SHORT,
-          walker->ifName,
-          inet_ntoa(forwardTo.sin_addr));
+        nPacketsToSend = 2;
       }
+
+      for (i = 0; i < nPacketsToSend; i++)
+      {
+        if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors <= 2)
+        {
+          /* For unicast, overwrite the local broadcast address which was filled in
+           * above */
+          COPY_IP(&forwardTo.sin_addr.s_addr, &bestNeighborLinks.links[i]->neighbor_iface_addr);
+        }
+
+        /* Forward the BMF packet via the encapsulation socket */
+        nBytesWritten = sendto(
+          walker->encapsulatingSkfd,
+          encapsulationUdpData,
+          encapsulationUdpDataLen,
+          MSG_DONTROUTE,
+          (struct sockaddr*) &forwardTo,
+          sizeof(forwardTo));                   
+
+        /* Evaluate and display result */
+        if (nBytesWritten != encapsulationUdpDataLen)
+        {
+          BmfPError("sendto() error forwarding encapsulated pkt on \"%s\"", walker->ifName);
+        }
+        else
+        {
+          /* Increase counter */
+          walker->nBmfPacketsTx++;
+
+          OLSR_PRINTF(
+            8,
+            "%s: --> forwarded on \"%s\" to %s\n",
+            PLUGIN_NAME_SHORT,
+            walker->ifName,
+            inet_ntoa(forwardTo.sin_addr));
+        } /* if */
+      } /* for */
     }  /* else if (iAmMpr) */
+
     else /* walker->olsrIntf != NULL && !iAmMpr */
     {
-      /* 'walker' is an OLSR interface and I am not selected as MPR */
+      /* 'walker' is an OLSR interface, but I am not selected as MPR. In that
+       * case, don't forward. */
       OLSR_PRINTF(
         8,
         "%s: --> not forwarding on \"%s\": I am not selected as MPR by %s\n",
         PLUGIN_NAME_SHORT,
         walker->ifName,
         olsr_ip_to_string(forwardedBy));
-    }
+    } /* else */
   } /* for */
-}
+} /* BmfEncapsulationPacketReceived */
 
 /* -------------------------------------------------------------------------
  * Function   : BmfTunPacketCaptured
- * Description: Handle a Ethernet frame, captured outgoing on the tuntap interface
+ * Description: Handle an IP packet, captured outgoing on the tuntap interface
  * Input      : encapsulationUdpData - space for the encapsulation header, followed by
- *                the captured Ethernet frame
+ *                the captured outgoing IP packet
  * Output     : none
  * Return     : none
  * Data Used  : none
  * Notes      : The packet is assumed to be captured on a socket of family
- *              PF_PACKET and type SOCK_RAW.
+ *              PF_PACKET and type SOCK_DGRAM (cooked).
  * ------------------------------------------------------------------------- */
 static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData)
 {
@@ -809,22 +867,15 @@
   union olsr_ip_addr dstIp;
   union olsr_ip_addr broadAddr;
   struct TBmfInterface* walker;
-  unsigned char* ethernetFrame;
-  u_int16_t ethernetFrameLen;
+  unsigned char* ipPacket;
+  u_int16_t ipPacketLen;
   struct ip* ipHeader;
   u_int32_t crc32;
   struct TEncapHeader* encapHdr;
 
-  ethernetFrame = GetEthernetFrame(encapsulationUdpData);
-  ethernetFrameLen = GetFrameLength(ethernetFrame);
-
-  /* Only forward IPv4 packets */
-  if (GetEtherType(ethernetFrame) != IPV4_TYPE)
-  {
-    return;
-  }
-
-  ipHeader = GetIpHeader(ethernetFrame);
+  ipPacket = GetIpPacket(encapsulationUdpData);
+  ipPacketLen = GetIpTotalLength(ipPacket);
+  ipHeader = GetIpHeader(encapsulationUdpData);
 
   /* Only forward multicast packets. If configured, also forward local broadcast packets */
   COPY_IP(&dstIp, &ipHeader->ip_dst);
@@ -844,14 +895,16 @@
     8,
     "%s: outgoing pkt of %ld bytes captured on tuntap interface \"%s\": %s->%s\n",
     PLUGIN_NAME_SHORT,
-    (long)ethernetFrameLen,
+    (long)ipPacketLen,
     EtherTunTapIfName,
     olsr_ip_to_string(&srcIp),
     olsr_ip_to_string(&dstIp));
 
+  /* Calculate packet fingerprint */
+  crc32 = PacketCrc32(ipPacket, ipPacketLen);
+
   /* Check if this packet was seen recently */
-  crc32 = PacketCrc32(ethernetFrame, ethernetFrameLen);
-  if (CheckAndMarkRecentPacket(Hash16(crc32)))
+  if (CheckAndMarkRecentPacket(crc32))
   {
     OLSR_PRINTF(
       8,
@@ -863,6 +916,9 @@
   /* Compose encapsulation header */
   encapHdr = (struct TEncapHeader*) encapsulationUdpData;
   memset (encapHdr, 0, ENCAP_HDR_LEN);
+  encapHdr->type = BMF_ENCAP_TYPE;
+  encapHdr->len = BMF_ENCAP_LEN;
+  encapHdr->reserved = 0;
   encapHdr->crc32 = htonl(crc32);
 
   /* Check with each network interface what needs to be done on it */
@@ -883,19 +939,37 @@
        * Answer 2 (better): Forward it. */
 
       int nBytesWritten;
+      struct sockaddr_ll dest;
 
-      /* Change source MAC address to that of sending interface */
-      SetFrameSourceMac(ethernetFrame, walker->macAddr);
-
-      /* If the encapsulated Ethernet frame is an IP local broadcast packet,
+      /* If the encapsulated IP packet is a local broadcast packet,
        * update its destination address to match the subnet of the network
        * interface on which the packet is being sent. */
-      CheckAndUpdateLocalBroadcast(GetIpPacket(ethernetFrame), &walker->broadAddr);
+      CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
 
-      nBytesWritten = write(walker->capturingSkfd, ethernetFrame, ethernetFrameLen);
-      if (nBytesWritten != ethernetFrameLen)
+      memset(&dest, 0, sizeof(dest));
+      dest.sll_family = AF_PACKET;
+      dest.sll_protocol = htons(ETH_P_IP);
+      dest.sll_ifindex = if_nametoindex(walker->ifName);
+      dest.sll_halen = IFHWADDRLEN;
+
+      /* Use all-ones as destination MAC address. When the IP destination is
+       * a multicast address, the destination MAC address should normally also
+       * be a multicast address. E.g., when the destination IP is 224.0.0.1,
+       * the destination MAC should be 01:00:5e:00:00:01. However, it does not
+       * seem to matter when the destination MAC address is set to all-ones
+       * in that case. */
+      memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
+
+      nBytesWritten = sendto(
+        walker->capturingSkfd,
+        ipPacket,
+        ipPacketLen,
+        0,
+        (struct sockaddr*) &dest,
+        sizeof(dest));
+      if (nBytesWritten != ipPacketLen)
       {
-        BmfPError("write() error forwarding pkt on \"%s\"", walker->ifName);
+        BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
       }
       else
       {
@@ -910,7 +984,7 @@
       } /* if */
     } /* if */
   } /* for */
-}
+} /* BmfTunPacketCaptured */
 
 /* -------------------------------------------------------------------------
  * Function   : DoBmf
@@ -959,7 +1033,7 @@
         struct sockaddr_ll pktAddr;
         socklen_t addrLen = sizeof(pktAddr);
         int nBytes;
-        unsigned char* ethernetFrame;
+        unsigned char* ipPacket;
 
         /* A packet was captured. */
 
@@ -967,10 +1041,10 @@
 
         /* Receive the captured Ethernet frame, leaving space for the BMF
          * encapsulation header */
-        ethernetFrame = GetEthernetFrame(rxBuffer);
+        ipPacket = GetIpPacket(rxBuffer);
         nBytes = recvfrom(
           skfd,
-          ethernetFrame,
+          ipPacket,
           BMF_BUFFER_SIZE - ENCAP_HDR_LEN,
           0,
           (struct sockaddr*)&pktAddr,
@@ -982,13 +1056,13 @@
           continue; /* for */
         } /* if (nBytes < 0) */
 
-        /* Check if the number of received bytes is large enough for an Ethernet
-         * frame which contains at least a minimum-size IP header.
+        /* Check if the number of received bytes is large enough for an IP
+         * packet which contains at least a minimum-size IP header.
          * Note: There is an apparent bug in the packet socket implementation in
          * combination with VLAN interfaces. On a VLAN interface, the value returned
          * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
          * returned on a non-VLAN interface, for the same ethernet frame. */
-        if (nBytes < IP_HDR_OFFSET + (int)sizeof(struct ip))
+        if (nBytes < (int)sizeof(struct ip))
         {
           olsr_printf(
             1,
@@ -1047,8 +1121,13 @@
           continue; /* for */
         } /* if (nBytes < 0) */
 
+        /* Check if the received packet is actually directed to another
+         * node on the LAN */
         if (pktAddr.sll_pkttype != PACKET_OTHERHOST)
         {
+          /* No, the packet is directed to this node. In that case it will
+           * be, or will already have been received, via the encapsulating
+           * socket. Discard it here. */
           continue; /* for */
         } /* if (pktAddr.sll_pkttype ...) */
 
@@ -1060,7 +1139,7 @@
           continue; /* for */
         }
 
-        udpHeader = (struct udphdr*)(rxBuffer + GetHeaderLength(rxBuffer));
+        udpHeader = (struct udphdr*)(rxBuffer + GetIpHeaderLength(rxBuffer));
         destPort = ntohs(udpHeader->dest);
         if (destPort != BMF_ENCAP_PORT)
         {
@@ -1079,7 +1158,7 @@
          * not) be 4 (bytes) larger than the value returned on a non-VLAN interface, for
          * the same ethernet frame. */
         minimumLength =
-          GetHeaderLength(rxBuffer) +
+          GetIpHeaderLength(rxBuffer) +
           sizeof(struct udphdr) +
           ENCAP_HDR_LEN +
           IP_HDR_OFFSET +
@@ -1102,7 +1181,7 @@
           walker,
           &forwardedBy,
           &forwardedTo,
-          rxBuffer + GetHeaderLength(rxBuffer) + sizeof(struct udphdr));
+          rxBuffer + GetIpHeaderLength(rxBuffer) + sizeof(struct udphdr));
 
       } /* if (skfd >= 0 && (FD_ISSET...)) */
     } /* for */
@@ -1157,6 +1236,10 @@
           continue; /* for */
         }
 
+        /* Unfortunately, the recvfrom call does not return the destination
+         * of the encapsulation packet (the destination may be either the
+         * my unicast or my local broadcast address). Therefore we fill in 'NULL'
+         * for the 'forwardedTo' parameter. */
         BmfEncapsulationPacketReceived(walker, &forwardedBy, NULL, rxBuffer);
 
       } /* if (skfd >= 0 && (FD_ISSET...)) */
@@ -1168,43 +1251,17 @@
        * network interface */
 
       int nBytes;
-      unsigned char* ethernetFrame;
+      unsigned char* ipPacket;
       unsigned char* bufferToRead;
       size_t nBytesToRead;
 
       nFdBitsSet--;
 
       /* Receive the packet, leaving space for the BMF encapsulation header */
-      ethernetFrame = GetEthernetFrame(rxBuffer);
+      ipPacket = GetIpPacket(rxBuffer);
     
-      bufferToRead = ethernetFrame;
+      bufferToRead = ipPacket;
       nBytesToRead = BMF_BUFFER_SIZE - ENCAP_HDR_LEN;
-      if (TunOrTap == TT_TUN)
-      {
-        u_int16_t type;
-
-        /* When using a tun-interface, also leave space for an Ethernet header */
-        bufferToRead += IP_HDR_OFFSET;
-        nBytesToRead -= IP_HDR_OFFSET;
-
-        /* Compose a valid Ethernet header, for other BMF-nodes which may be
-         * receiving their BMF packets on a tap-interface. */
-
-        /* Use all-ones as destination MAC address. When the IP destination is
-         * a multicast address, the destination MAC address should normally also
-         * be a multicast address. E.g., when the destination IP is 224.0.0.1,
-         * the destination MAC should be 01:00:5e:00:00:01. However, it does not
-         * seem to matter when the destination MAC address is set to all-ones
-         * in that case. */
-        memset(ethernetFrame, 0xFF, IFHWADDRLEN);
-
-        /* Source MAC address is not important. Set to all-zeros */
-        memset(ethernetFrame + IFHWADDRLEN, 0x00, IFHWADDRLEN);
-
-        /* Ethertype = 0800 = IP */
-        type = htons(0x0800);
-        memcpy(ethernetFrame + ETH_TYPE_OFFSET, &type, 2);
-      }
 
       nBytes = read(EtherTunTapFd, bufferToRead, nBytesToRead);
 
@@ -1214,13 +1271,9 @@
       }
       else
       {
-        /* Check if the number of received bytes is large enough for an Ethernet
-         * frame which contains at least a minimum-size IP header */
-        if (TunOrTap == TT_TUN)
-        {
-          nBytes += IP_HDR_OFFSET;
-        }
-        if (nBytes < IP_HDR_OFFSET + (int)sizeof(struct ip))
+        /* Check if the number of received bytes is large enough for an IP
+         * packet which contains at least a minimum-size IP header */
+        if (nBytes < (int)sizeof(struct ip))
         {
           olsr_printf(
             1,
@@ -1235,11 +1288,11 @@
 
           BmfTunPacketCaptured(rxBuffer);
 
-        } /* if (nBytes < IP_HDR_OFFSET... */
+        } /* if (nBytes < ... */
       } /* if (nBytes < 0) */
     } /* if (nFdBitsSet > 0 && ... */
   } /* while (nFdBitsSet > 0) */
-}
+} /* DoBmf */
 
 /* -------------------------------------------------------------------------
  * Function   : BmfSignalHandler
@@ -1252,7 +1305,7 @@
 static void BmfSignalHandler(int signo __attribute__((unused)))
 {
   BmfThreadRunning = 0;
-}
+} /* BmfSignalHandler */
 
 /* -------------------------------------------------------------------------
  * Function   : BmfRun
@@ -1293,7 +1346,7 @@
   }
 
   return NULL;
-}
+} /* BmfRun */
 
 /* -------------------------------------------------------------------------
  * Function   : InterfaceChange
@@ -1338,8 +1391,9 @@
       interf->int_name, action);
     break;
   }
+
   return 0;
-}
+} /* InterfaceChange */
 
 /* -------------------------------------------------------------------------
  * Function   : InitBmf
@@ -1376,7 +1430,7 @@
   }
 
   return 1;
-}
+} /* InitBmf */
 
 /* -------------------------------------------------------------------------
  * Function   : CloseBmf
@@ -1384,7 +1438,7 @@
  * Input      : none
  * Output     : none
  * Return     : none
- * Data Used  : BmfThreadRunning, BmfThread
+ * Data Used  : BmfThread
  * ------------------------------------------------------------------------- */
 void CloseBmf(void)
 {
@@ -1414,7 +1468,7 @@
 
   /* Clean up after the BmfThread has been killed */
   CloseBmfNetworkInterfaces();
-}
+} /* CloseBmf */
 
 /* -------------------------------------------------------------------------
  * Function   : RegisterBmfParameter
@@ -1427,11 +1481,7 @@
  * ------------------------------------------------------------------------- */
 int RegisterBmfParameter(char* key, char* value)
 {
-  if (strcmp(key, "DropMac") == 0)
-  {
-    return DropMac(value);
-  }
-  else if (strcmp(key, "NonOlsrIf") == 0)
+  if (strcmp(key, "NonOlsrIf") == 0)
   {
     return AddNonOlsrBmfIf(value);
   }
@@ -1443,10 +1493,6 @@
   {
     return SetBmfInterfaceName(value);
   }
-  else if (strcmp(key, "BmfInterfaceType") == 0)
-  {
-    return SetBmfInterfaceType(value);
-  }
   else if (strcmp(key, "BmfInterfaceIp") == 0)
   {
     return SetBmfInterfaceIp(value);
@@ -1462,5 +1508,5 @@
 
   /* Key not recognized */
   return 0;
-}
+} /* RegisterBmfParameter */
 
diff -Nur olsrd-0.5.0.cvs/lib/bmf/src/Bmf.h olsrd-0.5.0/lib/bmf/src/Bmf.h
--- olsrd-0.5.0.cvs/lib/bmf/src/Bmf.h	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/src/Bmf.h	2007-05-13 04:29:02.000000000 +0200
@@ -3,7 +3,7 @@
 
 /*
  * OLSR Basic Multicast Forwarding (BMF) plugin.
- * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
+ * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
  * Written by Erik Tromp.
  * All rights reserved.
  *
@@ -43,9 +43,9 @@
 /* BMF plugin data */
 #define PLUGIN_NAME "OLSRD Basic Multicast Forwarding (BMF) plugin"
 #define PLUGIN_NAME_SHORT "OLSRD BMF"
-#define PLUGIN_VERSION "1.4 (" __DATE__ " " __TIME__ ")"
+#define PLUGIN_VERSION "1.5 (" __DATE__ " " __TIME__ ")"
 #define PLUGIN_COPYRIGHT "  (C) Thales Communications Huizen, Netherlands"
-#define PLUGIN_AUTHOR "  Erik Tromp (erik.tromp@nl.thalesgroup.com)"
+#define PLUGIN_AUTHOR "  Erik Tromp (eriktromp@users.sourceforge.net)"
 #define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION "\n" PLUGIN_COPYRIGHT "\n" PLUGIN_AUTHOR
 
 /* UDP-Port on which multicast packets are encapsulated */
diff -Nur olsrd-0.5.0.cvs/lib/bmf/src/DropList.c olsrd-0.5.0/lib/bmf/src/DropList.c
--- olsrd-0.5.0.cvs/lib/bmf/src/DropList.c	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/src/DropList.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,126 +0,0 @@
-/*
- * OLSR Basic Multicast Forwarding (BMF) plugin.
- * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
- * Written by Erik Tromp.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without 
- * modification, are permitted provided that the following conditions 
- * are met:
- *
- * * Redistributions of source code must retain the above copyright 
- *   notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright 
- *   notice, this list of conditions and the following disclaimer in 
- *   the documentation and/or other materials provided with the 
- *   distribution.
- * * Neither the name of Thales, BMF nor the names of its 
- *   contributors may be used to endorse or promote products derived 
- *   from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
- * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* -------------------------------------------------------------------------
- * File       : DropList.c
- * Description: List of MAC addresses of hosts from which received multicast
- *              and local broadcast packets are dropped.
- * Created    : 29 Jun 2006
- *
- * ------------------------------------------------------------------------- */
-
-
-#include "DropList.h"
-
-/* System includes */
-#include <assert.h> /* assert() */
-#include <stddef.h> /* NULL */
-#include <stdio.h> /* sscanf */
-#include <stdlib.h> /* malloc */
-#include <string.h> /* memcmp */
-
-/* OLSRD includes */
-#include "olsr.h" /* olsr_printf */
-
-/* Plugin includes */
-#include "Bmf.h" /* PLUGIN_NAME */
-#include "Packet.h" /* IFHWADDRLEN */
-
-static struct TMacAddress* DroppedMacAddresses = NULL;
-
-/* -------------------------------------------------------------------------
- * Function   : DropMac
- * Description: Register a MAC address in the drop list
- * Input      : macStr - MAC address as string
- * Output     : none
- * Return     : fail (0) or success (1)
- * Data Used  : DroppedMacAddresses
- * Notes      : The registered MAC address will be matched to the source MAC 
- *              address of incoming multicast packets. If matched, the multicast 
- *              packet will be dropped. 
- *              The drop list is needed only in lab environments, where hidden
- *              nodes are simulated by using iptables with the
- *              -m mac helper and --mac-source option (as in: 
- *              "iptables -A INPUT -m mac --mac-source 00:0C:29:EE:C9:D0 -j DROP") 
- *              The drop list is needed because network interfaces in promiscuous 
- *              mode will still capture packets even if they are specified to 
- *              be dropped by iptables.
- * ------------------------------------------------------------------------- */
-int DropMac(const char* macStr)
-{
-  unsigned int mac[6];
-  int n;
-  struct TMacAddress* newMacAddress;
-  int i;
-
-  assert(macStr != NULL);
-
-  n = sscanf(macStr, "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
-  if (n != 6)
-  {
-    olsr_printf(1, "%s: Invalid Ethernet address '%s'\n", PLUGIN_NAME, macStr);
-    return 0;
-  }
-
-  newMacAddress = malloc(sizeof(struct TMacAddress));
-  for (i = 0; i < 6; i++)
-  {
-    newMacAddress->addr[i] = (unsigned char) mac[i];
-  }
-  newMacAddress->next = DroppedMacAddresses;
-  DroppedMacAddresses = newMacAddress;
-
-  return 1;
-}
-
-/* -------------------------------------------------------------------------
- * Function   : IsInDropList
- * Description: Check if a MAC address is in the drop list
- * Input      : macAddress
- * Output     : none
- * Return     : true (1) or false (0)
- * Data Used  : DroppedMacAddresses
- * ------------------------------------------------------------------------- */
-int IsInDropList(const unsigned char* macAddress)
-{
-  struct TMacAddress* ma = DroppedMacAddresses;
-
-  assert(macAddress != NULL);
-
-  while (ma != NULL)
-  {
-    if (memcmp(ma->addr, macAddress, IFHWADDRLEN) == 0) return 1;
-    ma = ma->next;
-  }
-  return 0;
-}
-
diff -Nur olsrd-0.5.0.cvs/lib/bmf/src/DropList.h olsrd-0.5.0/lib/bmf/src/DropList.h
--- olsrd-0.5.0.cvs/lib/bmf/src/DropList.h	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/src/DropList.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,52 +0,0 @@
-#ifndef _BMF_DROPLIST_H
-#define _BMF_DROPLIST_H
-
-/*
- * OLSR Basic Multicast Forwarding (BMF) plugin.
- * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
- * Written by Erik Tromp.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without 
- * modification, are permitted provided that the following conditions 
- * are met:
- *
- * * Redistributions of source code must retain the above copyright 
- *   notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright 
- *   notice, this list of conditions and the following disclaimer in 
- *   the documentation and/or other materials provided with the 
- *   distribution.
- * * Neither the name of Thales, BMF nor the names of its 
- *   contributors may be used to endorse or promote products derived 
- *   from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
- * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* -------------------------------------------------------------------------
- * File       : DropList.h
- * Description: List of MAC addresses of hosts from which all packets are dropped.
- * Created    : 29 Jun 2006
- *
- * ------------------------------------------------------------------------- */
-
-struct TMacAddress
-{
-  unsigned char addr[6];
-  struct TMacAddress* next;
-};
-
-int DropMac(const char* macStr);
-int IsInDropList(const unsigned char* macAddress);
-
-#endif /* _BMF_DROPLIST_H */
diff -Nur olsrd-0.5.0.cvs/lib/bmf/src/NetworkInterfaces.c olsrd-0.5.0/lib/bmf/src/NetworkInterfaces.c
--- olsrd-0.5.0.cvs/lib/bmf/src/NetworkInterfaces.c	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/src/NetworkInterfaces.c	2007-05-13 04:29:24.000000000 +0200
@@ -1,6 +1,6 @@
 /*
  * OLSR Basic Multicast Forwarding (BMF) plugin.
- * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
+ * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
  * Written by Erik Tromp.
  * All rights reserved.
  *
@@ -50,7 +50,7 @@
 #include <assert.h> /* assert() */
 #include <net/if.h> /* socket(), ifreq, if_indextoname(), if_nametoindex() */
 #include <netinet/in.h> /* htons() */
-#include <linux/if_ether.h> /* ETH_P_ALL */
+#include <linux/if_ether.h> /* ETH_P_IP */
 #include <linux/if_packet.h> /* packet_mreq, PACKET_MR_PROMISC, PACKET_ADD_MEMBERSHIP */
 #include <linux/if_tun.h> /* IFF_TAP */
 #include <netinet/ip.h> /* struct ip */
@@ -87,12 +87,6 @@
  * setting the plugin parameter "BmfInterface". */
 char EtherTunTapIfName[IFNAMSIZ] = "bmf0";
 
-/* If the plugin parameter "BmfInterfaceType" is set to "tap", an
- * EtherTap interface will be used, and this variable will be set to TT_TAP. If
- * "BmfInterfaceType" is set to "tun" or not set at all, an IP tunnel interface 
- * used, and this variable will be set to TT_TUN. */
-enum TTunOrTap TunOrTap = TT_TUN;
-
 /* The underlying mechanism to forward multicast packets. Either:
  * - BM_BROADCAST: BMF uses the IP local broadcast as destination address
  * - BM_UNICAST_PROMISCUOUS: BMF uses the IP address of the best neighbor as
@@ -136,33 +130,7 @@
   strncpy(EtherTunTapIfName, ifname, IFNAMSIZ - 1);
   EtherTunTapIfName[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
   return 1;
-}
-
-/* -------------------------------------------------------------------------
- * Function   : SetBmfInterfaceType
- * Description: Overrule the default network interface type ("tun") of the
- *              EtherTunTap interface
- * Input      : iftype - network interface type, either "tun" or "tap"
- * Output     : none
- * Return     : fail (0) or success (1)
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-int SetBmfInterfaceType(const char* iftype)
-{
-  if (strcmp(iftype, "tun") == 0)
-  {
-    TunOrTap = TT_TUN;
-    return 1;
-  }
-  else if (strcmp(iftype, "tap") == 0)
-  {
-    TunOrTap = TT_TAP;
-    return 1;
-  }
-
-  /* Value not recognized */
-  return 0;
-}
+} /* SetBmfInterfaceName */
 
 /* -------------------------------------------------------------------------
  * Function   : SetBmfInterfaceIp
@@ -223,7 +191,7 @@
 
   /* Compose IP broadcast address in host byte order */
   EtherTunTapIpBroadcast = EtherTunTapIp;
-  for (i=prefixLen; i < IPV4_MAX_PREFIXLEN; i++)
+  for (i = prefixLen; i < IPV4_MAX_PREFIXLEN; i++)
   {
     EtherTunTapIpBroadcast |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i));
   }
@@ -231,7 +199,7 @@
   TunTapIpOverruled = 1;
 
   return 1;
-}
+} /* SetBmfInterfaceIp */
 
 /* -------------------------------------------------------------------------
  * Function   : SetCapturePacketsOnOlsrInterfaces
@@ -257,7 +225,7 @@
 
   /* Value not recognized */
   return 0;
-}
+} /* SetCapturePacketsOnOlsrInterfaces */
 
 /* -------------------------------------------------------------------------
  * Function   : SetBmfMechanism
@@ -283,7 +251,7 @@
 
   /* Value not recognized */
   return 0;
-}
+} /* SetBmfMechanism */
 
 /* -------------------------------------------------------------------------
  * Function   : AddDescriptorToInputSet
@@ -304,7 +272,7 @@
 
   /* Add descriptor to input set */
   FD_SET(skfd, &InputSet);
-}
+} /* AddDescriptorToInputSet */
 
 /* To save the state of the IP spoof filter for the EtherTunTap interface */
 static char EthTapSpoofState = '1';
@@ -366,7 +334,7 @@
   fclose(procSpoof);
 
   return 1;
-}
+} /* DeactivateSpoofFilter */
 
 /* -------------------------------------------------------------------------
  * Function   : RestoreSpoofFilter
@@ -398,7 +366,7 @@
     fputc(EthTapSpoofState, procSpoof);
     fclose(procSpoof);
   }
-}
+} /* RestoreSpoofFilter */
 
 #ifndef USING_THALES_LINK_COST_ROUTING
 /* -------------------------------------------------------------------------
@@ -421,35 +389,41 @@
   {
     return 1.0 / (loss * neigh_loss);
   }
-}
+} /* CalcEtx */
 #endif /* USING_THALES_LINK_COST_ROUTING */
 
 /* -------------------------------------------------------------------------
- * Function   : GetBestNeighbor
- * Description: Get the best neighbor on an interface to send a BMF packet to
+ * Function   : GetBestTwoNeighbors
+ * Description: Find at most two best neighbors on a network interface to forward
+ *              a BMF packet to
  * Input      : intf - the network interface
  *              source - the source IP address of the BMF packet 
  *              forwardedBy - the IP address of the node that forwarded the BMF
  *                packet
  *              forwardedTo - the IP address of the node to which the BMF packet
- *                was directed 
+ *                was directed
  * Output     : nPossibleNeighbors - number of found possible neighbors
- * Return     : the best neighbor, or NULL if none found
+ * Return     : The list of the two best neighbors. If only one best neighbor is
+ *              found, the second list entry is NULL. If no neigbors are found,
+ *              the first and second list entries are both NULL.
  * Data Used  : none
  * ------------------------------------------------------------------------- */
-struct link_entry* GetBestNeighbor(
+struct TBestNeighbors GetBestTwoNeighbors(
   struct TBmfInterface* intf,
   union olsr_ip_addr* source,
   union olsr_ip_addr* forwardedBy,
   union olsr_ip_addr* forwardedTo,
   int* nPossibleNeighbors)
 {
+  struct TBestNeighbors result;
+  result.links[0] = NULL;
+  result.links[1] = NULL;
+
   /* handle the non-LQ case */
 
   if (olsr_cnf->lq_level == 0)
   {
     struct link_entry* walker;
-    struct link_entry* bestLink = NULL;
     *nPossibleNeighbors = 0;
 
     /* TODO: get_link_set() is not thread-safe! */
@@ -513,34 +487,18 @@
 
       *nPossibleNeighbors += 1;
 
-      /* Remember the first found link */
-      if (bestLink == NULL)
+      /* In the non-LQ case, it is not possible to select neigbors
+       * by quality or cost. So just remember the first two found links. */
+      if (result.links[0] == NULL)
       {
-        bestLink = walker;
+        result.links[0] = walker;
       }
-
+      else if (result.links[1] == NULL)
+      {
+        result.links[1] = walker;
+      } /* if */
     } /* for */
 
-    if (bestLink == NULL)
-    {
-      OLSR_PRINTF(
-        9,
-        "%s: ----> No suitable neighbor found to forward to on \"%s\"\n",
-        PLUGIN_NAME_SHORT,
-        intf->ifName);
-    }
-    else
-    {
-      OLSR_PRINTF(
-        9,
-        "%s: ----> Best %sneighbor to forward to on \"%s\" is %s\n",
-        PLUGIN_NAME_SHORT,
-        *nPossibleNeighbors == 1 ? "(and only) " : "",
-        intf->ifName,
-        olsr_ip_to_string(&bestLink->neighbor_iface_addr));
-    }
-
-    return bestLink;
   }
   /* handle the LQ case */
   else
@@ -548,9 +506,9 @@
 #ifdef USING_THALES_LINK_COST_ROUTING
 
     struct link_entry* walker;
-    struct link_entry* bestLink = NULL;
     float previousLinkCost = INFINITE_COST;
     float bestLinkCost = INFINITE_COST;
+    float oneButBestLinkCost = INFINITE_COST;
     *nPossibleNeighbors = 0;
 
     if (forwardedBy != NULL)
@@ -709,41 +667,26 @@
 
       *nPossibleNeighbors += 1;
 
-      /* Remember the best link. If all are very bad, remember none. */
+      /* Remember the best two links. If all are very bad, remember none. */
       if (walker->link_cost < bestLinkCost)
       {
-        bestLink = walker;
+        result.links[1] = result.links[0];
+        result.links[0] = walker;
         bestLinkCost = walker->link_cost;
-	    }
+      }
+      else if (walker->link_cost < oneButBestLinkCost)
+      {
+        result.links[1] = walker;
+        oneButBestLinkCost = walker->link_cost;
+      } /* if */
     } /* for */
 
-    if (bestLink == NULL)
-    {
-      OLSR_PRINTF(
-        9,
-        "%s: ----> No suitable neighbor found to forward to on \"%s\"\n",
-        PLUGIN_NAME_SHORT,
-        intf->ifName);
-    }
-    else
-    {
-      OLSR_PRINTF(
-        9,
-        "%s: ----> Best %sneighbor to forward to on \"%s\" is %s\n",
-        PLUGIN_NAME_SHORT,
-        *nPossibleNeighbors == 1 ? "(and only) " : "",
-        intf->ifName,
-        olsr_ip_to_string(&bestLink->neighbor_iface_addr));
-    }
-
-    return bestLink;
-
 #else /* USING_THALES_LINK_COST_ROUTING */
         
     struct link_entry* walker;
-    struct link_entry* bestLink = NULL;
     float previousLinkEtx = INFINITE_ETX;
     float bestEtx = INFINITE_ETX; 
+    float oneButBestEtx = INFINITE_ETX; 
     *nPossibleNeighbors = 0;
 
     if (forwardedBy != NULL)
@@ -919,40 +862,60 @@
 
       *nPossibleNeighbors += 1;
 
-      /* Remember the best link. If all are very bad, remember none. */
+      /* Remember the best two links. If all are very bad, remember none. */
       if (currEtx < bestEtx)
       {
-        bestLink = walker;
+        result.links[1] = result.links[0];
+        result.links[0] = walker;
         bestEtx = currEtx;
       }
-
+      else if (currEtx < oneButBestEtx)
+      {
+        result.links[1] = walker;
+        oneButBestEtx = currEtx;
+      } /* if */
     } /* for */
 
-    if (bestLink == NULL)
-    {
-      OLSR_PRINTF(
-        9,
-        "%s: ----> No suitable neighbor found to forward to on \"%s\"\n",
-        PLUGIN_NAME_SHORT,
-        intf->ifName);
-    }
-    else
+#endif /* USING_THALES_LINK_COST_ROUTING */
+
+  } /* if */
+
+  /* Display the result of the neighbor search */
+  if (result.links[0] == NULL)
+  {
+    OLSR_PRINTF(
+      9,
+      "%s: ----> No suitable neighbor found to forward to on \"%s\"\n",
+      PLUGIN_NAME_SHORT,
+      intf->ifName);
+  }
+  else
+  {
+    OLSR_PRINTF(
+      9,
+      "%s: ----> Best neighbor%s to forward to on \"%s\": ",
+      PLUGIN_NAME_SHORT,
+      *nPossibleNeighbors == 1 ? "" : "s",
+      intf->ifName);
+
+    OLSR_PRINTF(
+      9,
+      "%s",
+      olsr_ip_to_string(&result.links[0]->neighbor_iface_addr));
+
+    if (result.links[1] != NULL)
     {
       OLSR_PRINTF(
         9,
-        "%s: ----> Best %sneighbor to forward to on \"%s\" is %s\n",
-        PLUGIN_NAME_SHORT,
-        *nPossibleNeighbors == 1 ? "(and only) " : "",
-        intf->ifName,
-        olsr_ip_to_string(&bestLink->neighbor_iface_addr));
-    }
-
-    return bestLink;
-
-#endif /* USING_THALES_LINK_COST_ROUTING */
+        ", %s",
+        olsr_ip_to_string(&result.links[1]->neighbor_iface_addr));
+    } /* if */
 
+    OLSR_PRINTF(9, "\n");
   } /* if */
-} /* GetBestNeighbor */
+
+  return result;
+} /* GetBestTwoNeighbors */
 
 /* -------------------------------------------------------------------------
  * Function   : CreateCaptureSocket
@@ -961,7 +924,7 @@
  * Output     : none
  * Return     : the socket descriptor ( >= 0), or -1 if an error occurred
  * Data Used  : none
- * Notes      : The socket is a raw packet socket, bound to the specified
+ * Notes      : The socket is a cooked IP packet socket, bound to the specified
  *              network interface
  * ------------------------------------------------------------------------- */
 static int CreateCaptureSocket(const char* ifName)
@@ -971,8 +934,8 @@
   struct ifreq req;
   struct sockaddr_ll bindTo;
 
-  /* Open raw packet socket */
-  int skfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+  /* Open cooked IP packet socket */
+  int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
   if (skfd < 0)
   {
     BmfPError("socket(PF_PACKET) error");
@@ -1004,7 +967,7 @@
   /* Bind the socket to the specified interface */
   memset(&bindTo, 0, sizeof(bindTo));
   bindTo.sll_family = AF_PACKET;
-  bindTo.sll_protocol = htons(ETH_P_ALL);
+  bindTo.sll_protocol = htons(ETH_P_IP);
   bindTo.sll_ifindex = ifIndex;
   memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
   bindTo.sll_halen = IFHWADDRLEN;
@@ -1027,17 +990,17 @@
   AddDescriptorToInputSet(skfd);
 
   return skfd;
-}
+} /* CreateCaptureSocket */
 
 /* -------------------------------------------------------------------------
  * Function   : CreateListeningSocket
  * Description: Create socket for promiscuously listening to BMF packets.
- *              Used when 'BmfMechanism' is BM_UNICAST_PROMISCUOUS
+ *              Used only when 'BmfMechanism' is BM_UNICAST_PROMISCUOUS
  * Input      : ifname - network interface (e.g. "eth0")
  * Output     : none
  * Return     : the socket descriptor ( >= 0), or -1 if an error occurred
  * Data Used  : none
- * Notes      : The socket is an UDP (datagram) packet socket, bound to the specified
+ * Notes      : The socket is a cooked IP packet socket, bound to the specified
  *              network interface
  * ------------------------------------------------------------------------- */
 static int CreateListeningSocket(const char* ifName)
@@ -1047,8 +1010,8 @@
   struct ifreq req;
   struct sockaddr_ll bindTo;
 
-  /* Open UDP packet socket */
-  int skfd = socket(PF_PACKET, SOCK_DGRAM, 0);
+  /* Open cooked IP packet socket */
+  int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
   if (skfd < 0)
   {
     BmfPError("socket(PF_PACKET) error");
@@ -1076,11 +1039,11 @@
     close(skfd);
     return -1;
   }
-   
+
   /* Bind the socket to the specified interface */
   memset(&bindTo, 0, sizeof(bindTo));
   bindTo.sll_family = AF_PACKET;
-  bindTo.sll_protocol = htons(ETH_P_ALL);
+  bindTo.sll_protocol = htons(ETH_P_IP);
   bindTo.sll_ifindex = ifIndex;
   memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
   bindTo.sll_halen = IFHWADDRLEN;
@@ -1103,7 +1066,7 @@
   AddDescriptorToInputSet(skfd);
 
   return skfd;
-}
+} /* CreateListeningSocket */
 
 /* -------------------------------------------------------------------------
  * Function   : CreateEncapsulateSocket
@@ -1170,7 +1133,7 @@
   AddDescriptorToInputSet(skfd);
 
   return skfd;
-}
+} /* CreateEncapsulateSocket */
 
 /* -------------------------------------------------------------------------
  * Function   : CreateLocalEtherTunTap
@@ -1206,16 +1169,9 @@
   strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
   ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
 
-  /* Specify either the IFF_TAP flag for Ethernet frames, or the IFF_TUN flag for IP.
+  /* Specify the IFF_TUN flag for IP packets.
    * Specify IFF_NO_PI for not receiving extra meta packet information. */
-  if (TunOrTap == TT_TUN)
-  {
-    ifreq.ifr_flags = IFF_TUN;
-  }
-  else
-  {
-    ifreq.ifr_flags = IFF_TAP;
-  }
+  ifreq.ifr_flags = IFF_TUN;
   ifreq.ifr_flags |= IFF_NO_PI;
 
   if (ioctl(etfd, TUNSETIFF, (void *)&ifreq) < 0)
@@ -1349,7 +1305,7 @@
   close(ioctlSkfd);
 
   return etfd;
-}
+} /* CreateLocalEtherTunTap */
 
 /* -------------------------------------------------------------------------
  * Function   : CreateInterface
@@ -1533,7 +1489,7 @@
     ifName);
 
   return nOpened;
-}
+} /* CreateInterface */
 
 /* -------------------------------------------------------------------------
  * Function   : CreateBmfNetworkInterfaces
@@ -1641,7 +1597,7 @@
     olsr_printf(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets);
   }
   return 0;
-}
+} /* CreateBmfNetworkInterfaces */
 
 /* -------------------------------------------------------------------------
  * Function   : AddInterface
@@ -1661,12 +1617,12 @@
   nOpened = CreateInterface(newIntf->int_name, newIntf);
 
   olsr_printf(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpened);
-}
+} /* AddInterface */
 
 /* -------------------------------------------------------------------------
  * Function   : CloseBmfNetworkInterfaces
  * Description: Closes every socket on each network interface used by BMF
- * Input      : newIntf - network interface to add
+ * Input      : none
  * Output     : none
  * Return     : none
  * Data Used  : none
@@ -1767,7 +1723,7 @@
     totalNonOlsrBmfPacketsRx,
     totalNonOlsrBmfPacketsRxDup,
     totalNonOlsrBmfPacketsTx);
-}
+} /* CloseBmfNetworkInterfaces */
 
 #define MAX_NON_OLSR_IFS 32
 static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
@@ -1800,7 +1756,7 @@
   NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
   nNonOlsrIfs++;
   return 1;
-}
+} /* AddNonOlsrBmfIf */
 
 /* -------------------------------------------------------------------------
  * Function   : IsNonOlsrBmfIf
@@ -1821,7 +1777,7 @@
     if (strncmp(NonOlsrIfNames[i], ifName, IFNAMSIZ) == 0) return 1;
   }
   return 0;
-}
+} /* IsNonOlsrBmfIf */
 
 /* -------------------------------------------------------------------------
  * Function   : CheckAndUpdateLocalBroadcast
@@ -1870,7 +1826,7 @@
     {
       /* Re-calculate UDP/IP checksum for new destination */
 
-      int ipHeaderLen = GetHeaderLength(ipPacket);
+      int ipHeaderLen = GetIpHeaderLength(ipPacket);
       struct udphdr* udph = (struct udphdr*) (ipPacket + ipHeaderLen);
 
       /* RFC 1624, Eq. 3: HC' = ~(~HC - m + m') */
@@ -1884,9 +1840,9 @@
       check = check + (check >> 16);
 
       udph->check = htons(check);
-     }
-  }
-}
+     } /* if */
+  } /* if */
+} /* CheckAndUpdateLocalBroadcast */
 
 /* -------------------------------------------------------------------------
  * Function   : AddMulticastRoute
@@ -1929,7 +1885,7 @@
     /* Continue anyway */
   }
   close(ioctlSkfd);
-}
+} /* AddMulticastRoute */
 
 /* -------------------------------------------------------------------------
  * Function   : DeleteMulticastRoute
@@ -1974,5 +1930,5 @@
       /* Continue anyway */
     }
     close(ioctlSkfd);
-  }
-}
+  } /* if */
+} /* DeleteMulticastRoute */
diff -Nur olsrd-0.5.0.cvs/lib/bmf/src/NetworkInterfaces.h olsrd-0.5.0/lib/bmf/src/NetworkInterfaces.h
--- olsrd-0.5.0.cvs/lib/bmf/src/NetworkInterfaces.h	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/src/NetworkInterfaces.h	2007-05-08 10:33:08.000000000 +0200
@@ -3,7 +3,7 @@
 
 /*
  * OLSR Basic Multicast Forwarding (BMF) plugin.
- * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
+ * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
  * Written by Erik Tromp.
  * All rights reserved.
  *
@@ -117,25 +117,28 @@
 
 extern int CapturePacketsOnOlsrInterfaces;
 
-enum TTunOrTap { TT_TUN = 0, TT_TAP };
-extern enum TTunOrTap TunOrTap;
-
 enum TBmfMechanism { BM_BROADCAST = 0, BM_UNICAST_PROMISCUOUS };
 extern enum TBmfMechanism BmfMechanism;
 
 int SetBmfInterfaceName(const char* ifname);
-int SetBmfInterfaceType(const char* iftype);
 int SetBmfInterfaceIp(const char* ip);
 int SetCapturePacketsOnOlsrInterfaces(const char* enable);
 int SetBmfMechanism(const char* mechanism);
 int DeactivateSpoofFilter(void);
 void RestoreSpoofFilter(void);
-struct link_entry* GetBestNeighbor(
+
+struct TBestNeighbors
+{
+  struct link_entry* links[2];
+};
+
+struct TBestNeighbors GetBestTwoNeighbors(
   struct TBmfInterface* intf,
   union olsr_ip_addr* source,
   union olsr_ip_addr* forwardedBy,
   union olsr_ip_addr* forwardedTo,
-  int* multipleNeighbors);
+  int* nPossibleNeighbors);
+
 int CreateBmfNetworkInterfaces(struct interface* skipThisIntf);
 void AddInterface(struct interface* newIntf);
 void CloseBmfNetworkInterfaces(void);
diff -Nur olsrd-0.5.0.cvs/lib/bmf/src/olsrd_plugin.c olsrd-0.5.0/lib/bmf/src/olsrd_plugin.c
--- olsrd-0.5.0.cvs/lib/bmf/src/olsrd_plugin.c	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/src/olsrd_plugin.c	2007-05-13 04:30:08.000000000 +0200
@@ -1,6 +1,6 @@
 /*
  * OLSR Basic Multicast Forwarding (BMF) plugin.
- * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
+ * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
  * Written by Erik Tromp.
  * All rights reserved.
  *
diff -Nur olsrd-0.5.0.cvs/lib/bmf/src/Packet.c olsrd-0.5.0/lib/bmf/src/Packet.c
--- olsrd-0.5.0.cvs/lib/bmf/src/Packet.c	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/src/Packet.c	2007-05-08 10:33:08.000000000 +0200
@@ -1,6 +1,6 @@
 /*
  * OLSR Basic Multicast Forwarding (BMF) plugin.
- * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
+ * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
  * Written by Erik Tromp.
  * All rights reserved.
  *
@@ -67,10 +67,10 @@
     return 1;
   }
   return 0;
-}
+} /* IsIpFragment */
 
 /* -------------------------------------------------------------------------
- * Function   : GetTotalLength
+ * Function   : GetIpTotalLength
  * Description: Retrieve the total length of the IP packet (in bytes) of
  *              an IP packet
  * Input      : ipPacket - the IP packet
@@ -78,7 +78,7 @@
  * Return     : IP packet length
  * Data Used  : none
  * ------------------------------------------------------------------------- */
-u_int16_t GetTotalLength(unsigned char* ipPacket)
+u_int16_t GetIpTotalLength(unsigned char* ipPacket)
 {
   struct iphdr* iph;
 
@@ -86,17 +86,17 @@
 
   iph = (struct iphdr*) ipPacket;
   return ntohs(iph->tot_len);
-}
+} /* GetIpTotalLength */
 
 /* -------------------------------------------------------------------------
- * Function   : GetHeaderLength
+ * Function   : GetIpHeaderLength
  * Description: Retrieve the IP header length (in bytes) of an IP packet
  * Input      : ipPacket - the IP packet
  * Output     : none
  * Return     : IP header length
  * Data Used  : none
  * ------------------------------------------------------------------------- */
-unsigned int GetHeaderLength(unsigned char* ipPacket)
+unsigned int GetIpHeaderLength(unsigned char* ipPacket)
 {
   struct iphdr* iph;
 
@@ -104,7 +104,7 @@
 
   iph = (struct iphdr*) ipPacket;
   return iph->ihl << 2;
-}
+} /* GetIpHeaderLength */
 
 /* -------------------------------------------------------------------------
  * Function   : GetTtl
@@ -123,7 +123,7 @@
 
   iph = (struct iphdr*) ipPacket;
   return iph->ttl;
-}
+} /* GetTtl */
 
 /* -------------------------------------------------------------------------
  * Function   : SaveTtlAndChecksum
@@ -143,7 +143,7 @@
   iph = (struct iphdr*) ipPacket;
   sttl->ttl = iph->ttl;
   sttl->check = ntohs(iph->check);
-}
+} /* SaveTtlAndChecksum */
 
 /* -------------------------------------------------------------------------
  * Function   : RestoreTtlAndChecksum
@@ -164,7 +164,7 @@
   iph = (struct iphdr*) ipPacket;
   iph->ttl = sttl->ttl;
   iph->check = htons(sttl->check);
-}
+} /* RestoreTtlAndChecksum */
 
 /* -------------------------------------------------------------------------
  * Function   : DecreaseTtlAndUpdateHeaderChecksum
@@ -188,100 +188,44 @@
   iph->ttl--; /* decrement ttl */
   sum = ntohs(iph->check) + 0x100; /* increment checksum high byte */
   iph->check = htons(sum + (sum>>16)); /* add carry */
-}
-
-/* -------------------------------------------------------------------------
- * Function   : GetEtherType
- * Description: Retrieve the EtherType of an Ethernet frame
- * Input      : ethernetFrame - the Ethernet frame
- * Output     : none
- * Return     : EtherType
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-u_int16_t GetEtherType(unsigned char* ethernetFrame)
-{
-  u_int16_t type;
-  memcpy(&type, ethernetFrame + ETH_TYPE_OFFSET, 2);
-  return ntohs(type);
-}
+} /* DecreaseTtlAndUpdateHeaderChecksum */
 
 /* -------------------------------------------------------------------------
  * Function   : GetIpHeader
- * Description: Retrieve the IP header from an Ethernet frame
- * Input      : ethernetFrame - the Ethernet frame
+ * Description: Retrieve the IP header from BMF encapsulation UDP data
+ * Input      : encapsulationUdpData - the encapsulation UDP data
  * Output     : none
  * Return     : IP header
  * Data Used  : none
  * ------------------------------------------------------------------------- */
-struct ip* GetIpHeader(unsigned char* ethernetFrame)
+struct ip* GetIpHeader(unsigned char* encapsulationUdpData)
 {
-  return (struct ip*)(ethernetFrame + IP_HDR_OFFSET);
-}
+  return (struct ip*)(encapsulationUdpData + ENCAP_HDR_LEN);
+} /* GetIpHeader */
 
 /* -------------------------------------------------------------------------
  * Function   : GetIpPacket
- * Description: Retrieve the IP packet from an Ethernet frame
- * Input      : ethernetFrame - the Ethernet frame
- * Output     : none
- * Return     : IP packet
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-unsigned char* GetIpPacket(unsigned char* ethernetFrame)
-{
-  return ethernetFrame + IP_HDR_OFFSET;
-}
-
-/* -------------------------------------------------------------------------
- * Function   : GetFrameLength
- * Description: Return the Ethernet frame length of an Ethernet frame containing
- *              an IP packet
- * Input      : ethernetFrame - the Ethernet frame
- * Output     : none
- * Return     : The frame length
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-u_int16_t GetFrameLength(unsigned char* ethernetFrame)
-{
-  return GetTotalLength(GetIpPacket(ethernetFrame)) + IP_HDR_OFFSET;
-}
-
-/* -------------------------------------------------------------------------
- * Function   : SetFrameSourceMac
- * Description: Set the source MAC address of an Ethernet frame
- * Input      : ethernetFrame - the Ethernet frame
-              : srcMac - the source MAC address
- * Output     : none
- * Return     : none
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-void SetFrameSourceMac(unsigned char* ethernetFrame, unsigned char* srcMac)
-{
-  memcpy(ethernetFrame + IFHWADDRLEN, srcMac, IFHWADDRLEN);
-}
-
-/* -------------------------------------------------------------------------
- * Function   : GetEthernetFrame
- * Description: Retrieve the Ethernet frame from BMF encapsulation UDP data
+ * Description: Retrieve the IP packet from BMF encapsulation UDP data
  * Input      : encapsulationUdpData - the encapsulation UDP data
  * Output     : none
- * Return     : The Ethernet frame
+ * Return     : The IP packet
  * Data Used  : none
  * ------------------------------------------------------------------------- */
-unsigned char* GetEthernetFrame(unsigned char* encapsulationUdpData)
+unsigned char* GetIpPacket(unsigned char* encapsulationUdpData)
 {
   return encapsulationUdpData + ENCAP_HDR_LEN;
-}
+} /* GetIpPacket */
 
 /* -------------------------------------------------------------------------
  * Function   : GetEncapsulationUdpDataLength
  * Description: Return the length of BMF encapsulation UDP data
  * Input      : encapsulationUdpData - the encapsulation UDP data
  * Output     : none
- * Return     : The packet length
+ * Return     : The encapsulation data length
  * Data Used  : none
  * ------------------------------------------------------------------------- */
 u_int16_t GetEncapsulationUdpDataLength(unsigned char* encapsulationUdpData)
 {
-  return GetFrameLength(GetEthernetFrame(encapsulationUdpData)) + ENCAP_HDR_LEN;
-}
+  return GetIpTotalLength(GetIpPacket(encapsulationUdpData)) + ENCAP_HDR_LEN;
+} /* GetEncapsulationUdpDataLength */
 
diff -Nur olsrd-0.5.0.cvs/lib/bmf/src/Packet.h olsrd-0.5.0/lib/bmf/src/Packet.h
--- olsrd-0.5.0.cvs/lib/bmf/src/Packet.h	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/src/Packet.h	2007-05-08 10:33:08.000000000 +0200
@@ -3,7 +3,7 @@
 
 /*
  * OLSR Basic Multicast Forwarding (BMF) plugin.
- * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
+ * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
  * Written by Erik Tromp.
  * All rights reserved.
  *
@@ -55,18 +55,21 @@
 #define IPV4_TYPE 0x0800
 
 /* BMF-encapsulated packets are Ethernet-IP-UDP packets, which start
- * with a 16-bytes BMF header (struct TEncapHeader), followed by the
+ * with a 8-bytes BMF header (struct TEncapHeader), followed by the
  * encapsulated Ethernet-IP packet itself */
 
 struct TEncapHeader
 {
+  /* Use a standard Type-Length-Value (TLV) element */
+  u_int8_t type;
+  u_int8_t len;
+  u_int16_t reserved; /* Always 0 */
   u_int32_t crc32;
-  u_int32_t futureExpansion1;
-  u_int32_t futureExpansion2;
-  u_int32_t futureExpansion3;
 } __attribute__((__packed__));
 
 #define	ENCAP_HDR_LEN ((int)sizeof(struct TEncapHeader))
+#define BMF_ENCAP_TYPE 1
+#define BMF_ENCAP_LEN 6
 
 struct TSaveTtl
 {
@@ -75,18 +78,14 @@
 } __attribute__((__packed__));
 
 int IsIpFragment(unsigned char* ipPacket);
-u_int16_t GetTotalLength(unsigned char* ipPacket);
-unsigned int GetHeaderLength(unsigned char* ipPacket);
+u_int16_t GetIpTotalLength(unsigned char* ipPacket);
+unsigned int GetIpHeaderLength(unsigned char* ipPacket);
 u_int8_t GetTtl(unsigned char* ipPacket);
 void SaveTtlAndChecksum(unsigned char* ipPacket, struct TSaveTtl* sttl);
 void RestoreTtlAndChecksum(unsigned char* ipPacket, struct TSaveTtl* sttl);
 void DecreaseTtlAndUpdateHeaderChecksum(unsigned char* ipPacket);
-u_int16_t GetEtherType(unsigned char* ethernetFrame);
-struct ip* GetIpHeader(unsigned char* ethernetFrame);
-unsigned char* GetIpPacket(unsigned char* ethernetFrame);
-u_int16_t GetFrameLength(unsigned char* ethernetFrame);
-void SetFrameSourceMac(unsigned char* ethernetFrame, unsigned char* srcMac);
-unsigned char* GetEthernetFrame(unsigned char* encapsulationUdpData);
+struct ip* GetIpHeader(unsigned char* encapsulationUdpData);
+unsigned char* GetIpPacket(unsigned char* encapsulationUdpData);
 u_int16_t GetEncapsulationUdpDataLength(unsigned char* encapsulationUdpData);
 
 #endif /* _BMF_PACKET_H */
diff -Nur olsrd-0.5.0.cvs/lib/bmf/src/PacketHistory.c olsrd-0.5.0/lib/bmf/src/PacketHistory.c
--- olsrd-0.5.0.cvs/lib/bmf/src/PacketHistory.c	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/src/PacketHistory.c	2007-05-13 04:30:30.000000000 +0200
@@ -1,6 +1,6 @@
 /*
  * OLSR Basic Multicast Forwarding (BMF) plugin.
- * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
+ * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
  * Written by Erik Tromp.
  * All rights reserved.
  *
@@ -48,12 +48,13 @@
 #include <netinet/ip.h> /* struct iphdr */
 
 /* OLSRD includes */
+#include "defs.h" /* GET_TIMESTAMP, TIMED_OUT */
 #include "olsr.h" /* olsr_printf */
 
-/* NULLPlugin includes */
+/* Plugin includes */
 #include "Packet.h"
 
-static u_int32_t PacketHistory[HISTORY_TABLE_SIZE];
+static struct TDupEntry* PacketHistory[HISTORY_HASH_SIZE];
 
 #define CRC_UPTO_NBYTES 256
 
@@ -85,7 +86,7 @@
     crc ^= ((crc & 0xff) << 4) << 1;
   }
   return crc;
-}
+} /* CalcCrcCcitt */
 #endif
 
 /* -------------------------------------------------------------------------
@@ -120,8 +121,8 @@
       }
     }
     CrcTable[i] = crc;
-  }
-}
+  } /* for */
+} /* GenerateCrc32Table */
 
 /* -------------------------------------------------------------------------
  * Function   : CalcCrc32
@@ -142,32 +143,26 @@
     crc = (crc >> 8) ^ CrcTable[j];
   }
   return crc ^ 0xffffffffUL;
-}
+} /* CalcCrc32 */
 
 /* -------------------------------------------------------------------------
  * Function   : PacketCrc32
- * Description: Calculates the CRC-32 value for an Ethernet frame
- * Input      : ethernetFrame - the Ethernet frame
- *              len - the number of octets in the Ethernet frame
+ * Description: Calculates the CRC-32 value for an IP packet
+ * Input      : ipPacket - the IP packet
+ *              len - the number of octets in the IP packet
  * Output     : none
- * Return     : 32-bits hash value
+ * Return     : 32-bits CRC value
  * Data Used  : none
- * Notes      : The source and destination MAC address are not taken into account
- *              in the CRC calculation.
  * ------------------------------------------------------------------------- */
-u_int32_t PacketCrc32(unsigned char* ethernetFrame, ssize_t len)
+u_int32_t PacketCrc32(unsigned char* ipPacket, ssize_t len)
 {
-  ssize_t nCrcBytes;
   struct TSaveTtl sttl;
   struct ip* ipHeader;
   u_int32_t result;
 
-  assert(ethernetFrame != NULL);
+  assert(ipPacket != NULL);
 
-  /* Start CRC calculation at ethertype; skip source and destination MAC 
-   * addresses, and ethertype.
-   *
-   * Also skip TTL: in a multi-homed OLSR-network, the same multicast packet
+  /* Skip TTL: in a multi-homed OLSR-network, the same multicast packet
    * may enter the network multiple times, each copy differing only in its
    * TTL value. BMF must not calculate a different CRC for packets that
    * differ only in TTL. Skip also the IP-header checksum, because it changes
@@ -176,30 +171,36 @@
    *
    * Clip number of bytes over which CRC is calculated to prevent
    * long packets from possibly claiming too much CPU resources. */
-  nCrcBytes = len - IP_HDR_OFFSET;
-  assert(nCrcBytes > 0);
-  if (nCrcBytes > CRC_UPTO_NBYTES)
+  assert(len > 0);
+  if (len > CRC_UPTO_NBYTES)
   {
-    nCrcBytes = CRC_UPTO_NBYTES;
+    len = CRC_UPTO_NBYTES;
   }
 
-  SaveTtlAndChecksum(GetIpPacket(ethernetFrame), &sttl);
+  SaveTtlAndChecksum(ipPacket, &sttl);
 
-  ipHeader = GetIpHeader(ethernetFrame);
+  ipHeader = (struct ip*)ipPacket;
   ipHeader->ip_ttl = 0xFF; /* fixed value of TTL for CRC-32 calculation */
   ipHeader->ip_sum = 0x5A5A; /* fixed value of IP header checksum for CRC-32 calculation */
 
-  result = CalcCrc32(ethernetFrame + IP_HDR_OFFSET, nCrcBytes);
+  result = CalcCrc32(ipPacket, len);
 
-  RestoreTtlAndChecksum(GetIpPacket(ethernetFrame), &sttl);
+  RestoreTtlAndChecksum(ipPacket, &sttl);
   return result;
-}
+} /* PacketCrc32 */
 
-/* Calculates a 16-bit hash value from a 32-bit hash value */
-u_int16_t Hash16(u_int32_t hash32)
+/* -------------------------------------------------------------------------
+ * Function   : Hash
+ * Description: Calculates a hash value from a 32-bit value
+ * Input      : from32 - 32-bit value
+ * Output     : none
+ * Return     : hash value
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+u_int32_t Hash(u_int32_t from32)
 {
-  return ((hash32 >> 16) + hash32) & 0xFFFFU;
-}
+  return ((from32 >> N_HASH_BITS) + from32) & ((1 << N_HASH_BITS) - 1);
+} /* Hash */
 
 /* -------------------------------------------------------------------------
  * Function   : InitPacketHistory
@@ -211,63 +212,61 @@
  * ------------------------------------------------------------------------- */
 void InitPacketHistory(void)
 {
-  memset(PacketHistory, 0, sizeof(PacketHistory));
-  GenerateCrc32Table();
-}
-
-/* -------------------------------------------------------------------------
- * Function   : MarkRecentPacket
- * Description: Record the fact that this packet was seen recently
- * Input      : hash16
- * Output     : none
- * Return     : none
- * Data Used  : PacketHistory
- * ------------------------------------------------------------------------- */
-void MarkRecentPacket(u_int16_t hash16)
-{
-  u_int32_t index;
-  uint offset;
-
-  index = hash16 / NPACKETS_PER_ENTRY;
-  assert(index < HISTORY_TABLE_SIZE);
+  int i;
 
-  offset = (hash16 % NPACKETS_PER_ENTRY) * NBITS_PER_PACKET;
-  assert(offset <= NBITS_IN_UINT32 - NBITS_PER_PACKET);
+  GenerateCrc32Table();
 
-  /* Mark as "seen recently" */
-  PacketHistory[index] = PacketHistory[index] | (0x3u << offset);
-}
+  for(i = 0; i < HISTORY_HASH_SIZE; i++)
+  {
+    PacketHistory[i] = NULL;
+  }
+} /* InitPacketHistory */
 
 /* -------------------------------------------------------------------------
  * Function   : CheckAndMarkRecentPacket
  * Description: Check if this packet was seen recently, then record the fact
  *              that this packet was seen recently.
- * Input      : hash16
+ * Input      : crc32 - 32-bits crc value of the packet
  * Output     : none
  * Return     : not recently seen (0), recently seen (1)
  * Data Used  : PacketHistory
  * ------------------------------------------------------------------------- */
-int CheckAndMarkRecentPacket(u_int16_t hash16)
+int CheckAndMarkRecentPacket(u_int32_t crc32)
 {
   u_int32_t index;
-  uint offset;
-  u_int32_t bitMask;
-  int result;
+  struct TDupEntry* walker;
+  struct TDupEntry* newEntry;
+
+  index = Hash(crc32);
+  assert(index < HISTORY_HASH_SIZE);
+
+  for (walker = PacketHistory[index]; walker != NULL; walker = walker->next)
+  {
+    if (walker->crc32 == crc32)
+    {
+      /* Found duplicate entry */
 
-  index = hash16 / NPACKETS_PER_ENTRY;
-  assert(index < HISTORY_TABLE_SIZE);
+      /* Always mark as "seen recently": refresh time-out */
+      walker->timeOut = GET_TIMESTAMP(HISTORY_HOLD_TIME);
 
-  offset =  (hash16 % NPACKETS_PER_ENTRY) * NBITS_PER_PACKET;
-  assert(offset <= NBITS_IN_UINT32 - NBITS_PER_PACKET);
+      return 1;
+    } /* if */
+  } /* for */
+
+  /* No duplicate entry found: create one */
+  newEntry = malloc(sizeof(struct TDupEntry));
+  if (newEntry != NULL)
+  {
+    newEntry->crc32 = crc32;
+    newEntry->timeOut = GET_TIMESTAMP(HISTORY_HOLD_TIME);
 
-  bitMask = 0x1u << offset;
-  result = ((PacketHistory[index] & bitMask) == bitMask);
-  
-  /* Always mark as "seen recently" */
-  PacketHistory[index] = PacketHistory[index] | (0x3u << offset);
+    /* Add new entry at the front of the list */
+    newEntry->next = PacketHistory[index];
+    PacketHistory[index] = newEntry;
+  }
 
-  return result;
-}
+  return 0;
+} /* CheckAndMarkRecentPacket */
   
 /* -------------------------------------------------------------------------
  * Function   : PrunePacketHistory
@@ -280,33 +279,37 @@
 void PrunePacketHistory(void* useless __attribute__((unused)))
 {
   uint i;
-  for (i = 0; i < HISTORY_TABLE_SIZE; i++)
+  for (i = 0; i < HISTORY_HASH_SIZE; i++)
   {
-    if (PacketHistory[i] > 0)
+    if (PacketHistory[i] != NULL)
     {
-      uint j;
-      for (j = 0; j < NPACKETS_PER_ENTRY; j++)
+      struct TDupEntry* nextEntry = PacketHistory[i];
+      struct TDupEntry* prevEntry = NULL;
+      while (nextEntry != NULL) 
       {
-        uint offset = j * NBITS_PER_PACKET;
+        struct TDupEntry* entry = nextEntry;
+        nextEntry = entry->next;
 
-        u_int32_t bitMask = 0x3u << offset;
-        u_int32_t bitsSeenRecenty = 0x3u << offset;
-        u_int32_t bitsTimingOut = 0x1u << offset;
-
-        /* 10 should never occur */
-        assert ((PacketHistory[i] & bitMask) != (0x2u << offset));
-        
-        if ((PacketHistory[i] & bitMask) == bitsSeenRecenty)
-        {
-          /* 11 -> 01 */
-          PacketHistory[i] &= ~bitMask | bitsTimingOut;
-        }
-        else if ((PacketHistory[i] & bitMask) == bitsTimingOut)
+        if (TIMED_OUT(entry->timeOut))
         {
-          /* 01 -> 00 */
-          PacketHistory[i] &= ~bitMask;
-        }
-      } /* for (j = ...) */
-    } /* if (PacketHistory[i] > 0) */
+          /* De-queue */
+          if (prevEntry != NULL)
+          {
+            prevEntry->next = entry->next;
+          }
+          else
+          {
+            PacketHistory[i] = entry->next;
+          } /* if */
+
+          /* De-allocate memory */
+          free(entry); 
+	      }
+	      else
+	      {
+	        prevEntry = entry;
+	      } /* if */
+      } /* while */
+    } /* if (PacketHistory[i] != NULL) */
   } /* for (i = ...) */
-}
+} /* PrunePacketHistory */
diff -Nur olsrd-0.5.0.cvs/lib/bmf/src/PacketHistory.h olsrd-0.5.0/lib/bmf/src/PacketHistory.h
--- olsrd-0.5.0.cvs/lib/bmf/src/PacketHistory.h	2007-06-23 13:15:19.000000000 +0200
+++ olsrd-0.5.0/lib/bmf/src/PacketHistory.h	2007-05-08 10:33:06.000000000 +0200
@@ -3,7 +3,7 @@
 
 /*
  * OLSR Basic Multicast Forwarding (BMF) plugin.
- * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
+ * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
  * Written by Erik Tromp.
  * All rights reserved.
  *
@@ -41,24 +41,28 @@
  *
  * ------------------------------------------------------------------------- */
 
+/* System includes */
 #include <sys/types.h> /* ssize_t */
+#include <sys/times.h> /* clock_t */
 
-/* 2 bits per seen packet: 
- * 11 = "seen recently",
- * 01 = "timing out"
- * 00 = "not seen recently"
- * Note that 10 is unused */
-#define NBITS_PER_PACKET 2
-#define NBITS_IN_UINT16 (sizeof(u_int16_t) * 8)
-#define NBITS_IN_UINT32 (sizeof(u_int32_t) * 8)
-#define NPACKETS_PER_ENTRY (NBITS_IN_UINT32 / NBITS_PER_PACKET)
-#define HISTORY_TABLE_SIZE ((1 << NBITS_IN_UINT16) / NPACKETS_PER_ENTRY)
+#define N_HASH_BITS 12
+#define HISTORY_HASH_SIZE (1 << N_HASH_BITS)
+
+/* Time-out of duplicate entries, in milliseconds */
+#define HISTORY_HOLD_TIME 3000
+
+struct TDupEntry
+{
+  u_int32_t crc32;
+  clock_t timeOut;
+  struct TDupEntry* next;
+};
 
 void InitPacketHistory(void);
-u_int32_t PacketCrc32(unsigned char* ethPkt, ssize_t len);
-u_int16_t Hash16(u_int32_t hash32);
-void MarkRecentPacket(u_int16_t hash16);
-int CheckAndMarkRecentPacket(u_int16_t hash16);
+u_int32_t PacketCrc32(unsigned char* ipPkt, ssize_t len);
+u_int32_t Hash(u_int32_t from32);
+void MarkRecentPacket(u_int32_t crc32);
+int CheckAndMarkRecentPacket(u_int32_t crc32);
 void PrunePacketHistory(void*);
 
 #endif /* _BMF_PACKETHISTORY_H */
