Pushed Eric Tromps (erik_tromp@hotmail.com) new BMF plugin version 1.7.0.
authorHenning Rogge <hrogge@googlemail.com>
Tue, 23 Mar 2010 11:56:06 +0000 (12:56 +0100)
committerHenning Rogge <hrogge@googlemail.com>
Tue, 23 Mar 2010 11:56:06 +0000 (12:56 +0100)
PThreads are no longer necessary for BMF.
Changed OLSRd version to pre-0.6.0 to keep it in sync with the plugins readme.

Makefile
README-Olsr-Extensions
lib/bmf/Makefile
lib/bmf/README_BMF.txt
lib/bmf/src/Bmf.c
lib/bmf/src/Bmf.h
lib/bmf/src/NetworkInterfaces.c
lib/bmf/src/PacketHistory.c

index 6b2f4ad..771af48 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -39,7 +39,7 @@
 # Please also write a new version to:
 # gui/win32/Main/Frontend.rc (line 71, around "CAPTION [...]")
 # gui/win32/Inst/installer.nsi (line 57, around "MessageBox MB_YESNO [...]")
-VERS =         pre-0.5.7.0
+VERS =         pre-0.6.0
 
 TOPDIR = .
 include Makefile.inc
index 62846e6..3cef2be 100644 (file)
@@ -1,6 +1,6 @@
-=======================================================
-      OLSRd (version 0.5.7.0) protocol extensions
-=======================================================
+=====================================================
+      OLSRd (version 0.6.0) protocol extensions
+=====================================================
 
 1.) Credits
 2.) Link quality algorithms
@@ -42,7 +42,7 @@ Concept:
 OLSRd (since version 0.5.6) use a dimensionless integer value for a
 representation of the 'cost' of each link. This is often called Link quality
 (LQ for short). There are multiple LQ-Plugins, each of them calculating a cost
-for the links of the router. At the moment (version 0.5.7.0) all lq_plugins are
+for the links of the router. At the moment (version 0.6.0) all lq_plugins are
 using an ETX-metric (expected transmission count) but others would be possible
 and imaginable, such as MIC [0], WCETT [1], etc.
 
@@ -80,7 +80,7 @@ link quality algorithm in the config file. Some embedded OLSRd versions
 are only compiled with one plugin (mostly etx_ff), so don't use the
 configuration option with these agents.
 
-There are four different link quality algorithms in OLSRd 0.5.7.0, two
+There are four different link quality algorithms in OLSRd 0.6.0, two
 current Funkfeuer/Freifunk ETX implementations and two legacy implementations.
 
 LinkQuality-Algorithm "etx_ff":
