2005-09-12 Paul Jakma <paul.jakma@sun.com>

	* (general) RTM_CHANGE and implicit withdraw on RTM_NEWADDR
	  support.
	* connected.c: (connected_withdraw) new function. withdraw a
	  connected subnet address set from zebra, and pass information
	  along to clients.
	  (connected_announce) similar, but to announce a new connected
	  subnet address set.
	  (connected_check_ipv4) renamed to connected_check, as its
	  AFI independent.
	  (connected_add_ipv{4,6}) Remove the connected address announce
	  stuff, use connected_announce instead.
	  If connected_check indicates address is already present,
	  treat it as an implicit withdraw of the existing address, ie
	  remove the old address details and replace with the new
	  details.
	  (connected_delete_ipv{4,6}) Use connected_withdraw.
	  (connected_check_ipv6) deleted in favour of connected_check.
	* connected.h: Rename connected_check_ipv4 to connected_check.
	  delete connected_check_ipv6.
	* interface.c: Use connected_check rather than the AFI specific
	  symbols.
	* kernel_socket.c: (rtm_read) RTM_CHANGE support. Create a
	  rib delete event for the existing route, before adding route
	  again.
	  (kernel_read) we can handle RTM_CHANGE now.
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index fe7411e..f391d53 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -623,8 +623,17 @@
 	p.prefixlen = IPV4_MAX_PREFIXLEN;
       else
 	p.prefixlen = ip_masklen (mask.sin.sin_addr);
-
-      if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD)
+      
+      /* Change, delete the old prefix, we have no further information
+       * to specify the route really
+       */
+      if (rtm->rtm_type == RTM_CHANGE)
+        rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
+                         NULL, 0, 0);
+      
+      if (rtm->rtm_type == RTM_GET 
+          || rtm->rtm_type == RTM_ADD
+          || rtm->rtm_type == RTM_CHANGE)
 	rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, 
 		      &p, &gate.sin.sin_addr, 0, 0, 0, 0);
       else
@@ -652,7 +661,16 @@
 	}
 #endif /* KAME */
 
-      if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD)
+      /* CHANGE: delete the old prefix, we have no further information
+       * to specify the route really
+       */
+      if (rtm->rtm_type == RTM_CHANGE)
+        rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
+                         NULL, 0, 0);
+      
+      if (rtm->rtm_type == RTM_GET 
+          || rtm->rtm_type == RTM_ADD
+          || rtm->rtm_type == RTM_CHANGE)
 	rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
 		      &p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0);
       else
@@ -920,6 +938,7 @@
     {
     case RTM_ADD:
     case RTM_DELETE:
+    case RTM_CHANGE:
       rtm_read (rtm);
       break;
     case RTM_IFINFO: