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/connection.cc b/connection.cc
index 3a7e4c3..f3a2e6d 100644
--- a/connection.cc
+++ b/connection.cc
@@ -66,10 +66,13 @@
const DeviceInfo *device_info)
: weak_ptr_factory_(this),
is_default_(false),
+ has_broadcast_domain_(false),
routing_request_count_(0),
interface_index_(interface_index),
interface_name_(interface_name),
technology_(technology),
+ local_(IPAddress::kFamilyUnknown),
+ gateway_(IPAddress::kFamilyUnknown),
lower_binder_(
interface_name_,
// Connection owns a single instance of |lower_binder_| so it's safe
@@ -169,6 +172,10 @@
if (is_default_) {
resolver_->SetDNSFromIPConfig(config);
}
+
+ local_ = local;
+ gateway_ = gateway;
+ has_broadcast_domain_ = !peer.IsValid();
}
void Connection::SetIsDefault(bool is_default) {
@@ -347,6 +354,21 @@
return;
}
lower_binder_.Attach(connection);
+ connection->CreateGatewayRoute();
+}
+
+bool Connection::CreateGatewayRoute() {
+ // Ensure that the gateway for the lower connection remains reachable,
+ // since we may create routes that conflict with it.
+ if (!has_broadcast_domain_) {
+ return false;
+ }
+ // It is not worth keeping track of this route, since it is benign,
+ // and only pins persistent state that was already true of the connection.
+ // If DHCP parameters change later (without the connection having been
+ // destroyed and recreated), the binding processes will likely terminate
+ // and restart, causing a new link route to be created.
+ return routing_table_->CreateLinkRoute(interface_index_, local_, gateway_);
}
void Connection::OnLowerDisconnect() {