1//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "shill/device.h"
18
19#include <errno.h>
20#include <netinet/in.h>
21#include <linux/if.h>  // NOLINT - Needs definitions from netinet/in.h
22#include <stdio.h>
23#include <string.h>
24#include <sys/param.h>
25#include <time.h>
26#include <unistd.h>
27
28#include <algorithm>
29#include <set>
30#include <string>
31#include <vector>
32
33#include <base/bind.h>
34#include <base/files/file_util.h>
35#include <base/memory/ref_counted.h>
36#include <base/stl_util.h>
37#include <base/strings/stringprintf.h>
38#include <base/strings/string_number_conversions.h>
39#include <base/strings/string_util.h>
40#if defined(__ANDROID__)
41#include <dbus/service_constants.h>
42#else
43#include <chromeos/dbus/service_constants.h>
44#endif  // __ANDROID__
45
46#include "shill/async_connection.h"
47#include "shill/connection.h"
48#include "shill/connection_tester.h"
49#include "shill/control_interface.h"
50#include "shill/dhcp/dhcp_config.h"
51#include "shill/dhcp/dhcp_provider.h"
52#include "shill/dhcp_properties.h"
53#include "shill/error.h"
54#include "shill/event_dispatcher.h"
55#include "shill/geolocation_info.h"
56#include "shill/http_proxy.h"
57#include "shill/icmp.h"
58#include "shill/ip_address_store.h"
59#include "shill/link_monitor.h"
60#include "shill/logging.h"
61#include "shill/manager.h"
62#include "shill/metrics.h"
63#include "shill/net/ip_address.h"
64#include "shill/net/ndisc.h"
65#include "shill/net/rtnl_handler.h"
66#include "shill/property_accessor.h"
67#include "shill/refptr_types.h"
68#include "shill/service.h"
69#include "shill/socket_info_reader.h"
70#include "shill/store_interface.h"
71#include "shill/technology.h"
72#include "shill/tethering.h"
73#include "shill/traffic_monitor.h"
74
75using base::Bind;
76using base::Callback;
77using base::FilePath;
78using base::StringPrintf;
79using std::set;
80using std::string;
81using std::vector;
82
83namespace shill {
84
85namespace Logging {
86static auto kModuleLogScope = ScopeLogger::kDevice;
87static string ObjectID(Device* d) { return d->GetRpcIdentifier(); }
88}
89
90// static
91const char Device::kIPFlagTemplate[] = "/proc/sys/net/%s/conf/%s/%s";
92// static
93const char Device::kIPFlagVersion4[] = "ipv4";
94// static
95const char Device::kIPFlagVersion6[] = "ipv6";
96// static
97const char Device::kIPFlagDisableIPv6[] = "disable_ipv6";
98// static
99const char Device::kIPFlagUseTempAddr[] = "use_tempaddr";
100// static
101const char Device::kIPFlagUseTempAddrUsedAndDefault[] = "2";
102// static
103const char Device::kIPFlagReversePathFilter[] = "rp_filter";
104// static
105const char Device::kIPFlagReversePathFilterEnabled[] = "1";
106// static
107const char Device::kIPFlagReversePathFilterLooseMode[] = "2";
108// static
109const char Device::kIPFlagArpAnnounce[] = "arp_announce";
110// static
111const char Device::kIPFlagArpAnnounceDefault[] = "0";
112// static
113const char Device::kIPFlagArpAnnounceBestLocal[] = "2";
114// static
115const char Device::kIPFlagArpIgnore[] = "arp_ignore";
116// static
117const char Device::kIPFlagArpIgnoreDefault[] = "0";
118// static
119const char Device::kIPFlagArpIgnoreLocalOnly[] = "1";
120// static
121const char Device::kStoragePowered[] = "Powered";
122// static
123const char Device::kStorageReceiveByteCount[] = "ReceiveByteCount";
124// static
125const char Device::kStorageTransmitByteCount[] = "TransmitByteCount";
126// static
127const char Device::kFallbackDnsTestHostname[] = "www.gstatic.com";
128// static
129const char* Device::kFallbackDnsServers[] = {
130    "8.8.8.8",
131    "8.8.4.4"
132};
133
134// static
135const int Device::kDNSTimeoutMilliseconds = 5000;
136const int Device::kLinkUnreliableThresholdSeconds = 60 * 60;
137const size_t Device::kHardwareAddressLength = 6U;
138
139Device::Device(ControlInterface* control_interface,
140               EventDispatcher* dispatcher,
141               Metrics* metrics,
142               Manager* manager,
143               const string& link_name,
144               const string& address,
145               int interface_index,
146               Technology::Identifier technology)
147    : enabled_(false),
148      enabled_persistent_(true),
149      enabled_pending_(enabled_),
150      reconnect_(true),
151      hardware_address_(address),
152      interface_index_(interface_index),
153      running_(false),
154      link_name_(link_name),
155      unique_id_(link_name),
156      control_interface_(control_interface),
157      dispatcher_(dispatcher),
158      metrics_(metrics),
159      manager_(manager),
160      weak_ptr_factory_(this),
161      adaptor_(control_interface->CreateDeviceAdaptor(this)),
162      portal_detector_callback_(Bind(&Device::PortalDetectorCallback,
163                                     weak_ptr_factory_.GetWeakPtr())),
164      technology_(technology),
165      portal_attempts_to_online_(0),
166      receive_byte_offset_(0),
167      transmit_byte_offset_(0),
168      dhcp_provider_(DHCPProvider::GetInstance()),
169      rtnl_handler_(RTNLHandler::GetInstance()),
170      time_(Time::GetInstance()),
171      last_link_monitor_failed_time_(0),
172      connection_tester_callback_(Bind(&Device::ConnectionTesterCallback,
173                                       weak_ptr_factory_.GetWeakPtr())),
174      is_loose_routing_(false),
175      is_multi_homed_(false),
176      connection_diagnostics_callback_(
177          Bind(&Device::ConnectionDiagnosticsCallback,
178               weak_ptr_factory_.GetWeakPtr())) {
179  store_.RegisterConstString(kAddressProperty, &hardware_address_);
180
181  // kBgscanMethodProperty: Registered in WiFi
182  // kBgscanShortIntervalProperty: Registered in WiFi
183  // kBgscanSignalThresholdProperty: Registered in WiFi
184
185  // kCellularAllowRoamingProperty: Registered in Cellular
186  // kCarrierProperty: Registered in Cellular
187  // kEsnProperty: Registered in Cellular
188  // kHomeProviderProperty: Registered in Cellular
189  // kImeiProperty: Registered in Cellular
190  // kIccidProperty: Registered in Cellular
191  // kImsiProperty: Registered in Cellular
192  // kManufacturerProperty: Registered in Cellular
193  // kMdnProperty: Registered in Cellular
194  // kMeidProperty: Registered in Cellular
195  // kMinProperty: Registered in Cellular
196  // kModelIDProperty: Registered in Cellular
197  // kFirmwareRevisionProperty: Registered in Cellular
198  // kHardwareRevisionProperty: Registered in Cellular
199  // kPRLVersionProperty: Registered in Cellular
200  // kSIMLockStatusProperty: Registered in Cellular
201  // kFoundNetworksProperty: Registered in Cellular
202  // kDBusObjectProperty: Register in Cellular
203
204  store_.RegisterConstString(kInterfaceProperty, &link_name_);
205  HelpRegisterConstDerivedRpcIdentifier(
206      kSelectedServiceProperty, &Device::GetSelectedServiceRpcIdentifier);
207  HelpRegisterConstDerivedRpcIdentifiers(kIPConfigsProperty,
208                                         &Device::AvailableIPConfigs);
209  store_.RegisterConstString(kNameProperty, &link_name_);
210  store_.RegisterConstBool(kPoweredProperty, &enabled_);
211  HelpRegisterConstDerivedString(kTypeProperty,
212                                 &Device::GetTechnologyString);
213  HelpRegisterConstDerivedUint64(kLinkMonitorResponseTimeProperty,
214                                 &Device::GetLinkMonitorResponseTime);
215
216  // TODO(cmasone): Chrome doesn't use this...does anyone?
217  // store_.RegisterConstBool(kReconnectProperty, &reconnect_);
218
219  // TODO(cmasone): Figure out what shill concept maps to flimflam's "Network".
220  // known_properties_.push_back(kNetworksProperty);
221
222  // kRoamThresholdProperty: Registered in WiFi
223  // kScanningProperty: Registered in WiFi, Cellular
224  // kScanIntervalProperty: Registered in WiFi, Cellular
225  // kWakeOnWiFiFeaturesEnabledProperty: Registered in WiFi
226
227  if (manager_ && manager_->device_info()) {  // Unit tests may not have these.
228    manager_->device_info()->GetByteCounts(
229        interface_index_, &receive_byte_offset_, &transmit_byte_offset_);
230    HelpRegisterConstDerivedUint64(kReceiveByteCountProperty,
231                                   &Device::GetReceiveByteCountProperty);
232    HelpRegisterConstDerivedUint64(kTransmitByteCountProperty,
233                                   &Device::GetTransmitByteCountProperty);
234  }
235
236  LOG(INFO) << "Device created: " << link_name_
237            << " index " << interface_index_;
238}
239
240Device::~Device() {
241  LOG(INFO) << "Device destructed: " << link_name_
242            << " index " << interface_index_;
243}
244
245void Device::Initialize() {
246  SLOG(this, 2) << "Initialized";
247  DisableArpFiltering();
248  EnableReversePathFilter();
249}
250
251void Device::LinkEvent(unsigned flags, unsigned change) {
252  SLOG(this, 2) << "Device " << link_name_
253                << std::showbase << std::hex
254                << " flags " << flags << " changed " << change
255                << std::dec << std::noshowbase;
256}
257
258void Device::Scan(ScanType scan_type, Error* error, const string& reason) {
259  SLOG(this, 2) << __func__ << " [Device] on " << link_name() << " from "
260                << reason;
261  Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
262                        "Device doesn't support scan.");
263}
264
265void Device::SetSchedScan(bool enable, Error* error) {
266  SLOG(this, 2) << __func__ << " [Device] on " << link_name();
267  Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
268                        "Device doesn't support scheduled scan.");
269}
270
271void Device::RegisterOnNetwork(const std::string& /*network_id*/, Error* error,
272                                 const ResultCallback& /*callback*/) {
273  Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
274                        "Device doesn't support network registration.");
275}
276
277void Device::RequirePIN(
278    const string& /*pin*/, bool /*require*/,
279    Error* error, const ResultCallback& /*callback*/) {
280  SLOG(this, 2) << __func__;
281  Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
282                        "Device doesn't support RequirePIN.");
283}
284
285void Device::EnterPIN(const string& /*pin*/,
286                      Error* error, const ResultCallback& /*callback*/) {
287  SLOG(this, 2) << __func__;
288  Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
289                        "Device doesn't support EnterPIN.");
290}
291
292void Device::UnblockPIN(const string& /*unblock_code*/,
293                        const string& /*pin*/,
294                        Error* error, const ResultCallback& /*callback*/) {
295  SLOG(this, 2) << __func__;
296  Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
297                        "Device doesn't support UnblockPIN.");
298}
299
300void Device::ChangePIN(const string& /*old_pin*/,
301                       const string& /*new_pin*/,
302                       Error* error, const ResultCallback& /*callback*/) {
303  SLOG(this, 2) << __func__;
304  Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
305                        "Device doesn't support ChangePIN.");
306}
307
308void Device::Reset(Error* error, const ResultCallback& /*callback*/) {
309  SLOG(this, 2) << __func__;
310  Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
311                        "Device doesn't support Reset.");
312}
313
314void Device::SetCarrier(const string& /*carrier*/,
315                        Error* error, const ResultCallback& /*callback*/) {
316  SLOG(this, 2) << __func__;
317  Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
318                        "Device doesn't support SetCarrier.");
319}
320
321bool Device::IsIPv6Allowed() const {
322  return true;
323}
324
325void Device::DisableIPv6() {
326  SLOG(this, 2) << __func__;
327  SetIPFlag(IPAddress::kFamilyIPv6, kIPFlagDisableIPv6, "1");
328}
329
330void Device::EnableIPv6() {
331  SLOG(this, 2) << __func__;
332  if (!IsIPv6Allowed()) {
333    LOG(INFO) << "Skip enabling IPv6 on " << link_name_
334              << " as it is not allowed.";
335    return;
336  }
337  SetIPFlag(IPAddress::kFamilyIPv6, kIPFlagDisableIPv6, "0");
338}
339
340void Device::EnableIPv6Privacy() {
341  SetIPFlag(IPAddress::kFamilyIPv6, kIPFlagUseTempAddr,
342            kIPFlagUseTempAddrUsedAndDefault);
343}
344
345void Device::SetLooseRouting(bool is_loose_routing) {
346  if (is_loose_routing == is_loose_routing_) {
347    return;
348  }
349  is_loose_routing_ = is_loose_routing;
350  if (is_multi_homed_) {
351    // Nothing to do: loose routing is already enabled, and should remain so.
352    return;
353  }
354  if (is_loose_routing) {
355    DisableReversePathFilter();
356  } else {
357    EnableReversePathFilter();
358  }
359}
360
361void Device::DisableReversePathFilter() {
362  // TODO(pstew): Current kernel doesn't offer reverse-path filtering flag
363  // for IPv6.  crbug.com/207193
364  SetIPFlag(IPAddress::kFamilyIPv4, kIPFlagReversePathFilter,
365            kIPFlagReversePathFilterLooseMode);
366}
367
368void Device::EnableReversePathFilter() {
369  SetIPFlag(IPAddress::kFamilyIPv4, kIPFlagReversePathFilter,
370            kIPFlagReversePathFilterEnabled);
371}
372
373void Device::SetIsMultiHomed(bool is_multi_homed) {
374  if (is_multi_homed == is_multi_homed_) {
375    return;
376  }
377  LOG(INFO) << "Device " << FriendlyName() << " multi-home state is now "
378            << is_multi_homed;
379  is_multi_homed_ = is_multi_homed;
380  if (is_multi_homed) {
381    EnableArpFiltering();
382    if (!is_loose_routing_) {
383      DisableReversePathFilter();
384    }
385  } else {
386    DisableArpFiltering();
387    if (!is_loose_routing_) {
388      EnableReversePathFilter();
389    }
390  }
391}
392
393void Device::DisableArpFiltering() {
394  SetIPFlag(IPAddress::kFamilyIPv4, kIPFlagArpAnnounce,
395            kIPFlagArpAnnounceDefault);
396  SetIPFlag(IPAddress::kFamilyIPv4, kIPFlagArpIgnore, kIPFlagArpIgnoreDefault);
397}
398
399void Device::EnableArpFiltering() {
400  SetIPFlag(IPAddress::kFamilyIPv4, kIPFlagArpAnnounce,
401            kIPFlagArpAnnounceBestLocal);
402  SetIPFlag(IPAddress::kFamilyIPv4, kIPFlagArpIgnore,
403            kIPFlagArpIgnoreLocalOnly);
404}
405
406bool Device::IsConnected() const {
407  if (selected_service_)
408    return selected_service_->IsConnected();
409  return false;
410}
411
412bool Device::IsConnectedToService(const ServiceRefPtr& service) const {
413  return service == selected_service_ && IsConnected();
414}
415
416bool Device::IsConnectedViaTether() const {
417  if (!ipconfig_.get())
418    return false;
419
420  ByteArray vendor_encapsulated_options =
421      ipconfig_->properties().vendor_encapsulated_options;
422  size_t android_vendor_encapsulated_options_len =
423      strlen(Tethering::kAndroidVendorEncapsulatedOptions);
424
425  return (vendor_encapsulated_options.size() ==
426          android_vendor_encapsulated_options_len) &&
427      !memcmp(&vendor_encapsulated_options[0],
428              Tethering::kAndroidVendorEncapsulatedOptions,
429              vendor_encapsulated_options.size());
430}
431
432string Device::GetRpcIdentifier() const {
433  return adaptor_->GetRpcIdentifier();
434}
435
436string Device::GetStorageIdentifier() const {
437  string id = GetRpcIdentifier();
438  ControlInterface::RpcIdToStorageId(&id);
439  size_t needle = id.find('_');
440  DLOG_IF(ERROR, needle == string::npos) << "No _ in storage id?!?!";
441  id.replace(id.begin() + needle + 1, id.end(), hardware_address_);
442  return id;
443}
444
445vector<GeolocationInfo> Device::GetGeolocationObjects() const {
446  return vector<GeolocationInfo>();
447}
448
449string Device::GetTechnologyString(Error* /*error*/) {
450  return Technology::NameFromIdentifier(technology());
451}
452
453const string& Device::FriendlyName() const {
454  return link_name_;
455}
456
457const string& Device::UniqueName() const {
458  return unique_id_;
459}
460
461bool Device::Load(StoreInterface* storage) {
462  const string id = GetStorageIdentifier();
463  if (!storage->ContainsGroup(id)) {
464    SLOG(this, 2) << "Device is not available in the persistent store: " << id;
465    return false;
466  }
467  enabled_persistent_ = true;
468  storage->GetBool(id, kStoragePowered, &enabled_persistent_);
469  uint64_t rx_byte_count = 0, tx_byte_count = 0;
470
471  manager_->device_info()->GetByteCounts(
472      interface_index_, &rx_byte_count, &tx_byte_count);
473  // If there is a byte-count present in the profile, the return value
474  // of Device::Get*ByteCount() should be the this stored value plus
475  // whatever additional bytes we receive since time-of-load.  We
476  // accomplish this by the subtractions below, which can validly
477  // roll over "negative" in the subtractions below and in Get*ByteCount.
478  uint64_t profile_byte_count;
479  if (storage->GetUint64(id, kStorageReceiveByteCount, &profile_byte_count)) {
480    receive_byte_offset_ = rx_byte_count - profile_byte_count;
481  }
482  if (storage->GetUint64(id, kStorageTransmitByteCount, &profile_byte_count)) {
483    transmit_byte_offset_ = tx_byte_count - profile_byte_count;
484  }
485
486  return true;
487}
488
489bool Device::Save(StoreInterface* storage) {
490  const string id = GetStorageIdentifier();
491  storage->SetBool(id, kStoragePowered, enabled_persistent_);
492  storage->SetUint64(id, kStorageReceiveByteCount, GetReceiveByteCount());
493  storage->SetUint64(id, kStorageTransmitByteCount, GetTransmitByteCount());
494  return true;
495}
496
497void Device::OnBeforeSuspend(const ResultCallback& callback) {
498  // Nothing to be done in the general case, so immediately report success.
499  callback.Run(Error(Error::kSuccess));
500}
501
502void Device::OnAfterResume() {
503  RenewDHCPLease();
504  if (link_monitor_) {
505    SLOG(this, 3) << "Informing Link Monitor of resume.";
506    link_monitor_->OnAfterResume();
507  }
508  // Resume from sleep, could be in different location now.
509  // Ignore previous link monitor failures.
510  if (selected_service_) {
511    selected_service_->set_unreliable(false);
512    reliable_link_callback_.Cancel();
513  }
514  last_link_monitor_failed_time_ = 0;
515}
516
517void Device::OnDarkResume(const ResultCallback& callback) {
518  // Nothing to be done in the general case, so immediately report success.
519  callback.Run(Error(Error::kSuccess));
520}
521
522void Device::DropConnection() {
523  SLOG(this, 2) << __func__;
524  DestroyIPConfig();
525  SelectService(nullptr);
526}
527
528void Device::DestroyIPConfig() {
529  DisableIPv6();
530  bool ipconfig_changed = false;
531  if (ipconfig_.get()) {
532    ipconfig_->ReleaseIP(IPConfig::kReleaseReasonDisconnect);
533    ipconfig_ = nullptr;
534    ipconfig_changed = true;
535  }
536  if (ip6config_.get()) {
537    StopIPv6DNSServerTimer();
538    ip6config_ = nullptr;
539    ipconfig_changed = true;
540  }
541  if (dhcpv6_config_.get()) {
542    dhcpv6_config_->ReleaseIP(IPConfig::kReleaseReasonDisconnect);
543    dhcpv6_config_ = nullptr;
544    ipconfig_changed = true;
545  }
546  // Emit updated IP configs if there are any changes.
547  if (ipconfig_changed) {
548    UpdateIPConfigsProperty();
549  }
550  DestroyConnection();
551}
552
553void Device::OnIPv6AddressChanged() {
554  IPAddress address(IPAddress::kFamilyIPv6);
555  if (!manager_->device_info()->GetPrimaryIPv6Address(
556          interface_index_, &address)) {
557    if (ip6config_) {
558      ip6config_ = nullptr;
559      UpdateIPConfigsProperty();
560    }
561    return;
562  }
563
564  IPConfig::Properties properties;
565  if (!address.IntoString(&properties.address)) {
566    LOG(ERROR) << "Unable to convert IPv6 address into a string!";
567    return;
568  }
569  properties.subnet_prefix = address.prefix();
570
571  if (!ip6config_) {
572    ip6config_ = new IPConfig(control_interface_, link_name_);
573  } else if (properties.address == ip6config_->properties().address &&
574             properties.subnet_prefix ==
575                 ip6config_->properties().subnet_prefix) {
576    SLOG(this, 2) << __func__ << " primary address for "
577                  << link_name_ << " is unchanged.";
578    return;
579  }
580
581  properties.address_family = IPAddress::kFamilyIPv6;
582  properties.method = kTypeIPv6;
583  // It is possible for device to receive DNS server notification before IP
584  // address notification, so preserve the saved DNS server if it exist.
585  properties.dns_servers = ip6config_->properties().dns_servers;
586  PrependDNSServers(IPAddress::kFamilyIPv6, &properties.dns_servers);
587  ip6config_->set_properties(properties);
588  UpdateIPConfigsProperty();
589  OnIPv6ConfigUpdated();
590}
591
592void Device::OnIPv6DnsServerAddressesChanged() {
593  vector<IPAddress> server_addresses;
594  uint32_t lifetime = 0;
595
596  // Stop any existing timer.
597  StopIPv6DNSServerTimer();
598
599  if (!manager_->device_info()->GetIPv6DnsServerAddresses(
600          interface_index_, &server_addresses, &lifetime)  || lifetime == 0) {
601    IPv6DNSServerExpired();
602    return;
603  }
604
605  vector<string> addresses_str;
606  for (const auto& ip : server_addresses) {
607    string address_str;
608    if (!ip.IntoString(&address_str)) {
609      LOG(ERROR) << "Unable to convert IPv6 address into a string!";
610      IPv6DNSServerExpired();
611      return;
612    }
613    addresses_str.push_back(address_str);
614  }
615
616  if (!ip6config_) {
617    ip6config_ = new IPConfig(control_interface_, link_name_);
618  }
619
620  if (lifetime != ND_OPT_LIFETIME_INFINITY) {
621    // Setup timer to monitor DNS server lifetime if not infinite lifetime.
622    StartIPv6DNSServerTimer(lifetime);
623    ip6config_->UpdateLeaseExpirationTime(lifetime);
624  } else {
625    ip6config_->ResetLeaseExpirationTime();
626  }
627
628  PrependDNSServers(IPAddress::kFamilyIPv6, &addresses_str);
629
630  // Done if no change in server addresses.
631  if (ip6config_->properties().dns_servers == addresses_str) {
632    SLOG(this, 2) << __func__ << " IPv6 DNS server list for "
633                  << link_name_ << " is unchanged.";
634    return;
635  }
636
637  ip6config_->UpdateDNSServers(addresses_str);
638  UpdateIPConfigsProperty();
639  OnIPv6ConfigUpdated();
640}
641
642void Device::StartIPv6DNSServerTimer(uint32_t lifetime_seconds) {
643  int64_t delay = static_cast<int64_t>(lifetime_seconds) * 1000;
644  ipv6_dns_server_expired_callback_.Reset(
645      base::Bind(&Device::IPv6DNSServerExpired, base::Unretained(this)));
646  dispatcher_->PostDelayedTask(ipv6_dns_server_expired_callback_.callback(),
647                               delay);
648}
649
650void Device::StopIPv6DNSServerTimer() {
651  ipv6_dns_server_expired_callback_.Cancel();
652}
653
654void Device::IPv6DNSServerExpired() {
655  if (!ip6config_) {
656    return;
657  }
658  ip6config_->UpdateDNSServers(vector<string>());
659  UpdateIPConfigsProperty();
660}
661
662void Device::StopAllActivities() {
663  StopTrafficMonitor();
664  StopPortalDetection();
665  StopConnectivityTest();
666  StopConnectionDiagnostics();
667  StopLinkMonitor();
668  StopDNSTest();
669  StopIPv6DNSServerTimer();
670}
671
672void Device::AddWakeOnPacketConnection(const string& ip_endpoint,
673                                       Error* error) {
674  Error::PopulateAndLog(
675      FROM_HERE, error, Error::kNotSupported,
676      "AddWakeOnPacketConnection not implemented for " + link_name_ + ".");
677  return;
678}
679
680void Device::RemoveWakeOnPacketConnection(const string& ip_endpoint,
681                                          Error* error) {
682  Error::PopulateAndLog(
683      FROM_HERE, error, Error::kNotSupported,
684      "RemoveWakeOnPacketConnection not implemented for " + link_name_ + ".");
685  return;
686}
687
688void Device::RemoveAllWakeOnPacketConnections(Error* error) {
689  Error::PopulateAndLog(
690      FROM_HERE, error, Error::kNotSupported,
691      "RemoveAllWakeOnPacketConnections not implemented for " + link_name_ +
692          ".");
693  return;
694}
695
696void Device::RenewDHCPLease() {
697  LOG(INFO) << __func__;
698
699  if (ipconfig_) {
700    SLOG(this, 3) << "Renewing IPv4 Address";
701    ipconfig_->RenewIP();
702  }
703  if (ip6config_) {
704    SLOG(this, 3) << "Waiting for new IPv6 configuration";
705    // Invalidate the old IPv6 configuration, will receive notifications
706    // from kernel for new IPv6 configuration if there is one.
707    StopIPv6DNSServerTimer();
708    ip6config_ = nullptr;
709    UpdateIPConfigsProperty();
710  }
711  if (dhcpv6_config_) {
712    SLOG(this, 3) << "Renewing DHCPv6 lease";
713    dhcpv6_config_->RenewIP();
714  }
715}
716
717bool Device::ShouldUseArpGateway() const {
718  return false;
719}
720
721bool Device::IsUsingStaticIP() const {
722  if (!selected_service_) {
723    return false;
724  }
725  return selected_service_->HasStaticIPAddress();
726}
727
728bool Device::IsUsingStaticNameServers() const {
729  if (!selected_service_) {
730    return false;
731  }
732  return selected_service_->HasStaticNameServers();
733}
734
735bool Device::AcquireIPConfig() {
736  return AcquireIPConfigWithLeaseName(string());
737}
738
739bool Device::AcquireIPConfigWithLeaseName(const string& lease_name) {
740  DestroyIPConfig();
741  EnableIPv6();
742  bool arp_gateway = manager_->GetArpGateway() && ShouldUseArpGateway();
743  DHCPConfigRefPtr dhcp_config;
744  if (selected_service_) {
745    dhcp_config =
746        dhcp_provider_->CreateIPv4Config(
747            link_name_,
748            lease_name,
749            arp_gateway,
750            *(DhcpProperties::Combine(
751                manager_->dhcp_properties(),
752                selected_service_->dhcp_properties())));
753
754  } else {
755    dhcp_config =
756        dhcp_provider_->CreateIPv4Config(link_name_,
757                                         lease_name,
758                                         arp_gateway,
759                                         manager_->dhcp_properties());
760  }
761  const int minimum_mtu = manager()->GetMinimumMTU();
762  if (minimum_mtu != IPConfig::kUndefinedMTU) {
763    dhcp_config->set_minimum_mtu(minimum_mtu);
764  }
765
766  ipconfig_ = dhcp_config;
767  ipconfig_->RegisterUpdateCallback(Bind(&Device::OnIPConfigUpdated,
768                                         weak_ptr_factory_.GetWeakPtr()));
769  ipconfig_->RegisterFailureCallback(Bind(&Device::OnIPConfigFailed,
770                                          weak_ptr_factory_.GetWeakPtr()));
771  ipconfig_->RegisterRefreshCallback(Bind(&Device::OnIPConfigRefreshed,
772                                          weak_ptr_factory_.GetWeakPtr()));
773  ipconfig_->RegisterExpireCallback(Bind(&Device::OnIPConfigExpired,
774                                         weak_ptr_factory_.GetWeakPtr()));
775  dispatcher_->PostTask(Bind(&Device::ConfigureStaticIPTask,
776                             weak_ptr_factory_.GetWeakPtr()));
777  if (!ipconfig_->RequestIP()) {
778    return false;
779  }
780
781#ifndef DISABLE_DHCPV6
782  // Only start DHCPv6 configuration instance only if DHCPv6 is enabled
783  // for this device.
784  if (manager_->IsDHCPv6EnabledForDevice(link_name_)) {
785    return AcquireIPv6ConfigWithLeaseName(lease_name);
786  }
787#endif  // DISABLE_DHCPV6
788  return true;
789}
790
791#ifndef DISABLE_DHCPV6
792bool Device::AcquireIPv6ConfigWithLeaseName(const string& lease_name) {
793  auto dhcpv6_config =
794      dhcp_provider_->CreateIPv6Config(link_name_, lease_name);
795  dhcpv6_config_ = dhcpv6_config;
796  dhcpv6_config_->RegisterUpdateCallback(
797      Bind(&Device::OnDHCPv6ConfigUpdated, weak_ptr_factory_.GetWeakPtr()));
798  dhcpv6_config_->RegisterFailureCallback(
799      Bind(&Device::OnDHCPv6ConfigFailed, weak_ptr_factory_.GetWeakPtr()));
800  dhcpv6_config_->RegisterExpireCallback(
801      Bind(&Device::OnDHCPv6ConfigExpired, weak_ptr_factory_.GetWeakPtr()));
802  if (!dhcpv6_config_->RequestIP()) {
803    return false;
804  }
805  return true;
806}
807#endif  // DISABLE_DHCPV6
808
809void Device::AssignIPConfig(const IPConfig::Properties& properties) {
810  DestroyIPConfig();
811  EnableIPv6();
812  ipconfig_ = new IPConfig(control_interface_, link_name_);
813  ipconfig_->set_properties(properties);
814  dispatcher_->PostTask(Bind(&Device::OnIPConfigUpdated,
815                             weak_ptr_factory_.GetWeakPtr(), ipconfig_, true));
816}
817
818void Device::DestroyIPConfigLease(const string& name) {
819  dhcp_provider_->DestroyLease(name);
820}
821
822void Device::HelpRegisterConstDerivedString(
823    const string& name,
824    string(Device::*get)(Error* error)) {
825  store_.RegisterDerivedString(
826      name,
827      StringAccessor(new CustomAccessor<Device, string>(this, get, nullptr)));
828}
829
830void Device::HelpRegisterConstDerivedRpcIdentifier(
831    const string& name,
832    RpcIdentifier(Device::*get)(Error* error)) {
833  store_.RegisterDerivedRpcIdentifier(
834      name,
835      RpcIdentifierAccessor(
836          new CustomAccessor<Device, RpcIdentifier>(this, get, nullptr)));
837}
838
839void Device::HelpRegisterConstDerivedRpcIdentifiers(
840    const string& name,
841    RpcIdentifiers(Device::*get)(Error*)) {
842  store_.RegisterDerivedRpcIdentifiers(
843      name,
844      RpcIdentifiersAccessor(
845          new CustomAccessor<Device, RpcIdentifiers>(this, get, nullptr)));
846}
847
848void Device::HelpRegisterConstDerivedUint64(
849    const string& name,
850    uint64_t(Device::*get)(Error*)) {
851  store_.RegisterDerivedUint64(
852      name,
853      Uint64Accessor(
854          new CustomAccessor<Device, uint64_t>(this, get, nullptr)));
855}
856
857void Device::ConnectionTesterCallback() {
858  LOG(INFO) << "Device " << FriendlyName() << ": Completed Connectivity Test";
859  return;
860}
861
862void Device::ConfigureStaticIPTask() {
863  SLOG(this, 2) << __func__ << " selected_service " << selected_service_.get()
864                << " ipconfig " << ipconfig_.get();
865
866  if (!selected_service_ || !ipconfig_) {
867    return;
868  }
869
870  if (IsUsingStaticIP()) {
871    SLOG(this, 2) << __func__ << " " << " configuring static IP parameters.";
872    // If the parameters contain an IP address, apply them now and bring
873    // the interface up.  When DHCP information arrives, it will supplement
874    // the static information.
875    OnIPConfigUpdated(ipconfig_, true);
876  } else {
877    // Either |ipconfig_| has just been created in AcquireIPConfig() or
878    // we're being called by OnIPConfigRefreshed().  In either case a
879    // DHCP client has been started, and will take care of calling
880    // OnIPConfigUpdated() when it completes.
881    SLOG(this, 2) << __func__ << " " << " no static IP address.";
882  }
883}
884
885bool Device::IPConfigCompleted(const IPConfigRefPtr& ipconfig) {
886  return ipconfig && !ipconfig->properties().address.empty() &&
887      !ipconfig->properties().dns_servers.empty();
888}
889
890void Device::OnIPv6ConfigUpdated() {
891  // Setup connection using IPv6 configuration only if the IPv6 configuration
892  // is ready for connection (contained both IP address and DNS servers), and
893  // there is no existing IPv4 connection. We always prefer IPv4
894  // configuration over IPv6.
895  if (IPConfigCompleted(ip6config_) &&
896      (!connection_ || connection_->IsIPv6())) {
897    SetupConnection(ip6config_);
898  }
899}
900
901void Device::SetupConnection(const IPConfigRefPtr& ipconfig) {
902  CreateConnection();
903  connection_->UpdateFromIPConfig(ipconfig);
904
905  // Report connection type.
906  Metrics::NetworkConnectionIPType ip_type =
907      connection_->IsIPv6() ? Metrics::kNetworkConnectionIPTypeIPv6
908                            : Metrics::kNetworkConnectionIPTypeIPv4;
909  metrics_->NotifyNetworkConnectionIPType(technology_, ip_type);
910
911  // Report if device have IPv6 connectivity
912  bool ipv6_connectivity = IPConfigCompleted(ip6config_);
913  metrics_->NotifyIPv6ConnectivityStatus(technology_, ipv6_connectivity);
914
915  // SetConnection must occur after the UpdateFromIPConfig so the
916  // service can use the values derived from the connection.
917  if (selected_service_) {
918    selected_service_->SetConnection(connection_);
919
920    // The service state change needs to happen last, so that at the
921    // time we report the state change to the manager, the service
922    // has its connection.
923    SetServiceState(Service::kStateConnected);
924    OnConnected();
925    portal_attempts_to_online_ = 0;
926
927    // Subtle: Start portal detection after transitioning the service
928    // to the Connected state because this call may immediately transition
929    // to the Online state.
930    StartPortalDetection();
931  }
932
933  SetHostname(ipconfig->properties().accepted_hostname);
934  StartLinkMonitor();
935  StartTrafficMonitor();
936}
937
938bool Device::SetHostname(const std::string& hostname) {
939  if (hostname.empty() || !manager()->ShouldAcceptHostnameFrom(link_name_)) {
940    return false;
941  }
942
943  string fixed_hostname = hostname;
944  if (fixed_hostname.length() > MAXHOSTNAMELEN) {
945    auto truncate_length = fixed_hostname.find('.');
946    if (truncate_length == string::npos || truncate_length > MAXHOSTNAMELEN) {
947      truncate_length = MAXHOSTNAMELEN;
948    }
949    fixed_hostname.resize(truncate_length);
950  }
951
952  return manager_->device_info()->SetHostname(fixed_hostname);
953}
954
955void Device::PrependDNSServersIntoIPConfig(const IPConfigRefPtr& ipconfig) {
956  const auto& properties = ipconfig->properties();
957
958  vector<string> servers(properties.dns_servers.begin(),
959                         properties.dns_servers.end());
960  PrependDNSServers(properties.address_family, &servers);
961  if (servers == properties.dns_servers) {
962    // If the server list is the same after being augmented then there's no need
963    // to update the config's list of servers.
964    return;
965  }
966
967  ipconfig->UpdateDNSServers(servers);
968}
969
970void Device::PrependDNSServers(const IPAddress::Family family,
971                               vector<string>* servers) {
972  vector<string>output_servers =
973      manager_->FilterPrependDNSServersByFamily(family);
974
975  set<string> unique(output_servers.begin(), output_servers.end());
976  for (const auto& server : *servers) {
977    if (unique.find(server) == unique.end()) {
978      output_servers.push_back(server);
979      unique.insert(server);
980    }
981  }
982  servers->swap(output_servers);
983}
984
985void Device::ConnectionDiagnosticsCallback(
986      const std::string& connection_issue,
987      const std::vector<ConnectionDiagnostics::Event>& diagnostic_events) {
988  SLOG(this, 2) << "Device " << FriendlyName()
989                << ": Completed Connection diagnostics";
990  // TODO(samueltan): add connection diagnostics metrics.
991}
992
993void Device::OnIPConfigUpdated(const IPConfigRefPtr& ipconfig,
994                               bool /*new_lease_acquired*/) {
995  SLOG(this, 2) << __func__;
996  if (selected_service_) {
997    ipconfig->ApplyStaticIPParameters(
998        selected_service_->mutable_static_ip_parameters());
999    if (IsUsingStaticIP()) {
1000      // If we are using a statically configured IP address instead
1001      // of a leased IP address, release any acquired lease so it may
1002      // be used by others.  This allows us to merge other non-leased
1003      // parameters (like DNS) when they're available from a DHCP server
1004      // and not overridden by static parameters, but at the same time
1005      // we avoid taking up a dynamic IP address the DHCP server could
1006      // assign to someone else who might actually use it.
1007      ipconfig->ReleaseIP(IPConfig::kReleaseReasonStaticIP);
1008    }
1009  }
1010  if (!IsUsingStaticNameServers()) {
1011    PrependDNSServersIntoIPConfig(ipconfig);
1012  }
1013  SetupConnection(ipconfig);
1014  UpdateIPConfigsProperty();
1015}
1016
1017void Device::OnIPConfigFailed(const IPConfigRefPtr& ipconfig) {
1018  SLOG(this, 2) << __func__;
1019  // TODO(pstew): This logic gets yet more complex when multiple
1020  // IPConfig types are run in parallel (e.g. DHCP and DHCP6)
1021  if (selected_service_) {
1022    if (IsUsingStaticIP()) {
1023      // Consider three cases:
1024      //
1025      // 1. We're here because DHCP failed while starting up. There
1026      //    are two subcases:
1027      //    a. DHCP has failed, and Static IP config has _not yet_
1028      //       completed. It's fine to do nothing, because we'll
1029      //       apply the static config shortly.
1030      //    b. DHCP has failed, and Static IP config has _already_
1031      //       completed. It's fine to do nothing, because we can
1032      //       continue to use the static config that's already
1033      //       been applied.
1034      //
1035      // 2. We're here because a previously valid DHCP configuration
1036      //    is no longer valid. There's still a static IP config,
1037      //    because the condition in the if clause evaluated to true.
1038      //    Furthermore, the static config includes an IP address for
1039      //    us to use.
1040      //
1041      //    The current configuration may include some DHCP
1042      //    parameters, overriden by any static parameters
1043      //    provided. We continue to use this configuration, because
1044      //    the only configuration element that is leased to us (IP
1045      //    address) will be overriden by a static parameter.
1046      return;
1047    }
1048  }
1049
1050  ipconfig->ResetProperties();
1051  UpdateIPConfigsProperty();
1052
1053  // Fallback to IPv6 if possible.
1054  if (IPConfigCompleted(ip6config_)) {
1055    if (!connection_ || !connection_->IsIPv6()) {
1056      // Setup IPv6 connection.
1057      SetupConnection(ip6config_);
1058    } else {
1059      // Ignore IPv4 config failure, since IPv6 is up.
1060    }
1061    return;
1062  }
1063
1064  OnIPConfigFailure();
1065  DestroyConnection();
1066}
1067
1068void Device::OnIPConfigRefreshed(const IPConfigRefPtr& ipconfig) {
1069  // Clear the previously applied static IP parameters.
1070  ipconfig->RestoreSavedIPParameters(
1071      selected_service_->mutable_static_ip_parameters());
1072
1073  dispatcher_->PostTask(Bind(&Device::ConfigureStaticIPTask,
1074                             weak_ptr_factory_.GetWeakPtr()));
1075}
1076
1077void Device::OnIPConfigFailure() {
1078  if (selected_service_) {
1079    Error error;
1080    selected_service_->DisconnectWithFailure(Service::kFailureDHCP,
1081                                             &error,
1082                                             __func__);
1083  }
1084}
1085
1086void Device::OnIPConfigExpired(const IPConfigRefPtr& ipconfig) {
1087  metrics()->SendToUMA(
1088      metrics()->GetFullMetricName(
1089          Metrics::kMetricExpiredLeaseLengthSecondsSuffix, technology()),
1090      ipconfig->properties().lease_duration_seconds,
1091      Metrics::kMetricExpiredLeaseLengthSecondsMin,
1092      Metrics::kMetricExpiredLeaseLengthSecondsMax,
1093      Metrics::kMetricExpiredLeaseLengthSecondsNumBuckets);
1094}
1095
1096void Device::OnDHCPv6ConfigUpdated(const IPConfigRefPtr& ipconfig,
1097                                   bool /*new_lease_acquired*/) {
1098  // Emit configuration update.
1099  UpdateIPConfigsProperty();
1100}
1101
1102void Device::OnDHCPv6ConfigFailed(const IPConfigRefPtr& ipconfig) {
1103  // Reset configuration data.
1104  ipconfig->ResetProperties();
1105  UpdateIPConfigsProperty();
1106}
1107
1108void Device::OnDHCPv6ConfigExpired(const IPConfigRefPtr& ipconfig) {
1109  // Reset configuration data.
1110  ipconfig->ResetProperties();
1111  UpdateIPConfigsProperty();
1112}
1113
1114void Device::OnConnected() {
1115  if (selected_service_->unreliable()) {
1116    // Post a delayed task to reset link back to reliable if no link
1117    // failure is detected in the next 5 minutes.
1118    reliable_link_callback_.Reset(
1119        base::Bind(&Device::OnReliableLink, base::Unretained(this)));
1120    dispatcher_->PostDelayedTask(
1121        reliable_link_callback_.callback(),
1122        kLinkUnreliableThresholdSeconds * 1000);
1123  }
1124}
1125
1126void Device::OnConnectionUpdated() {
1127  if (selected_service_) {
1128    manager_->UpdateService(selected_service_);
1129  }
1130}
1131
1132void Device::CreateConnection() {
1133  SLOG(this, 2) << __func__;
1134  if (!connection_.get()) {
1135    connection_ = new Connection(interface_index_,
1136                                 link_name_,
1137                                 technology_,
1138                                 manager_->device_info(),
1139                                 control_interface_);
1140  }
1141}
1142
1143void Device::DestroyConnection() {
1144  SLOG(this, 2) << __func__ << " on " << link_name_;
1145  StopAllActivities();
1146  if (selected_service_.get()) {
1147    SLOG(this, 3) << "Clearing connection of service "
1148                  << selected_service_->unique_name();
1149    selected_service_->SetConnection(nullptr);
1150  }
1151  connection_ = nullptr;
1152}
1153
1154void Device::SelectService(const ServiceRefPtr& service) {
1155  SLOG(this, 2) << __func__ << ": service "
1156                << (service ? service->unique_name() : "*reset*")
1157                << " on " << link_name_;
1158
1159  if (selected_service_.get() == service.get()) {
1160    // No change to |selected_service_|. Return early to avoid
1161    // changing its state.
1162    return;
1163  }
1164
1165  if (selected_service_.get()) {
1166    if (selected_service_->state() != Service::kStateFailure) {
1167      selected_service_->SetState(Service::kStateIdle);
1168    }
1169    // Just in case the Device subclass has not already done so, make
1170    // sure the previously selected service has its connection removed.
1171    selected_service_->SetConnection(nullptr);
1172    // Reset link status for the previously selected service.
1173    selected_service_->set_unreliable(false);
1174    reliable_link_callback_.Cancel();
1175    StopAllActivities();
1176  }
1177
1178  // Newly selected service (network), previous failures doesn't apply
1179  // anymore.
1180  last_link_monitor_failed_time_ = 0;
1181
1182  selected_service_ = service;
1183  adaptor_->EmitRpcIdentifierChanged(
1184      kSelectedServiceProperty, GetSelectedServiceRpcIdentifier(nullptr));
1185}
1186
1187void Device::SetServiceState(Service::ConnectState state) {
1188  if (selected_service_.get()) {
1189    selected_service_->SetState(state);
1190  }
1191}
1192
1193void Device::SetServiceFailure(Service::ConnectFailure failure_state) {
1194  if (selected_service_.get()) {
1195    selected_service_->SetFailure(failure_state);
1196  }
1197}
1198
1199void Device::SetServiceFailureSilent(Service::ConnectFailure failure_state) {
1200  if (selected_service_.get()) {
1201    selected_service_->SetFailureSilent(failure_state);
1202  }
1203}
1204
1205bool Device::SetIPFlag(IPAddress::Family family, const string& flag,
1206                       const string& value) {
1207  string ip_version;
1208  if (family == IPAddress::kFamilyIPv4) {
1209    ip_version = kIPFlagVersion4;
1210  } else if (family == IPAddress::kFamilyIPv6) {
1211    ip_version = kIPFlagVersion6;
1212  } else {
1213    NOTIMPLEMENTED();
1214  }
1215  FilePath flag_file(StringPrintf(kIPFlagTemplate, ip_version.c_str(),
1216                                  link_name_.c_str(), flag.c_str()));
1217  SLOG(this, 2) << "Writing " << value << " to flag file "
1218                << flag_file.value();
1219  if (base::WriteFile(flag_file, value.c_str(), value.length()) != 1) {
1220    string message = StringPrintf("IP flag write failed: %s to %s",
1221                                  value.c_str(), flag_file.value().c_str());
1222    if (!base::PathExists(flag_file) &&
1223        ContainsValue(written_flags_, flag_file.value())) {
1224      SLOG(this, 2) << message << " (device is no longer present?)";
1225    } else {
1226      LOG(ERROR) << message;
1227    }
1228    return false;
1229  } else {
1230    written_flags_.insert(flag_file.value());
1231  }
1232  return true;
1233}
1234
1235string Device::PerformTDLSOperation(const string& /* operation */,
1236                                    const string& /* peer */,
1237                                    Error* /* error */) {
1238  return "";
1239}
1240
1241void Device::ResetByteCounters() {
1242  manager_->device_info()->GetByteCounts(
1243      interface_index_, &receive_byte_offset_, &transmit_byte_offset_);
1244  manager_->UpdateDevice(this);
1245}
1246
1247bool Device::RestartPortalDetection() {
1248  StopPortalDetection();
1249  return StartPortalDetection();
1250}
1251
1252bool Device::RequestPortalDetection() {
1253  if (!selected_service_) {
1254    SLOG(this, 2) << FriendlyName()
1255                  << ": No selected service, so no need for portal check.";
1256    return false;
1257  }
1258
1259  if (!connection_.get()) {
1260    SLOG(this, 2) << FriendlyName()
1261                  << ": No connection, so no need for portal check.";
1262    return false;
1263  }
1264
1265  if (selected_service_->state() != Service::kStatePortal) {
1266    SLOG(this, 2) << FriendlyName()
1267                  << ": Service is not in portal state.  "
1268                  << "No need to start check.";
1269    return false;
1270  }
1271
1272  if (!connection_->is_default()) {
1273    SLOG(this, 2) << FriendlyName()
1274                  << ": Service is not the default connection.  "
1275                  << "Don't start check.";
1276    return false;
1277  }
1278
1279  if (portal_detector_.get() && portal_detector_->IsInProgress()) {
1280    SLOG(this, 2) << FriendlyName()
1281                  << ": Portal detection is already running.";
1282    return true;
1283  }
1284
1285  return StartPortalDetection();
1286}
1287
1288bool Device::StartPortalDetection() {
1289  DCHECK(selected_service_);
1290  if (selected_service_->IsPortalDetectionDisabled()) {
1291    SLOG(this, 2) << "Service " << selected_service_->unique_name()
1292                  << ": Portal detection is disabled; "
1293                  << "marking service online.";
1294    SetServiceConnectedState(Service::kStateOnline);
1295    return false;
1296  }
1297
1298  if (selected_service_->IsPortalDetectionAuto() &&
1299      !manager_->IsPortalDetectionEnabled(technology())) {
1300    // If portal detection is disabled for this technology, immediately set
1301    // the service state to "Online".
1302    SLOG(this, 2) << "Device " << FriendlyName()
1303                  << ": Portal detection is disabled; "
1304                  << "marking service online.";
1305    SetServiceConnectedState(Service::kStateOnline);
1306    return false;
1307  }
1308
1309  if (selected_service_->HasProxyConfig()) {
1310    // Services with HTTP proxy configurations should not be checked by the
1311    // connection manager, since we don't have the ability to evaluate
1312    // arbitrary proxy configs and their possible credentials.
1313    SLOG(this, 2) << "Device " << FriendlyName()
1314                  << ": Service has proxy config; marking it online.";
1315    SetServiceConnectedState(Service::kStateOnline);
1316    return false;
1317  }
1318
1319  portal_detector_.reset(new PortalDetector(connection_,
1320                                            dispatcher_,
1321                                            portal_detector_callback_));
1322  if (!portal_detector_->Start(manager_->GetPortalCheckURL())) {
1323    LOG(ERROR) << "Device " << FriendlyName()
1324               << ": Portal detection failed to start: likely bad URL: "
1325               << manager_->GetPortalCheckURL();
1326    SetServiceConnectedState(Service::kStateOnline);
1327    return false;
1328  }
1329
1330  SLOG(this, 2) << "Device " << FriendlyName()
1331                << ": Portal detection has started.";
1332  return true;
1333}
1334
1335void Device::StopPortalDetection() {
1336  SLOG(this, 2) << "Device " << FriendlyName()
1337                << ": Portal detection stopping.";
1338  portal_detector_.reset();
1339}
1340
1341bool Device::StartConnectionDiagnosticsAfterPortalDetection(
1342    const PortalDetector::Result& result) {
1343  connection_diagnostics_.reset(new ConnectionDiagnostics(
1344      connection_, dispatcher_, metrics_, manager_->device_info(),
1345      connection_diagnostics_callback_));
1346  if (!connection_diagnostics_->StartAfterPortalDetection(
1347      manager_->GetPortalCheckURL(), result)) {
1348    LOG(ERROR) << "Device " << FriendlyName()
1349               << ": Connection diagnostics failed to start: likely bad URL: "
1350               << manager_->GetPortalCheckURL();
1351    connection_diagnostics_.reset();
1352    return false;
1353  }
1354
1355  SLOG(this, 2) << "Device " << FriendlyName()
1356                << ": Connection diagnostics has started.";
1357  return true;
1358}
1359
1360void Device::StopConnectionDiagnostics() {
1361  SLOG(this, 2) << "Device " << FriendlyName()
1362                << ": Connection diagnostics stopping.";
1363  connection_diagnostics_.reset();
1364}
1365
1366bool Device::StartConnectivityTest() {
1367  LOG(INFO) << "Device " << FriendlyName() << " starting connectivity test.";
1368
1369  connection_tester_.reset(new ConnectionTester(connection_,
1370                                                dispatcher_,
1371                                                connection_tester_callback_));
1372  connection_tester_->Start();
1373  return true;
1374}
1375
1376void Device::StopConnectivityTest() {
1377  SLOG(this, 2) << "Device " << FriendlyName()
1378                << ": Connectivity test stopping.";
1379  connection_tester_.reset();
1380}
1381
1382void Device::set_link_monitor(LinkMonitor* link_monitor) {
1383  link_monitor_.reset(link_monitor);
1384}
1385
1386bool Device::StartLinkMonitor() {
1387  if (!manager_->IsTechnologyLinkMonitorEnabled(technology())) {
1388    SLOG(this, 2) << "Device " << FriendlyName()
1389                  << ": Link Monitoring is disabled.";
1390    return false;
1391  }
1392
1393  if (selected_service_ && selected_service_->link_monitor_disabled()) {
1394    SLOG(this, 2) << "Device " << FriendlyName()
1395                  << ": Link Monitoring is disabled for the selected service";
1396    return false;
1397  }
1398
1399  if (!link_monitor()) {
1400    set_link_monitor(
1401      new LinkMonitor(
1402          connection_, dispatcher_, metrics(), manager_->device_info(),
1403          Bind(&Device::OnLinkMonitorFailure, weak_ptr_factory_.GetWeakPtr()),
1404          Bind(&Device::OnLinkMonitorGatewayChange,
1405               weak_ptr_factory_.GetWeakPtr())));
1406  }
1407
1408  SLOG(this, 2) << "Device " << FriendlyName()
1409                << ": Link Monitor starting.";
1410  return link_monitor_->Start();
1411}
1412
1413void Device::StopLinkMonitor() {
1414  SLOG(this, 2) << "Device " << FriendlyName()
1415                << ": Link Monitor stopping.";
1416  link_monitor_.reset();
1417}
1418
1419void Device::OnUnreliableLink() {
1420  SLOG(this, 2) << "Device " << FriendlyName()
1421                << ": Link is unreliable.";
1422  selected_service_->set_unreliable(true);
1423  reliable_link_callback_.Cancel();
1424  metrics_->NotifyUnreliableLinkSignalStrength(
1425      technology_, selected_service_->strength());
1426}
1427
1428void Device::OnReliableLink() {
1429  SLOG(this, 2) << "Device " << FriendlyName()
1430                << ": Link is reliable.";
1431  selected_service_->set_unreliable(false);
1432  // TODO(zqiu): report signal strength to UMA.
1433}
1434
1435void Device::OnLinkMonitorFailure() {
1436  SLOG(this, 2) << "Device " << FriendlyName()
1437                << ": Link Monitor indicates failure.";
1438  if (!selected_service_) {
1439    return;
1440  }
1441
1442  time_t now;
1443  time_->GetSecondsBoottime(&now);
1444
1445  if (last_link_monitor_failed_time_ != 0 &&
1446      now - last_link_monitor_failed_time_ < kLinkUnreliableThresholdSeconds) {
1447    OnUnreliableLink();
1448  }
1449  last_link_monitor_failed_time_ = now;
1450}
1451
1452void Device::OnLinkMonitorGatewayChange() {
1453  string gateway_mac = link_monitor()->gateway_mac_address().HexEncode();
1454  int connection_id = manager_->CalcConnectionId(
1455      ipconfig_->properties().gateway, gateway_mac);
1456
1457  CHECK(selected_service_);
1458  selected_service_->set_connection_id(connection_id);
1459
1460  manager_->ReportServicesOnSameNetwork(connection_id);
1461}
1462
1463bool Device::StartDNSTest(
1464    const vector<string>& dns_servers,
1465    bool retry_until_success,
1466    const Callback<void(const DNSServerTester::Status)>& callback) {
1467  if (dns_server_tester_.get()) {
1468    LOG(ERROR) << FriendlyName() << ": "
1469               << "Failed to start DNS Test: current test still running";
1470    return false;
1471  }
1472
1473  dns_server_tester_.reset(new DNSServerTester(connection_,
1474                                               dispatcher_,
1475                                               dns_servers,
1476                                               retry_until_success,
1477                                               callback));
1478  dns_server_tester_->Start();
1479  return true;
1480}
1481
1482void Device::StopDNSTest() {
1483  dns_server_tester_.reset();
1484}
1485
1486void Device::FallbackDNSResultCallback(const DNSServerTester::Status status) {
1487  StopDNSTest();
1488  int result = Metrics::kFallbackDNSTestResultFailure;
1489  if (status == DNSServerTester::kStatusSuccess) {
1490    result = Metrics::kFallbackDNSTestResultSuccess;
1491
1492    // Switch to fallback DNS server if service is configured to allow DNS
1493    // fallback.
1494    CHECK(selected_service_);
1495    if (selected_service_->is_dns_auto_fallback_allowed()) {
1496      LOG(INFO) << "Device " << FriendlyName()
1497                << ": Switching to fallback DNS servers.";
1498      // Save the DNS servers from ipconfig.
1499      config_dns_servers_ = ipconfig_->properties().dns_servers;
1500      SwitchDNSServers(vector<string>(std::begin(kFallbackDnsServers),
1501                                      std::end(kFallbackDnsServers)));
1502      // Start DNS test for configured DNS servers.
1503      StartDNSTest(config_dns_servers_,
1504                   true,
1505                   Bind(&Device::ConfigDNSResultCallback,
1506                        weak_ptr_factory_.GetWeakPtr()));
1507    }
1508  }
1509  metrics()->NotifyFallbackDNSTestResult(technology_, result);
1510}
1511
1512void Device::ConfigDNSResultCallback(const DNSServerTester::Status status) {
1513  StopDNSTest();
1514  // DNS test failed to start due to internal error.
1515  if (status == DNSServerTester::kStatusFailure) {
1516    return;
1517  }
1518
1519  // Switch back to the configured DNS servers.
1520  LOG(INFO) << "Device " << FriendlyName()
1521            << ": Switching back to configured DNS servers.";
1522  SwitchDNSServers(config_dns_servers_);
1523}
1524
1525void Device::SwitchDNSServers(const vector<string>& dns_servers) {
1526  CHECK(ipconfig_);
1527  CHECK(connection_);
1528  // Push new DNS servers setting to the IP config object.
1529  ipconfig_->UpdateDNSServers(dns_servers);
1530  // Push new DNS servers setting to the current connection, so the resolver
1531  // will be updated to use the new DNS servers.
1532  connection_->UpdateDNSServers(dns_servers);
1533  // Allow the service to notify Chrome of ipconfig changes.
1534  selected_service_->NotifyIPConfigChanges();
1535  // Restart the portal detection with the new DNS setting.
1536  RestartPortalDetection();
1537}
1538
1539void Device::set_traffic_monitor(TrafficMonitor* traffic_monitor) {
1540  traffic_monitor_.reset(traffic_monitor);
1541}
1542
1543bool Device::TimeToNextDHCPLeaseRenewal(uint32_t* result) {
1544  if (!ipconfig() && !ip6config()) {
1545    return false;
1546  }
1547  uint32_t time_to_ipv4_lease_expiry = UINT32_MAX;
1548  uint32_t time_to_ipv6_lease_expiry = UINT32_MAX;
1549  if (ipconfig()) {
1550    ipconfig()->TimeToLeaseExpiry(&time_to_ipv4_lease_expiry);
1551  }
1552  if (ip6config()) {
1553    ip6config()->TimeToLeaseExpiry(&time_to_ipv6_lease_expiry);
1554  }
1555  *result = std::min(time_to_ipv4_lease_expiry, time_to_ipv6_lease_expiry);
1556  return true;
1557}
1558
1559bool Device::IsTrafficMonitorEnabled() const {
1560  return false;
1561}
1562
1563void Device::StartTrafficMonitor() {
1564  // Return if traffic monitor is not enabled for this device.
1565  if (!IsTrafficMonitorEnabled()) {
1566    return;
1567  }
1568
1569  SLOG(this, 2) << "Device " << FriendlyName()
1570                << ": Traffic Monitor starting.";
1571  if (!traffic_monitor_.get()) {
1572    traffic_monitor_.reset(new TrafficMonitor(this, dispatcher_));
1573    traffic_monitor_->set_network_problem_detected_callback(
1574        Bind(&Device::OnEncounterNetworkProblem,
1575             weak_ptr_factory_.GetWeakPtr()));
1576  }
1577  traffic_monitor_->Start();
1578}
1579
1580void Device::StopTrafficMonitor() {
1581  // Return if traffic monitor is not enabled for this device.
1582  if (!IsTrafficMonitorEnabled()) {
1583    return;
1584  }
1585
1586  if (traffic_monitor_.get()) {
1587    SLOG(this, 2) << "Device " << FriendlyName()
1588                  << ": Traffic Monitor stopping.";
1589    traffic_monitor_->Stop();
1590  }
1591  traffic_monitor_.reset();
1592}
1593
1594void Device::OnEncounterNetworkProblem(int reason) {
1595  int metric_code;
1596  switch (reason) {
1597    case TrafficMonitor::kNetworkProblemCongestedTxQueue:
1598      metric_code = Metrics::kNetworkProblemCongestedTCPTxQueue;
1599      break;
1600    case TrafficMonitor::kNetworkProblemDNSFailure:
1601      metric_code = Metrics::kNetworkProblemDNSFailure;
1602      break;
1603    default:
1604      LOG(ERROR) << "Invalid network problem code: " << reason;
1605      return;
1606  }
1607
1608  metrics()->NotifyNetworkProblemDetected(technology_, metric_code);
1609  // Stop the traffic monitor, only report the first network problem detected
1610  // on the connection for now.
1611  StopTrafficMonitor();
1612}
1613
1614void Device::SetServiceConnectedState(Service::ConnectState state) {
1615  DCHECK(selected_service_.get());
1616
1617  if (!selected_service_.get()) {
1618    LOG(ERROR) << FriendlyName() << ": "
1619               << "Portal detection completed but no selected service exists!";
1620    return;
1621  }
1622
1623  if (!selected_service_->IsConnected()) {
1624    LOG(ERROR) << FriendlyName() << ": "
1625               << "Portal detection completed but selected service "
1626               << selected_service_->unique_name()
1627               << " is in non-connected state.";
1628    return;
1629  }
1630
1631  if (state == Service::kStatePortal && connection_->is_default() &&
1632      manager_->GetPortalCheckInterval() != 0) {
1633    CHECK(portal_detector_.get());
1634    if (!portal_detector_->StartAfterDelay(
1635            manager_->GetPortalCheckURL(),
1636            manager_->GetPortalCheckInterval())) {
1637      LOG(ERROR) << "Device " << FriendlyName()
1638                 << ": Portal detection failed to restart: likely bad URL: "
1639                 << manager_->GetPortalCheckURL();
1640      SetServiceState(Service::kStateOnline);
1641      portal_detector_.reset();
1642      return;
1643    }
1644    SLOG(this, 2) << "Device " << FriendlyName()
1645                  << ": Portal detection retrying.";
1646  } else {
1647    SLOG(this, 2) << "Device " << FriendlyName()
1648                  << ": Portal will not retry.";
1649    portal_detector_.reset();
1650  }
1651
1652  SetServiceState(state);
1653}
1654
1655void Device::PortalDetectorCallback(const PortalDetector::Result& result) {
1656  if (!result.final) {
1657    SLOG(this, 2) << "Device " << FriendlyName()
1658                  << ": Received non-final status: "
1659                  << ConnectivityTrial::StatusToString(
1660                      result.trial_result.status);
1661    return;
1662  }
1663
1664  SLOG(this, 2) << "Device " << FriendlyName()
1665                << ": Received final status: "
1666                << ConnectivityTrial::StatusToString(
1667                    result.trial_result.status);
1668
1669  portal_attempts_to_online_ += result.num_attempts;
1670
1671  int portal_status = Metrics::PortalDetectionResultToEnum(result);
1672  metrics()->SendEnumToUMA(
1673      metrics()->GetFullMetricName(Metrics::kMetricPortalResultSuffix,
1674                                   technology()),
1675      portal_status,
1676      Metrics::kPortalResultMax);
1677
1678  if (result.trial_result.status == ConnectivityTrial::kStatusSuccess) {
1679    SetServiceConnectedState(Service::kStateOnline);
1680
1681    metrics()->SendToUMA(
1682        metrics()->GetFullMetricName(
1683            Metrics::kMetricPortalAttemptsToOnlineSuffix, technology()),
1684        portal_attempts_to_online_,
1685        Metrics::kMetricPortalAttemptsToOnlineMin,
1686        Metrics::kMetricPortalAttemptsToOnlineMax,
1687        Metrics::kMetricPortalAttemptsToOnlineNumBuckets);
1688  } else {
1689    // Set failure phase and status.
1690    if (selected_service_.get()) {
1691      selected_service_->SetPortalDetectionFailure(
1692          ConnectivityTrial::PhaseToString(result.trial_result.phase),
1693          ConnectivityTrial::StatusToString(result.trial_result.status));
1694    }
1695    SetServiceConnectedState(Service::kStatePortal);
1696
1697    metrics()->SendToUMA(
1698        metrics()->GetFullMetricName(
1699            Metrics::kMetricPortalAttemptsSuffix, technology()),
1700        result.num_attempts,
1701        Metrics::kMetricPortalAttemptsMin,
1702        Metrics::kMetricPortalAttemptsMax,
1703        Metrics::kMetricPortalAttemptsNumBuckets);
1704
1705    StartConnectionDiagnosticsAfterPortalDetection(result);
1706
1707    // TODO(zqiu): Only support fallback DNS server for IPv4 for now.
1708    if (connection_->IsIPv6()) {
1709      return;
1710    }
1711
1712    // Perform fallback DNS test if the portal failure is DNS related.
1713    // The test will send a  DNS request to Google's DNS server to determine
1714    // if the DNS failure is due to bad DNS server settings.
1715    if ((portal_status == Metrics::kPortalResultDNSFailure) ||
1716        (portal_status == Metrics::kPortalResultDNSTimeout)) {
1717      StartDNSTest(vector<string>(std::begin(kFallbackDnsServers),
1718                                  std::end(kFallbackDnsServers)),
1719                   false,
1720                   Bind(&Device::FallbackDNSResultCallback,
1721                        weak_ptr_factory_.GetWeakPtr()));
1722    }
1723  }
1724}
1725
1726string Device::GetSelectedServiceRpcIdentifier(Error* /*error*/) {
1727  if (!selected_service_) {
1728    return "/";
1729  }
1730  return selected_service_->GetRpcIdentifier();
1731}
1732
1733vector<string> Device::AvailableIPConfigs(Error* /*error*/) {
1734  vector<string> ipconfigs;
1735  if (ipconfig_) {
1736    ipconfigs.push_back(ipconfig_->GetRpcIdentifier());
1737  }
1738  if (ip6config_) {
1739    ipconfigs.push_back(ip6config_->GetRpcIdentifier());
1740  }
1741  if (dhcpv6_config_) {
1742    ipconfigs.push_back(dhcpv6_config_->GetRpcIdentifier());
1743  }
1744  return ipconfigs;
1745}
1746
1747uint64_t Device::GetLinkMonitorResponseTime(Error* error) {
1748  if (!link_monitor_.get()) {
1749    // It is not strictly an error that the link monitor does not
1750    // exist, but returning an error here allows the GetProperties
1751    // call in our Adaptor to omit this parameter.
1752    error->Populate(Error::kNotFound, "Device is not running LinkMonitor");
1753    return 0;
1754  }
1755  return link_monitor_->GetResponseTimeMilliseconds();
1756}
1757
1758uint64_t Device::GetReceiveByteCount() {
1759  uint64_t rx_byte_count = 0, tx_byte_count = 0;
1760  manager_->device_info()->GetByteCounts(
1761      interface_index_, &rx_byte_count, &tx_byte_count);
1762  return rx_byte_count - receive_byte_offset_;
1763}
1764
1765uint64_t Device::GetTransmitByteCount() {
1766  uint64_t rx_byte_count = 0, tx_byte_count = 0;
1767  manager_->device_info()->GetByteCounts(
1768      interface_index_, &rx_byte_count, &tx_byte_count);
1769  return tx_byte_count - transmit_byte_offset_;
1770}
1771
1772uint64_t Device::GetReceiveByteCountProperty(Error* /*error*/) {
1773  return GetReceiveByteCount();
1774}
1775
1776uint64_t Device::GetTransmitByteCountProperty(Error* /*error*/) {
1777  return GetTransmitByteCount();
1778}
1779
1780bool Device::IsUnderlyingDeviceEnabled() const {
1781  return false;
1782}
1783
1784// callback
1785void Device::OnEnabledStateChanged(const ResultCallback& callback,
1786                                   const Error& error) {
1787  SLOG(this, 2) << __func__
1788                << " (target: " << enabled_pending_ << ","
1789                << " success: " << error.IsSuccess() << ")"
1790                << " on " << link_name_;
1791  if (error.IsSuccess()) {
1792    enabled_ = enabled_pending_;
1793    manager_->UpdateEnabledTechnologies();
1794    adaptor_->EmitBoolChanged(kPoweredProperty, enabled_);
1795  }
1796  enabled_pending_ = enabled_;
1797  if (!callback.is_null())
1798    callback.Run(error);
1799}
1800
1801void Device::SetEnabled(bool enable) {
1802  SLOG(this, 2) << __func__ << "(" << enable << ")";
1803  Error error;
1804  SetEnabledChecked(enable, false, &error, ResultCallback());
1805
1806  // SetEnabledInternal might fail here if there is an unfinished enable or
1807  // disable operation. Don't log error in this case, as this method is only
1808  // called when the underlying device is already in the target state and the
1809  // pending operation should eventually bring the device to the expected
1810  // state.
1811  LOG_IF(ERROR,
1812         error.IsFailure() &&
1813         !error.IsOngoing() &&
1814         error.type() != Error::kInProgress)
1815      << "Enabled failed, but no way to report the failure.";
1816}
1817
1818void Device::SetEnabledNonPersistent(bool enable,
1819                                     Error* error,
1820                                     const ResultCallback& callback) {
1821  SetEnabledChecked(enable, false, error, callback);
1822}
1823
1824void Device::SetEnabledPersistent(bool enable,
1825                                  Error* error,
1826                                  const ResultCallback& callback) {
1827  SetEnabledChecked(enable, true, error, callback);
1828}
1829
1830void Device::SetEnabledChecked(bool enable,
1831                               bool persist,
1832                               Error* error,
1833                               const ResultCallback& callback) {
1834  DCHECK(error);
1835  SLOG(this, 2) << "Device " << link_name_ << " "
1836                << (enable ? "starting" : "stopping");
1837  if (enable && manager_->IsTechnologyProhibited(technology())) {
1838    error->Populate(Error::kPermissionDenied, "The " +
1839                    Technology::NameFromIdentifier(technology()) +
1840                    " technology is prohibited");
1841    return;
1842  }
1843
1844  if (enable == enabled_) {
1845    if (enable != enabled_pending_ && persist) {
1846      // Return an error, as there is an ongoing operation to achieve the
1847      // opposite.
1848      Error::PopulateAndLog(
1849          FROM_HERE, error, Error::kOperationFailed,
1850          enable ? "Cannot enable while the device is disabling." :
1851                   "Cannot disable while the device is enabling.");
1852      return;
1853    }
1854    LOG(INFO) << "Already in desired enable state.";
1855    error->Reset();
1856    return;
1857  }
1858
1859  if (enabled_pending_ == enable) {
1860    Error::PopulateAndLog(FROM_HERE, error, Error::kInProgress,
1861                          "Enable operation already in progress");
1862    return;
1863  }
1864
1865  if (persist) {
1866    enabled_persistent_ = enable;
1867    manager_->UpdateDevice(this);
1868  }
1869
1870  SetEnabledUnchecked(enable, error, callback);
1871}
1872
1873void Device::SetEnabledUnchecked(bool enable, Error* error,
1874                                 const ResultCallback& on_enable_complete) {
1875  enabled_pending_ = enable;
1876  EnabledStateChangedCallback chained_callback =
1877      Bind(&Device::OnEnabledStateChanged,
1878           weak_ptr_factory_.GetWeakPtr(), on_enable_complete);
1879  if (enable) {
1880    running_ = true;
1881    Start(error, chained_callback);
1882  } else {
1883    running_ = false;
1884    DestroyIPConfig();         // breaks a reference cycle
1885    SelectService(nullptr);    // breaks a reference cycle
1886    rtnl_handler_->SetInterfaceFlags(interface_index(), 0, IFF_UP);
1887    SLOG(this, 3) << "Device " << link_name_ << " ipconfig_ "
1888                  << (ipconfig_ ? "is set." : "is not set.");
1889    SLOG(this, 3) << "Device " << link_name_ << " ip6config_ "
1890                  << (ip6config_ ? "is set." : "is not set.");
1891    SLOG(this, 3) << "Device " << link_name_ << " connection_ "
1892                  << (connection_ ? "is set." : "is not set.");
1893    SLOG(this, 3) << "Device " << link_name_ << " selected_service_ "
1894                  << (selected_service_ ? "is set." : "is not set.");
1895    Stop(error, chained_callback);
1896  }
1897}
1898
1899void Device::UpdateIPConfigsProperty() {
1900  adaptor_->EmitRpcIdentifierArrayChanged(
1901      kIPConfigsProperty, AvailableIPConfigs(nullptr));
1902}
1903
1904bool Device::ResolvePeerMacAddress(const string& input,
1905                                   string* output,
1906                                   Error* error) {
1907  if (!MakeHardwareAddressFromString(input).empty()) {
1908    // Input is already a MAC address.
1909    *output = input;
1910    return true;
1911  }
1912
1913  IPAddress ip_address(IPAddress::kFamilyIPv4);
1914  if (!ip_address.SetAddressFromString(input)) {
1915    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
1916                          "Peer is neither an IP Address nor a MAC address");
1917    return false;
1918  }
1919
1920  // Peer address was specified as an IP address which we need to resolve.
1921  const DeviceInfo* device_info = manager()->device_info();
1922  if (!device_info->HasDirectConnectivityTo(interface_index_, ip_address)) {
1923    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
1924                          "IP address is not local to this interface");
1925    return false;
1926  }
1927
1928  ByteString mac_address;
1929  if (device_info->GetMACAddressOfPeer(interface_index_,
1930                                       ip_address,
1931                                       &mac_address)) {
1932    *output = MakeStringFromHardwareAddress(
1933        vector<uint8_t>(mac_address.GetConstData(),
1934                        mac_address.GetConstData() +
1935                        mac_address.GetLength()));
1936    SLOG(this, 2) << "ARP cache lookup returned peer: " << *output;
1937    return true;
1938  }
1939
1940  if (!Icmp().TransmitEchoRequest(ip_address, 1, 1)) {
1941    Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
1942                          "Failed to send ICMP request to peer to setup ARP");
1943  } else {
1944    // ARP request was transmitted successfully, address resolution is still
1945    // pending.
1946    error->Populate(Error::kInProgress,
1947                    "Peer MAC address was not found in the ARP cache, "
1948                    "but an ARP request was sent to find it.  "
1949                    "Please try again.");
1950  }
1951  return false;
1952}
1953
1954// static
1955vector<uint8_t> Device::MakeHardwareAddressFromString(
1956    const string& address_string) {
1957  string address_nosep;
1958  base::RemoveChars(address_string, ":", &address_nosep);
1959  vector<uint8_t> address_bytes;
1960  base::HexStringToBytes(address_nosep, &address_bytes);
1961  if (address_bytes.size() != kHardwareAddressLength) {
1962    return vector<uint8_t>();
1963  }
1964  return address_bytes;
1965}
1966
1967// static
1968string Device::MakeStringFromHardwareAddress(
1969    const vector<uint8_t>& address_bytes) {
1970  CHECK_EQ(kHardwareAddressLength, address_bytes.size());
1971  return StringPrintf("%02x:%02x:%02x:%02x:%02x:%02x",
1972                      address_bytes[0], address_bytes[1], address_bytes[2],
1973                      address_bytes[3], address_bytes[4], address_bytes[5]);
1974}
1975
1976bool Device::RequestRoam(const std::string& addr, Error* error) {
1977  return false;
1978}
1979
1980}  // namespace shill
1981