1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2014 The Android Open Source Project 3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License"); 5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License. 6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at 7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// http://www.apache.org/licenses/LICENSE-2.0 9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software 11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS, 12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and 14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License. 15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 16127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 172240e8c03451c6b6f21eb8944d8a1c0747ac10b3Ben Chan#include "shill/vpn/third_party_vpn_driver.h" 18127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 191f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi#include <algorithm> 201f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi 21127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include <fcntl.h> 22127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include <unistd.h> 23127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 24127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include <base/posix/eintr_wrapper.h> 25127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include <base/strings/string_number_conversions.h> 26127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include <base/strings/string_split.h> 27289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#if defined(__ANDROID__) 28289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#include <dbus/service_constants.h> 29289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#else 30127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include <chromeos/dbus/service_constants.h> 31289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#endif // __ANDROID__ 32127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 33127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include "shill/connection.h" 34127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include "shill/control_interface.h" 35127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include "shill/device_info.h" 36127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include "shill/error.h" 37127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include "shill/file_io.h" 38024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart#include "shill/ipconfig.h" 39127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include "shill/logging.h" 40127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include "shill/manager.h" 41127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include "shill/property_accessor.h" 42127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include "shill/store_interface.h" 43127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi#include "shill/virtual_device.h" 442240e8c03451c6b6f21eb8944d8a1c0747ac10b3Ben Chan#include "shill/vpn/vpn_service.h" 45127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 46127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthinamespace shill { 47127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 48127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthinamespace Logging { 49127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 50127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthistatic auto kModuleLogScope = ScopeLogger::kVPN; 51e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewartstatic std::string ObjectID(const ThirdPartyVpnDriver* v) { 52127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return "(third_party_vpn_driver)"; 53127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 54127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 55127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} // namespace Logging 56127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 57127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthinamespace { 58127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 59127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthiconst int32_t kConstantMaxMtu = (1 << 16) - 1; 606349d151d2e4e78cccd17dd1bcef2ad5b9755e64Prabhu Kaliamoorthiconst int32_t kConnectTimeoutSeconds = 60*5; 61127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 62e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewartstd::string IPAddressFingerprint(const IPAddress& address) { 63762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi static const std::string hex_to_bin[] = { 64762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", 65762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"}; 66762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi std::string fingerprint; 67762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi const size_t address_length = address.address().GetLength(); 68e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart const uint8_t* raw_address = address.address().GetConstData(); 69762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi for (size_t i = 0; i < address_length; ++i) { 70762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi fingerprint += hex_to_bin[raw_address[i] >> 4]; 71762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi fingerprint += hex_to_bin[raw_address[i] & 0xf]; 72762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi } 73762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi return fingerprint.substr(0, address.prefix()); 74762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi} 75762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi 76127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} // namespace 77127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 78127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthiconst VPNDriver::Property ThirdPartyVpnDriver::kProperties[] = { 79127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi { kProviderHostProperty, 0 }, 80552d2dfbf38c5e8a3bcf37a07ac06c487b2b7e7ePrabhu Kaliamoorthi { kProviderTypeProperty, 0 }, 81552d2dfbf38c5e8a3bcf37a07ac06c487b2b7e7ePrabhu Kaliamoorthi { kExtensionNameProperty, 0 }, 82552d2dfbf38c5e8a3bcf37a07ac06c487b2b7e7ePrabhu Kaliamoorthi { kConfigurationNameProperty, 0 } 83127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi}; 84127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 85e42d186ab3383b4a6bb267f490770af5932588b8Paul StewartThirdPartyVpnDriver* ThirdPartyVpnDriver::active_client_ = nullptr; 86127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 87e42d186ab3383b4a6bb267f490770af5932588b8Paul StewartThirdPartyVpnDriver::ThirdPartyVpnDriver(ControlInterface* control, 88e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart EventDispatcher* dispatcher, 89e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart Metrics* metrics, Manager* manager, 90e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart DeviceInfo* device_info) 91127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi : VPNDriver(dispatcher, manager, kProperties, arraysize(kProperties)), 92127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi control_(control), 93127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi dispatcher_(dispatcher), 94127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi metrics_(metrics), 95127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi device_info_(device_info), 96127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi tun_fd_(-1), 97127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi parameters_expected_(false) { 98127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi file_io_ = FileIO::GetInstance(); 99127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 100127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 101127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu KaliamoorthiThirdPartyVpnDriver::~ThirdPartyVpnDriver() { 102127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi Cleanup(Service::kStateIdle, Service::kFailureUnknown, 103127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi Service::kErrorDetailsNone); 104127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 105127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 106e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewartvoid ThirdPartyVpnDriver::InitPropertyStore(PropertyStore* store) { 107127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi VPNDriver::InitPropertyStore(store); 108127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi store->RegisterDerivedString( 109f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthi kObjectPathSuffixProperty, 110127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi StringAccessor( 111127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi new CustomWriteOnlyAccessor<ThirdPartyVpnDriver, std::string>( 112127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi this, &ThirdPartyVpnDriver::SetExtensionId, 113127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi &ThirdPartyVpnDriver::ClearExtensionId, nullptr))); 114127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 115127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 116e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewartbool ThirdPartyVpnDriver::Load(StoreInterface* storage, 117e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart const std::string& storage_id) { 118127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi bool return_value = VPNDriver::Load(storage, storage_id); 119127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (adaptor_interface_ == nullptr) { 120f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthi storage->GetString(storage_id, kObjectPathSuffixProperty, 121f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthi &object_path_suffix_); 122127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi adaptor_interface_.reset(control_->CreateThirdPartyVpnAdaptor(this)); 123127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 124127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return return_value; 125127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 126127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 127e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewartbool ThirdPartyVpnDriver::Save(StoreInterface* storage, 128e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart const std::string& storage_id, 129127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi bool save_credentials) { 130127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi bool return_value = VPNDriver::Save(storage, storage_id, save_credentials); 131f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthi storage->SetString(storage_id, kObjectPathSuffixProperty, 132f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthi object_path_suffix_); 133127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return return_value; 134127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 135127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 136e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewartvoid ThirdPartyVpnDriver::ClearExtensionId(Error* error) { 137127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error->Populate(Error::kNotSupported, 138127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi "Clearing extension id is not supported."); 139127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 140127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 141e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewartbool ThirdPartyVpnDriver::SetExtensionId(const std::string& value, 142e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart Error* error) { 143127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (adaptor_interface_ == nullptr) { 144f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthi object_path_suffix_ = value; 145127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi adaptor_interface_.reset(control_->CreateThirdPartyVpnAdaptor(this)); 146127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return true; 147127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 148127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error->Populate(Error::kAlreadyExists, "Extension ID is set"); 149127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return false; 150127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 151127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 152127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthivoid ThirdPartyVpnDriver::UpdateConnectionState( 153e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart Service::ConnectState connection_state, std::string* error_message) { 154127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (active_client_ != this) { 155127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append("Unexpected call"); 156127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return; 157127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 158a63da1dc556b1ec9a5b3676a75665ad1a5fda0bcBin Jin if (service_ && connection_state == Service::kStateFailure) { 159127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi service_->SetState(connection_state); 160a63da1dc556b1ec9a5b3676a75665ad1a5fda0bcBin Jin Cleanup(Service::kStateFailure, Service::kFailureUnknown, 161a63da1dc556b1ec9a5b3676a75665ad1a5fda0bcBin Jin Service::kErrorDetailsNone); 162a63da1dc556b1ec9a5b3676a75665ad1a5fda0bcBin Jin } else if (!service_ || connection_state != Service::kStateOnline) { 163a63da1dc556b1ec9a5b3676a75665ad1a5fda0bcBin Jin // We expect "failure" and "connected" messages from the client, but we 164a63da1dc556b1ec9a5b3676a75665ad1a5fda0bcBin Jin // only set state for these "failure" messages. "connected" message (which 165a63da1dc556b1ec9a5b3676a75665ad1a5fda0bcBin Jin // is corresponding to kStateOnline here) will simply be ignored. 166127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append("Invalid argument"); 167127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 168127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 169127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 170e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewartvoid ThirdPartyVpnDriver::SendPacket(const std::vector<uint8_t>& ip_packet, 171e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart std::string* error_message) { 172127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (active_client_ != this) { 173127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append("Unexpected call"); 174127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return; 175127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } else if (tun_fd_ < 0) { 176127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append("Device not open"); 177127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return; 178127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } else if (file_io_->Write(tun_fd_, ip_packet.data(), ip_packet.size()) != 179127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi static_cast<ssize_t>(ip_packet.size())) { 180127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append("Partial write"); 181127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi adaptor_interface_->EmitPlatformMessage( 182127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi static_cast<uint32_t>(PlatformMessage::kError)); 183127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 184127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 185127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 186127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthivoid ThirdPartyVpnDriver::ProcessIp( 187e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart const std::map<std::string, std::string>& parameters, const char* key, 188e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart std::string* target, bool mandatory, std::string* error_message) { 189127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi // TODO(kaliamoorthi): Add IPV6 support. 190127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi auto it = parameters.find(key); 191127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (it != parameters.end()) { 192127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (IPAddress(parameters.at(key)).family() == IPAddress::kFamilyIPv4) { 193127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi *target = parameters.at(key); 194127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } else { 195127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append(key).append(" is not a valid IP;"); 196127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 197127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } else if (mandatory) { 198127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append(key).append(" is missing;"); 199127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 200127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 201127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 202f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthivoid ThirdPartyVpnDriver::ProcessIPArray( 203e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart const std::map<std::string, std::string>& parameters, const char* key, 204e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart char delimiter, std::vector<std::string>* target, bool mandatory, 205e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart std::string* error_message, std::string* warning_message) { 206127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi std::vector<std::string> string_array; 207127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi auto it = parameters.find(key); 208127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (it != parameters.end()) { 2093a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko string_array = base::SplitString( 21067c6ddfc8ce0d32b3869c37c29cb0320c1b04cbdAlex Vakulenko parameters.at(key), std::string{delimiter}, base::TRIM_WHITESPACE, 2113a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko base::SPLIT_WANT_ALL); 212127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 213127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi // Eliminate invalid IPs 214127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi for (auto value = string_array.begin(); value != string_array.end();) { 215127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (IPAddress(*value).family() != IPAddress::kFamilyIPv4) { 216762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi warning_message->append(*value + " for " + key + " is invalid;"); 217762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi value = string_array.erase(value); 218762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi } else { 219762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi ++value; 220762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi } 221762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi } 222762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi 223762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi if (!string_array.empty()) { 224762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi target->swap(string_array); 225762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi } else { 226762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi error_message->append(key).append(" has no valid values or is empty;"); 227762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi } 228762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi } else if (mandatory) { 229762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi error_message->append(key).append(" is missing;"); 230762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi } 231762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi} 232762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi 233762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthivoid ThirdPartyVpnDriver::ProcessIPArrayCIDR( 234e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart const std::map<std::string, std::string>& parameters, const char* key, 235e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart char delimiter, std::vector<std::string>* target, bool mandatory, 236e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart std::string* error_message, std::string* warning_message) { 237762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi std::vector<std::string> string_array; 238762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi IPAddress address(IPAddress::kFamilyIPv4); 239762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi auto it = parameters.find(key); 240762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi if (it != parameters.end()) { 2413a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko string_array = base::SplitString( 24267c6ddfc8ce0d32b3869c37c29cb0320c1b04cbdAlex Vakulenko parameters.at(key), std::string{delimiter}, base::TRIM_WHITESPACE, 2433a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko base::SPLIT_WANT_ALL); 244762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi 245762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // Eliminate invalid IPs 246762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi for (auto value = string_array.begin(); value != string_array.end();) { 247762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi if (!address.SetAddressAndPrefixFromString(*value)) { 248762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi warning_message->append(*value + " for " + key + " is invalid;"); 249762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi value = string_array.erase(value); 250762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi continue; 251762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi } 252762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi const std::string cidr_key = IPAddressFingerprint(address); 253762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi if (known_cidrs_.find(cidr_key) != known_cidrs_.end()) { 254762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi warning_message->append("Duplicate entry for " + *value + " in " + key + 255762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi " found;"); 256127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi value = string_array.erase(value); 257127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } else { 258762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi known_cidrs_.insert(cidr_key); 259127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi ++value; 260127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 261127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 262127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 263127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (!string_array.empty()) { 264127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi target->swap(string_array); 265127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } else { 266127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append(key).append(" has no valid values or is empty;"); 267127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 268127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } else if (mandatory) { 269127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append(key).append(" is missing;"); 270127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 271127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 272127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 273127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthivoid ThirdPartyVpnDriver::ProcessSearchDomainArray( 274e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart const std::map<std::string, std::string>& parameters, const char* key, 275e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart char delimiter, std::vector<std::string>* target, bool mandatory, 276e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart std::string* error_message) { 277127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi std::vector<std::string> string_array; 278127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi auto it = parameters.find(key); 279127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (it != parameters.end()) { 2803a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko string_array = base::SplitString( 28167c6ddfc8ce0d32b3869c37c29cb0320c1b04cbdAlex Vakulenko parameters.at(key), std::string{delimiter}, base::TRIM_WHITESPACE, 2823a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko base::SPLIT_WANT_ALL); 283127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 284127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (!string_array.empty()) { 285127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi target->swap(string_array); 286127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } else { 287127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append(key).append(" has no valid values or is empty;"); 288127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 289127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } else if (mandatory) { 290127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append(key).append(" is missing;"); 291127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 292127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 293127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 294127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthivoid ThirdPartyVpnDriver::ProcessInt32( 295e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart const std::map<std::string, std::string>& parameters, const char* key, 296e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart int32_t* target, int32_t min_value, int32_t max_value, bool mandatory, 297e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart std::string* error_message) { 298127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi int32_t value = 0; 299127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi auto it = parameters.find(key); 300127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (it != parameters.end()) { 301127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (base::StringToInt(parameters.at(key), &value) && value >= min_value && 302127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi value <= max_value) { 303127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi *target = value; 304127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } else { 305127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append(key).append(" not in expected range;"); 306127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 307127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } else if (mandatory) { 308127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append(key).append(" is missing;"); 309127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 310127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 311127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 312127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthivoid ThirdPartyVpnDriver::SetParameters( 313e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart const std::map<std::string, std::string>& parameters, 314e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart std::string* error_message, std::string* warning_message) { 315127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi // TODO(kaliamoorthi): Add IPV6 support. 316127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (!parameters_expected_ || active_client_ != this) { 317127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi error_message->append("Unexpected call"); 318127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return; 319127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 320127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 321762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi ip_properties_ = IPConfig::Properties(); 322f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthi ip_properties_.address_family = IPAddress::kFamilyIPv4; 323f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthi 324e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi ProcessIp(parameters, kAddressParameterThirdPartyVpn, &ip_properties_.address, 325e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi true, error_message); 326e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi ProcessIp(parameters, kBroadcastAddressParameterThirdPartyVpn, 327e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi &ip_properties_.broadcast_address, false, error_message); 328127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 329762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi ip_properties_.gateway = ip_properties_.address; 330762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi 331e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi ProcessInt32(parameters, kSubnetPrefixParameterThirdPartyVpn, 332e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi &ip_properties_.subnet_prefix, 0, 32, true, error_message); 333e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi ProcessInt32(parameters, kMtuParameterThirdPartyVpn, &ip_properties_.mtu, 334e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi IPConfig::kMinIPv4MTU, kConstantMaxMtu, false, error_message); 335127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 336e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi ProcessSearchDomainArray(parameters, kDomainSearchParameterThirdPartyVpn, 337e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi kNonIPDelimiter, &ip_properties_.domain_search, 338e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi false, error_message); 339e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi ProcessIPArray(parameters, kDnsServersParameterThirdPartyVpn, kIPDelimiter, 340762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi &ip_properties_.dns_servers, true, error_message, 341762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi warning_message); 342f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthi 343762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi known_cidrs_.clear(); 344762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi 345e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi ProcessIPArrayCIDR(parameters, kExclusionListParameterThirdPartyVpn, 346e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi kIPDelimiter, &ip_properties_.exclusion_list, true, 347e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi error_message, warning_message); 3481f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi if (!ip_properties_.exclusion_list.empty()) { 3491f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi // The first excluded IP is used to find the default gateway. The logic that 3501f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi // finds the default gateway does not work for default route "0.0.0.0/0". 3511f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi // Hence, this code ensures that the first IP is not default. 3521f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi IPAddress address(ip_properties_.address_family); 3531f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi address.SetAddressAndPrefixFromString(ip_properties_.exclusion_list[0]); 3541f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi if (address.IsDefault() && !address.prefix()) { 3551f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi if (ip_properties_.exclusion_list.size() > 1) { 3561f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi swap(ip_properties_.exclusion_list[0], 3571f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi ip_properties_.exclusion_list[1]); 3581f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi } else { 3591f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi // When there is only a single entry which is a default address, it can 3601f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi // be cleared since the default behavior is to not route any traffic to 3611f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi // the tunnel interface. 3621f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi ip_properties_.exclusion_list.clear(); 3631f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi } 3641f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi } 3651f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi } 366762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi 367762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi std::vector<std::string> inclusion_list; 368e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi ProcessIPArrayCIDR(parameters, kInclusionListParameterThirdPartyVpn, 369e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi kIPDelimiter, &inclusion_list, true, error_message, 370e0e205bf5e625398d02be89bda076ea9fd761896Prabhu Kaliamoorthi warning_message); 371762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi 372762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi IPAddress ip_address(ip_properties_.address_family); 373762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi IPConfig::Route route; 374762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi route.gateway = ip_properties_.gateway; 375762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi for (auto value = inclusion_list.begin(); value != inclusion_list.end(); 376762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi ++value) { 377762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi ip_address.SetAddressAndPrefixFromString(*value); 378762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi ip_address.IntoString(&route.host); 379762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi IPAddress::GetAddressMaskFromPrefix( 380762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi ip_address.family(), ip_address.prefix()).IntoString(&route.netmask); 381762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi ip_properties_.routes.push_back(route); 382f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthi } 383127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 384127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (error_message->empty()) { 385762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi ip_properties_.user_traffic_only = true; 3861f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi ip_properties_.default_route = false; 3879a3fbf6be2e73c698a2bee3b7c1a0f389bec775aKevin Cernekee ip_properties_.blackhole_ipv6 = true; 388f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthi device_->SelectService(service_); 389127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi device_->UpdateIPConfig(ip_properties_); 390762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi device_->SetLooseRouting(true); 391127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi StopConnectTimeout(); 392127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi parameters_expected_ = false; 393127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 394127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 395127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 396e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewartvoid ThirdPartyVpnDriver::OnInput(InputData* data) { 397127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi // TODO(kaliamoorthi): This is not efficient, transfer the descriptor over to 398127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi // chrome browser or use a pipe in between. Avoid using DBUS for packet 399127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi // transfer. 400127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi std::vector<uint8_t> ip_packet(data->buf, data->buf + data->len); 401127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi adaptor_interface_->EmitPacketReceived(ip_packet); 402127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 403127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 404e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewartvoid ThirdPartyVpnDriver::OnInputError(const std::string& error) { 405127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi LOG(ERROR) << error; 406127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi CHECK_EQ(active_client_, this); 407127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi adaptor_interface_->EmitPlatformMessage( 408127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi static_cast<uint32_t>(PlatformMessage::kError)); 409127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 410127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 411127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthivoid ThirdPartyVpnDriver::Cleanup(Service::ConnectState state, 412127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi Service::ConnectFailure failure, 413e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart const std::string& error_details) { 414127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi SLOG(this, 2) << __func__ << "(" << Service::ConnectStateToString(state) 415762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi << ", " << error_details << ")"; 416127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi StopConnectTimeout(); 417127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi int interface_index = -1; 418127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (device_) { 419127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi interface_index = device_->interface_index(); 420127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi device_->DropConnection(); 421127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi device_->SetEnabled(false); 422127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi device_ = nullptr; 423127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 424127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (interface_index >= 0) { 425127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi device_info_->DeleteInterface(interface_index); 426127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 427127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi tunnel_interface_.clear(); 428127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (service_) { 429127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (state == Service::kStateFailure) { 430127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi service_->SetErrorDetails(error_details); 431127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi service_->SetFailure(failure); 432127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } else { 433127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi service_->SetState(state); 434127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 435127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi service_ = nullptr; 436127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 437127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (tun_fd_ > 0) { 438127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi file_io_->Close(tun_fd_); 439127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi tun_fd_ = -1; 440127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 441127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi io_handler_.reset(); 442127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (active_client_ == this) { 443127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi adaptor_interface_->EmitPlatformMessage( 444127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi static_cast<uint32_t>(PlatformMessage::kDisconnected)); 445127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi active_client_ = nullptr; 446127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 447127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi parameters_expected_ = false; 448127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 449127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 450e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewartvoid ThirdPartyVpnDriver::Connect(const VPNServiceRefPtr& service, 451e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewart Error* error) { 452127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi SLOG(this, 2) << __func__; 453127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi CHECK(adaptor_interface_); 454127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi CHECK(!active_client_); 4556349d151d2e4e78cccd17dd1bcef2ad5b9755e64Prabhu Kaliamoorthi StartConnectTimeout(kConnectTimeoutSeconds); 456127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi ip_properties_ = IPConfig::Properties(); 457127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi service_ = service; 458127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi service_->SetState(Service::kStateConfiguring); 459127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (!device_info_->CreateTunnelInterface(&tunnel_interface_)) { 46034f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError, 461127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi "Could not create tunnel interface."); 462127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi Cleanup(Service::kStateFailure, Service::kFailureInternal, 463127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi "Unable to create tun interface"); 464127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 465127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi // Wait for the ClaimInterface callback to continue the connection process. 466127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 467127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 468e42d186ab3383b4a6bb267f490770af5932588b8Paul Stewartbool ThirdPartyVpnDriver::ClaimInterface(const std::string& link_name, 469127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi int interface_index) { 470127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (link_name != tunnel_interface_) { 471127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return false; 472127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 473127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi CHECK(!active_client_); 474127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 475440828614ed1529b839e58457ef0002794e499ecKevin Cernekee SLOG(this, 2) << "Claiming " << link_name << " for third party VPN tunnel"; 476127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 477127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi CHECK(!device_); 478127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi device_ = new VirtualDevice(control_, dispatcher(), metrics_, manager(), 479127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi link_name, interface_index, Technology::kVPN); 480127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi device_->SetEnabled(true); 481127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 482127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi tun_fd_ = device_info_->OpenTunnelInterface(tunnel_interface_); 483127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (tun_fd_ < 0) { 484127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi Cleanup(Service::kStateFailure, Service::kFailureInternal, 485127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi "Unable to open tun interface"); 486127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } else { 487127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi io_handler_.reset(dispatcher_->CreateInputHandler( 488127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi tun_fd_, 489127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi base::Bind(&ThirdPartyVpnDriver::OnInput, base::Unretained(this)), 490127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi base::Bind(&ThirdPartyVpnDriver::OnInputError, 491127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi base::Unretained(this)))); 492127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi active_client_ = this; 493127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi parameters_expected_ = true; 494127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi adaptor_interface_->EmitPlatformMessage( 495127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi static_cast<uint32_t>(PlatformMessage::kConnected)); 496127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 497127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return true; 498127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 499127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 500127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthivoid ThirdPartyVpnDriver::Disconnect() { 501127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi SLOG(this, 2) << __func__; 502127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi CHECK(adaptor_interface_); 503127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (active_client_ == this) { 504127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi Cleanup(Service::kStateIdle, Service::kFailureUnknown, 505127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi Service::kErrorDetailsNone); 506127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 507127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 508127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 509127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthistd::string ThirdPartyVpnDriver::GetProviderType() const { 510127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return std::string(kProviderThirdPartyVpn); 511127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 512127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 513127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthivoid ThirdPartyVpnDriver::OnConnectionDisconnected() { 514f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthi Cleanup(Service::kStateFailure, Service::kFailureInternal, 515f2fe7f001ed2a761341aa8098b5b58ea65a51311Prabhu Kaliamoorthi "Underlying network disconnected."); 516127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 517127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 518127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthivoid ThirdPartyVpnDriver::OnConnectTimeout() { 519127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi SLOG(this, 2) << __func__; 520127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi VPNDriver::OnConnectTimeout(); 52178097469a1cd40b5b1874be4c977d4eb4d51e97fMaksim Ivanov adaptor_interface_->EmitPlatformMessage( 52278097469a1cd40b5b1874be4c977d4eb4d51e97fMaksim Ivanov static_cast<uint32_t>(PlatformMessage::kError)); 523127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi Cleanup(Service::kStateFailure, Service::kFailureConnect, 524127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi "Connection timed out"); 525127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 526127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 527127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} // namespace shill 528