shill: connection: Fix FixGatewayReachability to handle P-t-P

...and add more thorough unit tests for it.

BUG=chromium-os:30052
TEST=New unit tests

Change-Id: Ic06ab2f84893e63f3b7d3f04c17f71ee4fa2d4b4
Reviewed-on: https://gerrit.chromium.org/gerrit/21202
Reviewed-by: Darin Petkov <petkov@chromium.org>
Commit-Ready: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/connection.cc b/connection.cc
index f836f2d..17c7ef2 100644
--- a/connection.cc
+++ b/connection.cc
@@ -89,16 +89,15 @@
     return;
   }
 
-  FixGatewayReachability(&local, gateway_address);
+  if (!FixGatewayReachability(&local, gateway_address, peer)) {
+    LOG(WARNING) << "Expect limited network connectivity.";
+  }
 
   rtnl_handler_->AddInterfaceAddress(interface_index_, local, broadcast, peer);
 
   if (gateway_address.IsValid()) {
     routing_table_->SetDefaultRoute(interface_index_, gateway_address,
                                     GetMetric(is_default_));
-  } else if (!peer.IsValid()) {
-    LOG(WARNING) << "No gateway or peer address was provided for this "
-                 << "connection.  Expect limited network connectivity.";
   }
 
   // Install any explicitly configured routes at the default metric.
@@ -186,10 +185,27 @@
 }
 
 // static
-void Connection::FixGatewayReachability(IPAddress *local,
-                                        const IPAddress &gateway) {
-  if (!gateway.IsValid() || local->CanReachAddress(gateway)) {
-    return;
+bool Connection::FixGatewayReachability(IPAddress *local,
+                                        const IPAddress &gateway,
+                                        const IPAddress &peer) {
+  if (!gateway.IsValid()) {
+    LOG(WARNING) << "No gateway address was provided for this connection.";
+    return false;
+  }
+
+  if (peer.IsValid()) {
+    if (gateway.Equals(peer)) {
+      return true;
+    }
+    LOG(WARNING) << "Gateway address "
+                 << gateway.ToString()
+                 << " does not match peer address "
+                 << peer.ToString();
+    return false;
+  }
+
+  if (local->CanReachAddress(gateway)) {
+    return true;
   }
 
   LOG(WARNING) << "Gateway "
@@ -209,10 +225,11 @@
   if (prefix < local->GetMinPrefixLength()) {
     // Restore the original prefix since we cannot find a better one.
     local->set_prefix(original_prefix);
-    LOG(WARNING) << "Expect limited network connectivity.";
-  } else {
-    LOG(WARNING) << "Mitigating this by setting local prefix to " << prefix;
+    return false;
   }
+
+  LOG(WARNING) << "Mitigating this by setting local prefix to " << prefix;
+  return true;
 }
 
 uint32 Connection::GetMetric(bool is_default) {