@@ -189,7 +189,7 @@ for most larger Funkfeuer/Freifunk meshs.
 (see https://dev.dd19.de/cgi-bin/gitweb.cgi?p=niit.git;a=summary)
 
 NIIT is a special linux kernel device that allows easy transmission of IPv4
-unicast traffic through an IPv6 network. Since version 0.5.7.0 OLSRd has
+unicast traffic through an IPv6 network. Since version 0.6.0 OLSRd has
 integrated support for NIIT in the routing daemon. So setting up IPv4 traffic
 over IPv6 OLSR meshs is very easy. Instead of creating routes and tunnels by
 hand all the administrator of a router needs to do is to, is to set up his own
@@ -219,7 +219,7 @@ More information on NIIT can be found at: http://wiki.freifunk.net/Niit
 The smartgateway mechanism was written by Markus Kittenberg and
 Henning Rogge to allow an OLSR user to directly choose their default
 internet gateway instead of relying on the hop by hop decisions on
-the way to the gateway. OLSRd 0.5.7.0 can create an IPIP tunnel
+the way to the gateway. OLSRd 0.6.0 can create an IPIP tunnel
 to the gateways OLSRd address to sidestep the same nasty effects
 described in the Nat-Threshold section.
 
index 7c1fceb..a72996b 100644 (file)
 
 OLSRD_PLUGIN = true
 PLUGIN_NAME =  olsrd_bmf
-PLUGIN_VER =   1.6.2
+PLUGIN_VER =   1.7.0
 
 TOPDIR = ../..
 include $(TOPDIR)/Makefile.inc
 
-LIBS +=        $(OS_LIB_PTHREAD)
+#LIBS +=       $(OS_LIB_PTHREAD)
 
 ifneq ($(OS),linux)
 
index eda6f65..ec313da 100644 (file)
@@ -1,6 +1,6 @@
 BASIC MULTICAST FORWARDING PLUGIN FOR OLSRD
 by Erik Tromp (eriktromp@users.sourceforge.net, erik_tromp@hotmail.com)
-Version 1.6.2
+Version 1.7.0
 
 1. Introduction
 ---------------
@@ -17,14 +17,14 @@ in the past 3-6 seconds are forwarded.
 2. How to build and install
 ---------------------------
 
-Download the olsr-bmf-v1.6.2.tar.gz file and save it into your OLSRD
+Download the olsr-bmf-v1.7.0.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.6.2.tar.gz
+  tar -zxvf ./olsr-bmf-v1.7.0.tar.gz
 
 then type:
 
@@ -47,7 +47,7 @@ Set permissions, e.g.:
 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.6.2"
+  LoadPlugin "olsrd_bmf.so.1.7.0"
   {
     # No PlParam entries required for basic operation
   }
@@ -63,18 +63,18 @@ olsrd daemon by entering at the shell prompt:
 
 Look at the output; it should list the BMF plugin, e.g.:
 
-  ---------- LOADING LIBRARY olsrd_bmf.so.1.6.2 ----------
-  OLSRD Basic Multicast Forwarding (BMF) plugin 1.6.2 (Jul 22 2008 10:45:12)
+  ---------- LOADING LIBRARY olsrd_bmf.so.1.7.0 ----------
+  OLSRD Basic Multicast Forwarding (BMF) plugin 1.7.0 (Mar 22 2010 21:44:23)
     (C) Thales Communications Huizen, Netherlands
     Erik Tromp (eriktromp@users.sourceforge.net)
   Checking plugin interface version:  5 - OK
   Trying to fetch plugin init function: OK
   Trying to fetch parameter table and it's size...
   Sending parameters...
-  "NonOlsrIf"/"eth0"... NonOlsrIf: OK
+  "NonOlsrIf"/"eth4"... NonOlsrIf: OK
   Running plugin_init function...
   OLSRD Basic Multicast Forwarding (BMF) plugin: opened 5 sockets
-  ---------- LIBRARY olsrd_bmf.so.1.6.2 LOADED ----------
+  ---------- LIBRARY olsrd_bmf.so.1.7.0 LOADED ----------
 
 
 4. How to check if it works
@@ -187,13 +187,14 @@ All configuration of BMF is done via the "LoadPlugin" section in
 the /etc/olsrd.conf file.
 
 The following gives an overview of all plugin parameters that can be
-configured:
+configured. Unless otherwise stated, settings may differ for each node in the
+network.
 
-  LoadPlugin "olsrd_bmf.so.1.6.2"
+  LoadPlugin "olsrd_bmf.so.1.7.0"
   {
     # Specify the name of the BMF network interface.
     # Defaults to "bmf0".
-    PlParam "BmfInterface" "mybmf0"
+    PlParam "BmfInterface" "bmf0"
 
     # Specify the IP address and mask for the BMF network interface.
     # By default, the IP address of the first OLSR interface is copied.
@@ -203,7 +204,9 @@ configured:
     # Enable or disable the flooding of local broadcast packets
     # (e.g. packets with IP destination 192.168.1.255). Either "yes"
     # or "no". Defaults to "yes".
-    PlParam "DoLocalBroadcast" "no"
+    # Note: all nodes in the same network should have the same setting for
+    # this plugin parameter.
+    PlParam "DoLocalBroadcast" "yes"
 
     # Enable or disable the capturing packets on the OLSR-enabled
     # interfaces (in promiscuous mode). Either "yes" or "no". Defaults
@@ -215,7 +218,7 @@ configured:
     # network interfaces will be flooded over the OLSR network.
     # NOTE: This parameter should be set consistently on all hosts throughout
     # the network. If not, hosts may receive multicast packets in duplicate.
-    PlParam "CapturePacketsOnOlsrInterfaces" "yes"
+    PlParam "CapturePacketsOnOlsrInterfaces" "no"
 
     # The forwarding mechanism to use. Either "Broadcast" or
     # "UnicastPromiscuous". Defaults to "Broadcast".
@@ -224,20 +227,24 @@ configured:
     # broadcast is not used. This saves air time on 802.11 WLAN networks,
     # on which unicast packets are usually sent at a much higher bit rate
     # than broadcast packets (which are sent at a basic bit rate).
-    PlParam "BmfMechanism" "UnicastPromiscuous"
+    # Note: all nodes in the same network should have the same setting for
+    # this plugin parameter.
+    PlParam "BmfMechanism" "Broadcast"
 
     # The number of times BMF will transmit the same packet whenever it decides
     # to use broadcast to forward a packet. Defaults to 1. Not used if
     # "BmfMechanism" is set to "UnicastPromiscuous".
-    PlParam "BroadcastRetransmitCount" "2"
+    PlParam "BroadcastRetransmitCount" "1"
 
     # If the number of neighbors to forward to is less than or equal to the
     # FanOutLimit, then packets to be relayed will be sent via unicast.
     # If the number is greater than the FanOutLimit the packet goes out
-    # as broadcast. Legal values are 1...10. See MAX_UNICAST_NEIGHBORS
-    # as defined in NetworkInterfaces.h . Defaults to 2. Not used if
-    # "BmfMechanism" is set to "UnicastPromiscuous".
-    PlParam "FanOutLimit" "4"
+    # as broadcast. Legal values are 0...10. See MAX_UNICAST_NEIGHBORS
+    # as defined in NetworkInterfaces.h . 0 means broadcast is always used,
+    # even if there is only 1 neighbor to forward to. Defaults to 2. 
+    # This plugin parameter is not used if "BmfMechanism" is set to
+    # "UnicastPromiscuous".
+    PlParam "FanOutLimit" "2"
 
     # List of non-OLSR interfaces to include
     PlParam     "NonOlsrIf"  "eth2"
@@ -343,7 +350,7 @@ want to forward multicast and local-broadcast IP packets, specify these
 interfaces one by one as "NonOlsrIf" parameters in the BMF plugin section
 of /etc/olsrd.conf. For example:
 
-  LoadPlugin "olsrd_bmf.so.1.6.2"
+  LoadPlugin "olsrd_bmf.so.1.7.0"
   {
     # Non-OLSR interfaces to participate in the multicast flooding
     PlParam     "NonOlsrIf"  "eth2"
@@ -401,7 +408,7 @@ Therefore, override the default IP address and prefix length of
 the BMF network interface, by editing the /etc/olsrd.conf file.
 For example:
 
-  LoadPlugin "olsrd_bmf.so.1.6.2"
+  LoadPlugin "olsrd_bmf.so.1.7.0"
   {
       PlParam "BmfInterfaceIp" "10.10.10.4/24"
   }
@@ -539,9 +546,18 @@ the BMF network interface, either by specifying the interface name itself
 10. Version history
 -------------------
 
-7 February 2010: (Henning Rogge <hrogge@googlemail.com>)
-* Ported 1.6.2 back into OLSRd for 0.5.7.0 release,
-* removed mutex
+21 March 2010: Version 1.7.0
+
+* Ported 1.6.2 back into OLSRd for 0.5.7.0 release: the BMF functions are
+  registered with OLSR so that a separate thread for BMF to run in is no longer
+  necessary. This also removes the need for a mutex to guarantee safe access to
+  OLSR data. Done by Henning Rogge <hrogge@googlemail.com>.
+* Code Cleanup: duplicate code moved to separate functions
+  'ForwardPacket (...)' and 'EncapsulateAndForwardPacket (...)'
+* Prevent the calling of 'sendto' when that would lead to blocking the
+  thread --> thanks to Daniele Lacamera for finding and solving this issue.
+* Changed the legal range of the 'FanOutLimit' plugin parameter from 1...10
+  to 0...10 .
 
 23 November 2008: Version 1.6.2
 
index ad5d06d..ab66bba 100644 (file)
 #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 */
 #include <netinet/ip.h> /* struct ip */
 #include <netinet/udp.h> /* struct udphdr */
 #include <unistd.h> /* read(), write() */
+#include <sys/poll.h> /* Daniele Lacamera: Added guard poll for sendto(), needs poll.h */
 
 /* OLSRD includes */
 #include "plugin_util.h" /* set_plugin_int */
@@ -65,7 +65,6 @@
 #include "mpr_selector_set.h" /* olsr_lookup_mprs_set() */
 #include "link_set.h" /* get_best_link_to_neighbor() */
 #include "net_olsr.h" /* ipequal */
-#include "scheduler.h" /* olsr_mutex */
 
 /* BMF includes */
 #include "NetworkInterfaces.h" /* TBmfInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */
@@ -73,9 +72,6 @@
 #include "Packet.h" /* ENCAP_HDR_LEN, BMF_ENCAP_TYPE, BMF_ENCAP_LEN etc. */
 #include "PacketHistory.h" /* InitPacketHistory() */
 
-static pthread_t BmfThread;
-static int BmfThreadRunning = 0;
-
 /* unicast/broadcast fan out limit */
 int FanOutLimit = 2;
 
@@ -131,7 +127,6 @@ union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip)
 {
   union olsr_ip_addr* result;
 
-  /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
   result = mid_lookup_main_addr(ip);
   if (result == NULL)
   {
@@ -141,20 +136,112 @@ union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip)
 } /* MainAddressOf */
 
 /* -------------------------------------------------------------------------
+ * Function   : ForwardPacket
+ * Description: Forward a raw IP packet
+ * Input      : intf - the network interface on which to forward the packet. The
+ *                packet will be forwarded on its 'capturing' socket.
+ *              ipPacket - the IP packet to be forwarded
+ *              ipPacketLen - the length of the IP packet to be forwarded
+ *              debugInfo - string to use printing debugging information
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+static void ForwardPacket(
+  struct TBmfInterface* intf,
+  unsigned char* ipPacket,
+  u_int16_t ipPacketLen,
+  const char* debugInfo)
+{
+  int nBytesWritten;
+  struct sockaddr_ll dest;
+
+  int pollret;
+  struct pollfd guard;
+  guard.fd = intf->capturingSkfd;
+  guard.events = POLLOUT;
+
+  /* If the 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(ipPacket, &intf->broadAddr);
+
+  memset(&dest, 0, sizeof(dest));
+  dest.sll_family = AF_PACKET;
+  dest.sll_protocol = htons(ETH_P_IP);
+  dest.sll_ifindex = if_nametoindex(intf->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);
+
+  /* Daniele Lacamera: poll guard to avoid locking in sendto().
+   * Wait at most 2 polling periods. Since we're running in the context of the main
+   * OLSR thread, we should not wait too long. 2 polling periods is considered a
+   * reasonable time. */
+  pollret = poll (&guard, 1, 2 * olsr_cnf->pollrate * MSEC_PER_SEC);
+  if (pollret <= 0)
+  {
+    BmfPError("sendto() on \"%s\": not ready to send pkt. pollret=%d\n", intf->ifName, pollret);
+
+    /* Apparently the network interface is jammed. Give up. */
+    return;
+  }
+
+  /* Forward the BMF packet via the capturing socket */
+  nBytesWritten = sendto(
+    intf->capturingSkfd,
+    ipPacket,
+    ipPacketLen,
+    0,
+    (struct sockaddr*) &dest,
+    sizeof(dest));
+  if (nBytesWritten != ipPacketLen)
+  {
+    BmfPError("sendto() error forwarding pkt on \"%s\"", intf->ifName);
+    return;
+  }
+
+  /* Increase counter */
+  intf->nBmfPacketsTx++;
+
+  OLSR_PRINTF(
+    8,
+    "%s: --> %s \"%s\"\n",
+    PLUGIN_NAME_SHORT,
+    debugInfo,
+    intf->ifName);
+} /* ForwardPacket */
+
+/* -------------------------------------------------------------------------
  * 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 IP packet
+ *              source - the source IP address of the BMF packet, or NULL if
+ *                unknown or not applicable
+ *              forwardedBy - the IP address of the node that forwarded the BMF
+ *                packet, or NULL if unknown or not applicable
+ *              forwardedTo - the IP address of the node to which the BMF packet
+ *                was directed, or NULL if unknown or not applicable
  * Output     : none
  * Return     : none
  * Data Used  : none
  * ------------------------------------------------------------------------- */
 static void EncapsulateAndForwardPacket(
   struct TBmfInterface* intf,
-  unsigned char* encapsulationUdpData)
+  unsigned char* encapsulationUdpData,
+  union olsr_ip_addr* source,
+  union olsr_ip_addr* forwardedBy,
+  union olsr_ip_addr* forwardedTo)
 {
-  /* The packet */
+  /* Retrieve the number of bytes to be forwarded via the encapsulation socket */
   u_int16_t udpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);
 
   /* The next destination(s) */
