android: fix the path of the tunnel node in the /dev tree
[olsrd.git] / lib / bmf / src / NetworkInterfaces.c
index 42a1291..27251c9 100644 (file)
 #include "ipcalc.h"
 #include "defs.h" /* olsr_cnf */
 #include "link_set.h" /* get_link_set() */
-#include "lq_route.h" /* MIN_LINK_QUALITY */
-#include "tc_set.h" /* olsr_lookup_tc_entry(), olsr_tc_lookup_dst() */
+#include "tc_set.h" /* olsr_lookup_tc_entry(), olsr_lookup_tc_edge() */
 #include "net_olsr.h" /* ipequal */
+#include "lq_plugin.h"
+#include "kernel_tunnel.h"
 
 /* Plugin includes */
 #include "Packet.h" /* IFHWADDRLEN */
@@ -108,6 +109,9 @@ u_int32_t EtherTunTapIpMask = 0xFFFFFFFF;
  * May be overruled by setting the plugin parameter "BmfinterfaceIp". */
 u_int32_t EtherTunTapIpBroadcast = ETHERTUNTAPIPNOTSET;
 
+/* Whether or not the BMF network interface must be marked as persistent */
+int EtherTunTapPersistent = 1;
+
 /* Whether or not the configuration has overruled the default IP
  * configuration of the EtherTunTap interface */
 int TunTapIpOverruled = 0;
@@ -212,6 +216,32 @@ int SetBmfInterfaceIp(
   return 0;
 } /* SetBmfInterfaceIp */
 
+/* -------------------------------------------------------------------------
+ * Function   : SetBmfInterfacePersistent
+ * Description: Determine if the EtherTunTap interface must be marked
+ *              persistent or not
+ * Input      : value - yes/true/1  or no/false/0
+ *              data  - not used
+ *              addon - not used
+ * Output     : none
+ * Return     : success (0) or fail (1)
+ * Data Used  : EtherTunTapPersistent
+ * ------------------------------------------------------------------------- */
+int SetBmfInterfacePersistent(
+  const char* value,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
+{
+       if (strcasecmp(value, "yes") == 0 || strcasecmp(value, "true") == 0 || strcasecmp(value, "1") == 0) {
+               EtherTunTapPersistent = 1;
+       } else if (strcasecmp(value, "no") == 0 || strcasecmp(value, "false") == 0 || strcasecmp(value, "0") == 0) {
+               EtherTunTapPersistent = 0;
+       } else {
+               return 1;
+       }
+       return 0;
+} /* SetBmfInterfacePersistent */
+
 /* -------------------------------------------------------------------------
  * Function   : SetCapturePacketsOnOlsrInterfaces
  * Description: Overrule the default setting, enabling or disabling the
@@ -333,7 +363,7 @@ int DeactivateSpoofFilter(void)
     return 0;
   }
 
-  EthTapSpoofState = fgetc(procSpoof);
+  EthTapSpoofState = (char)fgetc(procSpoof);
   fclose(procSpoof);
 
   /* Open procfile for writing */
@@ -389,40 +419,17 @@ void RestoreSpoofFilter(void)
   }
 } /* RestoreSpoofFilter */
 
-#ifndef USING_THALES_LINK_COST_ROUTING
-/* -------------------------------------------------------------------------
- * Function   : CalcEtx
- * Description: Calculate the Expected Transmission Count (ETX) value, based on
- *              link loss fraction and inverse link loss fraction
- * Input      : loss - link loss fraction
- *              neigh_loss - inverse link loss fraction 
- * Output     : none
- * Return     : the ETX value
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-static float CalcEtx(float loss, float neigh_loss) 
-{
-  if (loss < MIN_LINK_QUALITY || neigh_loss < MIN_LINK_QUALITY)
-  {
-    return INFINITE_ETX;
-  }
-  else
-  {
-    return 1.0 / (loss * neigh_loss);
-  }
-} /* CalcEtx */
-#endif /* USING_THALES_LINK_COST_ROUTING */
-
 /* -------------------------------------------------------------------------
  * Function   : FindNeighbors
  * 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)
@@ -438,6 +445,9 @@ void FindNeighbors(
   union olsr_ip_addr* forwardedTo,
   int* nPossibleNeighbors)
 {
+#ifndef NODEBUG
+  struct ipaddr_str buf;
+#endif /* NODEBUG */
   int i;
 
   /* Initialize */
