shill: Connection: If IP Address changes, flush everything

If a new IP configuration arrives which changes the address
assigned to the family of this IPConfig, flush addresses
and routes before applying the new configuration.  Otherwise,
we end up adding the new address inclusively as a secondary
IP address and userspace programs continue to use the old
address.

BUG=chromium-os:33066
TEST=New unit tests.  Manual: Change DHCP server configuration,
unplug and replug to the same network.  The old DHCP configuration
is loaded (since the lease is still valid and the gateway is
reachable) but when the new DHCP information arrives, ensure that
the new IP address (and only that address) is configured, and the
routes are sane (i.e., both LAN interface route and default route
exist).

Change-Id: Ic746368d97c503271995ff30b6818d770f4340c5
Reviewed-on: https://gerrit.chromium.org/gerrit/29170
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Commit-Ready: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/device_info.cc b/device_info.cc
index e45e1a0..3838a15 100644
--- a/device_info.cc
+++ b/device_info.cc
@@ -606,6 +606,33 @@
   }
 }
 
+bool DeviceInfo::HasOtherAddress(
+    int interface_index, const IPAddress &this_address) const {
+  SLOG(Device, 3) << __func__ << "(" << interface_index << ")";
+  const Info *info = GetInfo(interface_index);
+  if (!info) {
+    return false;
+  }
+  const vector<AddressData> &addresses = info->ip_addresses;
+  vector<AddressData>::const_iterator iter;
+  bool has_other_address = false;
+  bool has_this_address = false;
+  for (iter = addresses.begin(); iter != addresses.end(); ++iter) {
+    if (iter->address.family() != this_address.family()) {
+      continue;
+    }
+    if (iter->address.address().Equals(this_address.address())) {
+      has_this_address = true;
+    } else if (this_address.family() == IPAddress::kFamilyIPv4) {
+      has_other_address = true;
+    } else if ((iter->scope == RT_SCOPE_UNIVERSE &&
+                (iter->flags & IFA_F_TEMPORARY) == 0)) {
+      has_other_address = true;
+    }
+  }
+  return has_other_address && !has_this_address;
+}
+
 bool DeviceInfo::GetFlags(int interface_index, unsigned int *flags) const {
   const Info *info = GetInfo(interface_index);
   if (!info) {