@@ -169,7 +256,14 @@ static void EncapsulateAndForwardPacket(
   int i;
 
   /* Find at most 'FanOutLimit' best neigbors to forward the packet to */
-  FindNeighbors(&bestNeighborLinks, &bestNeighbor, intf, NULL, NULL, NULL, &nPossibleNeighbors);
+  FindNeighbors(
+    &bestNeighborLinks,
+    &bestNeighbor,
+    intf,
+    source,
+    forwardedBy,
+    forwardedTo,
+    &nPossibleNeighbors);
 
   if (nPossibleNeighbors <= 0)
   {
@@ -179,7 +273,7 @@ static void EncapsulateAndForwardPacket(
       PLUGIN_NAME_SHORT,
       intf->ifName);
     return;
-  }
+  } /* if */
 
   /* Compose destination of encapsulation packet */
 
@@ -225,12 +319,30 @@ static void EncapsulateAndForwardPacket(
   {
     int nBytesWritten;
 
+    int pollret;
+    struct pollfd guard;
+    guard.fd = intf->encapsulatingSkfd;
+    guard.events = POLLOUT;
+
     if (sendUnicast == 1)
     {
       /* For unicast, overwrite the local broadcast address which was filled in above */
       forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4;
     }
 
+    /* Daniele Lacamera: poll guard to avoid locking in sendto().
+     * Wait at most 2 polling periods. Since we're running in the context of the main
+     * OLSR thread, we should not wait too long. 2 polling periods is considered a
+     * reasonable time. */
+    pollret = poll (&guard, 1, 2 * olsr_cnf->pollrate * MSEC_PER_SEC);
+    if (pollret <= 0)
+    {
+      BmfPError("sendto() on \"%s\": not ready to send pkt. pollret=%d\n", intf->ifName, pollret);
+
+      /* Apparently the network interface is jammed. Give up and return. */
+      return;
+    }
+
     /* Forward the BMF packet via the encapsulation socket */
     nBytesWritten = sendto(
       intf->encapsulatingSkfd,
@@ -243,20 +355,19 @@ static void EncapsulateAndForwardPacket(
     /* 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));
+      BmfPError("sendto() error forwarding encapsulated pkt on \"%s\"", intf->ifName);
+      return;
     } /* if (nBytesWritten != udpDataLen) */
+
+    /* Increase counter */
+    intf->nBmfPacketsTx++;
+
+    OLSR_PRINTF(
+      8,
+      "%s: --> forwarded encapsulated packet on \"%s\" to %s\n",
+      PLUGIN_NAME_SHORT,
+      intf->ifName,
+      inet_ntoa(forwardTo.sin_addr));
   } /* for */
 } /* EncapsulateAndForwardPacket */
 
@@ -373,15 +484,13 @@ static void BmfPacketCaptured(
   encapHdr->crc32 = htonl(crc32);
 
   /* Check if the frame is captured on an OLSR interface from an OLSR neighbor.
-   * Assumption: olsr_mutex has been grabbed for safe access to OLSR data.
    * TODO: get_best_link_to_neighbor() may be very CPU-expensive, a simpler call
    * would do here (something like 'get_any_link_to_neighbor()'). */
   isFromOlsrNeighbor =
     (isFromOlsrIntf /* The frame is captured on an OLSR interface... */
     && get_best_link_to_neighbor(origIp) != NULL); /* ...from an OLSR neighbor */ 
 
-  /* Check with OLSR if I am MPR for that neighbor.
-   * Assumption: olsr_mutex has been grabbed for safe access to OLSR data. */
+  /* Check with OLSR if I am MPR for that neighbor */
   iAmMpr = olsr_lookup_mprs_set(origIp) != NULL;
 
   /* Check with each network interface what needs to be done on it */
@@ -462,62 +571,21 @@ static void BmfPacketCaptured(
       else
       {
         /* Case 1.2 and 1.3 */
-        EncapsulateAndForwardPacket(walker, encapsulationUdpData);
+        EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL);
       }
     } /* if (isFromOlsrIntf && isToOlsrIntf) */
 
     else if (isFromOlsrIntf && !isToOlsrIntf)
     {
       /* Case 2: Forward from OLSR interface to non-OLSR interface */
-
-      int nBytesWritten;
-      struct sockaddr_ll dest;
-
-      /* 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(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 = sendto(
-        walker->capturingSkfd,
-        ipPacket,
-        ipPacketLen,
-        0,
-        (struct sockaddr*) &dest,
-        sizeof(dest));
-      if (nBytesWritten != ipPacketLen)
-      {
-        BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
-      }
-      else
-      {
-        /* Increase counter */
-        walker->nBmfPacketsTx++;
-
-        OLSR_PRINTF(8, "%s: --> forwarded on \"%s\"\n", PLUGIN_NAME_SHORT, walker->ifName);
-      }
+      ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded to non-OLSR interface");
     } /* else if (isFromOlsrIntf && !isToOlsrIntf) */
 
     else if (!isFromOlsrIntf && isToOlsrIntf)
     {
       /* Case 3: Forward from a non-OLSR interface to an OLSR interface.
        * Encapsulate and forward packet. */
-
-      EncapsulateAndForwardPacket(walker, encapsulationUdpData);
+      EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL);
     } /* else if (!isFromOlsrIntf && isToOlsrIntf) */
 
     else
@@ -536,50 +604,7 @@ static void BmfPacketCaptured(
 
       else
       {
-        int nBytesWritten;
-        struct sockaddr_ll dest;
-
-        /* 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(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 = sendto(
-          walker->capturingSkfd,
-          ipPacket,
-          ipPacketLen,
-          0,
-          (struct sockaddr*) &dest,
-          sizeof(dest));
-        if (nBytesWritten != ipPacketLen)
-        {
-          BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
-        }
-        else
-        {
-          /* Increase counter */
-          walker->nBmfPacketsTx++;
-
-          OLSR_PRINTF(
-            8,
-            "%s: --> forwarded from non-OLSR on non-OLSR \"%s\"\n",
-            PLUGIN_NAME_SHORT,
-            walker->ifName);
-        }
+        ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded from non-OLSR to non-OLSR interface");
       } /* if (intf == walker) */
     } /* if */
   } /* for */
@@ -608,14 +633,12 @@ static void BmfEncapsulationPacketReceived(
   unsigned char* encapsulationUdpData)
 {
   int iAmMpr; /* True (1) if I am selected as MPR by 'forwardedBy' */
-  struct sockaddr_in forwardTo; /* Next destination of encapsulation 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;
 #ifndef NODEBUG
   struct ipaddr_str mcSrcBuf, mcDstBuf, forwardedByBuf, forwardedToBuf;
@@ -717,18 +740,9 @@ static void BmfEncapsulationPacketReceived(
     }
   } /* if (EtherTunTapFd >= 0) */
 
-  /* Check if I am MPR for the forwarder.
-   * Assumption: olsr_mutex has been grabbed for safe access to OLSR data. */
+  /* Check if I am MPR for the forwarder */
   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)
   {
@@ -744,156 +758,19 @@ static void BmfEncapsulationPacketReceived(
     /* 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 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(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 = sendto(
-        walker->capturingSkfd,
-        ipPacket,
-        ipPacketLen,
-        0,
-        (struct sockaddr*) &dest,
-        sizeof(dest));
-      if (nBytesWritten != ipPacketLen)
-      {
-        BmfPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName);
-      }
-      else
-      {
-        /* Increase counter */
-        walker->nBmfPacketsTx++;
-
-        OLSR_PRINTF(
-          8,
-          "%s: --> unpacked and forwarded on \"%s\"\n",
-          PLUGIN_NAME_SHORT,
-          walker->ifName);
-      }
+      ForwardPacket (walker, ipPacket, ipPacketLen, "unpacked and forwarded to non-OLSR interface");
     } /* if (walker->olsrIntf == NULL) */
 
     /* 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;
-      struct link_entry* bestNeighbor;
-      int nPossibleNeighbors;
-      int nPacketsToSend;
-      int sendUnicast; /* 0 = send broadcast; 1 = send unicast */
-      int i;
-
-      /* Retrieve at most two best neigbors to forward the packet to */
-      FindNeighbors(
-        &bestNeighborLinks,
-        &bestNeighbor,
+      EncapsulateAndForwardPacket (
         walker,
+        encapsulationUdpData,
         &mcSrc,
         forwardedBy,
-        forwardedTo,
-        &nPossibleNeighbors);
-
-      if (nPossibleNeighbors <= 0)
-      {
-        OLSR_PRINTF(
-          8,
-          "%s: --> not forwarding on \"%s\": there is no neighbor that needs my retransmission\n",
-          PLUGIN_NAME_SHORT,
-          walker->ifName);
-
-        continue; /* for */
-      }
-
-      /* Compose destination of encapsulation packet.
-       * Start by filling in the local broadcast address. This may be overwritten later. */
-      forwardTo.sin_addr = walker->broadAddr.v4;
-
-      /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
-       *   unicast packet (to the best neighbor).
-       * - But if the BMF mechanism is BM_BROADCAST,
-       *   - send 'nPossibleNeighbors' unicast packets if there are up to
-       *     'FanOutLimit' possible neighbors,
-       *   - if there are more than 'FanOutLimit' possible neighbors, then
-       *     send a (WLAN-air-expensive, less reliable) broadcast packet. */
-      if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
-      {
-        /* One unicast packet to the best neighbor */
-        nPacketsToSend = 1;
-        sendUnicast = 1;
-        bestNeighborLinks.links[0] = bestNeighbor;
-      }
-      else /* BmfMechanism == BM_BROADCAST */
-      {
-        if (nPossibleNeighbors <= FanOutLimit)
-        {
-          /* 'nPossibleNeighbors' unicast packets */
-          nPacketsToSend = nPossibleNeighbors;
-          sendUnicast = 1;
-        }
-        else /* nPossibleNeighbors > FanOutLimit */
-        {
-          /* One broadcast packet, possibly retransmitted as specified in the
-           * 'BroadcastRetransmitCount' plugin parameter */
-          nPacketsToSend = BroadcastRetransmitCount;
-          sendUnicast = 0;
-        } /* if */
-      } /* if */
-
-      for (i = 0; i < nPacketsToSend; i++)
-      {
-        int nBytesWritten;
-
-        if (sendUnicast)
-        {    
-          /* For unicast, overwrite the local broadcast address which was filled in above */
-          forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4;
-        }
-
-        /* 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 */
+        forwardedTo);
     }  /* else if (iAmMpr) */
 
     else /* walker->olsrIntf != NULL && !iAmMpr */
