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