diff -Nur olsrd-0.5.3.orig/README-NAT-Thresh.txt olsrd-0.5.3/README-NAT-Thresh.txt
--- olsrd-0.5.3.orig/README-NAT-Thresh.txt	1970-01-01 01:00:00.000000000 +0100
+++ olsrd-0.5.3/README-NAT-Thresh.txt	2007-09-04 16:04:52.000000000 +0200
@@ -0,0 +1,61 @@
+While doing the routing-cleanup in process_routes.c,
+a new parameter was added for olsrd.conf which defines
+a threshold for HNA4-0/0 Routes active for LQ/ETX mode:
+
+NatThreshold <0.1..1.0> (default: 1.0, feature is off)
+
+Theory of operation:
+
+Most private internet gateways uses a technique named
+NAT (Network Address Translation) to map multiple private
+IPs to a single globally valid IP mosty aquired via DHCP 
+or PPP from the provider's IP address pool.
+
+* Switching routes does not hurt if the endpoint is not NAT'ed,
+  e.g. you transfer data from another node in the mesh.
+
+* If you have a single NAT gateway in your mesh, all is fine too.
+
+* In most bigger meshes, there will exist a bunch of NAT gateways 
+  competing for users. For a particular node, the best gateway is
+  selected in terms of ETX values. This selects the best reachable NAT
+  gateway in range. This is the standard operation and it works fine.
+
+* If you have more than one NAT gateway, all connection oriented
+  services via the gateway are dropped if a particular node switches
+  from one NAT gateway to another.
+
+* A workaround for this is to use a tunnelling setup and provide 
+  internet for the whole mesh via an external proxy server or so.
+  You can also provide internet via tunnels offered by the gateway
+  nodes - so you do not use default routes and HNA with 0/0 at all.
+
+The problem is this: Suppose you have two or more NAT gateways in
+range with comparable ETX values. Because of marginal fluctuations
+in the ETX packet loss measurement results, the gateway selection
+may switch in the middle of a file transfer or phone call. If the
+ETX values are really not to different, say 5.02 and 4.99, you will
+also experience that the file transfer triggers the gateway switch.
+Because a heavy loaded link will always produce more packet loss 
+compared to an unused link.
+
+The NatThreshold will prevent the switch in the default route for
+a particular node if the ETX values for one 0/0 route to another
+0/0 route are not too different. It will also prevent the 2-4 minutes
+"flaptime" experienced when one link slowly lowers ETX while another
+link slowly rises it's ETX due to air and weather.
+
+So why only a small value (e.g. 0.9, so the ETX values need to differ by
+10%) default? Because this may introduce routing loops. The standard way
+to cope with this effects is to lower a particalar ETX value by using
+LinkQualityMult. This is not always possible (e.g. for intermediate nodes
+between you and the gateway).
+
+Also: the initial selected default route may not be the optimal one if
+NatThreshold is active (means: the route may stick to a lower ETX link).
+If you start a download using that low-ETX link, this will trigger the 
+change from the initial low-ETX to the optimal-ETX link. But only, if 
+the threshold is not too sticky...
+
+Feel free to play with this. Comments and testimonals are welcome.
+Aug 2007, Sven-Ola-aet-Gmx.de
diff -Nur olsrd-0.5.3.orig/src/lq_route.c olsrd-0.5.3/src/lq_route.c
--- olsrd-0.5.3.orig/src/lq_route.c	2007-09-04 16:04:52.000000000 +0200
+++ olsrd-0.5.3/src/lq_route.c	2007-09-04 16:04:52.000000000 +0200
@@ -588,9 +588,9 @@
    */
   olsr_spf_run_full(&cand_tree, &path_tree);
 
-  // save the old routing table
+  // Start with an empty routing table
 
-  olsr_move_route_table(routingtable, old_routes);
+  olsr_free_routing_table(routingtable);
 
   OLSR_PRINTF(2, "\n--- %02d:%02d:%02d.%02d ------------------------------------------------- DIJKSTRA\n\n",
               nowtm->tm_hour,
@@ -670,9 +670,9 @@
     }
   }
 
-  // save the old HNA routing table
+  // Start with an empty HNA routing table
 
-  olsr_move_route_table(hna_routes, old_hna);
+  olsr_free_routing_table(hna_routes);
 
   // add HNA routes
 