@@ -995,8 +872,7 @@ static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData)
     if (walker->olsrIntf != NULL)
     {
       /* On an OLSR interface: encapsulate and forward packet. */
-
-      EncapsulateAndForwardPacket(walker, encapsulationUdpData);
+      EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL);
     }
     else
     {
@@ -1004,51 +880,7 @@ static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData)
        * Answer 1: nothing. Multicast routing between non-OLSR interfaces
        * is to be done by other protocols (e.g. PIM, DVMRP).
        * Answer 2 (better): Forward it. */
-
-      int nBytesWritten;
-      struct sockaddr_ll dest;
-
-      /* 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(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 = sendto(
-        walker->capturingSkfd,
-        ipPacket,
-        ipPacketLen,
-        0,
-        (struct sockaddr*) &dest,
-        sizeof(dest));
-      if (nBytesWritten != ipPacketLen)
-      {
-        BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
-      }
-      else
-      {
-        /* Increase counter */
-        walker->nBmfPacketsTx++;
-
-        OLSR_PRINTF(
-          8,
-          "%s: --> forwarded from non-OLSR to non-OLSR \"%s\"\n",
-          PLUGIN_NAME_SHORT,
-          walker->ifName);
-      } /* if */
+      ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded from non-OLSR to non-OLSR interface");
     } /* if */
   } /* for */
 } /* BmfTunPacketCaptured */
@@ -1062,370 +894,241 @@ static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData)
  * Return     : none
  * Data Used  : BmfInterfaces
  * ------------------------------------------------------------------------- */
