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