@@ -757,13 +757,7 @@
 
   // move the route changes into the kernel
 
-  olsr_update_kernel_routes();
-  olsr_update_kernel_hna_routes();
-
-  // free the saved routing table
-
-  olsr_free_routing_table(old_routes);
-  olsr_free_routing_table(old_hna);
+  olsr_update_routes(routingtable, hna_routes);
 }
 
 /*
diff -Nur olsrd-0.5.3.orig/src/olsr.c olsrd-0.5.3/src/olsr.c
--- olsrd-0.5.3.orig/src/olsr.c	2007-08-01 18:22:57.000000000 +0200
+++ olsrd-0.5.3/src/olsr.c	2007-09-04 16:04:52.000000000 +0200
@@ -174,8 +174,7 @@
 
       if (olsr_cnf->lq_level < 2)
         {
-          olsr_calculate_routing_table();
-          olsr_calculate_hna_routes();
+          olsr_calculate_routing_table(OLSR_FALSE);
         }
     }
   
@@ -185,8 +184,7 @@
 
       if (olsr_cnf->lq_level < 2)
         {
-          olsr_calculate_routing_table();
-          olsr_calculate_hna_routes();
+          olsr_calculate_routing_table(OLSR_FALSE);
         }
     }
 
@@ -196,7 +194,7 @@
 
       if (olsr_cnf->lq_level < 2)
         {
-          olsr_calculate_hna_routes();
+          olsr_calculate_routing_table(OLSR_TRUE);
         }
     }
   
diff -Nur olsrd-0.5.3.orig/src/process_routes.c olsrd-0.5.3/src/process_routes.c
--- olsrd-0.5.3.orig/src/process_routes.c	2007-09-04 16:04:52.000000000 +0200
+++ olsrd-0.5.3/src/process_routes.c	2007-09-04 16:04:52.000000000 +0200
@@ -86,392 +86,280 @@
   return 1;
 }
 
-/**
- *Checks if there exists a route to a given host
- *in a given hash table.
- *
- *@param dst the host to check for
- *@param table the table to check
- *
- *@return 1 if the host exists in the table, 0 if not
- */
-int
-olsr_find_up_route(struct rt_entry *dst, struct rt_entry *table)
-{ 
-  struct rt_entry  *destination;
-  const olsr_u32_t  hash = olsr_hashing(&dst->rt_dst);
-
-  for(destination = table[hash].next; destination != &table[hash]; destination = destination->next)
-    {
-      //printf("Checking %s hc: %d ", olsr_ip_to_string(&dst->rt_dst), dst->rt_metric);
-      //printf("vs %s hc: %d ... ", olsr_ip_to_string(&destination->rt_dst), destination->rt_metric);      
-      if (COMP_IP(&destination->rt_dst, &dst->rt_dst) &&
-	  COMP_IP(&destination->rt_router, &dst->rt_router) &&
-	  (destination->rt_if->if_index == dst->rt_if->if_index))
-	{
-	  if(destination->rt_metric == dst->rt_metric)
-	    {
-	      return 1;
-	    }
-	  else
-	    {
-	      return 0;
-	    }
-	}
-    }
-  return 0;
-}
+#undef DEBUG
+#define DEBUG_DEFGW
 
+#ifdef DEBUG
+#define ROUTE_ERRORLEVEL 0
+#else
+#define ROUTE_ERRORLEVEL 1
+#endif
 
