Teco Boots <teco@inf-net.nl> dyn_gw plugin. Thank you Teco for the contribution.
authorHenning Rogge <hrogge@googlemail.com>
Wed, 24 Feb 2010 17:40:36 +0000 (18:40 +0100)
committerHenning Rogge <hrogge@googlemail.com>
Wed, 24 Feb 2010 17:40:36 +0000 (18:40 +0100)
files/olsrd.conf.default.full
lib/dyn_gw/Makefile
lib/dyn_gw/README_DYN_GW
lib/dyn_gw/src/olsrd_dyn_gw.c
lib/dyn_gw/src/olsrd_dyn_gw.h

index ea73f0e..9ceb6fd 100644 (file)
@@ -399,27 +399,49 @@ LoadPlugin "olsrd_txtinfo.so.0.1"
 #   PlParam     "Keyfile"   "/etc/olsr-keyfile.txt"
 #}
 
-#LoadPlugin "olsrd_dyn_gw.so.0.4"
+#LoadPlugin "olsrd_dyn_gw.so.0.5"
 #{
-    # Here parameters are set to be sent to the
-    # plugin. Theese are on the form "key" "value".
-    # Parameters ofcause, differs from plugin to plugin.
-    # Consult the documentation of your plugin for details.
-
-    # Example: dyn_gw params
-
-    # how often to check for Internet connectivity
-    # defaults to 5 secs
-#   PlParam     "Interval"   "40"
+    # The plugin check interval can be set here in milliseconds.
+    # The default is 1000 ms (1 second).
+#    PlParam     "CheckInterval"  "5000"
     
-    # if one or more IPv4 addresses are given, do a ping on these in
+    # The ping check interval in case there is any pinged host specified.
+    # The default is 5 seconds.
+#    PlParam     "PingInterval"   "40"
+    
+    # If one or more IPv4 addresses are given, do a ping on these in
     # descending order to validate that there is not only an entry in
-    # routing table, but also a real internet connection. If any of
+    # routing table, but also a real network connection. If any of
     # these addresses could be pinged successfully, the test was
     # succesful, i.e. if the ping on the 1st address was successful,the
-    # 2nd won't be pinged
-#   PlParam     "Ping"       "141.1.1.1"
-#   PlParam     "Ping"       "194.25.2.129"
+    # 2nd won't be pinged.
+    #
+    # The Ping list applies to the group of HNAs specified above or to the 
+               # default internet gateway when no HNA is specified.
+               #
+               # Running the plugin without parameters acts as the 'old' dyn_gw_plain.
+    
+    #   The following ping entries for the internet gateway
+#    PlParam "Ping"   "141.1.1.1"
+#    PlParam "Ping"   "194.25.2.129"
+    
+    #   First group of HNAs with related ping host
+#    PlParam   "HNA"      "192.168.80.0 255.255.255.0"
+#    PlParam   "HNA"      "192.168.81.0 255.255.255.0"
+#    PlParam   "Ping"   "192.168.81.12"
+    
+    #   Second HNA group with multiple related ping hosts.
+    #   Specifying multiple ping hosts provides redundancy.
+#    PlParam "HNA"    "192.168.100.0 255.255.255.0"
+#    PlParam "HNA"    "192.168.101.0 255.255.255.0"
+#    PlParam "HNA"    "192.168.102.0 255.255.255.0"
+#    PlParam "Ping"   "192.168.100.10"
+#    PlParam "Ping"   "192.168.101.10"
+    
+    #   Third HNA group without ping check
+#    PlParam "HNA"    "192.168.200.0 255.255.255.0"
+#    PlParam "HNA"    "192.168.201.0 255.255.255.0"
+#    PlParam "HNA"    "192.168.202.0 255.255.255.0"
 #}
 
 #LoadPlugin "olsrd_dyn_gw_plain.so.0.4"
index 967e6f8..3baf443 100644 (file)
@@ -38,7 +38,7 @@
 
 OLSRD_PLUGIN = true
 PLUGIN_NAME =  olsrd_dyn_gw
-PLUGIN_VER =   0.4
+PLUGIN_VER =   0.5
 
 TOPDIR = ../..
 include $(TOPDIR)/Makefile.inc
index 149f546..0aea1f9 100644 (file)
@@ -1,50 +1,6 @@
 DYNAMIC INTERNET GATEWAY PLUGIN FOR olsr.org olsrd
 by Andreas Tonnesen(andreto@olsr.org)
-addittions by Jens Nachitgall
-
-21.12.2004
-  bjoern Riemer
-- added universal hna checking
-  the plParams are parsed in spechial order, first the HNA parameter syntax: "net mask"
-  the following Ping parameter are only used for the previus HNA entry.
-  if there is no previus HNA entry then HNA "0.0.0.0 0.0.0.0" for internet GW is assumed
-
-30.11.2004
-
-  updates by Jens:
-
-- Upgraded to confirm with v2 plugin interface
-- removed IPC stuff
-- Removed much unnessecarry stuff
-- Added an optional validation based on the ping command, which caused
-  some internal restructuring, e.g. the dependency of a threading
-  library)
-- the config file accepts an "Interval", meaning how often the check is
-  done
-
-HOW TO USE
-
-Add an entry like this to your olsrd configuration file:
-
-LoadPlugin "olsrd_dyn_gw.so.0.4"
-{
-    # how often to look for a inet gw, in seconds
-    # defaults to 5 secs, if commented out
-    PlParam     "Interval"   "40"
-    
-    # if one or more IPv4 addresses are given, do a ping on these in
-    # descending order to validate that there is not only an entry in
-    # routing table, but also a real internet connection. If any of
-    # these addresses could be pinged successfully, the test was
-    # succesful, i.e. if the ping on the 1st address was successful,the
-    # 2nd won't be pinged
-    PlParam     "Ping"       "141.1.1.1"
-    PlParam     "Ping"       "194.25.2.129"
-    PlParam    "HNA"   "192.168.80.0 255.255.255.0"
-    PlParam    "HNA"   "192.168.81.0 255.255.255.0"
-    PlParam    "Ping"  "192.168.81.12"
-}
-
+Additions by Jens Nachitgall and others
 
 ABOUT
 
@@ -55,7 +11,7 @@ This is a plugin that checks if the local node has a Internet-
 connection. A Internet-connetion is identified by a "default gw" with a
 hopcount of 0. That is a route to 0.0.0.0/0 with metric 0.  By default
 the check is done every 5 secs. You can change the check interval by
-providing an value for "Interval" in the plugin's section of olsrd.conf.
+providing an value for "PingInterval" in the plugin's section of olsrd.conf.
 
 If one or more IPv4 addresses are given as values for "Ping" in the
 section or dyn_gw in olsrd.conf, then a test is done to validate if
@@ -76,9 +32,104 @@ the OLSR network. If the route is removed the HNA messages
 will not be transmitted. This check is totally dynamic and
 Internet connectivity might come and go.
 
+This plugin can also process more specific routes by specifying groups of HNAs
+(Host and Network Association) and ping hosts. 
+
 This plugin will work very good with a automatic network cable
 detection daemon such as  netplug:
 http://freshmeat.net/projects/key-netplug/
 
 This plugin is a good example of using plugins for other stuff
 than packet transmission.
+
+HOW TO USE (version 0.5)
+
+LoadPlugin "olsrd_dyn_gw.so.0.5"
+{
+    # The plugin check interval can be set here in milliseconds.
+    # The default is 1000 ms (1 second).
+    PlParam     "CheckInterval"  "5000"
+    
+    # The ping check interval in case there is any pinged host specified.
+    # The default is 5 seconds.
+    PlParam     "PingInterval"   "40"
+    
+    # If one or more IPv4 addresses are given, do a ping on these in
+    # descending order to validate that there is not only an entry in
+    # routing table, but also a real network connection. If any of
+    # these addresses could be pinged successfully, the test was
+    # succesful, i.e. if the ping on the 1st address was successful,the
+    # 2nd won't be pinged.
+    #
+    # The Ping list applies to the group of HNAs specified above or to the 
+               # default internet gateway when no HNA is specified.
+               #
+               # Running the plugin without parameters acts as the 'old' dyn_gw_plain.
+    
+    #   The following ping entries for the internet gateway
+    PlParam "Ping"   "141.1.1.1"
+    PlParam "Ping"   "194.25.2.129"
+    
+    #   First group of HNAs with related ping host
+    PlParam    "HNA"      "192.168.80.0 255.255.255.0"
+    PlParam    "HNA"      "192.168.81.0 255.255.255.0"
+    PlParam    "Ping"   "192.168.81.12"
+    
+    #   Second HNA group with multiple related ping hosts.
+    #   Specifying multiple ping hosts provides redundancy.
+    PlParam "HNA"    "192.168.100.0 255.255.255.0"
+    PlParam "HNA"    "192.168.101.0 255.255.255.0"
+    PlParam "HNA"    "192.168.102.0 255.255.255.0"
+    PlParam "Ping"   "192.168.100.10"
+    PlParam "Ping"   "192.168.101.10"
+    
+    #   Third HNA group without ping check
+    PlParam "HNA"    "192.168.200.0 255.255.255.0"
+    PlParam "HNA"    "192.168.201.0 255.255.255.0"
+    PlParam "HNA"    "192.168.202.0 255.255.255.0"
+}
+
+--------------------------------------------------------------------------------
+Change log:
+
+18.02.2010
+  Caspar van Zon / C2SC
+- Changed HNA checking.
+  The 'Ping' PlParam processing has been modified so that it is not only valid 
+       for the previous HNA entry but all entries proceeding the ping parameter until 
+       either the beginning of the list or the previous ping parameter.
+       If there is no previous HNA entry then HNA '0.0.0.0 0.0.0.0' for the internet
+       gateway is inserted instead.
+- Two new interval parameters 'PingInterval' and 'CheckInterval' have been
+  introduced. 'PingInterval' is the new name for the 'Interval' parameter, the
+  old name has been maintained as well for compatibility. The 'CheckInterval' is
+  new and specifies the check interval for the OLSR event loop in milliseconds.
+- When no ping hosts are specified at all the thread for the ping check will not
+  be started, eliminating the thread totally is left for future improvement.
+- Code and variable names have been cleaned up in various places to improve both
+  readability and maintainability.
+- Due to significant changes in the code base and the modified functionality the
+  version of the package has been increased to version 0.5
+- Running the plugin without parameters acts like dyn_gw_plain so the 
+  dyn_gw_plain plugin can be made obsolete.
+       
+21.12.2004
+  bjoern Riemer
+- added universal hna checking
+  the plParams are parsed in spechial order, first the HNA parameter syntax: "net mask"
+  the following Ping parameter are only used for the previus HNA entry.
+  if there is no previus HNA entry then HNA "0.0.0.0 0.0.0.0" for internet GW is assumed
+
+30.11.2004
+
+  updates by Jens:
+
+- Upgraded to confirm with v2 plugin interface
+- removed IPC stuff
+- Removed much unnessecarry stuff
+- Added an optional validation based on the ping command, which caused
+  some internal restructuring, e.g. the dependency of a threading
+  library)
+- the config file accepts an "Interval", meaning how often the check is
+  done
+
index b910fa7..ed03157 100644 (file)
@@ -52,6 +52,7 @@
 #include "defs.h"
 #include "ipcalc.h"
 #include "scheduler.h"