@@ -454,12 +464,7 @@ void FindNeighbors(
   {
     struct link_entry* walker;
 
-    /* TODO: get_link_set() is not thread-safe! */
-    for (walker = get_link_set(); walker != NULL; walker = walker->next) 
-    {
-#ifndef NODEBUG
-      struct ipaddr_str buf;
-#endif
+    OLSR_FOR_ALL_LINK_ENTRIES(walker) {
       union olsr_ip_addr* neighborMainIp;
 
       /* Consider only links from the specified interface */
@@ -470,7 +475,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));
@@ -481,12 +486,9 @@ void FindNeighbors(
        * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
       if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
       {
-#ifndef NODEBUG
-        struct ipaddr_str buf;
-#endif
         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));
 
@@ -496,12 +498,9 @@ void FindNeighbors(
       /* Rely on short-circuit boolean evaluation */
       if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
       {
-#ifndef NODEBUG
-        struct ipaddr_str buf;
-#endif
         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));
 
@@ -511,12 +510,9 @@ void FindNeighbors(
       /* Rely on short-circuit boolean evaluation */
       if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
       {
-#ifndef NODEBUG
-        struct ipaddr_str buf;
-#endif
         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));
 
@@ -543,7 +539,7 @@ void FindNeighbors(
       }
 
       *nPossibleNeighbors += 1;
-    } /* for */
+    } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
 
   }
   /* handle the LQ case */
@@ -565,7 +561,6 @@ void FindNeighbors(
       }
     }
 
-    /* TODO: get_link_set() is not thread-safe! */
     for (walker = get_link_set(); walker != NULL; walker = walker->next) 
     {
       union olsr_ip_addr* neighborMainIp;
@@ -580,10 +575,10 @@ 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(&walker->neighbor_iface_addr));
+        olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
       neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
 
@@ -593,9 +588,9 @@ 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(&walker->neighbor_iface_addr));
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
         continue; /* for */
       }
@@ -605,9 +600,9 @@ 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(&walker->neighbor_iface_addr));
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
         continue; /* for */
       }
@@ -617,9 +612,9 @@ 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(&walker->neighbor_iface_addr));
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
         continue; /* for */
       }
@@ -630,9 +625,9 @@ 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(&walker->neighbor_iface_addr));
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
         continue; /* for */
       }
@@ -640,15 +635,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(&walker->neighbor_iface_addr),
+        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.
-       * TODO: get_best_link_to_neighbor() is not thread-safe. */
+       * other interface. */
       bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
 
       if (walker != bestLinkToNeighbor)
@@ -657,9 +651,9 @@ 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(&walker->neighbor_iface_addr));
+            olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
         }
         else
         {
@@ -667,9 +661,9 @@ 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(&walker->neighbor_iface_addr),
+            olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
             bestIntf->int_name,
             bestLinkToNeighbor->link_cost);
         }
@@ -683,8 +677,8 @@ void FindNeighbors(
           9,
           "%s: ----> 2-hop path from %s via me to %s will cost %5.2f\n",
           PLUGIN_NAME_SHORT,
-          olsr_ip_to_string(forwardedBy),
-          olsr_ip_to_string(&walker->neighbor_iface_addr),
+          olsr_ip_to_string(&forwardedByBuf, forwardedBy),
+          olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
           previousLinkCost + walker->link_cost);
       }
 