-/**
- *Create a list containing the entries in from_table
- *that do not exist in in_table
- *
- *@param from_table the table to use
- *@param in_table the routes already added
- *
- *@return a poiter to a linked list of routes to add
- */
-struct destination_n *
-olsr_build_update_list(struct rt_entry *from_table,struct rt_entry *in_table)
+#define GET_MASK(mask) (AF_INET == olsr_cnf->ip_version ? mask.v4 : mask.v6)
+
+static char mask_buf[16];
+static char* olsr_netmask_to_string(const union hna_netmask *mask)
 {
-  struct destination_n *kernel_route_list = NULL;
-  struct rt_entry      *destination;
-  int                   idx;
-  
-  for(idx=0;idx<HASHSIZE;idx++)
-    {
-      for(destination = from_table[idx].next;
-	  destination != &from_table[idx];
-	  destination = destination->next)
+	if (AF_INET == olsr_cnf->ip_version)
 	{
-	  if (!olsr_find_up_route(destination, in_table))
-	    {
-	      struct destination_n *route_list;
-	      route_list = olsr_malloc(sizeof(struct destination_n), "create route tmp list");
-	      
-	      route_list->destination = destination;
-	      
-	      route_list->next = kernel_route_list;
-	      kernel_route_list = route_list;
-	    }
-	}   
-    }
-  
-  return (kernel_route_list);
-}
-
-
-
-
-
-/**
- *Deletes all OLSR routes
- *
- *
- *@return 1
- */
-int
-olsr_delete_all_kernel_routes(void)
-{ 
-  struct destination_n *delete_kernel_list;
-  struct destination_n *tmp;
-
-  OLSR_PRINTF(1, "Deleting all routes...\n");
-
-  delete_kernel_list = olsr_build_update_list(hna_routes, old_hna);
-
-  OLSR_PRINTF(1, "HNA list:\n");
-  for(tmp = delete_kernel_list;tmp;tmp = tmp->next)
-    {
-      union olsr_ip_addr *tmp_addr = &tmp->destination->rt_dst;
-      OLSR_PRINTF(1, "Dest: %s\n", olsr_ip_to_string(tmp_addr));
-    }
-
-  olsr_delete_routes_from_kernel(delete_kernel_list);
-
-  delete_kernel_list = olsr_build_update_list(routingtable,old_routes);
-
-  OLSR_PRINTF(1, "Route list:\n");
-  for(tmp = delete_kernel_list;tmp;tmp = tmp->next)
-    {
-      union olsr_ip_addr *tmp_addr = &tmp->destination->rt_dst;
-      OLSR_PRINTF(1, "Dest: %s\n", olsr_ip_to_string(tmp_addr));
-    }
-  olsr_delete_routes_from_kernel(delete_kernel_list);
-  return 1;
+		inet_ntop(AF_INET, &mask->v4, mask_buf, sizeof(mask_buf));
+	}
+	else
+	{
+		sprintf(mask_buf, "%d", mask->v6);
+	}
+	return mask_buf;
 }
 
-
-/**
- *Perform all neccessary actions for an update of the 
- *routes in the kernel.
- *
- *@return nada
- */
-void
-olsr_update_kernel_routes(void)
+static int olsr_add_rt(struct rt_entry *new, olsr_bool preadd)
 {
-  struct destination_n *delete_kernel_list;
-  struct destination_n *add_kernel_list;
-
-  OLSR_PRINTF(3, "Updating kernel routes...\n");
-  delete_kernel_list = olsr_build_update_list(old_routes, routingtable);
-  add_kernel_list = olsr_build_update_list(routingtable, old_routes);
-
-  olsr_delete_routes_from_kernel(delete_kernel_list);
-  olsr_add_routes_in_kernel(add_kernel_list);
+	int ret = 0;
+#ifdef DEBUG
+#ifdef DEBUG_DEFGW
+	if (0 == GET_MASK(new->rt_mask))
+#endif
+	OLSR_PRINTF(0, "%sAdd route to %s/%s via %s dev %s hops %d etx %f\n",
+		(preadd ? "Pre-" : ""),
+		olsr_ip_to_string(&new->rt_dst),
+		olsr_netmask_to_string(&new->rt_mask),
+		olsr_ip_to_string(&new->rt_router),
+		new->rt_if->int_name,
+		new->rt_metric,
+		new->rt_etx);
+#endif
+	if(!olsr_cnf->host_emul)
+	{
+		if(0 > (ret = (olsr_cnf->ip_version == AF_INET ?
+			olsr_addroute_function(new) :
+			olsr_addroute6_function(new))))
+		{
+			const char* err_msg;
+#ifndef DEBUG
+			if (preadd) return ret;
+#endif			
+			err_msg = strerror(errno);
+			OLSR_PRINTF(ROUTE_ERRORLEVEL, "Add route to %s/%s via %s dev %s hops %d: %s\n",
+				olsr_ip_to_string(&new->rt_dst),
+				olsr_netmask_to_string(&new->rt_mask),
+				olsr_ip_to_string(&new->rt_router),
+				new->rt_if->int_name,
+				new->rt_metric,
+				err_msg);
+			olsr_syslog(OLSR_LOG_ERR, "Add route to %s/%s via %s dev %s hops %d: %s\n",
+				olsr_ip_to_string(&new->rt_dst),
+				olsr_netmask_to_string(&new->rt_mask),
+				olsr_ip_to_string(&new->rt_router),
+				new->rt_if->int_name,
+				new->rt_metric,
+				err_msg);
+		}
+	}
+	return ret;
 }
 
