1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2012 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// 16dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 17dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart#include "shill/connection.h" 18dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 199a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart#include <arpa/inet.h> 209a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart#include <linux/rtnetlink.h> 219a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 228a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko#include <set> 238a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko 242cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart#include <base/strings/stringprintf.h> 252cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart 26608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu#include "shill/control_interface.h" 279a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart#include "shill/device_info.h" 28a330ecd23b1ce4112fd7a28f4b2a062b8df10735Peter Qiu#include "shill/firewall_proxy_interface.h" 29b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley#include "shill/logging.h" 308d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/rtnl_handler.h" 31dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart#include "shill/routing_table.h" 32dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 33d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#if !defined(__ANDROID__) 34d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#include "shill/resolver.h" 35d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#else 36d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#include "shill/dns_server_proxy.h" 379429723aad30865ab4604a6074dece9c6d45c0ccPeter Qiu#include "shill/dns_server_proxy_factory.h" 38d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#endif // __ANDROID__ 39d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu 4013e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkovusing base::Bind; 4113e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkovusing base::Closure; 4213e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkovusing base::Unretained; 4313e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkovusing std::deque; 44fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymousing std::set; 45dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewartusing std::string; 46d62d6035f45ab5caf04a558a70fbc78457775f97Paul Stewartusing std::vector; 47dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 48dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewartnamespace shill { 49dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 50c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinnamespace Logging { 51c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinstatic auto kModuleLogScope = ScopeLogger::kConnection; 52a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartstatic string ObjectID(Connection* c) { 5355d9550e72197a203efbe06087edc2424676d886Paul Stewart if (c == nullptr) 5455d9550e72197a203efbe06087edc2424676d886Paul Stewart return "(connection)"; 55c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein return c->interface_name(); 56c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein} 57c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein} 58c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein 59d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#if defined(__ANDROID__) 60d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiunamespace { 61d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiuconst char* kGoogleDNSServers[] = { 62d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu "8.8.4.4", 63d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu "8.8.8.8" 64d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu}; 65d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu} // namespace 66d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#endif // __ANDROID__ 67d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu 68dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart// static 697fab89734d88724a288e96a9996b15548c5294c7Ben Chanconst uint32_t Connection::kDefaultMetric = 1; 70dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart// static 717fab89734d88724a288e96a9996b15548c5294c7Ben Chanconst uint32_t Connection::kNonDefaultMetricBase = 10; 72762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi// static 73762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthiconst uint32_t Connection::kMarkForUserTraffic = 0x1; 74762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi// static 75762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthiconst uint8_t Connection::kSecondaryTableId = 0x1; 76dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 77a794cd60a7339d576ea2eed263a4f0a20fb255afPaul StewartConnection::Binder::Binder(const string& name, 78a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Closure& disconnect_callback) 7913e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov : name_(name), 8013e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov client_disconnect_callback_(disconnect_callback) {} 8113e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov 8213e6d55b9dd86148ae68588f367c48e81ad33b74Darin PetkovConnection::Binder::~Binder() { 83cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan Attach(nullptr); 8413e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov} 8513e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov 86a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid Connection::Binder::Attach(const ConnectionRefPtr& to_connection) { 8713e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov if (connection_) { 8813e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov connection_->DetachBinder(this); 8913e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov LOG(INFO) << name_ << ": unbound from connection: " 9013e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov << connection_->interface_name(); 91ef1f9fec08b3a251a84ae3e4ef7ef15fdc2a1544Darin Petkov connection_.reset(); 9213e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov } 93ef1f9fec08b3a251a84ae3e4ef7ef15fdc2a1544Darin Petkov if (to_connection) { 94ef1f9fec08b3a251a84ae3e4ef7ef15fdc2a1544Darin Petkov connection_ = to_connection->weak_ptr_factory_.GetWeakPtr(); 9513e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov connection_->AttachBinder(this); 9613e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov LOG(INFO) << name_ << ": bound to connection: " 9713e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov << connection_->interface_name(); 9813e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov } 9913e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov} 10013e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov 10113e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkovvoid Connection::Binder::OnDisconnect() { 10213e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov LOG(INFO) << name_ << ": bound connection disconnected: " 10313e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov << connection_->interface_name(); 104ef1f9fec08b3a251a84ae3e4ef7ef15fdc2a1544Darin Petkov connection_.reset(); 10513e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov if (!client_disconnect_callback_.is_null()) { 106c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(connection_.get(), 2) << "Running client disconnect callback."; 10713e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov client_disconnect_callback_.Run(); 10813e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov } 10913e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov} 11013e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov 1119a908080fc2a72dbf06f995b878fc8a3693b725aPaul StewartConnection::Connection(int interface_index, 1129a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart const std::string& interface_name, 113e00600e1ec769b3acf0709e843c1f0ae73bd2fdbPaul Stewart Technology::Identifier technology, 114608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu const DeviceInfo* device_info, 115608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu ControlInterface* control_interface) 11613e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov : weak_ptr_factory_(this), 11713e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov is_default_(false), 1184a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart has_broadcast_domain_(false), 119c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart routing_request_count_(0), 120dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart interface_index_(interface_index), 121dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart interface_name_(interface_name), 122e00600e1ec769b3acf0709e843c1f0ae73bd2fdbPaul Stewart technology_(technology), 123762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi user_traffic_only_(false), 124762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi table_id_(RT_TABLE_MAIN), 1254a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart local_(IPAddress::kFamilyUnknown), 1264a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart gateway_(IPAddress::kFamilyUnknown), 12713e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov lower_binder_( 12813e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov interface_name_, 12913e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // Connection owns a single instance of |lower_binder_| so it's safe 13013e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // to use an Unretained callback. 13113e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov Bind(&Connection::OnLowerDisconnect, Unretained(this))), 1329a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart device_info_(device_info), 133d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#if !defined(__ANDROID__) 134dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart resolver_(Resolver::GetInstance()), 1359429723aad30865ab4604a6074dece9c6d45c0ccPeter Qiu#else 1369429723aad30865ab4604a6074dece9c6d45c0ccPeter Qiu dns_server_proxy_factory_(DNSServerProxyFactory::GetInstance()), 137d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#endif // __ANDROID__ 138dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart routing_table_(RoutingTable::GetInstance()), 139608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu rtnl_handler_(RTNLHandler::GetInstance()), 140608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu control_interface_(control_interface) { 141c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << "(" << interface_index << ", " 142c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << interface_name << ", " 143c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << Technology::NameFromIdentifier(technology) << ")"; 144dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart} 145dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 146dd60e4549cc8898f7f517283eacc58f67570bd1fPaul StewartConnection::~Connection() { 147c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << " " << interface_name_; 1489a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 14913e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov NotifyBindersOnDisconnect(); 15013e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov 151c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart DCHECK(!routing_request_count_); 152fb46caf4f23a41e73dfd87547121b5fb0230295aThieu Le routing_table_->FlushRoutes(interface_index_); 153e93b038972d43fd703b3c68603fb4d02bec6504ePaul Stewart routing_table_->FlushRoutesWithTag(interface_index_); 1549a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart device_info_->FlushAddresses(interface_index_); 15577e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi TearDownIptableEntries(); 156dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart} 157dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 158a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid Connection::UpdateFromIPConfig(const IPConfigRefPtr& config) { 159c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << " " << interface_name_; 160e613202d36e3bfb06a40eea1888694413210ef7ePaul Stewart 161a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const IPConfig::Properties& properties = config->properties(); 162762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi user_traffic_only_ = properties.user_traffic_only; 163762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi table_id_ = user_traffic_only_ ? kSecondaryTableId : (uint8_t)RT_TABLE_MAIN; 164762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi 16573fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart IPAddress gateway(properties.address_family); 16673fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart if (!properties.gateway.empty() && 16773fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart !gateway.SetAddressFromString(properties.gateway)) { 16873fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart LOG(ERROR) << "Gateway address " << properties.gateway << " is invalid"; 169e93b038972d43fd703b3c68603fb4d02bec6504ePaul Stewart return; 170e93b038972d43fd703b3c68603fb4d02bec6504ePaul Stewart } 171e93b038972d43fd703b3c68603fb4d02bec6504ePaul Stewart 172762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi excluded_ips_cidr_ = properties.exclusion_list; 173762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi 17473fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart IPAddress trusted_ip(properties.address_family); 175762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi if (!excluded_ips_cidr_.empty()) { 176762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi const std::string first_excluded_ip = excluded_ips_cidr_[0]; 177762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi excluded_ips_cidr_.erase(excluded_ips_cidr_.begin()); 178762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // A VPN connection can currently be bound to exactly one lower connection 179762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // such as eth0 or wan0. The excluded IPs are pinned to the gateway of 180762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // that connection. Setting up the routing table this way ensures that when 181762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // the lower connection goes offline, the associated entries in the routing 182762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // table are removed. On the flip side, when there are multiple connections 183762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // such as eth0 and wan0 and some IPs can be reached quickly over one 184762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // connection and the others over a different connection, all routes are 185762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // still pinned to a connection. 186762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // 187762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // The optimal connection to reach the first excluded IP is found below. 188762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // When this is found the route for the remaining excluded IPs are pinned in 189762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // the method PinPendingRoutes below. 190762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi if (!trusted_ip.SetAddressAndPrefixFromString(first_excluded_ip)) { 19173fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart LOG(ERROR) << "Trusted IP address " 192762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi << first_excluded_ip << " is invalid"; 19373fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart return; 19473fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart } 19573fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart if (!PinHostRoute(trusted_ip, gateway)) { 196762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi LOG(ERROR) << "Unable to pin host route to " << first_excluded_ip; 19773fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart return; 19873fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart } 19973fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart } 20073fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart 2019a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart IPAddress local(properties.address_family); 2029a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (!local.SetAddressFromString(properties.address)) { 2039a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart LOG(ERROR) << "Local address " << properties.address << " is invalid"; 2049a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart return; 2059a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 20648100b0f484fb59d5f34eb4565375759202295e1Paul Stewart local.set_prefix(properties.subnet_prefix); 2079a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 2089a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart IPAddress broadcast(properties.address_family); 2091062d9deedace1cf4b3b374c5d40c53047fd6778Paul Stewart if (properties.broadcast_address.empty()) { 210fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart if (properties.peer_address.empty()) { 2111062d9deedace1cf4b3b374c5d40c53047fd6778Paul Stewart LOG(WARNING) << "Broadcast address is not set. Using default."; 212fe1c0e17fe470de449a1aadb6c202a41da146ef7Paul Stewart broadcast = local.GetDefaultBroadcast(); 2131062d9deedace1cf4b3b374c5d40c53047fd6778Paul Stewart } 2141062d9deedace1cf4b3b374c5d40c53047fd6778Paul Stewart } else if (!broadcast.SetAddressFromString(properties.broadcast_address)) { 2159a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart LOG(ERROR) << "Broadcast address " << properties.broadcast_address 2169a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart << " is invalid"; 2179a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart return; 2189a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 2199a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 22048100b0f484fb59d5f34eb4565375759202295e1Paul Stewart IPAddress peer(properties.address_family); 22148100b0f484fb59d5f34eb4565375759202295e1Paul Stewart if (!properties.peer_address.empty() && 22248100b0f484fb59d5f34eb4565375759202295e1Paul Stewart !peer.SetAddressFromString(properties.peer_address)) { 22348100b0f484fb59d5f34eb4565375759202295e1Paul Stewart LOG(ERROR) << "Peer address " << properties.peer_address 22448100b0f484fb59d5f34eb4565375759202295e1Paul Stewart << " is invalid"; 22548100b0f484fb59d5f34eb4565375759202295e1Paul Stewart return; 22648100b0f484fb59d5f34eb4565375759202295e1Paul Stewart } 22748100b0f484fb59d5f34eb4565375759202295e1Paul Stewart 228c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart if (!FixGatewayReachability(local, &peer, &gateway, trusted_ip)) { 22953a303873f9a89ff0121777476d33afc9b77b987Paul Stewart LOG(WARNING) << "Expect limited network connectivity."; 23053a303873f9a89ff0121777476d33afc9b77b987Paul Stewart } 2315b7ba8c2e9e5ab5e67c68d0cde963141beb501d8Paul Stewart 23205a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart if (device_info_->HasOtherAddress(interface_index_, local)) { 23305a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart // The address has changed for this interface. We need to flush 23405a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart // everything and start over. 23505a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart LOG(INFO) << __func__ << ": Flushing old addresses and routes."; 23605a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart routing_table_->FlushRoutes(interface_index_); 23705a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart device_info_->FlushAddresses(interface_index_); 23805a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } 23905a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart 240e78ec548060d969fecdb488d6fed711d843bba91Paul Stewart LOG(INFO) << __func__ << ": Installing with parameters:" 241e78ec548060d969fecdb488d6fed711d843bba91Paul Stewart << " local=" << local.ToString() 242e78ec548060d969fecdb488d6fed711d843bba91Paul Stewart << " broadcast=" << broadcast.ToString() 243e78ec548060d969fecdb488d6fed711d843bba91Paul Stewart << " peer=" << peer.ToString() 244e78ec548060d969fecdb488d6fed711d843bba91Paul Stewart << " gateway=" << gateway.ToString(); 24548100b0f484fb59d5f34eb4565375759202295e1Paul Stewart rtnl_handler_->AddInterfaceAddress(interface_index_, local, broadcast, peer); 246dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 2471f58903c02e9a8e29816f7a7659afa331b005d9cPrabhu Kaliamoorthi if (gateway.IsValid() && properties.default_route) { 248e78ec548060d969fecdb488d6fed711d843bba91Paul Stewart routing_table_->SetDefaultRoute(interface_index_, gateway, 249762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi GetMetric(is_default_), 250762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi table_id_); 251762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi } 252762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi 253762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi if (user_traffic_only_) { 25477e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi SetupIptableEntries(); 2555b7ba8c2e9e5ab5e67c68d0cde963141beb501d8Paul Stewart } 256dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 2573f68bb1e3768969a1db686325ae9a84c8fd06005Paul Stewart // Install any explicitly configured routes at the default metric. 258762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi routing_table_->ConfigureRoutes(interface_index_, config, kDefaultMetric, 259762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi table_id_); 2603f68bb1e3768969a1db686325ae9a84c8fd06005Paul Stewart 261024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart SetMTU(properties.mtu); 262024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart 263a016312b7470e124774aec197e3b43bc795637c3Ben Chan if (properties.blackhole_ipv6) { 264a016312b7470e124774aec197e3b43bc795637c3Ben Chan routing_table_->CreateBlackholeRoute(interface_index_, 265a016312b7470e124774aec197e3b43bc795637c3Ben Chan IPAddress::kFamilyIPv6, 266762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi kDefaultMetric, 267762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi table_id_); 268a016312b7470e124774aec197e3b43bc795637c3Ben Chan } 269a016312b7470e124774aec197e3b43bc795637c3Ben Chan 270d62d6035f45ab5caf04a558a70fbc78457775f97Paul Stewart // Save a copy of the last non-null DNS config. 271dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart if (!config->properties().dns_servers.empty()) { 272dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart dns_servers_ = config->properties().dns_servers; 273d62d6035f45ab5caf04a558a70fbc78457775f97Paul Stewart } 274d62d6035f45ab5caf04a558a70fbc78457775f97Paul Stewart 275d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#if defined(__ANDROID__) 276d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu // Default to Google's DNS server if it is not provided through DHCP. 277d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu if (config->properties().dns_servers.empty()) { 278d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu LOG(INFO) << "Default to use Google DNS servers"; 279d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu dns_servers_ = 280d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu vector<string>(std::begin(kGoogleDNSServers), 281d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu std::end(kGoogleDNSServers)); 282d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu } 283d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#endif // __ANDROID__ 284d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu 285d62d6035f45ab5caf04a558a70fbc78457775f97Paul Stewart if (!config->properties().domain_search.empty()) { 286dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart dns_domain_search_ = config->properties().domain_search; 287d62d6035f45ab5caf04a558a70fbc78457775f97Paul Stewart } 288d62d6035f45ab5caf04a558a70fbc78457775f97Paul Stewart 289d62d6035f45ab5caf04a558a70fbc78457775f97Paul Stewart if (!config->properties().domain_name.empty()) { 290d62d6035f45ab5caf04a558a70fbc78457775f97Paul Stewart dns_domain_name_ = config->properties().domain_name; 291dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart } 292dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 29310241e32c136ba99e7533ca1370e2e8eca241b7cPaul Stewart ipconfig_rpc_identifier_ = config->GetRpcIdentifier(); 29410241e32c136ba99e7533ca1370e2e8eca241b7cPaul Stewart 295a89154bfedfd8872242083ffe4f084fdc774c078Peter Qiu PushDNSConfig(); 2964a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart 2974a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart local_ = local; 2984a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart gateway_ = gateway; 2994a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart has_broadcast_domain_ = !peer.IsValid(); 300dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart} 301dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 30277e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthibool Connection::SetupIptableEntries() { 303a330ecd23b1ce4112fd7a28f4b2a062b8df10735Peter Qiu if (!firewall_proxy_) { 304a330ecd23b1ce4112fd7a28f4b2a062b8df10735Peter Qiu firewall_proxy_.reset(control_interface_->CreateFirewallProxy()); 30577e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi } 30677e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi 30777e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi std::vector<std::string> user_names; 30877e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi user_names.push_back("chronos"); 309eac0ffcefc46764b7416c67e2a9f363b2531dccbKevin Cernekee user_names.push_back("debugd"); 31077e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi 311a330ecd23b1ce4112fd7a28f4b2a062b8df10735Peter Qiu if (!firewall_proxy_->RequestVpnSetup(user_names, interface_name_)) { 31277e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi LOG(ERROR) << "VPN iptables setup request failed."; 31377e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi return false; 31477e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi } 31577e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi 31677e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi return true; 31777e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi} 31877e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi 31977e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthibool Connection::TearDownIptableEntries() { 320a330ecd23b1ce4112fd7a28f4b2a062b8df10735Peter Qiu return firewall_proxy_ ? firewall_proxy_->RemoveVpnSetup() : true; 32177e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi} 32277e768323e57058b4660bb72ba2544a1cbe6d435Prabhu Kaliamoorthi 323c1dec4d5cad7c6ee2cd8dbc4f47e4d30403dcca1Paul Stewartvoid Connection::SetIsDefault(bool is_default) { 324c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << " " << interface_name_ 325c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << " (index " << interface_index_ << ") " 326c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << is_default_ << " -> " << is_default; 327dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart if (is_default == is_default_) { 328dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart return; 329dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart } 330dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 3317cfca0467e47aa91b485c485b92befb33a1fd61fPaul Stewart routing_table_->SetDefaultMetric(interface_index_, GetMetric(is_default)); 332dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 333c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart is_default_ = is_default; 334c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart 335a89154bfedfd8872242083ffe4f084fdc774c078Peter Qiu PushDNSConfig(); 336dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart if (is_default) { 337c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart DeviceRefPtr device = device_info_->GetDevice(interface_index_); 338c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart if (device) { 339c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart device->RequestPortalDetection(); 340c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart } 341dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart } 342e78ec548060d969fecdb488d6fed711d843bba91Paul Stewart routing_table_->FlushCache(); 343dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart} 344dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart 345a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid Connection::UpdateDNSServers(const vector<string>& dns_servers) { 346a89154bfedfd8872242083ffe4f084fdc774c078Peter Qiu dns_servers_ = dns_servers; 347a89154bfedfd8872242083ffe4f084fdc774c078Peter Qiu PushDNSConfig(); 348a89154bfedfd8872242083ffe4f084fdc774c078Peter Qiu} 349a89154bfedfd8872242083ffe4f084fdc774c078Peter Qiu 3506f65c0b387f6dde8113f52745b758ca1c4f349bePaul Stewartvoid Connection::PushDNSConfig() { 351a89154bfedfd8872242083ffe4f084fdc774c078Peter Qiu if (!is_default_) { 352d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#if defined(__ANDROID__) 353d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu // Stop DNS server proxy to avoid having multiple instances of it running. 354d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu // Only run DNS server proxy for the current default connection. 355d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu dns_server_proxy_.reset(); 356d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#endif // __ANDROID__ 357a89154bfedfd8872242083ffe4f084fdc774c078Peter Qiu return; 358a89154bfedfd8872242083ffe4f084fdc774c078Peter Qiu } 359a89154bfedfd8872242083ffe4f084fdc774c078Peter Qiu 3606f65c0b387f6dde8113f52745b758ca1c4f349bePaul Stewart vector<string> domain_search = dns_domain_search_; 3616f65c0b387f6dde8113f52745b758ca1c4f349bePaul Stewart if (domain_search.empty() && !dns_domain_name_.empty()) { 362c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Setting domain search to domain name " 363c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << dns_domain_name_; 3646f65c0b387f6dde8113f52745b758ca1c4f349bePaul Stewart domain_search.push_back(dns_domain_name_ + "."); 3656f65c0b387f6dde8113f52745b758ca1c4f349bePaul Stewart } 366d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#if !defined(__ANDROID__) 36723ac6b72d44c446bca88175883ba26b39c5ed817mukesh agrawal resolver_->SetDNSFromLists(dns_servers_, domain_search); 368d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#else 3699429723aad30865ab4604a6074dece9c6d45c0ccPeter Qiu dns_server_proxy_.reset( 3709429723aad30865ab4604a6074dece9c6d45c0ccPeter Qiu dns_server_proxy_factory_->CreateDNSServerProxy(dns_servers_)); 371d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu dns_server_proxy_->Start(); 372d5d3482e261beaee1a13622143d4abf728165fb9Peter Qiu#endif // __ANDROID__ 3736f65c0b387f6dde8113f52745b758ca1c4f349bePaul Stewart} 3746f65c0b387f6dde8113f52745b758ca1c4f349bePaul Stewart 375c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewartvoid Connection::RequestRouting() { 376c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart if (routing_request_count_++ == 0) { 377c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart DeviceRefPtr device = device_info_->GetDevice(interface_index_); 378c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart DCHECK(device.get()); 379c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart if (!device.get()) { 380c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart LOG(ERROR) << "Device is NULL!"; 381c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart return; 382c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart } 3832cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart device->SetLooseRouting(true); 384c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart } 385c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart} 386c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart 387c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewartvoid Connection::ReleaseRouting() { 3888a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko DCHECK_GT(routing_request_count_, 0); 389c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart if (--routing_request_count_ == 0) { 390c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart DeviceRefPtr device = device_info_->GetDevice(interface_index_); 391c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart DCHECK(device.get()); 392c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart if (!device.get()) { 393c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart LOG(ERROR) << "Device is NULL!"; 394c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart return; 395c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart } 3962cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart device->SetLooseRouting(false); 397c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart 398c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart // Clear any cached routes that might have accumulated while reverse-path 399c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart // filtering was disabled. 400c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart routing_table_->FlushCache(); 401c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart } 402c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart} 403c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart 404a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartbool Connection::RequestHostRoute(const IPAddress& address) { 40513e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // Do not set interface_index_ since this may not be the default route through 40613e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // which this destination can be found. However, we should tag the created 40713e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // route with our interface index so we can clean this route up when this 40813e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // connection closes. Also, add route query callback to determine the lower 40913e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // connection and bind to it. 41013e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov if (!routing_table_->RequestRouteToHost( 411762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi address, 41213e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov -1, 41313e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov interface_index_, 4145eb0542cb67358d9030367498a4ad741fc42af4fDarin Petkov Bind(&Connection::OnRouteQueryResponse, 415762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi weak_ptr_factory_.GetWeakPtr()), 416762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi table_id_)) { 417f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart LOG(ERROR) << "Could not request route to " << address.ToString(); 418f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return false; 419f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 420f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart 421f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return true; 422f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart} 423f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart 424762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthibool Connection::PinPendingRoutes(int interface_index, 425762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi RoutingTableEntry entry) { 426762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // The variable entry is locally modified, hence is passed by value in the 427762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi // second argument above. 428762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi for (auto excluded_ip = excluded_ips_cidr_.begin(); 429762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi excluded_ip != excluded_ips_cidr_.end(); ++excluded_ip) { 430762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi if (!entry.dst.SetAddressAndPrefixFromString(*excluded_ip) || 431762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi !entry.dst.IsValid() || 432762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi !routing_table_->AddRoute(interface_index, entry)) { 433762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi LOG(ERROR) << "Unable to setup route for " << *excluded_ip << "."; 434762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi } 435762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi } 436762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi 437762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi return true; 438762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi} 439762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi 4402cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewartstring Connection::GetSubnetName() const { 441182888eab7478f28001b1235f8d2b75063445db8Paul Stewart if (!local().IsValid()) { 442182888eab7478f28001b1235f8d2b75063445db8Paul Stewart return ""; 443182888eab7478f28001b1235f8d2b75063445db8Paul Stewart } 4442cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart return base::StringPrintf("%s/%d", 4452cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart local().GetNetworkPart().ToString().c_str(), 4462cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart local().prefix()); 4472cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart} 4482cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart 449c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewartbool Connection::FixGatewayReachability(const IPAddress& local, 450a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart IPAddress* peer, 451a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart IPAddress* gateway, 452a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const IPAddress& trusted_ip) { 45355d9550e72197a203efbe06087edc2424676d886Paul Stewart SLOG(nullptr, 2) << __func__ 454c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart << " local " << local.ToString() 45555d9550e72197a203efbe06087edc2424676d886Paul Stewart << ", peer " << peer->ToString() 45655d9550e72197a203efbe06087edc2424676d886Paul Stewart << ", gateway " << gateway->ToString() 45755d9550e72197a203efbe06087edc2424676d886Paul Stewart << ", trusted_ip " << trusted_ip.ToString(); 45873fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart if (!gateway->IsValid()) { 45953a303873f9a89ff0121777476d33afc9b77b987Paul Stewart LOG(WARNING) << "No gateway address was provided for this connection."; 46053a303873f9a89ff0121777476d33afc9b77b987Paul Stewart return false; 46153a303873f9a89ff0121777476d33afc9b77b987Paul Stewart } 46253a303873f9a89ff0121777476d33afc9b77b987Paul Stewart 4634925829bd8be852a625086e3628a2fb89286ddd8Paul Stewart if (peer->IsValid()) { 46455d9550e72197a203efbe06087edc2424676d886Paul Stewart if (!gateway->HasSameAddressAs(*peer)) { 46573fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart LOG(WARNING) << "Gateway address " 46673fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart << gateway->ToString() 46773fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart << " does not match peer address " 46873fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart << peer->ToString(); 46973fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart return false; 47053a303873f9a89ff0121777476d33afc9b77b987Paul Stewart } 47155d9550e72197a203efbe06087edc2424676d886Paul Stewart if (gateway->HasSameAddressAs(trusted_ip)) { 47273fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // In order to send outgoing traffic in a point-to-point network, 47373fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // the gateway IP address isn't of significance. As opposed to 47473fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // broadcast networks, we never ARP for the gateway IP address, 47573fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // but just send the IP packet addressed to the recipient. As 47673fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // such, since using the external trusted IP address as the 47773fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // gateway or peer wreaks havoc on the routing rules, we choose 47873fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // not to supply a gateway address. Here's an example: 47973fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // 48073fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // Client <-> Internet <-> VPN Gateway <-> Internal Network 48173fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // 192.168.1.2 10.0.1.25 172.16.5.0/24 48273fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // 48373fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // In this example, a client connects to a VPN gateway on its 48473fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // public IP address 10.0.1.25. It gets issued an IP address 48573fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // from the VPN internal pool. For some VPN gateways, this 48673fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // results in a pushed-down PPP configuration which specifies: 48773fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // 48873fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // Client local address: 172.16.5.13 48973fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // Client peer address: 10.0.1.25 49073fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // Client default gateway: 10.0.1.25 49173fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // 49273fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // If we take this literally, we need to resolve the fact that 49373fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // 10.0.1.25 is now listed as the default gateway and interface 49473fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // peer address for the point-to-point interface. However, in 49573fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // order to route tunneled packets to the VPN gateway we must 49673fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // use the external route through the physical interface and 49773fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // not the tunnel, or else we end up in an infinite loop 49873fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // re-entering the tunnel trying to route towards the VPN server. 49973fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // 50073fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // We can do this by pinning a route, but we would need to wait 50173fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // for the pinning process to complete before assigning this 50273fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // address. Currently this process is asynchronous and will 50373fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // complete only after returning to the event loop. Additionally, 50473fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // since there's no metric associated with assigning an address 50573fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // to an interface, it's always possible that having the peer 50673fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // address of the interface might still trump a host route. 50773fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // 50873fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // To solve this problem, we reset the peer and gateway 50973fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // addresses. Neither is required in order to perform the 51073fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // underlying routing task. A gateway route can be specified 51173fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // without an IP endpoint on point-to-point links, and simply 51273fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // specify the outbound interface index. Similarly, a peer 51373fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // IP address is not necessary either, and will be assigned 51473fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // the same IP address as the local IP. This approach 51573fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // simplifies routing and doesn't change the desired 51673fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // functional behavior. 51773fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart // 51873fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart LOG(INFO) << "Removing gateway and peer addresses to preserve " 51973fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart << "routability to trusted IP address."; 52073fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart peer->SetAddressToDefault(); 52173fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart gateway->SetAddressToDefault(); 52273fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart } 52373fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart return true; 52453a303873f9a89ff0121777476d33afc9b77b987Paul Stewart } 52553a303873f9a89ff0121777476d33afc9b77b987Paul Stewart 526c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart if (local.CanReachAddress(*gateway)) { 52753a303873f9a89ff0121777476d33afc9b77b987Paul Stewart return true; 5285b7ba8c2e9e5ab5e67c68d0cde963141beb501d8Paul Stewart } 5295b7ba8c2e9e5ab5e67c68d0cde963141beb501d8Paul Stewart 5305b7ba8c2e9e5ab5e67c68d0cde963141beb501d8Paul Stewart LOG(WARNING) << "Gateway " 53173fcc3f6560240d0d5dde15927cc0b51dc692dd5Paul Stewart << gateway->ToString() 5325b7ba8c2e9e5ab5e67c68d0cde963141beb501d8Paul Stewart << " is unreachable from local address/prefix " 533c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart << local.ToString() << "/" << local.prefix(); 534c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart 535c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart IPAddress gateway_with_max_prefix(*gateway); 536c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart gateway_with_max_prefix.set_prefix( 537c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart IPAddress::GetMaxPrefixLength(gateway_with_max_prefix.family())); 538c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart IPAddress default_address(gateway->family()); 539c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart RoutingTableEntry entry(gateway_with_max_prefix, 540c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart default_address, 541c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart default_address, 542c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart 0, 543c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart RT_SCOPE_LINK, 544c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart false, 545c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart table_id_, 546c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart RoutingTableEntry::kDefaultTag); 547c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart 548c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart if (!routing_table_->AddRoute(interface_index_, entry)) { 549c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart LOG(ERROR) << "Unable to add link-scoped route to gateway."; 550c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart return false; 5515b7ba8c2e9e5ab5e67c68d0cde963141beb501d8Paul Stewart } 5525b7ba8c2e9e5ab5e67c68d0cde963141beb501d8Paul Stewart 553c8fab0c129ea3e55fd89719f6e16c78ca505e05cPaul Stewart LOG(WARNING) << "Mitigating this by creating a link route to the gateway."; 55453a303873f9a89ff0121777476d33afc9b77b987Paul Stewart 55553a303873f9a89ff0121777476d33afc9b77b987Paul Stewart return true; 5565b7ba8c2e9e5ab5e67c68d0cde963141beb501d8Paul Stewart} 5575b7ba8c2e9e5ab5e67c68d0cde963141beb501d8Paul Stewart 5587fab89734d88724a288e96a9996b15548c5294c7Ben Chanuint32_t Connection::GetMetric(bool is_default) { 5597cfca0467e47aa91b485c485b92befb33a1fd61fPaul Stewart // If this is not the default route, assign a metric based on the interface 5607cfca0467e47aa91b485c485b92befb33a1fd61fPaul Stewart // index. This way all non-default routes (even to the same gateway IP) end 5617cfca0467e47aa91b485c485b92befb33a1fd61fPaul Stewart // up with unique metrics so they do not collide. 5627cfca0467e47aa91b485c485b92befb33a1fd61fPaul Stewart return is_default ? kDefaultMetric : kNonDefaultMetricBase + interface_index_; 5637cfca0467e47aa91b485c485b92befb33a1fd61fPaul Stewart} 5647cfca0467e47aa91b485c485b92befb33a1fd61fPaul Stewart 565a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartbool Connection::PinHostRoute(const IPAddress& trusted_ip, 566a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const IPAddress& gateway) { 567c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 568e435d34d8bc77ab7b821833e9029eac990f677adPaul Stewart if (!trusted_ip.IsValid()) { 569e435d34d8bc77ab7b821833e9029eac990f677adPaul Stewart LOG(ERROR) << "No trusted IP -- unable to pin host route."; 570e93b038972d43fd703b3c68603fb4d02bec6504ePaul Stewart return false; 571e93b038972d43fd703b3c68603fb4d02bec6504ePaul Stewart } 572e93b038972d43fd703b3c68603fb4d02bec6504ePaul Stewart 573e435d34d8bc77ab7b821833e9029eac990f677adPaul Stewart if (!gateway.IsValid()) { 574e435d34d8bc77ab7b821833e9029eac990f677adPaul Stewart // Although we cannot pin a host route, we are also not going to create 575e435d34d8bc77ab7b821833e9029eac990f677adPaul Stewart // a gateway route that will interfere with our primary connection, so 576e435d34d8bc77ab7b821833e9029eac990f677adPaul Stewart // it is okay to return success here. 577e435d34d8bc77ab7b821833e9029eac990f677adPaul Stewart LOG(WARNING) << "No gateway -- unable to pin host route."; 578e435d34d8bc77ab7b821833e9029eac990f677adPaul Stewart return true; 579e435d34d8bc77ab7b821833e9029eac990f677adPaul Stewart } 580e435d34d8bc77ab7b821833e9029eac990f677adPaul Stewart 581e93b038972d43fd703b3c68603fb4d02bec6504ePaul Stewart return RequestHostRoute(trusted_ip); 582e93b038972d43fd703b3c68603fb4d02bec6504ePaul Stewart} 583e93b038972d43fd703b3c68603fb4d02bec6504ePaul Stewart 584024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewartvoid Connection::SetMTU(int32_t mtu) { 585024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart SLOG(this, 2) << __func__ << " " << mtu; 586024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart // Make sure the MTU value is valid. 587024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart if (mtu == IPConfig::kUndefinedMTU) { 588024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart mtu = IPConfig::kDefaultMTU; 589024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart } else { 590024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart int min_mtu = IsIPv6() ? IPConfig::kMinIPv6MTU : IPConfig::kMinIPv4MTU; 591024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart if (mtu < min_mtu) { 592024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart SLOG(this, 2) << __func__ << " MTU " << mtu 593024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart << " is too small; adjusting up to " << min_mtu; 594024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart mtu = min_mtu; 595024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart } 596024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart } 597024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart 598024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart rtnl_handler_->SetInterfaceMTU(interface_index_, mtu); 599024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart} 600024a6c80bc8474d828af6d961ea7fe0d67d69587Paul Stewart 60113e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkovvoid Connection::OnRouteQueryResponse(int interface_index, 602a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const RoutingTableEntry& entry) { 603c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << "(" << interface_index << ", " 604c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << entry.tag << ")" << " @ " << interface_name_; 605cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan lower_binder_.Attach(nullptr); 60613e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov DeviceRefPtr device = device_info_->GetDevice(interface_index); 60713e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov if (!device) { 60813e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov LOG(ERROR) << "Unable to lookup device for index " << interface_index; 60913e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov return; 61013e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov } 61113e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov ConnectionRefPtr connection = device->connection(); 61213e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov if (!connection) { 61313e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov LOG(ERROR) << "Device " << interface_index << " has no connection."; 61413e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov return; 61513e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov } 6169a0f121f98ebc46704773555334b43af14842abePaul Stewart if (connection == this) { 6179a0f121f98ebc46704773555334b43af14842abePaul Stewart LOG(ERROR) << "Avoiding a connection bind loop for " << interface_name(); 6189a0f121f98ebc46704773555334b43af14842abePaul Stewart return; 6199a0f121f98ebc46704773555334b43af14842abePaul Stewart } 62013e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov lower_binder_.Attach(connection); 6214a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart connection->CreateGatewayRoute(); 6228596f9f1341d3698543e1010ac1710cbe91e35d5Paul Stewart device->OnConnectionUpdated(); 623762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi PinPendingRoutes(interface_index, entry); 6244a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart} 6254a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart 6264a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewartbool Connection::CreateGatewayRoute() { 6274a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart // Ensure that the gateway for the lower connection remains reachable, 6284a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart // since we may create routes that conflict with it. 6294a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart if (!has_broadcast_domain_) { 6304a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart return false; 6314a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart } 632856b8848e200a30006502c90f567923135454cf4Paul Stewart 633856b8848e200a30006502c90f567923135454cf4Paul Stewart // If there is no gateway, don't try to create a route to it. 634856b8848e200a30006502c90f567923135454cf4Paul Stewart if (!gateway_.IsValid()) { 635856b8848e200a30006502c90f567923135454cf4Paul Stewart return false; 636856b8848e200a30006502c90f567923135454cf4Paul Stewart } 637856b8848e200a30006502c90f567923135454cf4Paul Stewart 6384a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart // It is not worth keeping track of this route, since it is benign, 6394a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart // and only pins persistent state that was already true of the connection. 6404a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart // If DHCP parameters change later (without the connection having been 6414a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart // destroyed and recreated), the binding processes will likely terminate 6424a6748d492214afcb7c484668fa8cfd3ad963f10Paul Stewart // and restart, causing a new link route to be created. 643762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi return routing_table_->CreateLinkRoute(interface_index_, local_, gateway_, 644762bfb8ab200a387fe732ec92423a5f0afe11bcfPrabhu Kaliamoorthi table_id_); 64513e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov} 64613e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov 64713e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkovvoid Connection::OnLowerDisconnect() { 648c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << " @ " << interface_name_; 64913e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // Ensures that |this| instance doesn't get destroyed in the middle of 65013e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // notifying the binders. This method needs to be separate from 65113e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // NotifyBindersOnDisconnect because the latter may be invoked by Connection's 65213e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // destructor when |this| instance's reference count is already 0. 65313e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov ConnectionRefPtr connection(this); 65413e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov connection->NotifyBindersOnDisconnect(); 65513e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov} 65613e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov 65713e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkovvoid Connection::NotifyBindersOnDisconnect() { 65813e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // Note that this method may be invoked by the destructor. 659c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << " @ " << interface_name_; 66013e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov 66113e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // Unbinds the lower connection before notifying the binders. This ensures 66213e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // correct behavior in case of circular binding. 663cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan lower_binder_.Attach(nullptr); 66413e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov while (!binders_.empty()) { 66513e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // Pop the binder first and then notify it to ensure that each binder is 66613e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov // notified only once. 667a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart Binder* binder = binders_.front(); 66813e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov binders_.pop_front(); 66913e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov binder->OnDisconnect(); 67013e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov } 67113e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov} 67213e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov 673a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid Connection::AttachBinder(Binder* binder) { 674c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << "(" << binder->name() << ")" << " @ " 675c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << interface_name_; 67613e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov binders_.push_back(binder); 67713e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov} 67813e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov 679a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid Connection::DetachBinder(Binder* binder) { 680c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << "(" << binder->name() << ")" << " @ " 681c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << interface_name_; 6826db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart for (auto it = binders_.begin(); it != binders_.end(); ++it) { 68313e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov if (binder == *it) { 68413e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov binders_.erase(it); 68513e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov return; 68613e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov } 68713e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov } 68813e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov} 68913e6d55b9dd86148ae68588f367c48e81ad33b74Darin Petkov 690fddc09ac26ba77cabb59810f01b705fca2efd10bAlex DeymoConnectionRefPtr Connection::GetCarrierConnection() { 691c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << " @ " << interface_name_; 692a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart set<Connection*> visited; 693fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo ConnectionRefPtr carrier = this; 694fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo while (carrier->GetLowerConnection()) { 695fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo if (ContainsKey(visited, carrier.get())) { 696fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo LOG(ERROR) << "Circular connection chain starting at: " 697fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo << carrier->interface_name(); 698fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo // If a loop is detected return a NULL value to signal that the carrier 699fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo // connection is unknown. 700cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan return nullptr; 701fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo } 702fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo visited.insert(carrier.get()); 703fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo carrier = carrier->GetLowerConnection(); 704fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo } 705c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Carrier connection: " << carrier->interface_name() 706c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << " @ " << interface_name_; 707fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo return carrier; 708fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo} 709fddc09ac26ba77cabb59810f01b705fca2efd10bAlex Deymo 710f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiubool Connection::IsIPv6() { 711f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu return local_.family() == IPAddress::kFamilyIPv6; 712f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu} 713f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu 714dd60e4549cc8898f7f517283eacc58f67570bd1fPaul Stewart} // namespace shill 715