@@ -694,28 +688,33 @@ void FindNeighbors(
        * neighbor, because the 'forwardedBy' node will forward the packet. */
       if (forwardedBy != NULL)
       {
-        /* TODO: olsr_lookup_tc_entry() is not thread-safe. */
         tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
         if (tcLastHop != NULL)
         {
-          struct topo_dst* tcDest;
-
-          /* TODO: olsr_tc_lookup_dst() is not thread-safe. */
-          tcDest = olsr_tc_lookup_dst(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
+          struct tc_edge_entry* tc_edge;
 
-          /* Rely on short-circuit boolean evaluation */
-          if (tcDest != NULL && previousLinkCost + walker->link_cost > tcDest->link_cost)
+          tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
+          
+          /* We are not interested in dead-end or dying edges. */
+          if (tc_edge != NULL && (tc_edge->flags & OLSR_TC_EDGE_DOWN) == 0)
           {
-            OLSR_PRINTF(
-              9,
-              "%s: ----> Not forwarding to %s: I am not an MPR between %s and %s, direct link costs %5.2f\n",
-              PLUGIN_NAME_SHORT,
-              olsr_ip_to_string(&walker->neighbor_iface_addr),
-              olsr_ip_to_string(forwardedBy),
-              olsr_ip_to_string(&walker->neighbor_iface_addr),
-              tcDest->link_cost);
-
-            continue; /* for */
+            if (previousLinkCost + walker->link_cost > tc_edge->link_cost)
+            {
+#ifndef NODEBUG
+              struct ipaddr_str neighbor_iface_buf, forw_buf;
+              olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
+#endif /* NODEBUG */
+              OLSR_PRINTF(
+                9,
+                "%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),
+                neighbor_iface_buf.buf,
+                tc_edge->link_cost);
+
+              continue; /* for */
+            } /* if */
           } /* if */
         } /* if */
       } /* if */
@@ -742,8 +741,8 @@ void FindNeighbors(
 #else /* USING_THALES_LINK_COST_ROUTING */
         
     struct link_entry* walker;
-    float previousLinkEtx = 2 * INFINITE_ETX;
-    float bestEtx = 2 * INFINITE_ETX;
+    olsr_linkcost previousLinkEtx = LINK_COST_BROKEN;
+    olsr_linkcost bestEtx = LINK_COST_BROKEN;
 
     if (forwardedBy != NULL)
     {
@@ -751,19 +750,11 @@ void FindNeighbors(
       struct link_entry* bestLinkFromForwarder = get_best_link_to_neighbor(forwardedBy);
       if (bestLinkFromForwarder != NULL)
       {
-        previousLinkEtx =
-          CalcEtx(
-            bestLinkFromForwarder->loss_link_quality,
-            bestLinkFromForwarder->neigh_link_quality);
+        previousLinkEtx = bestLinkFromForwarder->linkcost;
       }
     }
 
-    /* TODO: get_link_set() is not thread-safe! */
-    for (walker = get_link_set(); walker != NULL; walker = walker->next) 
-    {
-#ifndef NODEBUG
-      struct ipaddr_str buf;
-#endif
+    OLSR_FOR_ALL_LINK_ENTRIES(walker) {
       union olsr_ip_addr* neighborMainIp;
       struct link_entry* bestLinkToNeighbor;
       struct tc_entry* tcLastHop;
@@ -777,7 +768,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));
@@ -790,7 +781,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));
 
@@ -802,7 +793,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));
 
@@ -814,7 +805,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));
 
@@ -824,15 +815,13 @@ void FindNeighbors(
       /* Found a candidate neighbor to direct our packet to */
 
       /* Calculate the link quality (ETX) of the link to the found neighbor */
-      currEtx = CalcEtx(
-        walker->loss_link_quality,
-        walker->neigh_link_quality);
+      currEtx = walker->linkcost;
  
-      if (currEtx >= INFINITE_ETX)
+      if (currEtx >= LINK_COST_BROKEN)
       {
         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));
 
@@ -842,27 +831,23 @@ 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);
+        (double)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.
-       * TODO: get_best_link_to_neighbor() is not thread-safe. */
+       * other interface. */
       bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
 
       if (walker != bestLinkToNeighbor)
       {
         if (bestLinkToNeighbor == NULL)
         {
-#ifndef NODEBUG
-          struct ipaddr_str buf;
-#endif
           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));
         }
@@ -870,19 +855,17 @@ void FindNeighbors(
         {
 #ifndef NODEBUG
           struct interface* bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr);
-          struct ipaddr_str buf;
-#endif
+          struct lqtextbuffer lqbuffer;
+#endif /* NODEBUG */
           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 %s\n",
             PLUGIN_NAME_SHORT,
             olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
-            bestIntf->int_name,
-            CalcEtx(
-              bestLinkToNeighbor->loss_link_quality,
-              bestLinkToNeighbor->neigh_link_quality));
+            bestIntf ? bestIntf->int_name : "NULL",
+            get_linkcost_text(bestLinkToNeighbor->linkcost, false, &lqbuffer));
         }
-        
+
         continue; /* for */
       }
 
