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/connection_unittest.cc b/connection_unittest.cc
index 2fd5bd0..e99f55a 100644
--- a/connection_unittest.cc
+++ b/connection_unittest.cc
@@ -120,6 +120,14 @@
     return connection->has_broadcast_domain_;
   }
 
+  uint32 GetDefaultMetric() {
+      return Connection::kDefaultMetric;
+  }
+
+  uint32 GetNonDefaultMetricBase() {
+      return Connection::kNonDefaultMetricBase;
+  }
+
  protected:
   class DisconnectCallbackTarget {
    public:
@@ -188,6 +196,10 @@
 }
 
 TEST_F(ConnectionTest, AddConfig) {
+  EXPECT_CALL(*device_info_,
+              HasOtherAddress(kTestDeviceInterfaceIndex0,
+                              IsIPAddress(local_address_, kPrefix0)))
+      .WillOnce(Return(false));
   EXPECT_CALL(rtnl_handler_,
               AddInterfaceAddress(kTestDeviceInterfaceIndex0,
                                   IsIPAddress(local_address_, kPrefix0),
@@ -196,12 +208,12 @@
   EXPECT_CALL(routing_table_,
               SetDefaultRoute(kTestDeviceInterfaceIndex0,
                               IsIPAddress(gateway_address_, 0),
-                              Connection::kNonDefaultMetricBase +
+                              GetNonDefaultMetricBase() +
                               kTestDeviceInterfaceIndex0));
   EXPECT_CALL(routing_table_,
               ConfigureRoutes(kTestDeviceInterfaceIndex0,
                               ipconfig_,
-                              Connection::kDefaultMetric));
+                              GetDefaultMetric()));
   connection_->UpdateFromIPConfig(ipconfig_);
   IPAddress test_local_address(local_address_);
   test_local_address.set_prefix(kPrefix0);
@@ -221,7 +233,7 @@
   EXPECT_FALSE(connection_->CreateGatewayRoute());
 
   EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
-                                               Connection::kDefaultMetric));
+                                               GetDefaultMetric()));
   EXPECT_CALL(resolver_, SetDNSFromLists(
       ipconfig_->properties().dns_servers,
       ipconfig_->properties().domain_search));
@@ -246,7 +258,7 @@
 
   EXPECT_CALL(routing_table_,
               SetDefaultMetric(kTestDeviceInterfaceIndex0,
-                               Connection::kNonDefaultMetricBase +
+                               GetNonDefaultMetricBase() +
                                kTestDeviceInterfaceIndex0));
   EXPECT_CALL(routing_table_, FlushCache())
       .WillOnce(Return(true));
@@ -261,6 +273,10 @@
   properties_.peer_address = kPeerAddress;
   properties_.gateway = string();
   UpdateProperties();
+  EXPECT_CALL(*device_info_,
+              HasOtherAddress(kTestDeviceInterfaceIndex0,
+                              IsIPAddress(local_address_, kPrefix0)))
+      .WillOnce(Return(false));
   EXPECT_CALL(rtnl_handler_,
               AddInterfaceAddress(kTestDeviceInterfaceIndex0,
                                   IsIPAddress(local_address_, kPrefix0),
@@ -270,7 +286,7 @@
   EXPECT_CALL(routing_table_,
               ConfigureRoutes(kTestDeviceInterfaceIndex0,
                               ipconfig_,
-                              Connection::kDefaultMetric));
+                              GetDefaultMetric()));
   connection_->UpdateFromIPConfig(ipconfig_);
   EXPECT_FALSE(GetHasBroadcastDomain(connection_));
 }
@@ -282,6 +298,10 @@
 
   // Connection should override with a prefix which will allow the
   // gateway to be reachable.
+  EXPECT_CALL(*device_info_,
+              HasOtherAddress(kTestDeviceInterfaceIndex0,
+                              IsIPAddress(local_address_, kPrefix0)))
+      .WillOnce(Return(false));
   EXPECT_CALL(rtnl_handler_,
               AddInterfaceAddress(kTestDeviceInterfaceIndex0,
                                   IsIPAddress(local_address_, kPrefix0),
@@ -290,12 +310,12 @@
   EXPECT_CALL(routing_table_,
               SetDefaultRoute(kTestDeviceInterfaceIndex0,
                               IsIPAddress(gateway_address_, 0),
-                              Connection::kNonDefaultMetricBase +
+                              GetNonDefaultMetricBase() +
                               kTestDeviceInterfaceIndex0));
   EXPECT_CALL(routing_table_,
               ConfigureRoutes(kTestDeviceInterfaceIndex0,
                               ipconfig_,
-                              Connection::kDefaultMetric));
+                              GetDefaultMetric()));
   connection_->UpdateFromIPConfig(ipconfig_);
 
   // Assign a gateway address that violates the minimum plausible prefix