-
-
-/**
- *Perform all neccessary actions for an update of the 
- *HNA routes in the kernel.
- *
- *@return nada
- */
-void
-olsr_update_kernel_hna_routes(void)
+static int olsr_del_rt(struct rt_entry *old)
 {
-  struct destination_n *delete_kernel_list;
-  struct destination_n *add_kernel_list;
-
-  OLSR_PRINTF(3, "Updating kernel HNA routes...\n");
-
-  delete_kernel_list = olsr_build_update_list(old_hna, hna_routes);
-  add_kernel_list = olsr_build_update_list(hna_routes, old_hna);
-
-  olsr_delete_routes_from_kernel(delete_kernel_list);
-  olsr_add_routes_in_kernel(add_kernel_list);
+	int ret = 0;
+#ifdef DEBUG
+#ifdef DEBUG_DEFGW
+	if (0 == GET_MASK(old->rt_mask))
+#endif
+	OLSR_PRINTF(0, "Del route to %s/%s via %s dev %s hops %d etx %f\n",
+		olsr_ip_to_string(&old->rt_dst),
+		olsr_netmask_to_string(&old->rt_mask),
+		olsr_ip_to_string(&old->rt_router),
+		old->rt_if->int_name,
+		old->rt_metric,
+		old->rt_etx);
+#endif
+	if(!olsr_cnf->host_emul)
+	{
+		if(0 > (ret = (AF_INET == olsr_cnf->ip_version ?
+			olsr_delroute_function(old) :
+			olsr_delroute6_function(old))))
+		{
+			const char * const err_msg = strerror(errno);
+			OLSR_PRINTF(ROUTE_ERRORLEVEL, "Del route to %s/%s via %s dev %s hops %d: %s\n",
+				olsr_ip_to_string(&old->rt_dst),
+				olsr_netmask_to_string(&old->rt_mask),
+				olsr_ip_to_string(&old->rt_router),
+				old->rt_if->int_name,
+				old->rt_metric,
+				err_msg);
+			olsr_syslog(OLSR_LOG_ERR, "Del route to %s/%s via %s dev %s hops %d: %s\n",
+				olsr_ip_to_string(&old->rt_dst),
+				olsr_netmask_to_string(&old->rt_mask),
+				olsr_ip_to_string(&old->rt_router),
+				old->rt_if->int_name,
+				old->rt_metric,
+				err_msg);
+			}
+	}
+	return ret;
 }
 
-
-/**
- *Create a copy of the routing table and
- *clear the current table
- *
- *@param original the table to move from
- *@param the table to move to
- *
- *@return nada
+/*
+ * Cleans entries from old_table not available in new_table
  */
-void
-olsr_move_route_table(struct rt_entry *original, struct rt_entry *new)
+static void olsr_clean_the_routes(struct rt_entry *old_table, const struct rt_entry *new_table, olsr_bool via_only)
 {
-  int idx;
-
-  for(idx=0;idx<HASHSIZE;idx++)
-    {
-      if(original[idx].next == &original[idx])
+	olsr_u8_t index;
+	for(index=0; index<HASHSIZE; index++)
 	{
-	  new[idx].next = &new[idx];
-	  new[idx].prev = &new[idx];
-	}
-      else
-	{
-	  /* Copy to old */
-	  new[idx].next = original[idx].next;
-	  new[idx].next->prev = &new[idx];
-	  new[idx].prev = original[idx].prev;
-	  new[idx].prev->next = &new[idx];
-
-	  /* Clear original */
-	  original[idx].next = &original[idx];
-	  original[idx].prev = &original[idx];
+		struct rt_entry *old;
+		for(old = old_table[index].next; old != &old_table[index]; old = old->next)
+		{
+			struct rt_entry *new;
+			olsr_bool del_entry = OLSR_TRUE;
+			const olsr_u32_t hash = olsr_hashing(&old->rt_dst);
+			if (via_only && COMP_IP(&old->rt_dst, &old->rt_router)) continue;
+			for(new = new_table[hash].next; new != &new_table[hash]; new = new->next)
+			{
+				if(COMP_IP(&old->rt_dst, &new->rt_dst) && GET_MASK(old->rt_mask) == GET_MASK(new->rt_mask))
+				{
+					del_entry = OLSR_FALSE;
+					break;
+				}
+			} /* for new */
+			if (del_entry && 0 <= olsr_del_rt(old))
+			{
+				struct rt_entry *tmp = old;
+				old = old->prev;
+				DEQUEUE_ELEM(tmp);
+				free(tmp);
+			}
+		} /* for old */
 	}
-    }
 }
 
