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