-static void DoBmf(void)
-{
-  int nFdBitsSet;
+void
+BMF_handle_captureFd(int skfd, void *data, unsigned int flags __attribute__ ((unused))) {
   unsigned char rxBuffer[BMF_BUFFER_SIZE];
-  fd_set rxFdSet;
-
-  assert(HighestSkfd >= 0);
-
-  /* Make a local copy of the set of file descriptors that select() can
-   * modify to indicate which descriptors actually changed status */
-  rxFdSet = InputSet;
+  struct TBmfInterface* walker = data;
+  struct sockaddr_ll pktAddr;
+  socklen_t addrLen = sizeof(pktAddr);
+  int nBytes;
+  unsigned char* ipPacket;
 
-  /* Wait (blocking) for packets received on any of the sockets.
-   * NOTE: don't use a timeout (last parameter). It causes a high system CPU load! */
-  nFdBitsSet = select(HighestSkfd + 1, &rxFdSet, NULL, NULL, NULL);
-  if (nFdBitsSet < 0)
+  /* Receive the captured Ethernet frame, leaving space for the BMF
+   * encapsulation header */
+  ipPacket = GetIpPacket(rxBuffer);
+  nBytes = recvfrom(
+    skfd,
+    ipPacket,
+    BMF_BUFFER_SIZE - ENCAP_HDR_LEN,
+    0,
+    (struct sockaddr*)&pktAddr,
+    &addrLen);
+  if (nBytes < 0)
   {
-    if (errno != EINTR)
-    {
-      BmfPError("select() error");
-    }
+    BmfPError("recvfrom() error on \"%s\"", walker->ifName);
+    return;
+  } /* if (nBytes < 0) */
+
+  /* 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 < (int)sizeof(struct ip))
+  {
+    olsr_printf(
+      1,
+      "%s: captured frame too short (%d bytes) on \"%s\"\n",
+      PLUGIN_NAME,
+      nBytes,
+      walker->ifName);
     return;
   }
 
-  while (nFdBitsSet > 0)
+  if (pktAddr.sll_pkttype == PACKET_OUTGOING ||
+      pktAddr.sll_pkttype == PACKET_MULTICAST ||
+      pktAddr.sll_pkttype == PACKET_BROADCAST)
   {
-    struct TBmfInterface* walker;
-
-    /* Guarantee safe access to OLSR data */
-#if 0
-    pthread_mutex_lock(&olsr_mutex);
-#endif
-
-    /* Check if a packet was received on the capturing socket (if any)
-     * of each network interface */
-    for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
-    {
-      int skfd = walker->capturingSkfd;
-      if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
-      {
-        struct sockaddr_ll pktAddr;
-        socklen_t addrLen = sizeof(pktAddr);
-        int nBytes;
-        unsigned char* ipPacket;
-
-        /* A packet was captured. */
-
-        nFdBitsSet--;
-
-        /* Receive the captured Ethernet frame, leaving space for the BMF
-         * encapsulation header */
-        ipPacket = GetIpPacket(rxBuffer);
-        nBytes = recvfrom(
-          skfd,
-          ipPacket,
-          BMF_BUFFER_SIZE - ENCAP_HDR_LEN,
-          0,
-          (struct sockaddr*)&pktAddr,
-          &addrLen);
-        if (nBytes < 0)
-        {
-          BmfPError("recvfrom() error on \"%s\"", walker->ifName);
-
-          continue; /* for */
-        } /* if (nBytes < 0) */
-
-        /* 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 < (int)sizeof(struct ip))
-        {
-          olsr_printf(
-            1,
-            "%s: captured frame too short (%d bytes) on \"%s\"\n",
-            PLUGIN_NAME,
-            nBytes,
-            walker->ifName);
-
-          continue; /* for */
-        }
-
-        if (pktAddr.sll_pkttype == PACKET_OUTGOING ||
-            pktAddr.sll_pkttype == PACKET_MULTICAST ||
-            pktAddr.sll_pkttype == PACKET_BROADCAST)
-        {
-          /* A multicast or broadcast packet was captured */
-
-          BmfPacketCaptured(walker, pktAddr.sll_pkttype, rxBuffer);
-
-        } /* if (pktAddr.sll_pkttype == ...) */
-      } /* if (skfd >= 0 && (FD_ISSET...)) */
-    } /* for */
-    
-    /* Check if a BMF encapsulation packet was received on the listening
-     * socket (if any) of each network interface */
-    for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
-    {
-      int skfd = walker->listeningSkfd;
-      if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
-      {
-        struct sockaddr_ll pktAddr;
-        socklen_t addrLen = sizeof(pktAddr);
-        int nBytes;
-        int minimumLength;
-        struct ip* ipHeader;
-        struct udphdr* udpHeader;
-        u_int16_t destPort;
-        union olsr_ip_addr forwardedBy;
-        union olsr_ip_addr forwardedTo;
-
-        /* Heard a BMF packet */
-
-        nFdBitsSet--;
-
-        nBytes = recvfrom(
-          skfd,
-          rxBuffer,
-          BMF_BUFFER_SIZE,
-          0,
-          (struct sockaddr*)&pktAddr,
-          &addrLen);
-        if (nBytes < 0)
-        {
-          BmfPError("recvfrom() error on \"%s\"", walker->ifName);
+    /* A multicast or broadcast packet was captured */
 
-          continue; /* for */
-        } /* if (nBytes < 0) */
+    BmfPacketCaptured(walker, pktAddr.sll_pkttype, rxBuffer);
 
-        /* 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 ...) */
-
-        /* Check if the received packet is UDP - BMF port */
-        ipHeader = (struct ip*)rxBuffer;
-        if (ipHeader->ip_p != SOL_UDP)
-        {
-          /* Not UDP */
-          continue; /* for */
-        }
-
-        udpHeader = (struct udphdr*)(rxBuffer + GetIpHeaderLength(rxBuffer));
-        destPort = ntohs(udpHeader->dest);
-        if (destPort != BMF_ENCAP_PORT)
-        {
-          /* Not BMF */
-          continue; /* for */
-        }
-
-        /* Check if the number of received bytes is large enough for a minimal BMF
-         * encapsulation packet, at least:
-         * - the IP header of the encapsulation IP packet
-         * - the UDP header of the encapsulation IP packet
-         * - the encapsulation header
-         * - a minimum IP header inside the encapsulated packet
-         * Note: 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. */
-        minimumLength =
-          GetIpHeaderLength(rxBuffer) +
-          sizeof(struct udphdr) +
-          ENCAP_HDR_LEN +
-          sizeof(struct ip);
-        if (nBytes < minimumLength)
-        {
-          olsr_printf(
-            1,
-            "%s: captured a too short encapsulation packet (%d bytes) on \"%s\"\n",
-            PLUGIN_NAME,
-            nBytes,
-            walker->ifName);
-
-          continue; /* for */
-        }
-
-        forwardedBy.v4 = ipHeader->ip_src;
-        forwardedTo.v4 = ipHeader->ip_dst;
-        BmfEncapsulationPacketReceived(
-          walker,
-          &forwardedBy,
-          &forwardedTo,
-          rxBuffer + GetIpHeaderLength(rxBuffer) + sizeof(struct udphdr));
-
-      } /* if (skfd >= 0 && (FD_ISSET...)) */
-    } /* for */
-
-    /* Check if a packet was received on the encapsulating socket (if any)
-     * of each network interface */
-    for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
-    {
-      int skfd = walker->encapsulatingSkfd;
-      if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
-      {
-        struct sockaddr_in from;
-        socklen_t fromLen = sizeof(from);
-        int nBytes;
-        int minimumLength;
-        union olsr_ip_addr forwardedBy;
-
-        /* An encapsulated packet was received */
-
-        nFdBitsSet--;
-
-        nBytes = recvfrom(
-          skfd,
-          rxBuffer,
-          BMF_BUFFER_SIZE,
-          0,
-          (struct sockaddr*)&from,
-          &fromLen);
-        if (nBytes < 0)
-        {
-          BmfPError("recvfrom() error on \"%s\"", walker->ifName);
+  } /* if (pktAddr.sll_pkttype == ...) */
+}
 
-          continue; /* for */
-        } /* if (nBytes < 0) */
+void
+BMF_handle_listeningFd(int skfd, void *data, unsigned int flags __attribute__ ((unused))) {
+  unsigned char rxBuffer[BMF_BUFFER_SIZE];
+  struct TBmfInterface* walker = data;
+  struct sockaddr_ll pktAddr;
+  socklen_t addrLen = sizeof(pktAddr);
+  int nBytes;
+  int minimumLength;
+  struct ip* ipHeader;
+  struct udphdr* udpHeader;
+  u_int16_t destPort;
+  union olsr_ip_addr forwardedBy;
+  union olsr_ip_addr forwardedTo;
+
+  /* Heard a BMF packet */
+
+  nBytes = recvfrom(
+    skfd,
+    rxBuffer,
+    BMF_BUFFER_SIZE,
+    0,
+    (struct sockaddr*)&pktAddr,
+    &addrLen);
+  if (nBytes < 0)
+  {
+    BmfPError("recvfrom() error on \"%s\"", walker->ifName);
+    return;
+  } /* if (nBytes < 0) */
 
-        forwardedBy.v4 = from.sin_addr;
+  /* 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. */
+    return;
+  } /* if (pktAddr.sll_pkttype ...) */
 
-        /* Check if the number of received bytes is large enough for a minimal BMF
-         * encapsulation packet, at least:
-         * - the encapsulation header
-         * - a minimum IP header inside the encapsulated packet */
-        minimumLength =
-          ENCAP_HDR_LEN +
-          sizeof(struct ip);
-        if (nBytes < minimumLength)
-        {
-          struct ipaddr_str buf;
-          olsr_printf(
-            1,
-            "%s: received a too short encapsulation packet (%d bytes) from %s on \"%s\"\n",
-            PLUGIN_NAME,
-            nBytes,
-            olsr_ip_to_string(&buf, &forwardedBy),
-            walker->ifName);
-
-          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...)) */
-    } /* for */
-
-    if (nFdBitsSet > 0 && FD_ISSET(EtherTunTapFd, &rxFdSet))
-    {
-      /* Check if an application has sent a packet out via the tuntap
-       * network interface */
+  /* Check if the received packet is UDP - BMF port */
+  ipHeader = (struct ip*)rxBuffer;
+  if (ipHeader->ip_p != SOL_UDP)
+  {
+    /* Not UDP */
+    return;
+  }
 
-      int nBytes;
-      unsigned char* ipPacket;
-      unsigned char* bufferToRead;
-      size_t nBytesToRead;
+  udpHeader = (struct udphdr*)(rxBuffer + GetIpHeaderLength(rxBuffer));
+  destPort = ntohs(udpHeader->dest);
+  if (destPort != BMF_ENCAP_PORT)
+  {
+    /* Not BMF */
+    return;
+  }
 
-      nFdBitsSet--;
+  /* Check if the number of received bytes is large enough for a minimal BMF
+   * encapsulation packet, at least:
+   * - the IP header of the encapsulation IP packet
+   * - the UDP header of the encapsulation IP packet
+   * - the encapsulation header
+   * - a minimum IP header inside the encapsulated packet
+   * Note: 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. */
+  minimumLength =
+    GetIpHeaderLength(rxBuffer) +
+    sizeof(struct udphdr) +
+    ENCAP_HDR_LEN +
+    sizeof(struct ip);
+  if (nBytes < minimumLength)
+  {
+    olsr_printf(
+      1,
+      "%s: captured a too short encapsulation packet (%d bytes) on \"%s\"\n",
+      PLUGIN_NAME,
+      nBytes,
+      walker->ifName);
 
-      /* Receive the packet, leaving space for the BMF encapsulation header */
-      ipPacket = GetIpPacket(rxBuffer);
-    
-      bufferToRead = ipPacket;
-      nBytesToRead = BMF_BUFFER_SIZE - ENCAP_HDR_LEN;
+    return;
+  }
 
-      nBytes = read(EtherTunTapFd, bufferToRead, nBytesToRead);
+  forwardedBy.v4 = ipHeader->ip_src;
+  forwardedTo.v4 = ipHeader->ip_dst;
+  BmfEncapsulationPacketReceived(
+    walker,
+    &forwardedBy,
+    &forwardedTo,
+    rxBuffer + GetIpHeaderLength(rxBuffer) + sizeof(struct udphdr));
 
-      if (nBytes < 0)
-      {
-        BmfPError("recvfrom() error on \"%s\"", EtherTunTapIfName);
-      }
-      else
-      {
-        /* 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,
-            "%s: captured packet too short (%d bytes) on \"%s\"\n",
-            PLUGIN_NAME,
-            nBytes,
-            EtherTunTapIfName);
-        }
-        else
-        {
-          /* An outbound packet was captured */
+}
 
-          BmfTunPacketCaptured(rxBuffer);
+void
+BMF_handle_encapsulatingFd(int skfd, void *data, unsigned int flags __attribute__ ((unused))) {
+  unsigned char rxBuffer[BMF_BUFFER_SIZE];
+  struct TBmfInterface* walker = data;
+  struct sockaddr_in from;
+  socklen_t fromLen = sizeof(from);
+  int nBytes;
+  int minimumLength;
+  union olsr_ip_addr forwardedBy;
+
+  /* An encapsulated packet was received */
+  nBytes = recvfrom(
+    skfd,
+    rxBuffer,
+    BMF_BUFFER_SIZE,
+    0,
+    (struct sockaddr*)&from,
+    &fromLen);
+  if (nBytes < 0)
+  {
+    BmfPError("recvfrom() error on \"%s\"", walker->ifName);
 
-        } /* if (nBytes < ... */
-      } /* if (nBytes < 0) */
-    } /* if (nFdBitsSet > 0 && ... */
+    return;
+  } /* if (nBytes < 0) */
+
+  forwardedBy.v4 = from.sin_addr;
+
+  /* Check if the number of received bytes is large enough for a minimal BMF
+   * encapsulation packet, at least:
+   * - the encapsulation header
+   * - a minimum IP header inside the encapsulated packet */
+  minimumLength =
+    ENCAP_HDR_LEN +
+    sizeof(struct ip);
+  if (nBytes < minimumLength)
+  {
+    struct ipaddr_str buf;
+    olsr_printf(
+      1,
+      "%s: received a too short encapsulation packet (%d bytes) from %s on \"%s\"\n",
+      PLUGIN_NAME,
+      nBytes,
+      olsr_ip_to_string(&buf, &forwardedBy),
+      walker->ifName);
+    return;
+  }
 