-
-/**
- *Delete a linked list of routes from the kernel.
- *
- *@param delete_kernel_list the list to delete
- *
- *@return nada
+/*
+ * Updates the kernel routing (either hna or standard table)
+ * Moves entries from new_table to old_table to reflect kernel status
  */
-void 
-olsr_delete_routes_from_kernel(struct destination_n *delete_kernel_list)
+static void olsr_update_the_routes(struct rt_entry *old_table, const struct rt_entry *new_table, olsr_bool link_only)
 {
-  struct destination_n *destination_ptr;
-  int metric_counter = 1;
-  olsr_bool last_run = OLSR_FALSE;
-
-
-  /* Find highest metric */
-  for(destination_ptr = delete_kernel_list;
-      destination_ptr != NULL;
-      destination_ptr = destination_ptr->next)
-    {
-      if(destination_ptr->destination->rt_metric > metric_counter)
-	metric_counter = destination_ptr->destination->rt_metric;
-    }
-
-#ifdef DEBUG
-  OLSR_PRINTF(3, "%s highest metric %d\n",
-	      __func__, metric_counter);
-#endif
- 
-  while(delete_kernel_list!=NULL)
-    {
-      struct destination_n *previous_node = delete_kernel_list;
-
-      assert(metric_counter);
-
-      /* searching for all the items with metric equal to n */
-      for(destination_ptr = delete_kernel_list; destination_ptr != NULL; )
+	olsr_u8_t index;
+	for(index=0; index<HASHSIZE; index++)
 	{
-
-	  if(destination_ptr->destination->rt_metric == metric_counter)
-	    {
-	      /* Make sure one-hop direct neighbors are deleted last */
-	      if(metric_counter == 1 &&
-		 (!last_run && 
-		  COMP_IP(&destination_ptr->destination->rt_dst, 
-			  &destination_ptr->destination->rt_router)))
-		{
-		  previous_node = destination_ptr;
-		  destination_ptr = destination_ptr->next;
-		}
-	      else
+		struct rt_entry *new;
+		for(new = new_table[index].next; new != &new_table[index]; new = new->next)
 		{
-		  olsr_16_t error;		  
+			struct rt_entry *old;
+			olsr_bool add_entry = OLSR_TRUE;
+			const olsr_u32_t hash = olsr_hashing(&new->rt_dst);
+			if (link_only && !COMP_IP(&new->rt_dst, &new->rt_router)) continue;
+			for(old = old_table[hash].next; old != &old_table[hash]; old = old->next)
+			{
+				if(COMP_IP(&old->rt_dst, &new->rt_dst) && GET_MASK(old->rt_mask) == GET_MASK(new->rt_mask))
+				{
 #ifdef DEBUG
-		  OLSR_PRINTF(3, "Deleting route to %s hopcount %d\n",
-			      olsr_ip_to_string(&destination_ptr->destination->rt_dst),
-			      destination_ptr->destination->rt_metric);
+#ifdef DEBUG_DEFGW
+					if (0 == GET_MASK(old->rt_mask))
 #endif
-		    if(!olsr_cnf->host_emul)
-		      {
-			if(0 > (error = (olsr_cnf->ip_version == AF_INET ?
-				olsr_delroute_function(destination_ptr->destination) :
-				olsr_delroute6_function(destination_ptr->destination))))
-			  {
-                            const char * const err_msg = strerror(errno);
-			    OLSR_PRINTF(1, "Delete route(%s):%s\n", olsr_ip_to_string(&destination_ptr->destination->rt_dst), err_msg);
-                            olsr_syslog(OLSR_LOG_ERR, "Delete route:%s", err_msg);
-			  }
-		    }
-		  
-		  /* Getting rid of this node and hooking up the broken point */
-		  if(destination_ptr == delete_kernel_list) 
-		    {
-		      destination_ptr = delete_kernel_list->next;
-		      free(delete_kernel_list);
-		      delete_kernel_list = destination_ptr;
-		      previous_node = delete_kernel_list;
-		    }
-		  else 
-		    {
-		      previous_node->next = destination_ptr->next;
-		      free(destination_ptr);
-		      destination_ptr = previous_node->next;
-		    }
-		}
-	    }
-	  else 
-	    {
-	      previous_node = destination_ptr;
-	      destination_ptr = destination_ptr->next;
-	    }
-		
+					OLSR_PRINTF(0, "Compare route to %s/%s via %s dev %s hops %d etx %f (old:%s=%f)\n",
+						olsr_ip_to_string(&new->rt_dst),
+						olsr_netmask_to_string(&new->rt_mask),
+						olsr_ip_to_string(&new->rt_router),
+						new->rt_if->int_name,
+						new->rt_metric,
+						new->rt_etx,
+						olsr_ip_to_string(&old->rt_router),
+						old->rt_etx);
+#endif
+					if(!COMP_IP(&old->rt_router, &new->rt_router) ||
+					   old->rt_if->if_index != new->rt_if->if_index ||
+					   old->rt_metric != new->rt_metric)
+					{
+						/* 
+						 * ioctl/rtnetlink offers no change route CMD. We try to add the new
+						 * route before deleting the old one. Does not work for switching ifaces,
+						 * if metric and router is unchanged.
+						 */
+						if ((old->rt_metric != new->rt_metric ||
+						    !COMP_IP(&old->rt_router, &new->rt_router)) &&
+						    0 <= olsr_add_rt(new, OLSR_TRUE))
+						{
+							struct rt_entry *tmp = new;
+							new = new->prev;
+							DEQUEUE_ELEM(tmp);
+							QUEUE_ELEM(old_table[hash], tmp);
+							add_entry = OLSR_FALSE;
+						}
+						if (0 <= olsr_del_rt(old))
+						{
+							struct rt_entry *tmp = old;
+							old = old->prev;
+							DEQUEUE_ELEM(tmp);
+							free(tmp);
+						}
+					}
+					else
+					{
+						/* Entry already exists: update etx only */
+						old->rt_etx = new->rt_etx;
+						add_entry = OLSR_FALSE;
+					}
+					break;
+				}
+			} /* for old */
+			
+			if (add_entry && 0 <= olsr_add_rt(new, OLSR_FALSE))
+			{
+				/* Move the routing entry from new to old */
+				struct rt_entry *tmp = new;
+				new = new->prev;
+				DEQUEUE_ELEM(tmp);
+				QUEUE_ELEM(old_table[hash], tmp);
+			}
+		} /* for new */
 	}
-      if((metric_counter == 1) && !last_run)
-        {
-	  last_run = OLSR_TRUE;
-        }
-      else
-        {
-	  metric_counter--;
-        }
-    }
+}
  
