ospf6d: Fixing a couple of issues with ospf6_route_remove () routine.

When a route_node has multiple ospf6_routes under it (common subnet case),
then the current implementation has an issue in adjusting the route_node->info
on a ospf6_route_remove() call.

The main reason is that it ends up using exact match to determine if the next
ospf6_route belongs to the same route_node or not. Fixing that part to use
rnode (the existing back-pointer to the route_node) from the ospf6_route to
determine that.

Also fixing some of the walks to turn them safe so that the route deletion is
fine.

Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index bb79900..7e94cef 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -106,14 +106,14 @@
 ospf6_abr_disable_area (struct ospf6_area *area)
 {
   struct ospf6_area *oa;
-  struct ospf6_route *ro;
+  struct ospf6_route *ro, *nro;
   struct ospf6_lsa *old;
   struct listnode *node, *nnode;
 
   /* Withdraw all summary prefixes previously originated */
-  for (ro = ospf6_route_head (area->summary_prefix); ro;
-       ro = ospf6_route_next (ro))
+  for (ro = ospf6_route_head (area->summary_prefix); ro; ro = nro)
     {
+      nro = ospf6_route_next (ro);
       old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id,
                                area->ospf6->router_id, area->lsdb);
       if (old)
@@ -122,9 +122,9 @@
     }
 
   /* Withdraw all summary router-routes previously originated */
-  for (ro = ospf6_route_head (area->summary_router); ro;
-       ro = ospf6_route_next (ro))
+  for (ro = ospf6_route_head (area->summary_router); ro; ro = nro)
     {
+      nro = ospf6_route_next (ro);
       old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id,
                                area->ospf6->router_id, area->lsdb);
       if (old)
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 870ab18..617f8d6 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -240,7 +240,7 @@
 {
   struct ospf6_as_external_lsa *external;
   struct prefix prefix;
-  struct ospf6_route *route;
+  struct ospf6_route *route, *nroute;
   char buf[64];
 
   external = (struct ospf6_as_external_lsa *)
@@ -274,8 +274,9 @@
 
   for (ospf6_route_lock (route);
        route && ospf6_route_is_prefix (&prefix, route);
-       route = ospf6_route_next (route))
+       route = nroute)
     {
+      nroute = ospf6_route_next (route);
       if (route->type != OSPF6_DEST_TYPE_NETWORK)
         continue;
       if (route->path.origin.type != lsa->header->type)
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index c13865c..dbd6ad9 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -1338,7 +1338,7 @@
   struct ospf6_area *oa;
   struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
   struct prefix prefix;
-  struct ospf6_route *route;
+  struct ospf6_route *route, *nroute;
   int prefix_num;
   struct ospf6_prefix *op;
   char *start, *current, *end;
@@ -1376,8 +1376,9 @@
 
       for (ospf6_route_lock (route);
            route && ospf6_route_is_prefix (&prefix, route);
-           route = ospf6_route_next (route))
+           route = nroute)
         {
+          nroute = ospf6_route_next (route);
           if (route->type != OSPF6_DEST_TYPE_NETWORK)
             continue;
           if (route->path.area_id != oa->area_id)
@@ -1407,7 +1408,7 @@
 void
 ospf6_intra_route_calculation (struct ospf6_area *oa)
 {
-  struct ospf6_route *route;
+  struct ospf6_route *route, *nroute;
   u_int16_t type;
   struct ospf6_lsa *lsa;
   void (*hook_add) (struct ospf6_route *) = NULL;
@@ -1434,8 +1435,9 @@
   oa->route_table->hook_remove = hook_remove;
 
   for (route = ospf6_route_head (oa->route_table); route;
-       route = ospf6_route_next (route))
+       route = nroute)
     {
+      nroute = ospf6_route_next (route);
       if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) &&
           CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD))
         {
@@ -1515,7 +1517,7 @@
 void
 ospf6_intra_brouter_calculation (struct ospf6_area *oa)
 {
-  struct ospf6_route *brouter, *copy;
+  struct ospf6_route *brouter, *nbrouter, *copy;
   void (*hook_add) (struct ospf6_route *) = NULL;
   void (*hook_remove) (struct ospf6_route *) = NULL;
   u_int32_t brouter_id;
@@ -1584,8 +1586,9 @@
   oa->ospf6->brouter_table->hook_remove = hook_remove;
 
   for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter;
-       brouter = ospf6_route_next (brouter))
+       brouter = nbrouter)
     {
+      nbrouter = ospf6_route_next (brouter);
       brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
       inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
       
diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c
index 5057556..1c6495b 100644
--- a/ospf6d/ospf6_route.c
+++ b/ospf6d/ospf6_route.c
@@ -620,7 +620,7 @@
 
   if (node->info == route)
     {
-      if (route->next && ospf6_route_is_same (route->next, route))
+      if (route->next && route->next->rnode == node)
         {
           node->info = route->next;
           SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index 858398e..ab18d38 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -371,11 +371,12 @@
 void
 ospf6_spf_table_finish (struct ospf6_route_table *result_table)
 {
-  struct ospf6_route *route;
+  struct ospf6_route *route, *nroute;
   struct ospf6_vertex *v;
   for (route = ospf6_route_head (result_table); route;
-       route = ospf6_route_next (route))
+       route = nroute)
     {
+      nroute = ospf6_route_next (route);
       v = (struct ospf6_vertex *) route->route_option;
       ospf6_vertex_delete (v);
       ospf6_route_remove (route, result_table);