-    /* Release safe access to OLSR data */
-#if 0
-    pthread_mutex_unlock(&olsr_mutex);
-#endif
-  } /* while (nFdBitsSet > 0) */
-} /* DoBmf */
+  /* 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);
+}
 
-/* -------------------------------------------------------------------------
- * Function   : BmfSignalHandler
- * Description: Signal handler function
- * Input      : signo - signal being handled
- * Output     : none
- * Return     : none
- * Data Used  : BmfThreadRunning
- * ------------------------------------------------------------------------- */
-static void BmfSignalHandler(int signo __attribute__((unused)))
-{
-  BmfThreadRunning = 0;
-} /* BmfSignalHandler */
+void
+BMF_handle_tuntapFd(int skfd __attribute__ ((unused)),
+    void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused))) {
+  unsigned char rxBuffer[BMF_BUFFER_SIZE];
+  int nBytes;
+  unsigned char* ipPacket;
+  unsigned char* bufferToRead;
+  size_t nBytesToRead;
 
-/* -------------------------------------------------------------------------
- * Function   : BmfRun
- * Description: Receiver thread function
- * Input      : useless - not used
- * Output     : none
- * Return     : not used
- * Data Used  : BmfThreadRunning
- * Notes      : Another thread can gracefully stop this thread by sending
- *              a SIGALRM signal.
- * ------------------------------------------------------------------------- */
-static void* BmfRun(void* useless __attribute__((unused)))
-{
-  /* Mask all signals except SIGALRM */
-  sigset_t blockedSigs;
-  sigfillset(&blockedSigs);
-  sigdelset(&blockedSigs, SIGALRM);
-  if (pthread_sigmask(SIG_BLOCK, &blockedSigs, NULL) != 0)
-  {
-    BmfPError("pthread_sigmask() error");
-  }
+  /* Receive the packet, leaving space for the BMF encapsulation header */
+  ipPacket = GetIpPacket(rxBuffer);
+    
+  bufferToRead = ipPacket;
+  nBytesToRead = BMF_BUFFER_SIZE - ENCAP_HDR_LEN;
 
-  /* Set up the signal handler for the process: use SIGALRM to terminate
-   * the BMF thread. Only if a signal handler is specified, does a blocking
-   * system call return with errno set to EINTR; if a signal hander is not
-   * specified, any system call in which the thread may be waiting will not
-   * return. Note that the BMF thread is usually blocked in the select()
-   * function (see DoBmf()). */
-  if (signal(SIGALRM, BmfSignalHandler) == SIG_ERR)
+  nBytes = read(EtherTunTapFd, bufferToRead, nBytesToRead);
+  if (nBytes < 0)
   {
-    BmfPError("signal() error");
+    BmfPError("recvfrom() error on \"%s\"", EtherTunTapIfName);
+    return;
   }
 
-  /* Call the thread function until flagged to exit */
-  while (BmfThreadRunning != 0)
+  /* 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))
   {
-    DoBmf();
+    olsr_printf(
+      1,
+      "%s: captured packet too short (%d bytes) on \"%s\"\n",
+      PLUGIN_NAME,
+      nBytes,
+      EtherTunTapIfName);
+    return;
   }
 
-  return NULL;
-} /* BmfRun */
+  BmfTunPacketCaptured(rxBuffer);
+}
 
 /* -------------------------------------------------------------------------
  * Function   : InterfaceChange
@@ -1486,7 +1189,7 @@ void InterfaceChange(int if_index __attribute__((unused)), struct interface* int
 /* -------------------------------------------------------------------------
  * Function   : SetFanOutLimit
  * Description: Overrule the default fan out limit value (2)
- * Input      : value - fan out limit value (1...MAX_UNICAST_NEIGHBORS)
+ * Input      : value - fan out limit value (0...MAX_UNICAST_NEIGHBORS)
  *              data - not used
  *              addon - not used
  * Output     : none
@@ -1501,7 +1204,7 @@ int SetFanOutLimit(
   if (set_plugin_int(value, &FanOutLimit, addon) == 0)
   {
     /* Extra check if within range */
-    if (FanOutLimit >= 1 && FanOutLimit <= MAX_UNICAST_NEIGHBORS)
+    if (FanOutLimit >= 0 && FanOutLimit <= MAX_UNICAST_NEIGHBORS)
     {
       return 0;
     }
@@ -1522,14 +1225,6 @@ int InitBmf(struct interface* skipThisIntf)
 {
   CreateBmfNetworkInterfaces(skipThisIntf);
 
-  /* Start running the multicast packet processing thread */
-  BmfThreadRunning = 1;
-  if (pthread_create(&BmfThread, NULL, BmfRun, NULL) != 0)
-  {
-    BmfPError("pthread_create() error");
-    return 0;
-  }
-
   if (EtherTunTapFd >= 0)
   {
     /* Deactivate IP spoof filter for EtherTunTap interface */
@@ -1565,24 +1260,6 @@ void CloseBmf(void)
     RestoreSpoofFilter();
   }
 
-  if (BmfThreadRunning)
-  {
-    /* Signal BmfThread to exit */
-    /* Strangely enough, all running threads receive the SIGALRM signal. But only the
-     * BMF thread is affected by this signal, having specified a handler for this
-     * signal in its thread entry function BmfRun(...). */
-    if (pthread_kill(BmfThread, SIGALRM) != 0)
-    {
-      BmfPError("pthread_kill() error");
-    }
-
-    /* Wait for BmfThread to acknowledge */
-    if (pthread_join(BmfThread, NULL) != 0)
-    {
-      BmfPError("pthread_join() error");
-    }
-  }
-
   /* Clean up after the BmfThread has been killed */
   CloseBmfNetworkInterfaces();
 } /* CloseBmf */
index 9987ab5..4561950 100644 (file)
@@ -46,7 +46,7 @@
 /* BMF plugin data */
 #define PLUGIN_NAME "OLSRD Basic Multicast Forwarding (BMF) plugin"
 #define PLUGIN_NAME_SHORT "OLSRD BMF"
-#define PLUGIN_VERSION "1.6.2 (" __DATE__ " " __TIME__ ")"
+#define PLUGIN_VERSION "1.7.0 (" __DATE__ " " __TIME__ ")"
 #define PLUGIN_COPYRIGHT "  (C) Thales Communications Huizen, Netherlands"
 #define PLUGIN_AUTHOR "  Erik Tromp (eriktromp@users.sourceforge.net)"
 #define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION "\n" PLUGIN_COPYRIGHT "\n" PLUGIN_AUTHOR
@@ -61,6 +61,11 @@ struct interface;
 extern int FanOutLimit;
 extern int BroadcastRetransmitCount;
 
+void BMF_handle_captureFd(int skfd, void *data, unsigned int);
+void BMF_handle_listeningFd(int skfd, void *data, unsigned int);
+void BMF_handle_encapsulatingFd(int skfd, void *data, unsigned int);
+void BMF_handle_tuntapFd(int, void*, unsigned int);
+
 void BmfPError(const char* format, ...) __attribute__((format(printf, 1, 2)));
 union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip);
 void InterfaceChange(int, struct interface* interf, enum olsr_ifchg_flag action);
index c29e7e1..92763e9 100644 (file)
@@ -394,11 +394,12 @@ void RestoreSpoofFilter(void)
  * Description: Find the 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 
+ *              source - the source IP address of the BMF packet, or NULL if
+ *                unknown or not applicable
  *              forwardedBy - the IP address of the node that forwarded the BMF
- *                packet
+ *                packet, or NULL if unknown or not applicable
  *              forwardedTo - the IP address of the node to which the BMF packet
- *                was directed
+ *                was directed, or NULL if unknown or not applicable
  * Output     : neighbors - list of (up to a number of 'FanOutLimit') neighbors.
  *              bestNeighbor - the best neighbor (in terms of lowest cost or ETX
  *                value)