+/*
+ * Updates kernel routing from new tables
+ */
+void olsr_update_routes(struct rt_entry *new_routes, struct rt_entry *new_hna)
+{
+	/*
+	 * Sven-Ola: The following is true at least with Linux. When the network link 
+	 * route for na iface was removed, you cannot add a "via" route before adding
+	 * a matching route with scope link first. It may be possible to remove a link
+	 * and then remove the dependant via routes, but the correct sequence is more
+	 * clean IMO. Here's an example of the mentioned config situation:
+	 *
+	 * > ifconfig wlan0 10.0.0.1 netmask 255.255.0.0 up
+	 * > route del -net 10.0.0.0 netmask 255.255.0.0 dev wlan0
+	 * > olsrd -d 0 -i wlan0 -nofork
+	 */
+
+	olsr_clean_the_routes(old_hna, new_hna, OLSR_FALSE);
+	if (NULL != new_routes)
+	{
+		olsr_clean_the_routes(old_routes, new_routes, OLSR_TRUE);
+		olsr_clean_the_routes(old_routes, new_routes, OLSR_FALSE);
+		olsr_update_the_routes(old_routes, new_routes, OLSR_TRUE);
+		olsr_update_the_routes(old_routes, new_routes, OLSR_FALSE);
+	}
+	olsr_update_the_routes(old_hna, new_hna, OLSR_FALSE);
 }
 
