summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Cernekee <cernekee@google.com>2016-01-23 19:46:05 -0800
committerKevin Cernekee <cernekee@google.com>2016-01-26 23:43:06 +0000
commitc1962fbd63fd48083528bc03cfa4e6045bfc9153 (patch)
tree35718c5168653028bbeca2624aa00b66c4b35056
parent9a3fbf6be2e73c698a2bee3b7c1a0f389bec775a (diff)
downloadshill-c1962fbd63fd48083528bc03cfa4e6045bfc9153.tar.gz
shill: Disconnect current VPN if the user tries to connect to another VPN
Currently this crashes shill if both providers are third party VPNs. We'll enforce a restriction at the shill layer because it isn't clear whether routing will be handled correctly if one connection disappears from the middle of a "stack" of VPNs. BUG: chromium:512509 TEST=manual Change-Id: I7de4bc8cd7e641e9b57bc005589c865b39ed242e
-rw-r--r--vpn/vpn_provider.cc8
-rw-r--r--vpn/vpn_provider.h3
-rw-r--r--vpn/vpn_service.cc1
3 files changed, 12 insertions, 0 deletions
diff --git a/vpn/vpn_provider.cc b/vpn/vpn_provider.cc
index 1cf4d6a6..b9965b61 100644
--- a/vpn/vpn_provider.cc
+++ b/vpn/vpn_provider.cc
@@ -346,4 +346,12 @@ bool VPNProvider::HasActiveService() const {
return false;
}
+void VPNProvider::DisconnectAll() {
+ for (const auto& service : services_) {
+ if (service->IsConnecting() || service->IsConnected()) {
+ service->Disconnect(nullptr, "user selected new config");
+ }
+ }
+}
+
} // namespace shill
diff --git a/vpn/vpn_provider.h b/vpn/vpn_provider.h
index aab3c49e..08c8923f 100644
--- a/vpn/vpn_provider.h
+++ b/vpn/vpn_provider.h
@@ -73,6 +73,9 @@ class VPNProvider : public ProviderInterface {
// Returns true if any of the managed VPN services is connecting or connected.
virtual bool HasActiveService() const;
+ // Disconnect any other active VPN services.
+ virtual void DisconnectAll();
+
private:
friend class VPNProviderTest;
FRIEND_TEST(VPNProviderTest, CreateService);
diff --git a/vpn/vpn_service.cc b/vpn/vpn_service.cc
index 7e8f71ec..1d7d12dc 100644
--- a/vpn/vpn_service.cc
+++ b/vpn/vpn_service.cc
@@ -84,6 +84,7 @@ void VPNService::Connect(Error* error, const char* reason) {
unique_name().c_str()));
return;
}
+ manager()->vpn_provider()->DisconnectAll();
Service::Connect(error, reason);
driver_->Connect(this, error);
}