[zebra] Retain configured IPv4 address upon removal by kernel

2007-04-08 Paul Jakma <paul.jakma@sun.com>

	* interface.c: (if_delete_update) Address removal triggered
	  by kernel shouldn't remove configured IPv4 address from connected
	  list.
diff --git a/zebra/interface.c b/zebra/interface.c
index ceee0e2..1c8d3a4 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -372,15 +372,10 @@
 void 
 if_delete_update (struct interface *ifp)
 {
-  struct listnode *node;
-  struct listnode *next;
-  struct listnode *first;
-  struct listnode *last;
   struct connected *ifc;
   struct prefix *p;
   struct route_node *rn;
   struct zebra_if *zebra_if;
-  struct list *addr_list;
 
   zebra_if = ifp->info;
 
@@ -401,7 +396,9 @@
   /* Delete connected routes from the kernel. */
   if (ifp->connected)
     {
-      last = NULL;
+      struct listnode *node;
+      struct listnode *last = NULL;
+
       while ((node = (last ? last->next : listhead (ifp->connected))))
 	{
 	  ifc = listgetdata (node);
@@ -410,21 +407,26 @@
 	  if (p->family == AF_INET
 	      && (rn = route_node_lookup (zebra_if->ipv4_subnets, p)))
 	    {
+	      struct listnode *anode;
+	      struct listnode *next;
+	      struct listnode *first;
+	      struct list *addr_list;
+	      
 	      route_unlock_node (rn);
 	      addr_list = (struct list *) rn->info;
 	      
 	      /* Remove addresses, secondaries first. */
 	      first = listhead (addr_list);
-	      for (node = first->next; node || first; node = next)
+	      for (anode = first->next; anode || first; anode = next)
 		{
-		  if (! node)
+		  if (!anode)
 		    {
-		      node = first;
+		      anode = first;
 		      first = NULL;
 		    }
-		  next = node->next;
+		  next = anode->next;
 
-		  ifc = listgetdata (node);
+		  ifc = listgetdata (anode);
 		  p = ifc->address;
 
 		  connected_down_ipv4 (ifp, ifc);
@@ -434,12 +436,17 @@
 		  UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
 
 		  /* Remove from subnet chain. */
-		  list_delete_node (addr_list, node);
+		  list_delete_node (addr_list, anode);
 		  route_unlock_node (rn);
 		  
 		  /* Remove from interface address list (unconditionally). */
-		  listnode_delete (ifp->connected, ifc);
-	      	  connected_free (ifc);
+		  if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
+		    {
+		      listnode_delete (ifp->connected, ifc);
+		      connected_free (ifc);
+                    }
+                  else
+                    last = node;
 		}
 
 	      /* Free chain list and respective route node. */