@@ -308,6 +328,10 @@
   // Connection cannot override this prefix, so it will switch to a
   // model where the peer address is set to the value of the gateway
   // address.
+  EXPECT_CALL(*device_info_,
+              HasOtherAddress(kTestDeviceInterfaceIndex0,
+                              IsIPAddress(local_address_, kPrefix1)))
+      .WillOnce(Return(false));
   EXPECT_CALL(rtnl_handler_,
               AddInterfaceAddress(kTestDeviceInterfaceIndex0,
                                   IsIPAddress(local_address_, kPrefix1),
@@ -322,7 +346,7 @@
 
 TEST_F(ConnectionTest, AddConfigReverse) {
   EXPECT_CALL(routing_table_, SetDefaultMetric(kTestDeviceInterfaceIndex0,
-                                               Connection::kDefaultMetric));
+                                               GetDefaultMetric()));
   vector<string> empty_list;
   EXPECT_CALL(resolver_, SetDNSFromLists(empty_list, empty_list));
   scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
@@ -342,6 +366,10 @@
   connection_->SetIsDefault(true);
   Mock::VerifyAndClearExpectations(&routing_table_);
 
+  EXPECT_CALL(*device_info_,
+              HasOtherAddress(kTestDeviceInterfaceIndex0,
+                              IsIPAddress(local_address_, kPrefix0)))
+      .WillOnce(Return(false));
   EXPECT_CALL(rtnl_handler_,
               AddInterfaceAddress(kTestDeviceInterfaceIndex0,
                                   IsIPAddress(local_address_, kPrefix0),
@@ -349,16 +377,40 @@
                                   IsIPAddress(default_address_, 0)));
   EXPECT_CALL(routing_table_, SetDefaultRoute(kTestDeviceInterfaceIndex0,
                                               IsIPAddress(gateway_address_, 0),
-                                              Connection::kDefaultMetric));
+                                              GetDefaultMetric()));
   EXPECT_CALL(routing_table_,
               ConfigureRoutes(kTestDeviceInterfaceIndex0,
                               ipconfig_,
-                              Connection::kDefaultMetric));
+                              GetDefaultMetric()));
   EXPECT_CALL(resolver_, SetDNSFromIPConfig(ipconfig_));
 
   connection_->UpdateFromIPConfig(ipconfig_);
 }
 
+TEST_F(ConnectionTest, HasOtherAddress) {
+  EXPECT_CALL(*device_info_,
+              HasOtherAddress(kTestDeviceInterfaceIndex0,
+                              IsIPAddress(local_address_, kPrefix0)))
+      .WillOnce(Return(true));
+  EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceInterfaceIndex0));
+  EXPECT_CALL(*device_info_, FlushAddresses(kTestDeviceInterfaceIndex0));
+  EXPECT_CALL(rtnl_handler_,
+              AddInterfaceAddress(kTestDeviceInterfaceIndex0,
+                                  IsIPAddress(local_address_, kPrefix0),
+                                  IsIPAddress(broadcast_address_, 0),
+                                  IsIPAddress(default_address_, 0)));
+  EXPECT_CALL(routing_table_,
+              SetDefaultRoute(kTestDeviceInterfaceIndex0,
+                              IsIPAddress(gateway_address_, 0),
+                              GetNonDefaultMetricBase() +
+                              kTestDeviceInterfaceIndex0));
+  EXPECT_CALL(routing_table_,
+              ConfigureRoutes(kTestDeviceInterfaceIndex0,
+                              ipconfig_,
+                              GetDefaultMetric()));
+  connection_->UpdateFromIPConfig(ipconfig_);
+}
+
 TEST_F(ConnectionTest, RouteRequest) {
   ConnectionRefPtr connection = GetNewConnection();
   scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(