@@ -890,14 +873,15 @@ void FindNeighbors(
       {
 #ifndef NODEBUG
         struct ipaddr_str forwardedByBuf, niaBuf;
-#endif
+        struct lqtextbuffer lqbuffer;
+#endif /* NODEBUG */
         OLSR_PRINTF(
           9,
-          "%s: ----> 2-hop path from %s via me to %s will cost ETX %5.2f\n",
+          "%s: ----> 2-hop path from %s via me to %s will cost ETX %s\n",
           PLUGIN_NAME_SHORT,
           olsr_ip_to_string(&forwardedByBuf, forwardedBy),
           olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
-          previousLinkEtx + currEtx);
+          get_linkcost_text(previousLinkEtx + currEtx, true, &lqbuffer));
       }
 
       /* Check the topology table whether the 'forwardedBy' node is itself a direct
@@ -906,35 +890,32 @@ void FindNeighbors(
        * neighbor, because the 'forwardedBy' node will forward the packet. */
       if (forwardedBy != NULL)
       {
-        /* TODO: olsr_lookup_tc_entry() is not thread-safe. */
         tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
         if (tcLastHop != NULL)
         {
           struct tc_edge_entry* tc_edge;
 
-          /* TODO: olsr_lookup_tc_edge() is not thread-safe. */
           tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
 
-          if (tc_edge != NULL)
-          {
-            float tcEtx = CalcEtx(
-              tc_edge->link_quality,
-              tc_edge->inverse_link_quality);
+          /* We are not interested in dead-end edges. */
+          if (tc_edge) {
+            olsr_linkcost tcEtx = tc_edge->cost;
 
             if (previousLinkEtx + currEtx > tcEtx)
             {
 #ifndef NODEBUG
               struct ipaddr_str neighbor_iface_buf, forw_buf;
+              struct lqtextbuffer lqbuffer;
               olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
-#endif
+#endif /* NODEBUG */
               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 %s\n",
                 PLUGIN_NAME_SHORT,
                 neighbor_iface_buf.buf,
                 olsr_ip_to_string(&forw_buf, forwardedBy),
                 neighbor_iface_buf.buf,
-                tcEtx);
+                get_linkcost_text(tcEtx, false, &lqbuffer));
 
               continue; /* for */
             } /* if */
@@ -958,7 +939,7 @@ void FindNeighbors(
       }
 
       *nPossibleNeighbors += 1;
-    } /* for */
+    } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
 
 #endif /* USING_THALES_LINK_COST_ROUTING */
 