-/**
- *Add a list of routes to the kernel. Adding
- *is done by hopcount to be sure a route
- *to the nexthop is added.
- *
- *@param add_kernel_list the linked list of routes to add
- *
- *@return nada
+/* 
+ * Exits from this modules (removes all routes from kernel)
  */
-void 
-olsr_add_routes_in_kernel(struct destination_n *add_kernel_list)
+int
+olsr_delete_all_kernel_routes(void)
 {
-  int metric_counter = 1;
-  olsr_bool first_run = OLSR_TRUE;
-  
-  while(add_kernel_list != NULL)
-    {
-      struct destination_n *destination_kernel = NULL;
-      struct destination_n *previous_node = add_kernel_list;
+	int index;
+	struct rt_entry null_table[HASHSIZE];
 
-      /* searching for all the items with metric equal to n */
-      for(destination_kernel = add_kernel_list; destination_kernel != NULL; )
+	for(index=0; index<HASHSIZE; index++)
 	{
-	  if((destination_kernel->destination->rt_metric == metric_counter) &&
-	     (!first_run || 
-              COMP_IP(&destination_kernel->destination->rt_dst,
-                      &destination_kernel->destination->rt_router)))
-	    {
-	      olsr_16_t error;
-	      /* First add all 1-hop routes that has themselves as GW */
-
-#ifdef DEBUG
-	      OLSR_PRINTF(3, "Adding route to %s hopcount %d\n",
-			  olsr_ip_to_string(&destination_kernel->destination->rt_dst),
-			  destination_kernel->destination->rt_metric);
-#endif
-			  
-		if(!olsr_cnf->host_emul)
-		  {
-		    if(0 > (error = (olsr_cnf->ip_version == AF_INET ?
-			olsr_addroute_function(destination_kernel->destination) :
-			olsr_addroute6_function(destination_kernel->destination))))
-		      {
-                        const char * const err_msg = strerror(errno);
-			OLSR_PRINTF(1, "Add route(%s): %s\n", olsr_ip_to_string(&destination_kernel->destination->rt_dst), err_msg);
-                        olsr_syslog(OLSR_LOG_ERR, "Add route:%s", err_msg);
-		      }
-		  }
-
-	      
-	      /* Getting rid of this node and hooking up the broken point */
-	      if(destination_kernel == add_kernel_list) 
-		{
-		  destination_kernel = add_kernel_list->next;
-		  free(add_kernel_list);
-		  add_kernel_list = destination_kernel;
-		  previous_node=add_kernel_list;
-		}
-	      else 
-		{
-		  previous_node->next = destination_kernel->next;
-		  free(destination_kernel);
-		  destination_kernel = previous_node->next;
-		}
-	    }
-	  else 
-	    {
-	      previous_node = destination_kernel;
-	      destination_kernel = destination_kernel->next;
-	    }
-		
+		null_table[index].next = &null_table[index];
+		null_table[index].prev = &null_table[index];
 	}
-      if(first_run)
-        {
-	  first_run = OLSR_FALSE;
-        }
-      else
-        {
-	  metric_counter++;
-        }
-    }
 	
+	olsr_clean_the_routes(old_hna, null_table, OLSR_FALSE);
+	olsr_clean_the_routes(old_routes, null_table, OLSR_TRUE);
+	olsr_clean_the_routes(old_routes, null_table, OLSR_FALSE);
+	return 1;
 }
-
-
-
diff -Nur olsrd-0.5.3.orig/src/process_routes.h olsrd-0.5.3/src/process_routes.h
--- olsrd-0.5.3.orig/src/process_routes.h	2007-09-04 16:04:52.000000000 +0200
+++ olsrd-0.5.3/src/process_routes.h	2007-09-04 16:04:52.000000000 +0200
@@ -47,9 +47,6 @@
 
 #include <sys/ioctl.h>
 
