[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. */