connection.cc revision 024a6c80bc8474d828af6d961ea7fe0d67d69587
1// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/connection.h"
6
7#include <arpa/inet.h>
8#include <linux/rtnetlink.h>
9
10#include <set>
11
12#include <base/strings/stringprintf.h>
13
14#include "shill/device_info.h"
15#include "shill/logging.h"
16#include "shill/net/rtnl_handler.h"
17#include "shill/resolver.h"
18#include "shill/routing_table.h"
19
20using base::Bind;
21using base::Closure;
22using base::Unretained;
23using std::deque;
24using std::set;
25using std::string;
26using std::vector;
27
28namespace shill {
29
30namespace Logging {
31static auto kModuleLogScope = ScopeLogger::kConnection;
32static string ObjectID(Connection *c) {
33  return c->interface_name();
34}
35}
36
37// static
38const uint32_t Connection::kDefaultMetric = 1;
39// static
40const uint32_t Connection::kNonDefaultMetricBase = 10;
41
42Connection::Binder::Binder(const string &name,
43                           const Closure &disconnect_callback)
44    : name_(name),
45      client_disconnect_callback_(disconnect_callback) {}
46
47Connection::Binder::~Binder() {
48  Attach(nullptr);
49}
50
51void Connection::Binder::Attach(const ConnectionRefPtr &to_connection) {
52  if (connection_) {
53    connection_->DetachBinder(this);
54    LOG(INFO) << name_ << ": unbound from connection: "
55              << connection_->interface_name();
56    connection_.reset();
57  }
58  if (to_connection) {
59    connection_ = to_connection->weak_ptr_factory_.GetWeakPtr();
60    connection_->AttachBinder(this);
61    LOG(INFO) << name_ << ": bound to connection: "
62              << connection_->interface_name();
63  }
64}
65
66void Connection::Binder::OnDisconnect() {
67  LOG(INFO) << name_ << ": bound connection disconnected: "
68            << connection_->interface_name();
69  connection_.reset();
70  if (!client_disconnect_callback_.is_null()) {
71    SLOG(connection_.get(), 2) << "Running client disconnect callback.";
72    client_disconnect_callback_.Run();
73  }
74}
75
76Connection::Connection(int interface_index,
77                       const std::string& interface_name,
78                       Technology::Identifier technology,
79                       const DeviceInfo *device_info)
80    : weak_ptr_factory_(this),
81      is_default_(false),
82      has_broadcast_domain_(false),
83      routing_request_count_(0),
84      interface_index_(interface_index),
85      interface_name_(interface_name),
86      technology_(technology),
87      local_(IPAddress::kFamilyUnknown),
88      gateway_(IPAddress::kFamilyUnknown),
89      lower_binder_(
90          interface_name_,
91          // Connection owns a single instance of |lower_binder_| so it's safe
92          // to use an Unretained callback.
93          Bind(&Connection::OnLowerDisconnect, Unretained(this))),
94      device_info_(device_info),
95      resolver_(Resolver::GetInstance()),
96      routing_table_(RoutingTable::GetInstance()),
97      rtnl_handler_(RTNLHandler::GetInstance()) {
98  SLOG(this, 2) << __func__ << "(" << interface_index << ", "
99                << interface_name << ", "
100                << Technology::NameFromIdentifier(technology) << ")";
101}
102
103Connection::~Connection() {
104  SLOG(this, 2) << __func__ << " " << interface_name_;
105
106  NotifyBindersOnDisconnect();
107
108  DCHECK(!routing_request_count_);
109  routing_table_->FlushRoutes(interface_index_);
110  routing_table_->FlushRoutesWithTag(interface_index_);
111  device_info_->FlushAddresses(interface_index_);
112}
113
114void Connection::UpdateFromIPConfig(const IPConfigRefPtr &config) {
115  SLOG(this, 2) << __func__ << " " << interface_name_;
116
117  const IPConfig::Properties &properties = config->properties();
118  IPAddress gateway(properties.address_family);
119  if (!properties.gateway.empty() &&
120      !gateway.SetAddressFromString(properties.gateway)) {
121    LOG(ERROR) << "Gateway address " << properties.gateway << " is invalid";
122    return;
123  }
124
125  IPAddress trusted_ip(properties.address_family);
126  if (!properties.trusted_ip.empty()) {
127    if (!trusted_ip.SetAddressFromString(properties.trusted_ip)) {
128      LOG(ERROR) << "Trusted IP address "
129                 << properties.trusted_ip << " is invalid";
130      return;
131    }
132    if (!PinHostRoute(trusted_ip, gateway)) {
133      LOG(ERROR) << "Unable to pin host route to " << properties.trusted_ip;
134      return;
135    }
136  }
137
138  IPAddress local(properties.address_family);
139  if (!local.SetAddressFromString(properties.address)) {
140    LOG(ERROR) << "Local address " << properties.address << " is invalid";
141    return;
142  }
143  local.set_prefix(properties.subnet_prefix);
144
145  IPAddress broadcast(properties.address_family);
146  if (properties.broadcast_address.empty()) {
147    if (properties.peer_address.empty()) {
148      LOG(WARNING) << "Broadcast address is not set.  Using default.";
149      broadcast = local.GetDefaultBroadcast();
150    }
151  } else if (!broadcast.SetAddressFromString(properties.broadcast_address)) {
152    LOG(ERROR) << "Broadcast address " << properties.broadcast_address
153               << " is invalid";
154    return;
155  }
156
157  IPAddress peer(properties.address_family);
158  if (!properties.peer_address.empty() &&
159      !peer.SetAddressFromString(properties.peer_address)) {
160    LOG(ERROR) << "Peer address " << properties.peer_address
161               << " is invalid";
162    return;
163  }
164
165  if (!FixGatewayReachability(&local, &peer, &gateway, trusted_ip)) {
166    LOG(WARNING) << "Expect limited network connectivity.";
167  }
168
169  if (device_info_->HasOtherAddress(interface_index_, local)) {
170    // The address has changed for this interface.  We need to flush
171    // everything and start over.
172    LOG(INFO) << __func__ << ": Flushing old addresses and routes.";
173    routing_table_->FlushRoutes(interface_index_);
174    device_info_->FlushAddresses(interface_index_);
175  }
176
177  LOG(INFO) << __func__ << ": Installing with parameters:"
178            << " local=" << local.ToString()
179            << " broadcast=" << broadcast.ToString()
180            << " peer=" << peer.ToString()
181            << " gateway=" << gateway.ToString();
182  rtnl_handler_->AddInterfaceAddress(interface_index_, local, broadcast, peer);
183
184  if (gateway.IsValid()) {
185    routing_table_->SetDefaultRoute(interface_index_, gateway,
186                                    GetMetric(is_default_));
187  }
188
189  // Install any explicitly configured routes at the default metric.
190  routing_table_->ConfigureRoutes(interface_index_, config, kDefaultMetric);
191
192  SetMTU(properties.mtu);
193
194  if (properties.blackhole_ipv6) {
195    routing_table_->CreateBlackholeRoute(interface_index_,
196                                         IPAddress::kFamilyIPv6,
197                                         kDefaultMetric);
198  }
199
200  // Save a copy of the last non-null DNS config.
201  if (!config->properties().dns_servers.empty()) {
202    dns_servers_ = config->properties().dns_servers;
203  }
204
205  if (!config->properties().domain_search.empty()) {
206    dns_domain_search_ = config->properties().domain_search;
207  }
208
209  if (!config->properties().domain_name.empty()) {
210    dns_domain_name_ = config->properties().domain_name;
211  }
212
213  ipconfig_rpc_identifier_ = config->GetRpcIdentifier();
214
215  PushDNSConfig();
216
217  local_ = local;
218  gateway_ = gateway;
219  has_broadcast_domain_ = !peer.IsValid();
220}
221
222void Connection::SetIsDefault(bool is_default) {
223  SLOG(this, 2) << __func__ << " " << interface_name_
224                << " (index " << interface_index_ << ") "
225                << is_default_ << " -> " << is_default;
226  if (is_default == is_default_) {
227    return;
228  }
229
230  routing_table_->SetDefaultMetric(interface_index_, GetMetric(is_default));
231
232  is_default_ = is_default;
233
234  PushDNSConfig();
235  if (is_default) {
236    DeviceRefPtr device = device_info_->GetDevice(interface_index_);
237    if (device) {
238      device->RequestPortalDetection();
239    }
240  }
241  routing_table_->FlushCache();
242}
243
244void Connection::UpdateDNSServers(const vector<string> &dns_servers) {
245  dns_servers_ = dns_servers;
246  PushDNSConfig();
247}
248
249void Connection::PushDNSConfig() {
250  if (!is_default_) {
251    return;
252  }
253
254  vector<string> domain_search = dns_domain_search_;
255  if (domain_search.empty() && !dns_domain_name_.empty()) {
256    SLOG(this, 2) << "Setting domain search to domain name "
257                  << dns_domain_name_;
258    domain_search.push_back(dns_domain_name_ + ".");
259  }
260  resolver_->SetDNSFromLists(dns_servers_, domain_search);
261}
262
263void Connection::RequestRouting() {
264  if (routing_request_count_++ == 0) {
265    DeviceRefPtr device = device_info_->GetDevice(interface_index_);
266    DCHECK(device.get());
267    if (!device.get()) {
268      LOG(ERROR) << "Device is NULL!";
269      return;
270    }
271    device->SetLooseRouting(true);
272  }
273}
274
275void Connection::ReleaseRouting() {
276  DCHECK_GT(routing_request_count_, 0);
277  if (--routing_request_count_ == 0) {
278    DeviceRefPtr device = device_info_->GetDevice(interface_index_);
279    DCHECK(device.get());
280    if (!device.get()) {
281      LOG(ERROR) << "Device is NULL!";
282      return;
283    }
284    device->SetLooseRouting(false);
285
286    // Clear any cached routes that might have accumulated while reverse-path
287    // filtering was disabled.
288    routing_table_->FlushCache();
289  }
290}
291
292bool Connection::RequestHostRoute(const IPAddress &address) {
293  // Set the prefix to be the entire address size.
294  IPAddress address_prefix(address);
295  address_prefix.set_prefix(address_prefix.GetLength() * 8);
296
297  // Do not set interface_index_ since this may not be the default route through
298  // which this destination can be found.  However, we should tag the created
299  // route with our interface index so we can clean this route up when this
300  // connection closes.  Also, add route query callback to determine the lower
301  // connection and bind to it.
302  if (!routing_table_->RequestRouteToHost(
303          address_prefix,
304          -1,
305          interface_index_,
306          Bind(&Connection::OnRouteQueryResponse,
307               weak_ptr_factory_.GetWeakPtr()))) {
308    LOG(ERROR) << "Could not request route to " << address.ToString();
309    return false;
310  }
311
312  return true;
313}
314
315string Connection::GetSubnetName() const {
316  if (!local().IsValid()) {
317    return "";
318  }
319  return base::StringPrintf("%s/%d",
320                            local().GetNetworkPart().ToString().c_str(),
321                            local().prefix());
322}
323
324// static
325bool Connection::FixGatewayReachability(IPAddress *local,
326                                        IPAddress *peer,
327                                        IPAddress *gateway,
328                                        const IPAddress &trusted_ip) {
329  if (!gateway->IsValid()) {
330    LOG(WARNING) << "No gateway address was provided for this connection.";
331    return false;
332  }
333
334  if (peer->IsValid()) {
335    if (!gateway->Equals(*peer)) {
336      LOG(WARNING) << "Gateway address "
337                   << gateway->ToString()
338                   << " does not match peer address "
339                   << peer->ToString();
340      return false;
341    }
342    if (gateway->Equals(trusted_ip)) {
343      // In order to send outgoing traffic in a point-to-point network,
344      // the gateway IP address isn't of significance.  As opposed to
345      // broadcast networks, we never ARP for the gateway IP address,
346      // but just send the IP packet addressed to the recipient.  As
347      // such, since using the external trusted IP address as the
348      // gateway or peer wreaks havoc on the routing rules, we choose
349      // not to supply a gateway address.  Here's an example:
350      //
351      //     Client    <->  Internet  <->  VPN Gateway  <->  Internal Network
352      //   192.168.1.2                      10.0.1.25         172.16.5.0/24
353      //
354      // In this example, a client connects to a VPN gateway on its
355      // public IP address 10.0.1.25.  It gets issued an IP address
356      // from the VPN internal pool.  For some VPN gateways, this
357      // results in a pushed-down PPP configuration which specifies:
358      //
359      //    Client local address:   172.16.5.13
360      //    Client peer address:    10.0.1.25
361      //    Client default gateway: 10.0.1.25
362      //
363      // If we take this literally, we need to resolve the fact that
364      // 10.0.1.25 is now listed as the default gateway and interface
365      // peer address for the point-to-point interface.  However, in
366      // order to route tunneled packets to the VPN gateway we must
367      // use the external route through the physical interface and
368      // not the tunnel, or else we end up in an infinite loop
369      // re-entering the tunnel trying to route towards the VPN server.
370      //
371      // We can do this by pinning a route, but we would need to wait
372      // for the pinning process to complete before assigning this
373      // address.  Currently this process is asynchronous and will
374      // complete only after returning to the event loop.  Additionally,
375      // since there's no metric associated with assigning an address
376      // to an interface, it's always possible that having the peer
377      // address of the interface might still trump a host route.
378      //
379      // To solve this problem, we reset the peer and gateway
380      // addresses.  Neither is required in order to perform the
381      // underlying routing task.  A gateway route can be specified
382      // without an IP endpoint on point-to-point links, and simply
383      // specify the outbound interface index.  Similarly, a peer
384      // IP address is not necessary either, and will be assigned
385      // the same IP address as the local IP.  This approach
386      // simplifies routing and doesn't change the desired
387      // functional behavior.
388      //
389      LOG(INFO) << "Removing gateway and peer addresses to preserve "
390                << "routability to trusted IP address.";
391      peer->SetAddressToDefault();
392      gateway->SetAddressToDefault();
393    }
394    return true;
395  }
396
397  if (local->CanReachAddress(*gateway)) {
398    return true;
399  }
400
401  LOG(WARNING) << "Gateway "
402               << gateway->ToString()
403               << " is unreachable from local address/prefix "
404               << local->ToString() << "/" << local->prefix();
405
406  bool found_new_prefix = false;
407  size_t original_prefix = local->prefix();
408  // Only try to expand the netmask if the configured prefix is
409  // less than "all ones".  This special-cases the "all-ones"
410  // prefix as a forced conversion to point-to-point networking.
411  if (local->prefix() < IPAddress::GetMaxPrefixLength(local->family())) {
412    size_t prefix = original_prefix - 1;
413    for (; prefix >= local->GetMinPrefixLength(); --prefix) {
414      local->set_prefix(prefix);
415      if (local->CanReachAddress(*gateway)) {
416        found_new_prefix = true;
417        break;
418      }
419    }
420  }
421
422  if (!found_new_prefix) {
423    // Restore the original prefix since we cannot find a better one.
424    local->set_prefix(original_prefix);
425    DCHECK(!peer->IsValid());
426    LOG(WARNING) << "Assuming point-to-point configuration.";
427    *peer = *gateway;
428    return true;
429  }
430
431  LOG(WARNING) << "Mitigating this by setting local prefix to "
432               << local->prefix();
433  return true;
434}
435
436uint32_t Connection::GetMetric(bool is_default) {
437  // If this is not the default route, assign a metric based on the interface
438  // index.  This way all non-default routes (even to the same gateway IP) end
439  // up with unique metrics so they do not collide.
440  return is_default ? kDefaultMetric : kNonDefaultMetricBase + interface_index_;
441}
442
443bool Connection::PinHostRoute(const IPAddress &trusted_ip,
444                              const IPAddress &gateway) {
445  SLOG(this, 2) << __func__;
446  if (!trusted_ip.IsValid()) {
447    LOG(ERROR) << "No trusted IP -- unable to pin host route.";
448    return false;
449  }
450
451  if (!gateway.IsValid()) {
452    // Although we cannot pin a host route, we are also not going to create
453    // a gateway route that will interfere with our primary connection, so
454    // it is okay to return success here.
455    LOG(WARNING) << "No gateway -- unable to pin host route.";
456    return true;
457  }
458
459  return RequestHostRoute(trusted_ip);
460}
461
462void Connection::SetMTU(int32_t mtu) {
463  SLOG(this, 2) << __func__ << " " << mtu;
464  // Make sure the MTU value is valid.
465  if (mtu == IPConfig::kUndefinedMTU) {
466    mtu = IPConfig::kDefaultMTU;
467  } else {
468    int min_mtu = IsIPv6() ? IPConfig::kMinIPv6MTU : IPConfig::kMinIPv4MTU;
469    if (mtu < min_mtu) {
470      SLOG(this, 2) << __func__ << " MTU " << mtu
471                    << " is too small; adjusting up to " << min_mtu;
472      mtu = min_mtu;
473    }
474  }
475
476  rtnl_handler_->SetInterfaceMTU(interface_index_, mtu);
477}
478
479void Connection::OnRouteQueryResponse(int interface_index,
480                                      const RoutingTableEntry &entry) {
481  SLOG(this, 2) << __func__ << "(" << interface_index << ", "
482                << entry.tag << ")" << " @ " << interface_name_;
483  lower_binder_.Attach(nullptr);
484  DeviceRefPtr device = device_info_->GetDevice(interface_index);
485  if (!device) {
486    LOG(ERROR) << "Unable to lookup device for index " << interface_index;
487    return;
488  }
489  ConnectionRefPtr connection = device->connection();
490  if (!connection) {
491    LOG(ERROR) << "Device " << interface_index << " has no connection.";
492    return;
493  }
494  lower_binder_.Attach(connection);
495  connection->CreateGatewayRoute();
496  device->OnConnectionUpdated();
497}
498
499bool Connection::CreateGatewayRoute() {
500  // Ensure that the gateway for the lower connection remains reachable,
501  // since we may create routes that conflict with it.
502  if (!has_broadcast_domain_) {
503    return false;
504  }
505
506  // If there is no gateway, don't try to create a route to it.
507  if (!gateway_.IsValid()) {
508    return false;
509  }
510
511  // It is not worth keeping track of this route, since it is benign,
512  // and only pins persistent state that was already true of the connection.
513  // If DHCP parameters change later (without the connection having been
514  // destroyed and recreated), the binding processes will likely terminate
515  // and restart, causing a new link route to be created.
516  return routing_table_->CreateLinkRoute(interface_index_, local_, gateway_);
517}
518
519void Connection::OnLowerDisconnect() {
520  SLOG(this, 2) << __func__ << " @ " << interface_name_;
521  // Ensures that |this| instance doesn't get destroyed in the middle of
522  // notifying the binders. This method needs to be separate from
523  // NotifyBindersOnDisconnect because the latter may be invoked by Connection's
524  // destructor when |this| instance's reference count is already 0.
525  ConnectionRefPtr connection(this);
526  connection->NotifyBindersOnDisconnect();
527}
528
529void Connection::NotifyBindersOnDisconnect() {
530  // Note that this method may be invoked by the destructor.
531  SLOG(this, 2) << __func__ << " @ " << interface_name_;
532
533  // Unbinds the lower connection before notifying the binders. This ensures
534  // correct behavior in case of circular binding.
535  lower_binder_.Attach(nullptr);
536  while (!binders_.empty()) {
537    // Pop the binder first and then notify it to ensure that each binder is
538    // notified only once.
539    Binder *binder = binders_.front();
540    binders_.pop_front();
541    binder->OnDisconnect();
542  }
543}
544
545void Connection::AttachBinder(Binder *binder) {
546  SLOG(this, 2) << __func__ << "(" << binder->name() << ")" << " @ "
547                            << interface_name_;
548  binders_.push_back(binder);
549}
550
551void Connection::DetachBinder(Binder *binder) {
552  SLOG(this, 2) << __func__ << "(" << binder->name() << ")" << " @ "
553                            << interface_name_;
554  for (auto it = binders_.begin(); it != binders_.end(); ++it) {
555    if (binder == *it) {
556      binders_.erase(it);
557      return;
558    }
559  }
560}
561
562ConnectionRefPtr Connection::GetCarrierConnection() {
563  SLOG(this, 2) << __func__ << " @ " << interface_name_;
564  set<Connection *> visited;
565  ConnectionRefPtr carrier = this;
566  while (carrier->GetLowerConnection()) {
567    if (ContainsKey(visited, carrier.get())) {
568      LOG(ERROR) << "Circular connection chain starting at: "
569                 << carrier->interface_name();
570      // If a loop is detected return a NULL value to signal that the carrier
571      // connection is unknown.
572      return nullptr;
573    }
574    visited.insert(carrier.get());
575    carrier = carrier->GetLowerConnection();
576  }
577  SLOG(this, 2) << "Carrier connection: " << carrier->interface_name()
578                << " @ " << interface_name_;
579  return carrier;
580}
581
582bool Connection::IsIPv6() {
583  return local_.family() == IPAddress::kFamilyIPv6;
584}
585
586}  // namespace shill
587