@@ -433,7 +434,6 @@ void FindNeighbors(
   {
     struct link_entry* walker;
 
-    /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
     OLSR_FOR_ALL_LINK_ENTRIES(walker) {
       union olsr_ip_addr* neighborMainIp;
 
@@ -445,7 +445,7 @@ void FindNeighbors(
 
       OLSR_PRINTF(
         8,
-        "%s: ----> Considering forwarding pkt on \"%s\" to %s\n",
+        "%s: ----> considering forwarding pkt on \"%s\" to %s\n",
         PLUGIN_NAME_SHORT,
         intf->ifName,
         olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
@@ -458,7 +458,7 @@ void FindNeighbors(
       {
         OLSR_PRINTF(
           9,
-          "%s: ----> Not forwarding to %s: is source of pkt\n",
+          "%s: ----> not forwarding to %s: is source of pkt\n",
           PLUGIN_NAME_SHORT,
           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
@@ -470,7 +470,7 @@ void FindNeighbors(
       {
         OLSR_PRINTF(
           9,
-          "%s: ----> Not forwarding to %s: is the node that forwarded the pkt\n",
+          "%s: ----> not forwarding to %s: is the node that forwarded the pkt\n",
           PLUGIN_NAME_SHORT,
           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
@@ -482,7 +482,7 @@ void FindNeighbors(
       {
         OLSR_PRINTF(
           9,
-          "%s: ----> Not forwarding to %s: is the node to which the pkt was forwarded\n",
+          "%s: ----> not forwarding to %s: is the node to which the pkt was forwarded\n",
           PLUGIN_NAME_SHORT,
           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
@@ -531,7 +531,6 @@ void FindNeighbors(
       }
     }
 
-    /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
     for (walker = get_link_set(); walker != NULL; walker = walker->next) 
     {
       union olsr_ip_addr* neighborMainIp;
@@ -546,7 +545,7 @@ void FindNeighbors(
 
       OLSR_PRINTF(
         9,
-        "%s: ----> Considering forwarding pkt on \"%s\" to %s\n",
+        "%s: ----> considering forwarding pkt on \"%s\" to %s\n",
         PLUGIN_NAME_SHORT,
         intf->ifName,
         olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
@@ -559,7 +558,7 @@ void FindNeighbors(
       {
         OLSR_PRINTF(
           9,
-          "%s: ----> Not forwarding to %s: is source of pkt\n",
+          "%s: ----> not forwarding to %s: is source of pkt\n",
           PLUGIN_NAME_SHORT,
           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
@@ -571,7 +570,7 @@ void FindNeighbors(
       {
         OLSR_PRINTF(
           9,
-          "%s: ----> Not forwarding to %s: is the node that forwarded the pkt\n",
+          "%s: ----> not forwarding to %s: is the node that forwarded the pkt\n",
           PLUGIN_NAME_SHORT,
           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
@@ -583,7 +582,7 @@ void FindNeighbors(
       {
         OLSR_PRINTF(
           9,
-          "%s: ----> Not forwarding to %s: is the node to which the pkt was forwarded\n",
+          "%s: ----> not forwarding to %s: is the node to which the pkt was forwarded\n",
           PLUGIN_NAME_SHORT,
           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
@@ -596,7 +595,7 @@ void FindNeighbors(
       {
         OLSR_PRINTF(
           9,
-          "%s: ----> Not forwarding to %s: link is timing out\n",
+          "%s: ----> not forwarding to %s: link is timing out\n",
           PLUGIN_NAME_SHORT,
           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
@@ -606,15 +605,14 @@ void FindNeighbors(
       /* Compare costs to check if the candidate neighbor is best reached via 'intf' */
       OLSR_PRINTF(
         9,
-        "%s: ----> Forwarding pkt to %s will cost %5.2f\n",
+        "%s: ----> forwarding pkt to %s will cost %5.2f\n",
         PLUGIN_NAME_SHORT,
         olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
         walker->link_cost);
 
       /* If the candidate neighbor is best reached via another interface, then skip 
        * the candidate neighbor; the candidate neighbor has been / will be selected via that
-       * other interface.
-       * Assumption: olsr_mutex has been grabbed for safe access to OLSR data. */
+       * other interface. */
       bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
 
       if (walker != bestLinkToNeighbor)
@@ -623,7 +621,7 @@ void FindNeighbors(
         {
           OLSR_PRINTF(
             9,
-            "%s: ----> Not forwarding to %s: no link found\n",
+            "%s: ----> not forwarding to %s: no link found\n",
             PLUGIN_NAME_SHORT,
             olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
         }
@@ -633,7 +631,7 @@ void FindNeighbors(
 
           OLSR_PRINTF(
             9,
-            "%s: ----> Not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %5.2f\n",
+            "%s: ----> not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %5.2f\n",
             PLUGIN_NAME_SHORT,
             olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
             bestIntf->int_name,
@@ -660,13 +658,11 @@ void FindNeighbors(
        * neighbor, because the 'forwardedBy' node will forward the packet. */
       if (forwardedBy != NULL)
       {
-        /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
         tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
         if (tcLastHop != NULL)
         {
           struct tc_edge_entry* tc_edge;
 
-          /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
           tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
           
           /* We are not interested in dead-end or dying edges. */
@@ -680,7 +676,7 @@ void FindNeighbors(
 #endif
               OLSR_PRINTF(
                 9,
-                "%s: ----> Not forwarding to %s: I am not an MPR between %s and %s, direct link costs %5.2f\n",
+                "%s: ----> not forwarding to %s: I am not an MPR between %s and %s, direct link costs %5.2f\n",
                 PLUGIN_NAME_SHORT,
                 neighbor_iface_buf.buf,
                 olsr_ip_to_string(&forw_buf, forwardedBy),
@@ -728,7 +724,6 @@ void FindNeighbors(
       }
     }
 
-    /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
     OLSR_FOR_ALL_LINK_ENTRIES(walker) {
       union olsr_ip_addr* neighborMainIp;
       struct link_entry* bestLinkToNeighbor;
@@ -743,7 +738,7 @@ void FindNeighbors(
 
       OLSR_PRINTF(
         9,
-        "%s: ----> Considering forwarding pkt on \"%s\" to %s\n",
+        "%s: ----> considering forwarding pkt on \"%s\" to %s\n",
         PLUGIN_NAME_SHORT,
         intf->ifName,
         olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
@@ -756,7 +751,7 @@ void FindNeighbors(
       {
         OLSR_PRINTF(
           9,
-          "%s: ----> Not forwarding to %s: is source of pkt\n",
+          "%s: ----> not forwarding to %s: is source of pkt\n",
           PLUGIN_NAME_SHORT,
           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
@@ -768,7 +763,7 @@ void FindNeighbors(
       {
         OLSR_PRINTF(
           9,
-          "%s: ----> Not forwarding to %s: is the node that forwarded the pkt\n",
+          "%s: ----> not forwarding to %s: is the node that forwarded the pkt\n",
           PLUGIN_NAME_SHORT,
           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
@@ -780,7 +775,7 @@ void FindNeighbors(
       {
         OLSR_PRINTF(
           9,
-          "%s: ----> Not forwarding to %s: is the node to which the pkt was forwarded\n",
+          "%s: ----> not forwarding to %s: is the node to which the pkt was forwarded\n",
           PLUGIN_NAME_SHORT,
           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
@@ -796,7 +791,7 @@ void FindNeighbors(
       {
         OLSR_PRINTF(
           9,
-          "%s: ----> Not forwarding to %s: link is timing out\n",
+          "%s: ----> not forwarding to %s: link is timing out\n",
           PLUGIN_NAME_SHORT,
           olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
@@ -806,15 +801,14 @@ void FindNeighbors(
       /* Compare costs to check if the candidate neighbor is best reached via 'intf' */
       OLSR_PRINTF(
         9,
-        "%s: ----> Forwarding pkt to %s will cost ETX %5.2f\n",
+        "%s: ----> forwarding pkt to %s will cost ETX %5.2f\n",
         PLUGIN_NAME_SHORT,
         olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
         currEtx);
 
       /* If the candidate neighbor is best reached via another interface, then skip 
        * the candidate neighbor; the candidate neighbor has been / will be selected via that
-       * other interface.
-       * Assumption: olsr_mutex has been grabbed for safe access to OLSR data. */
+       * other interface. */
       bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
 
       if (walker != bestLinkToNeighbor)
@@ -823,7 +817,7 @@ void FindNeighbors(
         {
           OLSR_PRINTF(
             9,
-            "%s: ----> Not forwarding to %s: no link found\n",
+            "%s: ----> not forwarding to %s: no link found\n",
             PLUGIN_NAME_SHORT,
             olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
         }
@@ -835,7 +829,7 @@ void FindNeighbors(
 #endif
           OLSR_PRINTF(
             9,
-            "%s: ----> Not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %s\n",
+            "%s: ----> not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %s\n",
             PLUGIN_NAME_SHORT,
             olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
             bestIntf->int_name,
@@ -866,13 +860,11 @@ void FindNeighbors(
        * neighbor, because the 'forwardedBy' node will forward the packet. */
       if (forwardedBy != NULL)
       {
-        /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
         tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
         if (tcLastHop != NULL)
         {
           struct tc_edge_entry* tc_edge;
 
-          /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
           tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
 
           /* We are not interested in dead-end edges. */
@@ -888,7 +880,7 @@ void FindNeighbors(
 #endif
               OLSR_PRINTF(
                 9,
-                "%s: ----> Not forwarding to %s: I am not an MPR between %s and %s, direct link costs %s\n",
+                "%s: ----> not forwarding to %s: I am not an MPR between %s and %s, direct link costs %s\n",
                 PLUGIN_NAME_SHORT,
                 neighbor_iface_buf.buf,
                 olsr_ip_to_string(&forw_buf, forwardedBy),
@@ -928,7 +920,7 @@ void FindNeighbors(
   {
     OLSR_PRINTF(
       9,
-      "%s: ----> No suitable neighbor found to forward to on \"%s\"\n",
+      "%s: ----> no suitable neighbor found to forward to on \"%s\"\n",
       PLUGIN_NAME_SHORT,
       intf->ifName);
   }
@@ -1182,7 +1174,6 @@ static int CreateLocalEtherTunTap(void)
 {
   static const char deviceName[] = "/dev/net/tun";
   struct ifreq ifreq;
-  union olsr_sockaddr sock;
   int etfd;
   int ioctlSkfd;
   int ioctlres;
@@ -1250,23 +1241,17 @@ static int CreateLocalEtherTunTap(void)
     EtherTunTapIp = ETHERTUNTAPDEFAULTIP;
   }
 
-  memset(&sock, 0, sizeof(sock));
-  sock.in4.sin_family = AF_INET;
-
-  sock.in4.sin_addr.s_addr = htonl(EtherTunTapIp);
-  ifreq.ifr_addr = sock.in;
+  ((struct sockaddr_in*)&ifreq.ifr_addr)->sin_addr.s_addr = htonl(EtherTunTapIp);
   ioctlres = ioctl(ioctlSkfd, SIOCSIFADDR, &ifreq);
   if (ioctlres >= 0)
   {
     /* Set net mask */
-    sock.in4.sin_addr.s_addr = htonl(EtherTunTapIpMask);
-    ifreq.ifr_netmask = sock.in;
+    ((struct sockaddr_in*)&ifreq.ifr_netmask)->sin_addr.s_addr = htonl(EtherTunTapIpMask);
     ioctlres = ioctl(ioctlSkfd, SIOCSIFNETMASK, &ifreq);
     if (ioctlres >= 0)
     {
       /* Set broadcast IP */
-      sock.in4.sin_addr.s_addr = htonl(EtherTunTapIpBroadcast);
-      ifreq.ifr_broadaddr = sock.in;
+      ((struct sockaddr_in*)&ifreq.ifr_broadaddr)->sin_addr.s_addr = htonl(EtherTunTapIpBroadcast);
       ioctlres = ioctl(ioctlSkfd, SIOCSIFBRDADDR, &ifreq);
       if (ioctlres >= 0)
       {
@@ -1431,6 +1416,16 @@ static int CreateInterface(
     return 0;
   }
 
+  /* add listeners to sockets */
+  if (capturingSkfd != -1) {
+    add_olsr_socket(capturingSkfd, NULL, BMF_handle_captureFd, newIf, SP_IMM_READ);
+  }
+  if (encapsulatingSkfd != -1) {
+    add_olsr_socket(encapsulatingSkfd, NULL, BMF_handle_encapsulatingFd, newIf, SP_IMM_READ);
+  }
+  if (listeningSkfd != -1) {
+    add_olsr_socket(listeningSkfd, NULL, BMF_handle_listeningFd, newIf, SP_IMM_READ);
+  }
   /* Copy data into TBmfInterface object */
   newIf->capturingSkfd = capturingSkfd;
   newIf->encapsulatingSkfd = encapsulatingSkfd;
@@ -1615,6 +1610,7 @@ int CreateBmfNetworkInterfaces(struct interface* skipThisIntf)
   EtherTunTapFd = CreateLocalEtherTunTap();
   if (EtherTunTapFd >= 0)
   {
+    add_olsr_socket(EtherTunTapFd, NULL, BMF_handle_tuntapFd, NULL, SP_IMM_READ);
     nOpenedSockets++;
   }
 
@@ -1665,11 +1661,19 @@ void CloseBmfNetworkInterfaces(void)
     if (bmfIf->capturingSkfd >= 0)
     {
       close(bmfIf->capturingSkfd);
+      remove_olsr_socket(bmfIf->capturingSkfd, NULL, BMF_handle_captureFd);
       nClosed++;
     }
     if (bmfIf->encapsulatingSkfd >= 0) 
     {
       close(bmfIf->encapsulatingSkfd);
+      remove_olsr_socket(bmfIf->encapsulatingSkfd, NULL, BMF_handle_encapsulatingFd);
+      nClosed++;
+    }
+    if (bmfIf->listeningSkfd >= 0)
+    {
+      close(bmfIf->listeningSkfd);
+      remove_olsr_socket(bmfIf->listeningSkfd, NULL, BMF_handle_listeningFd);
       nClosed++;
     }
 
@@ -1710,6 +1714,7 @@ void CloseBmfNetworkInterfaces(void)
   if (EtherTunTapFd >= 0)
   {
     close(EtherTunTapFd);
+    remove_olsr_socket(EtherTunTapFd, NULL, BMF_handle_tuntapFd);
     nClosed++;
 
     OLSR_PRINTF(7, "%s: closed \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
@@ -1726,14 +1731,14 @@ void CloseBmfNetworkInterfaces(void)
 
   OLSR_PRINTF(
     7,
-    "%s: Total all OLSR interfaces    : RX pkts %d (%d dups); TX pkts %d\n",
+    "%s: total all OLSR interfaces    : RX pkts %d (%d dups); TX pkts %d\n",
     PLUGIN_NAME_SHORT,
     totalOlsrBmfPacketsRx,
     totalOlsrBmfPacketsRxDup,
     totalOlsrBmfPacketsTx);
   OLSR_PRINTF(
     7,
-    "%s: Total all non-OLSR interfaces: RX pkts %d (%d dups); TX pkts %d\n",
+    "%s: total all non-OLSR interfaces: RX pkts %d (%d dups); TX pkts %d\n",
     PLUGIN_NAME_SHORT,
     totalNonOlsrBmfPacketsRx,
     totalNonOlsrBmfPacketsRxDup,
@@ -1876,8 +1881,6 @@ void CheckAndUpdateLocalBroadcast(unsigned char* ipPacket, union olsr_ip_addr* b
 void AddMulticastRoute(void)
 {
   struct rtentry kernel_route;
-  union olsr_sockaddr sock;
-
   int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
   if (ioctlSkfd < 0)
   {
@@ -1887,17 +1890,13 @@ void AddMulticastRoute(void)
 
   memset(&kernel_route, 0, sizeof(struct rtentry));
 
-  kernel_route.rt_gateway.sa_family = AF_INET;
+  ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
+  ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
+  ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
 
   /* 224.0.0.0/4 */
-  memset(&sock, 0, sizeof(sock));
-  sock.in4.sin_family = AF_INET;
-
-  sock.in4.sin_addr.s_addr = htonl(0xE0000000);
-  kernel_route.rt_dst = sock.in;
-
-  sock.in4.sin_addr.s_addr = htonl(0xF0000000);
-  kernel_route.rt_genmask = sock.in;
+  ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = htonl(0xE0000000);
+  ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = htonl(0xF0000000);
 
   kernel_route.rt_metric = 0;
   kernel_route.rt_flags = RTF_UP;
@@ -1927,8 +1926,6 @@ void DeleteMulticastRoute(void)
   if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP)
   {
     struct rtentry kernel_route;
-    union olsr_sockaddr sock;
-
     int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
     if (ioctlSkfd < 0)
     {
@@ -1938,17 +1935,13 @@ void DeleteMulticastRoute(void)
 
     memset(&kernel_route, 0, sizeof(struct rtentry));
 
-    kernel_route.rt_gateway.sa_family = AF_INET;
+    ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
+    ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
+    ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
 
     /* 224.0.0.0/4 */
-    memset(&sock, 0, sizeof(sock));
-    sock.in4.sin_family = AF_INET;
-
-    sock.in4.sin_addr.s_addr = htonl(0xE0000000);
-    kernel_route.rt_dst = sock.in;
-
-    sock.in4.sin_addr.s_addr = htonl(0xF0000000);
-    kernel_route.rt_genmask = sock.in;
+    ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = htonl(0xE0000000);
+    ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = htonl(0xF0000000);
 
     kernel_route.rt_metric = 0;
     kernel_route.rt_flags = RTF_UP;
index e759ae9..a1150da 100644 (file)
@@ -49,7 +49,7 @@
 #include <stdlib.h> /* free() */
 
 /* OLSRD includes */
-#include "olsr.h" /* olsr_printf */
+#include "olsr.h" /* olsr_malloc */
 #include "scheduler.h" /* GET_TIMESTAMP, TIMED_OUT */
 
 /* Plugin includes */