-extern struct rt_entry old_routes[HASHSIZE];
-extern struct rt_entry old_hna[HASHSIZE];
-
 typedef int (*olsr_route_function)(struct rt_entry*);
 
 extern olsr_route_function olsr_addroute_function;
@@ -63,26 +60,8 @@
 int
 olsr_init_old_table(void);
 
-int
-olsr_find_up_route(struct rt_entry *dst,struct rt_entry *table);
-
-struct destination_n *
-olsr_build_update_list(struct rt_entry *from_table, struct rt_entry *in_table);
-
-void
-olsr_update_kernel_routes(void);
-
-void
-olsr_update_kernel_hna_routes(void);
-
-void
-olsr_move_route_table(struct rt_entry *, struct rt_entry *);
-
-void
-olsr_delete_routes_from_kernel(struct destination_n *delete_kernel_list);
-
 void
-olsr_add_routes_in_kernel(struct destination_n *add_kernel_list);
+olsr_update_routes(struct rt_entry *new_routes, struct rt_entry *new_hna);
 
 int
 olsr_delete_all_kernel_routes(void);
diff -Nur olsrd-0.5.3.orig/src/routing_table.c olsrd-0.5.3/src/routing_table.c
--- olsrd-0.5.3.orig/src/routing_table.c	2007-09-04 16:04:52.000000000 +0200
+++ olsrd-0.5.3/src/routing_table.c	2007-09-04 16:04:52.000000000 +0200
@@ -421,12 +421,12 @@
  *
  *@return nada
  */
-void 
-olsr_calculate_routing_table(void)
+static void
+olsr_calculate_routes(void)
 {
   struct destination_n *list_destination_n_1;
 
-  olsr_move_route_table(routingtable, old_routes);
+  olsr_free_routing_table(routingtable);
 
   /* Add neighbors */
   olsr_fill_routing_table_with_neighbors();
@@ -518,16 +518,8 @@
       printf("************** TABLES ****************\n");
       printf("Routing table:\n");
       olsr_print_routing_table(routingtable);
-      printf("Old table:\n");
-      olsr_print_routing_table(old_routes);
       printf("**************************************\n");
     }
-
-  
-  /* Update routes */
-  olsr_update_kernel_routes();
-
-  olsr_free_routing_table(old_routes);
 }
 
 
@@ -620,7 +612,7 @@
  *Calculate the HNA routes
  *
  */
-void
+static void
 olsr_calculate_hna_routes(void)
 {
   int idx;
@@ -629,7 +621,7 @@
   OLSR_PRINTF(3, "Calculating HNA routes\n");
 #endif
 
-  olsr_move_route_table(hna_routes, old_hna);
+  olsr_free_routing_table(hna_routes);
 
   for(idx=0;idx<HASHSIZE;idx++)
     {
@@ -707,21 +699,32 @@
 	}
     }
 
-  /* Update kernel */
-  olsr_update_kernel_hna_routes();
-
   if(olsr_cnf->debug_level > 2)
     {
       OLSR_PRINTF(3, "HNA table:\n");
       olsr_print_routing_table(hna_routes);
     }
-
-  olsr_free_routing_table(old_hna);
 }
 
 
 
 
+/**
+ * Combined routing and hna calculation
+ */
+void 
+olsr_calculate_routing_table(olsr_bool only_hna)
+{
+  if(!only_hna)
+    olsr_calculate_routes();
+    
+  olsr_calculate_hna_routes();
+  
+  olsr_update_routes(only_hna ? routingtable : NULL, hna_routes);
+}
+
+
+
 
 /**
  *Print the routingtable to STDOUT
diff -Nur olsrd-0.5.3.orig/src/routing_table.h olsrd-0.5.3/src/routing_table.h
--- olsrd-0.5.3.orig/src/routing_table.h	2007-09-04 16:04:52.000000000 +0200
+++ olsrd-0.5.3/src/routing_table.h	2007-09-04 16:04:52.000000000 +0200
@@ -98,10 +98,7 @@
 olsr_init_routing_table(void);
 
 void 
-olsr_calculate_routing_table(void);
-
-void
-olsr_calculate_hna_routes(void);
+olsr_calculate_routing_table(olsr_bool only_hna);
 
 void
 olsr_print_routing_table(struct rt_entry *);
