Fix several memory leaks and a locking inconsistency in mid_set for tc-entries
authorHenning Rogge <hrogge@googlemail.com>
Sat, 22 Aug 2009 19:46:04 +0000 (21:46 +0200)
committerHenning Rogge <hrogge@googlemail.com>
Sat, 22 Aug 2009 19:46:04 +0000 (21:46 +0200)
13 files changed:
lib/txtinfo/src/olsrd_txtinfo.c
src/hna_set.c
src/interfaces.c
src/interfaces.h
src/link_set.c
src/main.c
src/mid_set.c
src/olsr_comport_txt.c
src/olsr_comport_txt.h
src/olsr_cookie.c
src/plugin_loader.c
src/tc_set.c
src/tc_set.h

index 1bea32d..e75db81 100644 (file)
@@ -225,6 +225,9 @@ txtinfo_pre_cleanup(void)
   for (i=0; i<ARRAYSIZE(commands); i++) {
     olsr_com_remove_normal_txtcommand(commands[i].cmd);
   }
+  for (i=link_keys_static; i<link_keys_count; i++) {
+    free(values_link[i]);
+  }
   ip_acl_flush(&allowed_nets);
   return false;
 }
index bf9dbd7..5e08af9 100644 (file)
@@ -149,7 +149,11 @@ void
 olsr_flush_hna_nets(struct tc_entry *tc)
 {
   struct hna_net *hna_net;
+#if !defined REMOVE_LOG_DEBUG
+  struct ipaddr_str buf;
+#endif
 
+  OLSR_DEBUG(LOG_TC, "flush hna nets of '%s' (%u)\n", olsr_ip_to_string(&buf, &tc->addr), tc->edge_tree.count);
   OLSR_FOR_ALL_TC_HNA_ENTRIES(tc, hna_net) {
     olsr_delete_hna_net(hna_net);
   } OLSR_FOR_ALL_TC_HNA_ENTRIES_END(tc, hna_net);
index 05cd772..d4ede2d 100644 (file)
@@ -92,7 +92,7 @@ static void check_interface_updates(void *);
  * @return if more than zero interfaces were configured
  */
 bool
-ifinit(void)
+init_interfaces(void)
 {
   struct olsr_if_config *tmp_if;
 
@@ -174,6 +174,20 @@ is_lost_interface_ip(union olsr_ip_addr *ip) {
   return get_lost_interface_ip(ip) != NULL;
 }
 
+void destroy_interfaces(void) {
+  struct interface *iface;
+  struct interface_lost *lost;
+
+  OLSR_FOR_ALL_INTERFACES(iface) {
+    struct interface **ptr = &iface;
+    remove_interface(ptr);
+  } OLSR_FOR_ALL_INTERFACES_END(iface)
+
+  OLSR_FOR_ALL_LOSTIF_ENTRIES(lost) {
+    remove_lost_interface_ip(lost);
+  } OLSR_FOR_ALL_LOSTIF_ENTRIES_END(lost);
+}
+
 /**
  * Callback function for periodic check of interface parameters.
  */
index 9c3189b..c730aab 100644 (file)
@@ -217,8 +217,9 @@ extern struct list_node EXPORT(interface_head);
 typedef int (*ifchg_cb_func) (struct interface *, int);
 
 
-bool ifinit(void);
+bool init_interfaces(void);
 bool EXPORT(is_lost_interface_ip)(union olsr_ip_addr *ip);
+void destroy_interfaces(void);
 void remove_interface(struct interface **);
 void run_ifchg_cbs(struct interface *, int);
 struct interface *if_ifwithsock(int);
index 40bcbc0..dd36f8e 100644 (file)
@@ -519,16 +519,12 @@ add_link_entry(const union olsr_ip_addr *local,
    * Now create a tc-edge for that link.
    */
   olsr_change_myself_tc();
+
+  link->link_tc_edge = olsr_lookup_tc_edge(tc_myself, remote_main);
   if (link->link_tc_edge == NULL) {
     link->link_tc_edge = olsr_add_tc_edge_entry(tc_myself, remote_main, 0);
   }
 
-  /*
-   * Mark the edge local such that it does not get deleted
-   * during cleanup functions.
-   */
-  link->link_tc_edge->is_local = 1;
-
   /*
    * Add the rt_path for the link-end. This is an optimization
    * that lets us install > 1 hop routes prior to receiving
index 02bf4ed..7ebbd91 100644 (file)
@@ -328,7 +328,7 @@ main(int argc, char *argv[])
     }
   }
   /* Initializing networkinterfaces */
-  if (!ifinit()) {
+  if (!init_interfaces()) {
     if (olsr_cnf->allow_no_interfaces) {
       OLSR_INFO(LOG_MAIN,
                 "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n");
@@ -510,7 +510,6 @@ static void
 olsr_shutdown(void)
 {
   struct mid_entry *mid;
-  struct interface *iface;
 
   olsr_delete_all_kernel_routes();
 
@@ -536,10 +535,7 @@ olsr_shutdown(void)
   olsr_destroy_pluginsystem();
 
   /* Remove active interfaces */
-  OLSR_FOR_ALL_INTERFACES(iface) {
-    struct interface **ptr = &iface;
-    remove_interface(ptr);
-  } OLSR_FOR_ALL_INTERFACES_END(iface)
+  destroy_interfaces();
 
   /* delete lo:olsr if neccesarry */
   if (olsr_cnf->source_ip_mode) {
index bf1fb3b..64a6de6 100644 (file)
@@ -95,7 +95,9 @@ olsr_expire_mid_entries(void *context)
 
   OLSR_DEBUG(LOG_MID, "MID aliases for %s timed out\n", olsr_ip_to_string(&buf, &tc->addr));
 
+  tc->mid_timer = NULL;
   olsr_flush_mid_entries(tc);
+  olsr_unlock_tc_entry(tc);
 }
 
 /**
@@ -107,8 +109,27 @@ olsr_expire_mid_entries(void *context)
 static void
 olsr_set_mid_timer(struct tc_entry *tc, uint32_t rel_timer)
 {
-  olsr_set_timer(&tc->mid_timer, rel_timer, OLSR_MID_JITTER,
-                 OLSR_TIMER_ONESHOT, &olsr_expire_mid_entries, tc, mid_validity_timer_cookie);
+  if (tc->mid_timer) {
+    olsr_change_timer(tc->mid_timer, rel_timer, OLSR_MID_JITTER, OLSR_TIMER_ONESHOT);
+  }
+  else {
+    tc->mid_timer = olsr_start_timer(rel_timer, OLSR_MID_JITTER, OLSR_TIMER_ONESHOT,
+        &olsr_expire_mid_entries, tc, mid_validity_timer_cookie);
+    olsr_lock_tc_entry(tc);
+  }
+}
+
+/**
+ * Delete possible duplicate entries in tc set.
+ * This optimization is not specified in rfc3626.
+ */
+static void
+olsr_flush_tc_duplicates(struct mid_entry *alias) {
+  struct tc_entry *tc;
+  tc = olsr_lookup_tc_entry(&alias->mid_alias_addr);
+  if (tc) {
+    olsr_delete_tc_entry(tc);
+  }
 }
 
 /**
@@ -250,13 +271,7 @@ olsr_insert_mid_entry(const union olsr_ip_addr *main_addr,
    */
   olsr_insert_routing_table(&alias->mid_alias_addr, 8 * olsr_cnf->ipsize, main_addr, OLSR_RT_ORIGIN_MID);
 
-  /*
-   * Start the timer. Because we provide the TC reference
-   * as callback data for the timer we need to lock
-   * the underlying TC entry again.
-   */
   olsr_set_mid_timer(alias->mid_tc, vtime);
-  olsr_lock_tc_entry(tc);
 
   return alias;
 }
@@ -305,6 +320,7 @@ olsr_update_mid_entry(const union olsr_ip_addr *main_addr,
    */
   olsr_fixup_mid_main_addr(main_addr, alias_addr);
   olsr_flush_nbr2_duplicates(alias);
+  olsr_flush_tc_duplicates(alias);
 
   /*
    * Recalculate topology.
@@ -400,11 +416,11 @@ olsr_flush_mid_entries(struct tc_entry *tc)
     olsr_delete_mid_entry(alias);
   } OLSR_FOR_ALL_TC_MID_ENTRIES_END(tc, alias);
 
-  /*
-   * Kill any pending timers.
-   */
-  olsr_set_mid_timer(tc, 0);
-  olsr_unlock_tc_entry(tc);
+  if (tc->mid_timer) {
+    olsr_stop_timer(tc->mid_timer);
+    olsr_unlock_tc_entry(tc);
+    tc->mid_timer = NULL;
+  }
 }
 
 /**
index 0ac534b..169dadb 100644 (file)
@@ -113,6 +113,9 @@ static olsr_txthandler txt_internal_handlers[] = {
   olsr_txtcmd_plugin
 };
 
+static struct olsr_txtcommand *txt_internal_normalcmd[ARRAYSIZE(txt_internal_names)];
+static struct olsr_txtcommand *txt_internal_helpcmd[ARRAYSIZE(txt_internal_names)];
+
 void
 olsr_com_init_txt(void) {
   size_t i;
@@ -126,23 +129,17 @@ olsr_com_init_txt(void) {
   txt_repeattimer_cookie = olsr_alloc_cookie("txt repeat timer", OLSR_COOKIE_TYPE_TIMER);
 
   for (i=0; i < ARRAYSIZE(txt_internal_names); i++) {
-    olsr_com_add_normal_txtcommand(txt_internal_names[i], txt_internal_handlers[i]);
-    olsr_com_add_help_txtcommand(txt_internal_names[i], olsr_txtcmd_displayhelp);
+    txt_internal_normalcmd[i] = olsr_com_add_normal_txtcommand(txt_internal_names[i], txt_internal_handlers[i]);
+    txt_internal_helpcmd[i] = olsr_com_add_help_txtcommand(txt_internal_names[i], olsr_txtcmd_displayhelp);
   }
 }
 
 void
 olsr_com_destroy_txt(void) {
-  struct olsr_txtcommand *cmd;
-  struct avl_node *node;
-
-  while ((node = avl_walk_first(&txt_normal_tree)) != NULL) {
-    cmd = txt_tree2cmd(node);
-    olsr_com_remove_normal_txtcommand(cmd);
-  }
-  while ((node = avl_walk_first(&txt_help_tree)) != NULL) {
-    cmd = txt_tree2cmd(node);
-    olsr_com_remove_help_txtcommand(cmd);
+  size_t i;
+  for (i=0; i < ARRAYSIZE(txt_internal_names); i++) {
+    olsr_com_remove_normal_txtcommand(txt_internal_normalcmd[i]);
+    olsr_com_remove_help_txtcommand(txt_internal_helpcmd[i]);
   }
 }
 struct olsr_txtcommand *
index b2f324d..1bee8ad 100644 (file)
@@ -75,7 +75,6 @@ struct olsr_txtcommand *EXPORT(olsr_com_add_normal_txtcommand) (
 struct olsr_txtcommand *EXPORT(olsr_com_add_help_txtcommand) (
     const char *command, olsr_txthandler handler);
 void EXPORT(olsr_com_remove_normal_txtcommand) (struct olsr_txtcommand *cmd);
-void EXPORT(olsr_com_remove_csv_txtcommand) (struct olsr_txtcommand *cmd);
 void EXPORT(olsr_com_remove_help_txtcommand) (struct olsr_txtcommand *cmd);
 
 enum olsr_txtcommand_result olsr_com_handle_txtcommand(struct comport_connection *con,
index 4c7f219..925635e 100644 (file)
@@ -341,7 +341,11 @@ olsr_cookie_free(struct olsr_cookie_info *ci, void *ptr)
    * Verify if there has been a memory overrun, or
    * the wrong owner is trying to free this.
    */
-  assert(!memcmp(&branding->cmb_sig, "cookie", 6) && branding->id == ci->ci_membrand);
+
+  if (!(memcmp(&branding->cmb_sig, "cookie", 6) == 0 && branding->id == ci->ci_membrand)) {
+    OLSR_ERROR(LOG_COOKIE, "Memory corruption at end of '%s' cookie\n", ci->ci_name);
+    olsr_exit(1);
+  }
 
   /* Kill the brand */
   memset(branding, 0, sizeof(*branding));
index 901cca3..4c3162c 100644 (file)
@@ -61,6 +61,8 @@ static bool plugin_tree_initialized = false;
 
 static struct olsr_cookie_info *plugin_mem_cookie = NULL;
 
+static bool olsr_internal_unload_plugin(struct olsr_plugin *plugin, bool cleanup);
+
 /**
  * This function is called by the constructor of a plugin.
  * because of this the first call has to initialize the list
@@ -70,7 +72,7 @@ static struct olsr_cookie_info *plugin_mem_cookie = NULL;
  */
 void
 olsr_hookup_plugin(struct olsr_plugin *pl_def) {
-  fprintf(stderr, "hookup %s\n", pl_def->p_name);
+  fprintf(stdout, "hookup %s\n", pl_def->p_name);
   if (!plugin_tree_initialized) {
     avl_init(&plugin_tree, avl_comp_strcasecmp);
     plugin_tree_initialized = true;
@@ -79,16 +81,6 @@ olsr_hookup_plugin(struct olsr_plugin *pl_def) {
   avl_insert(&plugin_tree, &pl_def->p_node, AVL_DUP_NO);
 }
 
-/**
- * This function is called by the destructor of a plugin.
- *
- * @param pl_def pointer to plugin definition
- */
-void
-olsr_unhookup_plugin(struct olsr_plugin *pl_def) {
-  avl_delete(&plugin_tree, &pl_def->p_node);
-}
-
 struct olsr_plugin *olsr_get_plugin(const char *libname) {
   struct avl_node *node;
   /* SOT: Hacked away the funny plugin check which fails if pathname is included */
@@ -158,7 +150,7 @@ olsr_destroy_pluginsystem(void) {
 
   OLSR_FOR_ALL_PLUGIN_ENTRIES(plugin) {
     olsr_deactivate_plugin(plugin);
-    olsr_unload_plugin(plugin);
+    olsr_internal_unload_plugin(plugin, true);
   } OLSR_FOR_ALL_PLUGIN_ENTRIES_END(plugin)
 }
 
@@ -263,15 +255,15 @@ olsr_load_plugin(const char *libname)
   return olsr_load_legacy_plugin(libname, dlhandle);
 }
 
-bool
-olsr_unload_plugin(struct olsr_plugin *plugin) {
+static bool
+olsr_internal_unload_plugin(struct olsr_plugin *plugin, bool cleanup) {
   bool legacy = false;
 
   if (plugin->active) {
     olsr_deactivate_plugin(plugin);
   }
 
-  if (plugin->dlhandle == NULL) {
+  if (plugin->dlhandle == NULL && !cleanup) {
     /* this is a static plugin, it cannot be unloaded */
     return true;
   }
@@ -280,6 +272,7 @@ olsr_unload_plugin(struct olsr_plugin *plugin) {
 
   /* remove first from tree */
   avl_delete(&plugin_tree, &plugin->p_node);
+  free(plugin->p_node.key);
 
   legacy = plugin->p_version == 5;
 
@@ -298,6 +291,11 @@ olsr_unload_plugin(struct olsr_plugin *plugin) {
   return false;
 }
 
+bool
+olsr_unload_plugin(struct olsr_plugin *plugin) {
+  return olsr_internal_unload_plugin(plugin, false);
+}
+
 bool olsr_activate_plugin(struct olsr_plugin *plugin) {
   struct plugin_param *params;
   unsigned int i;
index 68777b9..899fa0b 100644 (file)
@@ -196,12 +196,6 @@ olsr_change_myself_tc(void)
     if (main_ip_change || entry->link_tc_edge == NULL) {
       struct nbr_entry *ne = entry->neighbor;
       entry->link_tc_edge = olsr_add_tc_edge_entry(tc_myself, &ne->nbr_addr, 0);
-
-      /*
-       * Mark the edge local such that it does not get deleted
-       * during cleanup functions.
-       */
-      entry->link_tc_edge->is_local = 1;
     }
   } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
   changes_topology = true;
@@ -218,19 +212,23 @@ void
 olsr_delete_tc_entry(struct tc_entry *tc)
 {
   struct tc_edge_entry *tc_edge;
+
 #if !defined REMOVE_LOG_DEBUG
   struct ipaddr_str buf;
 #endif
-  OLSR_DEBUG(LOG_TC, "TC: del entry %s\n", olsr_ip_to_string(&buf, &tc->addr));
+  OLSR_DEBUG(LOG_TC, "TC: del entry %s %u %s\n", olsr_ip_to_string(&buf, &tc->addr),
+      tc->edge_tree.count, tc->is_virtual ? "true" : "false");
 
   /* we don't want to keep this node */
   tc->is_virtual = true;
 
+  if (tc->edge_tree.count == 0) {
+    olsr_cleanup_tc_entry(tc);
+    return;
+  }
   /* The delete all non-virtual edges, the last one will clean up the tc if possible */
   OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
-    /* we don't need this edge for the tc, so mark it virtual for possible cleanup */
-
-    tc_edge->is_virtual = 1;
+    /* we don't need this edge for the tc, so let's try to remove it */
     olsr_delete_tc_edge_entry(tc_edge);
   } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
 }
@@ -243,14 +241,11 @@ olsr_delete_tc_entry(struct tc_entry *tc)
 static void
 olsr_cleanup_tc_entry(struct tc_entry *tc) {
   struct rt_path *rtp;
+  struct ipaddr_str buf;
 
+  OLSR_DEBUG(LOG_TC, "TC: del entry %s %u\n", olsr_ip_to_string(&buf, &tc->addr), tc->refcount);
   assert (tc->edge_tree.count == 0);
 
-  /*
-   * Delete the rt_path for ourselves.
-   */
-  olsr_delete_routing_table(&tc->addr, 8 * olsr_cnf->ipsize, &tc->addr, OLSR_RT_ORIGIN_TC);
-
   OLSR_FOR_ALL_PREFIX_ENTRIES(tc, rtp) {
     olsr_delete_rt_path(rtp);
   } OLSR_FOR_ALL_PREFIX_ENTRIES_END(tc, rtp);
@@ -431,7 +426,7 @@ olsr_add_tc_edge_entry(struct tc_entry *tc, union olsr_ip_addr *addr, uint16_t a
   }
 
   /* don't create an inverse edge for a tc pointing to us ! */
-  if (tc_neighbor != tc_myself) {
+  if (1 && tc_neighbor != tc_myself) {
     tc_edge_inv = olsr_lookup_tc_edge(tc_neighbor, &tc->addr);
     if (!tc_edge_inv ) {
       OLSR_DEBUG(LOG_TC, "TC:   creating inverse edge for %s\n", olsr_ip_to_string(&buf, &tc->addr));
@@ -462,24 +457,22 @@ olsr_add_tc_edge_entry(struct tc_entry *tc, union olsr_ip_addr *addr, uint16_t a
  *
  * @param tc the TC entry
  * @param tc_edge the TC edge entry
+ * @return true if the tc entry was deleted, false otherwise
  */
 void
 olsr_delete_tc_edge_entry(struct tc_edge_entry *tc_edge)
 {
   struct tc_entry *tc;
-  struct link_entry *link;
   struct tc_edge_entry *tc_edge_inv;
 #if !defined REMOVE_LOG_DEBUG
   struct ipaddr_str buf;
 #endif
 
+  tc_edge->is_virtual = 1;
+
   tc_edge_inv = tc_edge->edge_inv;
-  if (tc_edge->is_local == 0 && tc_edge_inv != NULL
-      && tc_edge_inv->is_virtual == 0 && tc_edge_inv->is_local == 0) {
-    /* mark this a virtual edge instead of removing it */
+  if (tc_edge_inv != NULL && tc_edge_inv->is_virtual == 0) {
     OLSR_DEBUG(LOG_TC, "TC: mark edge entry %s\n", olsr_tc_edge_to_string(tc_edge));
-
-    tc_edge->is_virtual = 1;
     return;
   }
 
@@ -503,29 +496,14 @@ olsr_delete_tc_edge_entry(struct tc_edge_entry *tc_edge)
 
   /* remove edge from tc FIRST */
   avl_delete(&tc->edge_tree, &tc_edge->edge_node);
+  OLSR_DEBUG(LOG_TC, "TC: %s down to %d edges\n", olsr_ip_to_string(&buf, &tc->addr), tc->edge_tree.count);
 
   /* now check if TC is virtual and has no edges left */
   if (tc->is_virtual && tc->edge_tree.count == 0) {
     /* cleanup virtual tc node */
     olsr_cleanup_tc_entry(tc);
   }
-
-  OLSR_DEBUG(LOG_TC, "TC: %s down to %d edges\n", olsr_ip_to_string(&buf, &tc->addr), tc->edge_tree.count);
   olsr_unlock_tc_entry(tc);
-
-  /*
-   * If this is a local edge, delete all references to it.
-   */
-  if (tc_edge->is_local) {
-    OLSR_FOR_ALL_LINK_ENTRIES(link) {
-      if (link->link_tc_edge == tc_edge) {
-        link->link_tc_edge = NULL;
-        break;
-      }
-    }
-    OLSR_FOR_ALL_LINK_ENTRIES_END(link);
-  }
-
   olsr_free_tc_edge_entry(tc_edge);
 }
 
@@ -544,7 +522,7 @@ delete_outdated_tc_edges(struct tc_entry *tc)
   OLSR_DEBUG(LOG_TC, "TC: deleting outdated TC-edge entries\n");
 
   OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
-    if (SEQNO_GREATER_THAN(tc->ansn, tc_edge->ansn) && !(tc_edge->is_local)) {
+    if (SEQNO_GREATER_THAN(tc->ansn, tc_edge->ansn)) {
       olsr_delete_tc_edge_entry(tc_edge);
       retval = true;
     }
@@ -588,7 +566,7 @@ olsr_delete_revoked_tc_edges(struct tc_entry *tc, uint16_t ansn, union olsr_ip_a
       }
     }
 
-    if (SEQNO_GREATER_THAN(ansn, tc_edge->ansn) && tc_edge->is_local == 0) {
+    if (SEQNO_GREATER_THAN(ansn, tc_edge->ansn)) {
       olsr_delete_tc_edge_entry(tc_edge);
       retval = 1;
     }
@@ -690,10 +668,6 @@ olsr_print_tc_table(void)
 {
 #if !defined REMOVE_LOG_INFO
   /* The whole function makes no sense without it. */
-  static char LOCAL[] = "local";
-  static char VIRTUAL[] = "virtual";
-  static char NORMAL[] = "";
-
   struct tc_entry *tc;
   const int ipwidth = olsr_cnf->ip_version == AF_INET ? 15 : 30;
 
@@ -706,20 +680,12 @@ olsr_print_tc_table(void)
     OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
       struct ipaddr_str addrbuf, dstaddrbuf;
       char lqbuffer1[LQTEXT_MAXLENGTH], lqbuffer2[LQTEXT_MAXLENGTH];
-      char *type = NORMAL;
-      /* there should be no local virtual edges ! */
-      if (tc_edge->is_local) {
-        type = LOCAL;
-      }
-      else if (tc_edge->is_virtual) {
-        type = VIRTUAL;
-      }
 
       OLSR_INFO_NH(LOG_TC, "%-*s %-*s %-7s      %8s %8s\n",
                    ipwidth, olsr_ip_to_string(&addrbuf, &tc->addr),
                    ipwidth, olsr_ip_to_string(&dstaddrbuf,
                                               &tc_edge->T_dest_addr),
-                   type,
+                   tc_edge->is_virtual ? "virtual" : "",
                    olsr_get_linkcost_text(tc_edge->cost, false, lqbuffer1, sizeof(lqbuffer1)),
                    olsr_get_linkcost_text(tc_edge->common_cost, false, lqbuffer2, sizeof(lqbuffer2)));
 
@@ -922,41 +888,29 @@ getRelevantTcCount(void)
 void
 olsr_delete_all_tc_entries(void) {
   struct tc_entry *tc;
-  struct tc_edge_entry *edge;
-
-  if (NULL == tc_myself) return;
-
-  /* first mark all nodes non-virtual and all edges virtual */
-  tc_myself->is_virtual = false;
-  OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc_myself, edge) {
-    edge->is_virtual = 1;
-  } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc_myself, edge)
+  struct link_entry *link;
 
+  /* then remove all tc entries */
   OLSR_FOR_ALL_TC_ENTRIES(tc) {
-    tc->is_virtual = false;
-    OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, edge) {
-      edge->is_virtual = 1;
-    } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, edge)
-  }OLSR_FOR_ALL_TC_ENTRIES_END(tc)
-
-  /* erase all edges */
-  OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc_myself, edge) {
-    olsr_delete_tc_edge_entry(edge);
-  } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc_myself, edge)
+    tc->is_virtual = 0;
+  } OLSR_FOR_ALL_TC_ENTRIES_END(tc)
+
   OLSR_FOR_ALL_TC_ENTRIES(tc) {
-    OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, edge) {
-      olsr_delete_tc_edge_entry(edge);
-    } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, edge)
-  }OLSR_FOR_ALL_TC_ENTRIES_END(tc)
+    if (tc != tc_myself) {
+      olsr_delete_tc_entry(tc);
+    }
+  } OLSR_FOR_ALL_TC_ENTRIES_END(tc)
 
-  /* then remove all tc entries */
-  tc_myself->is_virtual = true;
+  /* kill all references in link_set */
+  OLSR_FOR_ALL_LINK_ENTRIES(link) {
+    link->link_tc_edge = NULL;
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(link)
+
+
+  /* kill tc_myself */
   olsr_delete_tc_entry(tc_myself);
+  olsr_unlock_tc_entry(tc_myself);
   tc_myself = NULL;
-  OLSR_FOR_ALL_TC_ENTRIES(tc) {
-    tc->is_virtual = true;
-    olsr_delete_tc_entry(tc);
-  }OLSR_FOR_ALL_TC_ENTRIES_END(tc)
 }
 
 static uint8_t
index dc61e45..b883b99 100644 (file)
@@ -64,7 +64,6 @@ struct tc_edge_entry {
   struct tc_entry *tc;                 /* backpointer to owning tc entry */
   olsr_linkcost cost;                  /* metric for tc received by this tc */
   olsr_linkcost common_cost;           /* common metric of both edges used for SPF calculation */
-  unsigned int is_local:1;             /* 1 if this is a local edge */
   unsigned int is_virtual:1;           /* 1 if this is a virtual edge created by the neighbors TC ? */
   uint16_t ansn;                       /* ansn of this edge, used for multipart msgs */
 };