@@ -969,15 +950,12 @@ 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);
   }
   else
   {
-#ifndef NODEBUG
-    struct ipaddr_str buf;
-#endif
     OLSR_PRINTF(
       9,
       "%s: ----> %d neighbors found on \"%s\"; best neighbor to forward to: %s\n",
@@ -1224,7 +1202,7 @@ static int CreateEncapsulateSocket(const char* ifName)
  * ------------------------------------------------------------------------- */
 static int CreateLocalEtherTunTap(void)
 {
-  static const char deviceName[] = "/dev/net/tun";
+  static const char * deviceName = OS_TUNNEL_PATH;
   struct ifreq ifreq;
   int etfd;
   int ioctlSkfd;
@@ -1293,17 +1271,17 @@ static int CreateLocalEtherTunTap(void)
     EtherTunTapIp = ETHERTUNTAPDEFAULTIP;
   }
 
-  ((struct sockaddr_in*)&ifreq.ifr_addr)->sin_addr.s_addr = htonl(EtherTunTapIp);
+  ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifreq.ifr_addr))->sin_addr.s_addr = htonl(EtherTunTapIp);
   ioctlres = ioctl(ioctlSkfd, SIOCSIFADDR, &ifreq);
   if (ioctlres >= 0)
   {
     /* Set net mask */
-    ((struct sockaddr_in*)&ifreq.ifr_netmask)->sin_addr.s_addr = htonl(EtherTunTapIpMask);
+    ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifreq.ifr_netmask))->sin_addr.s_addr = htonl(EtherTunTapIpMask);
     ioctlres = ioctl(ioctlSkfd, SIOCSIFNETMASK, &ifreq);
     if (ioctlres >= 0)
     {
       /* Set broadcast IP */
-      ((struct sockaddr_in*)&ifreq.ifr_broadaddr)->sin_addr.s_addr = htonl(EtherTunTapIpBroadcast);
+      ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifreq.ifr_broadaddr))->sin_addr.s_addr = htonl(EtherTunTapIpBroadcast);
       ioctlres = ioctl(ioctlSkfd, SIOCSIFBRDADDR, &ifreq);
       if (ioctlres >= 0)
       {
@@ -1350,9 +1328,9 @@ static int CreateLocalEtherTunTap(void)
   /* Use ioctl to make the tuntap persistent. Otherwise it will disappear
    * when this program exits. That is not desirable, since a multicast
    * daemon (e.g. mrouted) may be using the tuntap interface. */
-  if (ioctl(etfd, TUNSETPERSIST, (void *)&ifreq) < 0)
+  if (ioctl(etfd, TUNSETPERSIST, EtherTunTapPersistent ? (void *)&ifreq : NULL) < 0)
   {
-    BmfPError("error making EtherTunTap interface \"%s\" persistent", EtherTunTapIfName);
+    BmfPError("error making EtherTunTap interface \"%s\" %spersistent", EtherTunTapIfName, !EtherTunTapPersistent ? "non-" : "");
 
     /* Continue anyway */
   }
@@ -1427,7 +1405,9 @@ static int CreateInterface(
     capturingSkfd = CreateCaptureSocket(ifName);
     if (capturingSkfd < 0)
     {
-      close(encapsulatingSkfd);
+      if (encapsulatingSkfd >= 0) {
+        close(encapsulatingSkfd);
+      }
       free(newIf);
       return 0;
     }
@@ -1442,8 +1422,9 @@ static int CreateInterface(
     listeningSkfd = CreateListeningSocket(ifName);
     if (listeningSkfd < 0)
     {
-      close(listeningSkfd);
-      close(encapsulatingSkfd); /* no problem if 'encapsulatingSkfd' is -1 */
+      if (encapsulatingSkfd >= 0) {
+        close(encapsulatingSkfd); /* no problem if 'encapsulatingSkfd' is -1 */
+      }
       free(newIf);
       return 0;
     }
@@ -1462,12 +1443,26 @@ static int CreateInterface(
   if (ioctl(ioctlSkfd, SIOCGIFHWADDR, &ifr) < 0)
   {
     BmfPError("ioctl(SIOCGIFHWADDR) error for interface \"%s\"", ifName);
-    close(capturingSkfd);
-    close(encapsulatingSkfd);
+    if (capturingSkfd >= 0) {
+      close(capturingSkfd);
+    }
+    if (encapsulatingSkfd >= 0) {
+      close(encapsulatingSkfd);
+    }
     free(newIf);
     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;
@@ -1494,11 +1489,11 @@ static int CreateInterface(
       BmfPError("ioctl(SIOCGIFADDR) error for interface \"%s\"", ifName);
 
       newIf->intAddr.v4.s_addr = inet_addr("0.0.0.0");
-         }
-         else
-         {
+    }
+    else
+    {
       /* Downcast to correct sockaddr subtype */
-      newIf->intAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
+      newIf->intAddr.v4 = ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&ifr.ifr_addr))->sin_addr;
     }
 
     /* For a non-OLSR interface, retrieve the IP broadcast address ourselves */
@@ -1510,18 +1505,14 @@ static int CreateInterface(
       BmfPError("ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName);
 
       newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0");
-         }
-         else
-         {
+    }
+    else
+    {
       /* Downcast to correct sockaddr subtype */
-      newIf->broadAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr;
+      newIf->broadAddr.v4 = ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&ifr.ifr_broadaddr))->sin_addr;
     }
   }
 
-  /* Initialize fragment history table */
-  memset(&newIf->fragmentHistory, 0, sizeof(newIf->fragmentHistory));
-  newIf->nextFragmentHistoryEntry = 0;
-
   /* Reset counters */
   newIf->nBmfPacketsRx = 0;
   newIf->nBmfPacketsRxDup = 0;
@@ -1532,6 +1523,7 @@ static int CreateInterface(
   if (BmfInterfaces == NULL)
   {
     /* First TBmfInterface object in list */
+    newIf->next = NULL;
     BmfInterfaces = newIf;
     LastBmfInterface = newIf;
   }
@@ -1630,7 +1622,7 @@ int CreateBmfNetworkInterfaces(struct interface* skipThisIntf)
     }
 
     /* ...find the OLSR interface structure, if any */
-    ipAddr.v4 =  ((struct sockaddr_in*)&ifr->ifr_addr)->sin_addr;
+    ipAddr.v4 =  ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifr->ifr_addr))->sin_addr;
     olsrIntf = if_ifwithaddr(&ipAddr);
 
     if (skipThisIntf != NULL && olsrIntf == skipThisIntf)