+#include "log.h"
 
 #include <stdio.h>
 #include <string.h>
@@ -88,8 +89,9 @@ struct ThreadPara {
 };
 #endif
 
+static int hna_check_interval  = DEFAULT_HNA_CHECK_INTERVAL;
 /* set default interval, in case none is given in the config file */
-static int check_interval = 5;
+static int ping_check_interval = DEFAULT_PING_CHECK_INTERVAL;
 
 /* list to store the Ping IP addresses given in the config file */
 struct ping_list {
@@ -100,27 +102,42 @@ struct ping_list {
 static struct ping_list *add_to_ping_list(const char *, struct ping_list *);
 
 struct hna_list {
-  union olsr_ip_addr hna_net;
+  union olsr_ip_addr hna_addr;
   uint8_t hna_prefixlen;
-  struct ping_list *ping_hosts;
-  int hna_added;
-  int probe_ok;
+  bool hna_added;
+  bool checked;
+  bool active;
   struct hna_list *next;
 };
 
-static struct hna_list *add_to_hna_list(struct hna_list *, union olsr_ip_addr *hna_net, uint8_t hna_prefixlen);
+static struct hna_list *add_to_hna_list(struct hna_list *, union olsr_ip_addr *hna_addr, uint8_t hna_prefixlen);
 
-struct hna_list *the_hna_list = NULL;
+struct hna_group {
+  struct hna_list *            hna_list;
+  struct ping_list *   ping_hosts;
+  bool                                                         probe_ok;
+  struct hna_group *   next;
+};
+
+bool hna_ping_check    = false;
+static struct hna_group * hna_groups = NULL;
+
+static struct hna_group *add_to_hna_group(struct hna_group *);
 
 static void looped_checks(void *) __attribute__ ((noreturn));
 
-static int check_gw(union olsr_ip_addr *, uint8_t, struct ping_list *);
+static bool check_gw(union olsr_ip_addr *, uint8_t, struct ping_list *);
 
 static int ping_is_possible(struct ping_list *);
 
 /* Event function to register with the scheduler */
 static void olsr_event_doing_hna(void *);
 
+struct hna_list* find_hna(uint32_t src_addr, uint32_t src_mask);
+
+char *get_ip_str(uint32_t address, char *s, size_t maxlen);
+int update_routing(void);
+
 /**
  * read config file parameters
  */
@@ -133,59 +150,69 @@ set_plugin_ping(const char *value, void *data __attribute__ ((unused)), set_plug
     OLSR_PRINTF(0, "Illegal IP address \"%s\"", value);
     return 1;
   }
-  /*if first ping without hna then assume inet gateway */
-  if (the_hna_list == NULL) {
-    union olsr_ip_addr temp_net;
-    union olsr_ip_addr temp_netmask;
-    temp_net.v4.s_addr = INET_NET;
-    temp_netmask.v4.s_addr = INET_PREFIX;
-    the_hna_list = add_to_hna_list(the_hna_list, &temp_net, olsr_netmask_to_prefix(&temp_netmask));
-    if (the_hna_list == NULL) {
+
+  if (hna_groups == NULL) { 
+    hna_groups = add_to_hna_group(hna_groups);
+    if (hna_groups == NULL)
       return 1;
-    }
-  }
-  the_hna_list->ping_hosts = add_to_ping_list(value, the_hna_list->ping_hosts);
+  } else {
+    if (hna_groups->hna_list != NULL) {
+      hna_groups = add_to_hna_group(hna_groups);
+               }
+       }
+
+  hna_groups->ping_hosts = add_to_ping_list(value, hna_groups->ping_hosts);
+  hna_ping_check = true;
+  
   return 0;
 }
 
 static int
 set_plugin_hna(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
 {
-  union olsr_ip_addr temp_net;
-  union olsr_ip_addr temp_netmask;
-  char s_netaddr[128];
+  union olsr_ip_addr temp_addr;
+  union olsr_ip_addr temp_mask;
+  char s_addr[128];
   char s_mask[128];
-
-  //192.168.1.0  255.255.255.0
-  int i = sscanf(value, "%127s %127s", s_netaddr, s_mask);
+  
+  //Example: 192.168.1.0  255.255.255.0
+  int i = sscanf(value, "%127s %127s", s_addr, s_mask);
   if (i != 2) {
     OLSR_PRINTF(0, "Cannot get IP address and netmask from \"%s\"", value);
     return 1;
   }
-  //printf("%s():i:%i; net:%s; mask:%s\n",__func__,i,s_netaddr,s_mask);
-  if (inet_pton(olsr_cnf->ip_version, s_netaddr, &temp_net) <= 0) {
-    OLSR_PRINTF(0, "Illegal IP address \"%s\"", s_netaddr);
+
+  if (inet_pton(olsr_cnf->ip_version, s_addr, &temp_addr) <= 0) {
+    OLSR_PRINTF(0, "Illegal IP address \"%s\"", s_addr);
     return 1;
   }
-  //printf("GOT: %s(%08x)",inet_ntoa(foo_addr),foo_addr.s_addr);
-  if (inet_pton(olsr_cnf->ip_version, s_mask, &temp_netmask) <= 0) {
+
+  if (inet_pton(olsr_cnf->ip_version, s_mask, &temp_mask) <= 0) {
     OLSR_PRINTF(0, "Illegal netmask \"%s\"", s_mask);
     return 1;
   }
-  //printf("/%s(%08x)\n",inet_ntoa(foo_addr),foo_addr.s_addr);
-  //printf("%s():got->%s/%s\n",__func__,olsr_ip_to_string((union olsr_ip_addr *)&));
-  the_hna_list = add_to_hna_list(the_hna_list, &temp_net, olsr_netmask_to_prefix(&temp_netmask));
-  if (the_hna_list == NULL) {
-    OLSR_PRINTF(0, "Error adding HNA in HNA-list");
+
+       if (hna_groups == NULL)
+       {
+    hna_groups = add_to_hna_group(hna_groups);
+    if (hna_groups == NULL) {
+      return 1;
+               }
+       }
+       
+  hna_groups->hna_list = add_to_hna_list(hna_groups->hna_list, &temp_addr, olsr_netmask_to_prefix(&temp_mask));
+  if (hna_groups->hna_list == NULL) {
     return 1;
   }
   return 0;
 }
 
 static const struct olsrd_plugin_parameters plugin_parameters[] = {
-  {.name = "interval",.set_plugin_parameter = &set_plugin_int,.data = &check_interval},
-  {.name = "ping",.set_plugin_parameter = &set_plugin_ping,.data = NULL},
-  {.name = "hna",.set_plugin_parameter = &set_plugin_hna,.data = NULL},
+  {.name = "interval",                 .set_plugin_parameter = &set_plugin_int,        .data = &ping_check_interval    },
+  {.name = "pinginterval",     .set_plugin_parameter = &set_plugin_int,        .data = &ping_check_interval    },
+  {.name = "checkinterval",    .set_plugin_parameter = &set_plugin_int,        .data = &hna_check_interval             },
+  {.name = "ping",                                     .set_plugin_parameter = &set_plugin_ping,       .data = NULL                                                                    },
+  {.name = "hna",                                              .set_plugin_parameter = &set_plugin_hna,        .data = NULL                                                                    },
 };
 
 void
@@ -208,23 +235,58 @@ olsrd_plugin_init(void)
 {
   pthread_t ping_thread;
 
-  //gw_net.v4 = INET_NET;
-  //gw_netmask.v4 = INET_PREFIX;
-
-  //gw_already_added = 0;
-  //has_available_gw = 0;
-
-  /* Remove all local Inet HNA entries */
-  /*while(remove_local_hna4_entry(&gw_net, &gw_netmask))
-     {
-     olsr_printf(1, "HNA Internet gateway deleted\n");
-     } */
-
-  pthread_create(&ping_thread, NULL, (void *(*)(void *))looped_checks, NULL);
+  if (hna_groups == NULL) {
+    hna_groups = add_to_hna_group(hna_groups);
+    if (hna_groups == NULL)
+      return 1;
+       }
+       
+       // Add a default gateway if the top entry was just a ping address
+       if (hna_groups->hna_list == NULL) {
+    union olsr_ip_addr temp_addr;
+    union olsr_ip_addr temp_mask;
+    
+    temp_addr.v4.s_addr = INET_ADDR;
+    temp_mask.v4.s_addr = INET_MASK;
+    hna_groups->hna_list = add_to_hna_list(hna_groups->hna_list, &temp_addr, olsr_netmask_to_prefix(&temp_mask));
+    if (hna_groups->hna_list == NULL) {
+      return 1;
+    }
+       }
+       
+  // Prepare all routing information
+  update_routing();
+  
+  if (hna_ping_check) {
+    pthread_create(&ping_thread, NULL, (void *(*)(void *))looped_checks, NULL);
+  } else {
+    struct hna_group *grp;
+    for (grp = hna_groups; grp; grp = grp->next) {
+      grp->probe_ok = true;
+               }
+       }
+
+       // Print the current configuration
+       {
+         struct hna_group *grp;
+         int i = 0;
+         for (grp = hna_groups; grp; grp = grp->next, ++i) {
+           struct hna_list *lst;
+           struct ping_list *png;
+           
+           olsr_printf(1, "Group %d:\n", i);
+           for (lst = grp->hna_list; lst; lst = lst->next) {
+             char addr[INET_ADDRSTRLEN];
+             olsr_printf(1, "  HNA %s\n", get_ip_str(lst->hna_addr.v4.s_addr, addr, INET_ADDRSTRLEN));
+                       }
+                       for (png = grp->ping_hosts; png; png = png->next) {
+                         olsr_printf(1, "  PING %s\n", png->ping_address);
+                       }
+               }
+       }
 
   /* Register the GW check */
-  olsr_start_timer(3 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC, &olsr_event_doing_hna, NULL, 0);
-
+  olsr_start_timer(hna_check_interval, 0, OLSR_TIMER_PERIODIC, &olsr_event_doing_hna, NULL, 0);
   return 1;
 }
 
@@ -235,30 +297,27 @@ olsrd_plugin_init(void)
 static void
 olsr_event_doing_hna(void *foo __attribute__ ((unused)))
 {
+  struct hna_group* grp;
   struct hna_list *li;
-  /*
-     if (has_available_gw == 1 && gw_already_added == 0) {
-     olsr_printf(1, "Adding OLSR local HNA entry for Internet\n");
-     add_local_hna_entry(&gw_net, &gw_netmask);
-     gw_already_added = 1;
-     } else if ((has_available_gw == 0) && (gw_already_added == 1)) {
-     // Remove all local Inet HNA entries /
-     while(remove_local_hna4_entry(&gw_net, &gw_netmask)) {
-     olsr_printf(1, "Removing OLSR local HNA entry for Internet\n");
-     }
-     gw_already_added = 0;
-     }
-   */
-  for (li = the_hna_list; li; li = li->next) {
-    if ((li->probe_ok == 1) && (li->hna_added == 0)) {
-      olsr_printf(1, "Adding OLSR local HNA entry\n");
-      ip_prefix_list_add(&olsr_cnf->hna_entries, &li->hna_net, li->hna_prefixlen);
-      li->hna_added = 1;
-    } else if ((li->probe_ok == 0) && (li->hna_added == 1)) {
-      while (ip_prefix_list_remove(&olsr_cnf->hna_entries, &li->hna_net, li->hna_prefixlen)) {
-        olsr_printf(1, "Removing OLSR local HNA entry\n");
-      }
-      li->hna_added = 0;
+
+  update_routing();
+  
+  for (grp = hna_groups; grp; grp = grp->next) {
+    for (li = grp->hna_list; li; li = li->next) {
+      if (!li->hna_added) {
+        if (grp->probe_ok && li->active) {
+          olsr_printf(1, "Adding OLSR local HNA entry\n");
+          ip_prefix_list_add(&olsr_cnf->hna_entries, &li->hna_addr, li->hna_prefixlen);
+          li->hna_added = true;
+                               }
+                       } else {
+                         if (!grp->probe_ok || !li->active) {
+          while (ip_prefix_list_remove(&olsr_cnf->hna_entries, &li->hna_addr, li->hna_prefixlen)) {
+            olsr_printf(1, "Removing OLSR local HNA entry\n");
+          }
+          li->hna_added = false;
+                               }
+                       }
     }
   }
 }
@@ -272,15 +331,24 @@ static void
 looped_checks(void *foo __attribute__ ((unused)))
 {
   for (;;) {
+    struct hna_group *grp;
     struct hna_list *li;
     struct timespec remainder_spec;
     /* the time to wait in "Interval" sec (see connfig), default=5sec */
-    struct timespec sleeptime_spec = { check_interval, 0L };
-
-    for (li = the_hna_list; li; li = li->next) {
-      /* check for gw in table entry and if Ping IPs are given also do pings */
-      li->probe_ok = check_gw(&li->hna_net, li->hna_prefixlen, li->ping_hosts);
-      //has_available_gw = check_gw(&gw_net, &gw_netmask);
+    struct timespec sleeptime_spec = { ping_check_interval, 0L };
+
+    for (grp = hna_groups; grp; grp = grp->next) {
+      for (li = grp->hna_list; li; li = li->next) {
+      
+               // If this HNA is not active skip to the next one
+        if (!li->active)
+          continue;
+          
+        /* check for gw in table entry and if Ping IPs are given also do pings */
+        grp->probe_ok = check_gw(&li->hna_addr, li->hna_prefixlen, grp->ping_hosts);
+        if (grp->probe_ok)
+                break; // Valid host found so we can bail out of the inner loop here
+      }
     }
 
     while (nanosleep(&sleeptime_spec, &remainder_spec) < 0)
@@ -289,16 +357,75 @@ looped_checks(void *foo __attribute__ ((unused)))
   // return NULL;
 }
 
-static int
-check_gw(union olsr_ip_addr *net, uint8_t prefixlen, struct ping_list *the_ping_list)
+/* -------------------------------------------------------------------------
+ * Function   : find_hna
+ * Description: Lookup an HNA that matches the specified parameters
+ * Input      : src_addr - IP address of the HNA to find
+ *              src_mask - Address mask of the HNA to find
+ * Output     : none
+ * Return     : The HNA specified or NULL when HNA not found
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+struct hna_list*
+find_hna(uint32_t src_addr, uint32_t src_mask)
+{
+  struct hna_group * grp;
+  struct hna_list *li;
+  union olsr_ip_addr mask;
+
+  for (grp = hna_groups; grp; grp = grp->next) {
+    for (li = grp->hna_list; li; li = li->next) {
+      olsr_prefix_to_netmask(&mask, li->hna_prefixlen);
+               if (li->hna_addr.v4.s_addr == src_addr && mask.v4.s_addr == src_mask) {
+                   return li;
+                       }
+               }
+       }
+  return NULL;
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : get_ip_str
+ * Description: Convert the specified address to an IPv4 compatible string
+ * Input      : address - IPv4 address to convert to string 
+ *              s       - string buffer to contain the resulting string
+ *              maxlen  - maximum length of the string buffer 
+ * Output     : none
+ * Return     : Pointer to the string buffer containing the result
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+char *
+get_ip_str(uint32_t address, char *s, size_t maxlen)
+{
+  struct sockaddr_in v4;
+  
+  v4.sin_addr.s_addr = address;
+  inet_ntop(AF_INET, &v4.sin_addr, s, maxlen);
+
+  return s;
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : update_routing
+ * Description: Mark the HNAs in the HNA list(s) corresponding to the results
+ *              found in the routing table. HNAs that are found in the routing
+ *              table will be marked as 'active', otherwise they'll remain
+ *              inactive.    
+ * Input      : nothing
+ * Output     : none
+ * Return     : -1 if an error occurred, 0 otherwise
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+int 
+update_routing(void)
 {
   char buf[1024], iface[16];
   uint32_t gate_addr, dest_addr, netmask;
   unsigned int iflags;
   int metric, refcnt, use;
-  int retval = 0;
-  union olsr_ip_addr mask;
-
+  struct hna_group *grp;
+  struct hna_list *li;
+  
   FILE *fp = fopen(PROCENTRY_ROUTE, "r");
   if (!fp) {
     perror(PROCENTRY_ROUTE);
@@ -306,55 +433,106 @@ check_gw(union olsr_ip_addr *net, uint8_t prefixlen, struct ping_list *the_ping_
     return -1;
   }
 
-  olsr_prefix_to_netmask(&mask, prefixlen);
+  // Phase 1: reset the 'checked' flag, during the check of the routing table we 
+       // will (re)discover whether the HNA is valid or not.
+  for (grp = hna_groups; grp; grp = grp->next) {
+    for (li = grp->hna_list; li; li = li->next) {
+      li->checked = false;
+               }
+       }
+
   /*
      olsr_printf(1, "Genmask         Destination     Gateway         "
      "Flags Metric Ref    Use Iface\n");
    */
   while (fgets(buf, sizeof(buf), fp)) {
-    int num = sscanf(buf, "%15s %128X %128X %X %d %d %d %128X \n",
-                     iface, &dest_addr, &gate_addr,
-                     &iflags, &refcnt, &use, &metric, &netmask);
+    struct hna_list *hna;
+    char s_addr[INET_ADDRSTRLEN], s_mask[INET_ADDRSTRLEN];
+    
+    int num = sscanf(buf, 
+                                "%15s %128X %128X %X %d %d %d %128X \n",
+                     iface, 
+                                                                                &dest_addr, 
+                                                                                &gate_addr,
+                     &iflags, 
+                                                                                &refcnt, 
+                                                                                &use, 
+                                                                                &metric, 
+                                                                                &netmask);
     if (num < 8)
       continue;
 
-    /*
-       olsr_printf(1, "%-15s ", olsr_ip_to_string((union olsr_ip_addr *)&netmask));
-
-       olsr_printf(1, "%-15s ", olsr_ip_to_string((union olsr_ip_addr *)&dest_addr));
+    get_ip_str(dest_addr, s_addr, INET_ADDRSTRLEN);
+    get_ip_str(netmask, s_mask, INET_ADDRSTRLEN);
+    
+    hna = find_hna(dest_addr, netmask);
+    if (hna == NULL) { // Entry not found, try the next one
+      continue;
+    }
+    
+    if ((iflags & RTF_UP) && (metric == 0)) {
+          hna->checked = true;
+    }
+  }
+  fclose(fp);
+  
+  // Phase 2: now copy the 'checked' flag to the 'active' flag.
+  // The total check is a 2-phase process so the ping check loop won't be 
+       // disturbed too badly.
+  for (grp = hna_groups; grp; grp = grp->next) {
+    for (li = grp->hna_list; li; li = li->next) {
+      li->active = li->checked;
+               }
+       }
+       
+       return 0;
+}
 
-       olsr_printf(1, "%-15s %-6d %-2d %7d %s\n",
-       olsr_ip_to_string((union olsr_ip_addr *)&gate_addr),
-       metric, refcnt, use, iface);
-     */
+/* -------------------------------------------------------------------------
+ * Function   : check_gw
+ * Description: Check the specified gateway(s) by sending a ping
+ * Input      : addr      - the address of the HNA to which the ping is related
+ *              prefixlen - the length of the prefix for this HNA 
+ *              the_ping_list - list with related ping hosts
+ * Output     : none
+ * Return     : true if the ping host could be reached, false otherwise
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+static bool
+check_gw(union olsr_ip_addr *addr, uint8_t prefixlen, struct ping_list *the_ping_list)
+{
+  bool retval = false;
+  union olsr_ip_addr mask;
 
-    if ((iflags & RTF_UP) && (metric == 0) && (netmask == mask.v4.s_addr) && (dest_addr == net->v4.s_addr)) {
-      if (((mask.v4.s_addr == INET_PREFIX) && (net->v4.s_addr == INET_NET)) && (!(iflags & RTF_GATEWAY))) {
-        fclose(fp);
-        return retval;
-      }
-      /* don't ping, if there was no "Ping" IP addr in the config file */
-      if (the_ping_list != NULL) {
-        /*validate the found inet gw by pinging */
-        if (ping_is_possible(the_ping_list)) {
-          olsr_printf(1, "HNA[%08x/%08x](ping is possible) VIA %s detected in routing table.\n", dest_addr, netmask, iface);
-          retval = 1;
-        }
-      } else {
-        olsr_printf(1, "HNA[%08x/%08x] VIA %s detected in routing table.\n", dest_addr, netmask, iface);
-        retval = 1;
-      }
+  olsr_prefix_to_netmask(&mask, prefixlen);
+  
+  /* don't ping, if there was no "Ping" IP addr in the config file */
+  if (the_ping_list != NULL) {
+    /*validate the found inet gw by pinging */
+    if (ping_is_possible(the_ping_list)) {
+      olsr_printf(1, "HNA[%08x/%08x](ping is possible) detected in routing table.\n", addr->v4.s_addr, mask.v4.s_addr);
+      retval = true;
     }
+  } else {
+    olsr_printf(1, "HNA[%08x/%08x] detected in routing table.\n", addr->v4.s_addr, mask.v4.s_addr);
+    retval = true;
   }
 
-  fclose(fp);
-  if (retval == 0) {
+  if (retval == false) {
     /* And we cast here since we get warnings on Win32 */
-    olsr_printf(1, "HNA[%08x/%08x] is invalid\n", (unsigned int)net->v4.s_addr, (unsigned int)mask.v4.s_addr);
+    olsr_printf(1, "HNA[%08x/%08x] is invalid\n", (unsigned int)addr->v4.s_addr, (unsigned int)mask.v4.s_addr);
   }
   return retval;
 }
 
+/* -------------------------------------------------------------------------
+ * Function   : ping_is_possible
+ * Description: Ping the specified host(s)
+ * Input      : the_ping_list - the list of hosts to ping
+ * Output     : none
+ * Return     : 1 if any host responded, 0 otherwise
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
 static int
 ping_is_possible(struct ping_list *the_ping_list)
 {
@@ -372,13 +550,23 @@ ping_is_possible(struct ping_list *the_ping_list)
   return 0;
 }
 
+/* -------------------------------------------------------------------------
+ * Function   : add_to_ping_list
+ * Description: Add a new ping host to the list of ping hosts
+ * Input      : ping_address - the address of the ping host
+ *              the_ping_list - the list of ping hosts 
+ * Output     : none
+ * Return     : a pointer to the newly added ping host, i.e. start of the list
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
 /* add the valid IPs to the head of the list */
 static struct ping_list *
 add_to_ping_list(const char *ping_address, struct ping_list *the_ping_list)
 {
-  struct ping_list *new = malloc(sizeof(struct ping_list));
+  struct ping_list *new = calloc(1, sizeof(struct ping_list));
   if (!new) {
     fprintf(stderr, "DYN GW: Out of memory!\n");
+    olsr_syslog(OLSR_LOG_ERR, "DYN GW: Out of memory!\n");
     exit(0);
   }
   new->ping_address = strdup(ping_address);
@@ -386,29 +574,60 @@ add_to_ping_list(const char *ping_address, struct ping_list *the_ping_list)
   return new;
 }
 
+/* -------------------------------------------------------------------------
+ * Function   : add_to_hna_list
+ * Description: Add a new HNA entry to the list of HNA entries
+ * Input      : list_root - the start of the list with HNA entries
+ *              hna_addr  - the address of the new HNA entry
+ *              prefixlen - the prefix-length of the new HNA entry 
+ * Output     : none
+ * Return     : a pointer to the newly added HNA entry, i.e. start of the list
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
 static struct hna_list *
-add_to_hna_list(struct hna_list *list_root, union olsr_ip_addr *hna_net, uint8_t hna_prefixlen)
+add_to_hna_list(struct hna_list *list_root, union olsr_ip_addr *hna_addr, uint8_t hna_prefixlen)
 {
-  struct hna_list *new = malloc(sizeof(struct hna_list));
+  struct hna_list *new = calloc(1, sizeof(struct hna_list));
   if (new == NULL) {
     fprintf(stderr, "DYN GW: Out of memory!\n");
+    olsr_syslog(OLSR_LOG_ERR, "DYN GW: Out of memory!\n");
     exit(0);
   }
-  //memcpy(&new->hna_net,hna_net,sizeof(union hna_net));
-  //memcpy(&new->hna_netmask,hna_netmask,sizeof(union hna_netmask));
-  new->hna_net.v4 = hna_net->v4;
+
+  new->hna_addr.v4 = hna_addr->v4;
   new->hna_prefixlen = hna_prefixlen;
-  new->hna_added = 0;
-  new->probe_ok = 0;
-  new->ping_hosts = NULL;
+  new->hna_added = false;
   new->next = list_root;
   return new;
 }
 
+/* -------------------------------------------------------------------------
+ * Function   : add_to_hna_group
+ * Description: Add a new HNA group to the list of HNA groups
+ * Input      : list_root - the start of the list with HNA groups
+ * Output     : none
+ * Return     : a pointer to the newly added HNA group, i.e. start of the list
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+static struct hna_group *
+add_to_hna_group(struct hna_group *list_root)
+{
+  struct hna_group *new = calloc(1, sizeof(struct hna_group));
+  if (new == NULL) {
+    fprintf(stderr, "DYN GW: Out of memory!\n");
+    olsr_syslog(OLSR_LOG_ERR, "DYN GW: Out of memory!\n");
+    exit(0);
+       }
+       
+       new->next =  list_root;
+       return new;
+}
+
+
 #ifdef WIN32
 
 /*
- * Windows ptread compat stuff
+ * Windows pthread compat stuff
  */
 static unsigned long __stdcall
 ThreadWrapper(void *Para)
index 229a08a..eba47e6 100644 (file)
 #include "olsrd_plugin.h"
 #include "plugin_util.h"
 
-#define INET_NET       0
-#define INET_PREFIX    0
+//#define INET_NET       0
+//#define INET_PREFIX    0
+#define INET_ADDR      0
+#define INET_MASK      0
 
 #define PROCENTRY_ROUTE "/proc/net/route"
 
+#define DEFAULT_HNA_CHECK_INTERVAL     1000
+#define DEFAULT_PING_CHECK_INTERVAL    5
+
 int olsrd_plugin_init(void);
 
 int olsrd_plugin_interface_version(void);