shill: Connection: Create a link route if we are bound

Due to the behavior of some VPN servers, we may lose our route
to the default gateway of a physical interface due to the routes
assigned by a virtual interfaces.  To avert this, set a host route
for the default gateway as we bind a lower connection.

BUG=chromium-os:32643
TEST=New unit tests; tried on a known-misbehaving net (actually
working from there right now); VPN autotests

Change-Id: I68db1da339f61c415f9ba8c2c26d8cdb0276b209
Reviewed-on: https://gerrit.chromium.org/gerrit/27705
Commit-Ready: Paul Stewart <pstew@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/routing_table.cc b/routing_table.cc
index 1b3f6db..7a3b002 100644
--- a/routing_table.cc
+++ b/routing_table.cc
@@ -533,4 +533,31 @@
   return true;
 }
 
+bool RoutingTable::CreateLinkRoute(int interface_index,
+                                   const IPAddress &local_address,
+                                   const IPAddress &remote_address) {
+  if (!local_address.CanReachAddress(remote_address)) {
+    LOG(ERROR) << __func__ << " failed: "
+               << remote_address.ToString() << " is not reachable from "
+               << local_address.ToString();
+    return false;
+  }
+
+  IPAddress default_address(local_address.family());
+  default_address.SetAddressToDefault();
+  IPAddress destination_address(remote_address);
+  destination_address.set_prefix(
+      IPAddress::GetMaxPrefixLength(remote_address.family()));
+  SLOG(Route, 2) << "Creating link route to " << destination_address.ToString()
+                 << " from " << local_address.ToString()
+                 << " on interface index " << interface_index;
+  return AddRoute(interface_index,
+                  RoutingTableEntry(destination_address,
+                                    local_address,
+                                    default_address,
+                                    0,
+                                    RT_SCOPE_LINK,
+                                    false));
+}
+
 }  // namespace shill