@@ -1655,6 +1647,7 @@ int CreateBmfNetworkInterfaces(struct interface* skipThisIntf)
   EtherTunTapFd = CreateLocalEtherTunTap();
   if (EtherTunTapFd >= 0)
   {
+    add_olsr_socket(EtherTunTapFd, NULL, BMF_handle_tuntapFd, NULL, SP_IMM_READ);
     nOpenedSockets++;
   }
 
@@ -1669,33 +1662,13 @@ int CreateBmfNetworkInterfaces(struct interface* skipThisIntf)
   return 0;
 } /* CreateBmfNetworkInterfaces */
 
-/* -------------------------------------------------------------------------
- * Function   : AddInterface
- * Description: Add an OLSR-enabled network interface to the list of BMF-enabled
- *              network interfaces
- * Input      : newIntf - network interface to add
- * Output     : none
- * Return     : none
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-void AddInterface(struct interface* newIntf)
-{
-  int nOpened;
-
-  assert(newIntf != NULL);
-
-  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      : none
  * Output     : none
  * Return     : none
- * Data Used  : none
+ * Data Used  : BmfInterfaces, LastBmfInterface
  * Notes      : Closes
  *              - the local EtherTunTap interface (e.g. "tun0" or "tap0")
  *              - for each BMF-enabled interface, the socket used for
@@ -1725,11 +1698,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++;
     }
 
@@ -1770,25 +1751,31 @@ 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);
   }
 
   BmfInterfaces = NULL;
+  LastBmfInterface = NULL;
+
+  /* Re-initialize the IP address for the BMF network interface. Thanks to
+   * Daniele Lacamera for finding and solving this bug. */
+  EtherTunTapIp = ETHERTUNTAPIPNOTSET;
 
   olsr_printf(1, "%s: closed %d sockets\n", PLUGIN_NAME_SHORT, nClosed);
 
   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,
@@ -1874,7 +1861,7 @@ void CheckAndUpdateLocalBroadcast(unsigned char* ipPacket, union olsr_ip_addr* b
 
   assert(ipPacket != NULL && broadAddr != NULL);
 
-  iph = (struct iphdr*) ipPacket;
+  iph = (struct iphdr*) ARM_NOWARN_ALIGN(ipPacket);
   destIp.v4.s_addr = iph->daddr;
   if (! IsMulticast(&destIp))
   {
@@ -1902,7 +1889,7 @@ void CheckAndUpdateLocalBroadcast(unsigned char* ipPacket, union olsr_ip_addr* b
       /* Re-calculate UDP/IP checksum for new destination */
 
       int ipHeaderLen = GetIpHeaderLength(ipPacket);
-      struct udphdr* udph = (struct udphdr*) (ipPacket + ipHeaderLen);
+      struct udphdr* udph = (struct udphdr*) ARM_NOWARN_ALIGN((ipPacket + ipHeaderLen));
 
       /* RFC 1624, Eq. 3: HC' = ~(~HC - m + m') */
 
@@ -1940,13 +1927,13 @@ void AddMulticastRoute(void)
 
   memset(&kernel_route, 0, sizeof(struct rtentry));
 
-  ((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;
+  ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sa_family = AF_INET;
+  ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_gateway))->sa_family = AF_INET;
+  ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sa_family = AF_INET;
 
   /* 224.0.0.0/4 */
-  ((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);
+  ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sin_addr.s_addr = htonl(0xE0000000);
+  ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sin_addr.s_addr = htonl(0xF0000000);
 
   kernel_route.rt_metric = 0;
   kernel_route.rt_flags = RTF_UP;
@@ -1985,13 +1972,13 @@ void DeleteMulticastRoute(void)
 
     memset(&kernel_route, 0, sizeof(struct rtentry));
 
-    ((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;
+    ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sa_family = AF_INET;
+    ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_gateway))->sa_family = AF_INET;
+    ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sa_family = AF_INET;
 
     /* 224.0.0.0/4 */
-    ((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);
+    ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sin_addr.s_addr = htonl(0xE0000000);
+    ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sin_addr.s_addr = htonl(0xF0000000);
 
     kernel_route.rt_metric = 0;
     kernel_route.rt_flags = RTF_UP;