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_info.h"
18
19 #include <arpa/inet.h>
20 #include <fcntl.h>
21 #include <linux/if_tun.h>
22 #include <linux/netlink.h>
23 #include <linux/rtnetlink.h>
24 #include <net/if.h>
25 #include <net/if_arp.h>
26 #include <netinet/ether.h>
27 #include <string.h>
28 #include <sys/ioctl.h>
29 #include <sys/socket.h>
30 #include <time.h>
31 #include <unistd.h>
32
33 #include <string>
34
35 #include <base/bind.h>
36 #include <base/files/file_enumerator.h>
37 #include <base/files/file_util.h>
38 #include <base/files/scoped_file.h>
39 #include <base/stl_util.h>
40 #include <base/strings/string_number_conversions.h>
41 #include <base/strings/string_util.h>
42 #include <base/strings/stringprintf.h>
43
44 #include "shill/control_interface.h"
45 #include "shill/device.h"
46 #include "shill/device_stub.h"
47 #include "shill/ethernet/ethernet.h"
48 #include "shill/ethernet/virtio_ethernet.h"
49 #include "shill/logging.h"
50 #include "shill/manager.h"
51 #include "shill/net/ndisc.h"
52 #include "shill/net/rtnl_handler.h"
53 #include "shill/net/rtnl_listener.h"
54 #include "shill/net/rtnl_message.h"
55 #include "shill/net/shill_time.h"
56 #include "shill/net/sockets.h"
57 #include "shill/routing_table.h"
58 #include "shill/service.h"
59 #include "shill/vpn/vpn_provider.h"
60
61 #if !defined(DISABLE_WIFI)
62 #include "shill/net/netlink_attribute.h"
63 #include "shill/net/netlink_manager.h"
64 #include "shill/net/nl80211_message.h"
65 #include "shill/wifi/wifi.h"
66 #endif // DISABLE_WIFI
67
68 using base::Bind;
69 using base::FileEnumerator;
70 using base::FilePath;
71 using base::StringPrintf;
72 using base::Unretained;
73 using std::map;
74 using std::set;
75 using std::string;
76 using std::vector;
77
78 namespace shill {
79
80 namespace Logging {
81 static auto kModuleLogScope = ScopeLogger::kDevice;
ObjectID(const DeviceInfo * d)82 static string ObjectID(const DeviceInfo* d) { return "(device_info)"; }
83 }
84
85 // static
86 const char DeviceInfo::kModemPseudoDeviceNamePrefix[] = "pseudomodem";
87 const char DeviceInfo::kEthernetPseudoDeviceNamePrefix[] = "pseudoethernet";
88 const char DeviceInfo::kIgnoredDeviceNamePrefix[] = "veth";
89 const char DeviceInfo::kDeviceInfoRoot[] = "/sys/class/net";
90 const char DeviceInfo::kDriverCdcEther[] = "cdc_ether";
91 const char DeviceInfo::kDriverCdcNcm[] = "cdc_ncm";
92 const char DeviceInfo::kDriverGdmWiMax[] = "gdm_wimax";
93 const char DeviceInfo::kDriverVirtioNet[] = "virtio_net";
94 const char DeviceInfo::kInterfaceUevent[] = "uevent";
95 const char DeviceInfo::kInterfaceUeventWifiSignature[] = "DEVTYPE=wlan\n";
96 const char DeviceInfo::kInterfaceDevice[] = "device";
97 const char DeviceInfo::kInterfaceDriver[] = "device/driver";
98 const char DeviceInfo::kInterfaceTunFlags[] = "tun_flags";
99 const char DeviceInfo::kInterfaceType[] = "type";
100 const char* DeviceInfo::kModemDrivers[] = {
101 "gobi",
102 "QCUSBNet2k",
103 "GobiNet",
104 "cdc_mbim",
105 "qmi_wwan"
106 };
107 const char DeviceInfo::kTunDeviceName[] = "/dev/net/tun";
108 const int DeviceInfo::kDelayedDeviceCreationSeconds = 5;
109 const int DeviceInfo::kRequestLinkStatisticsIntervalMilliseconds = 20000;
110
DeviceInfo(ControlInterface * control_interface,EventDispatcher * dispatcher,Metrics * metrics,Manager * manager)111 DeviceInfo::DeviceInfo(ControlInterface* control_interface,
112 EventDispatcher* dispatcher,
113 Metrics* metrics,
114 Manager* manager)
115 : control_interface_(control_interface),
116 dispatcher_(dispatcher),
117 metrics_(metrics),
118 manager_(manager),
119 link_callback_(Bind(&DeviceInfo::LinkMsgHandler, Unretained(this))),
120 address_callback_(Bind(&DeviceInfo::AddressMsgHandler, Unretained(this))),
121 rdnss_callback_(Bind(&DeviceInfo::RdnssMsgHandler, Unretained(this))),
122 device_info_root_(kDeviceInfoRoot),
123 routing_table_(RoutingTable::GetInstance()),
124 rtnl_handler_(RTNLHandler::GetInstance()),
125 #if !defined(DISABLE_WIFI)
126 netlink_manager_(NetlinkManager::GetInstance()),
127 #endif // DISABLE_WIFI
128 sockets_(new Sockets()),
129 time_(Time::GetInstance()) {
130 }
131
~DeviceInfo()132 DeviceInfo::~DeviceInfo() {}
133
AddDeviceToBlackList(const string & device_name)134 void DeviceInfo::AddDeviceToBlackList(const string& device_name) {
135 black_list_.insert(device_name);
136 // Remove the current device info if it exist, since it will be out-dated.
137 RemoveInfo(GetIndex(device_name));
138 // Request link info update to allow device info to be recreated.
139 if (manager_->running()) {
140 rtnl_handler_->RequestDump(RTNLHandler::kRequestLink);
141 }
142 }
143
RemoveDeviceFromBlackList(const string & device_name)144 void DeviceInfo::RemoveDeviceFromBlackList(const string& device_name) {
145 black_list_.erase(device_name);
146 // Remove the current device info if it exist, since it will be out-dated.
147 RemoveInfo(GetIndex(device_name));
148 // Request link info update to allow device info to be recreated.
149 if (manager_->running()) {
150 rtnl_handler_->RequestDump(RTNLHandler::kRequestLink);
151 }
152 }
153
IsDeviceBlackListed(const string & device_name)154 bool DeviceInfo::IsDeviceBlackListed(const string& device_name) {
155 return ContainsKey(black_list_, device_name);
156 }
157
Start()158 void DeviceInfo::Start() {
159 link_listener_.reset(
160 new RTNLListener(RTNLHandler::kRequestLink, link_callback_));
161 address_listener_.reset(
162 new RTNLListener(RTNLHandler::kRequestAddr, address_callback_));
163 rdnss_listener_.reset(
164 new RTNLListener(RTNLHandler::kRequestRdnss, rdnss_callback_));
165 rtnl_handler_->RequestDump(RTNLHandler::kRequestLink |
166 RTNLHandler::kRequestAddr);
167 request_link_statistics_callback_.Reset(
168 Bind(&DeviceInfo::RequestLinkStatistics, AsWeakPtr()));
169 dispatcher_->PostDelayedTask(request_link_statistics_callback_.callback(),
170 kRequestLinkStatisticsIntervalMilliseconds);
171 }
172
Stop()173 void DeviceInfo::Stop() {
174 link_listener_.reset();
175 address_listener_.reset();
176 infos_.clear();
177 request_link_statistics_callback_.Cancel();
178 delayed_devices_callback_.Cancel();
179 delayed_devices_.clear();
180 }
181
GetUninitializedTechnologies() const182 vector<string> DeviceInfo::GetUninitializedTechnologies() const {
183 set<string> unique_technologies;
184 set<Technology::Identifier> initialized_technologies;
185 for (const auto& info : infos_) {
186 Technology::Identifier technology = info.second.technology;
187 if (info.second.device) {
188 // If there is more than one device for a technology and at least
189 // one of them has been initialized, make sure that it doesn't get
190 // listed as uninitialized.
191 initialized_technologies.insert(technology);
192 unique_technologies.erase(Technology::NameFromIdentifier(technology));
193 continue;
194 }
195 if (Technology::IsPrimaryConnectivityTechnology(technology) &&
196 !ContainsKey(initialized_technologies, technology))
197 unique_technologies.insert(Technology::NameFromIdentifier(technology));
198 }
199 return vector<string>(unique_technologies.begin(), unique_technologies.end());
200 }
201
RegisterDevice(const DeviceRefPtr & device)202 void DeviceInfo::RegisterDevice(const DeviceRefPtr& device) {
203 SLOG(this, 2) << __func__ << "(" << device->link_name() << ", "
204 << device->interface_index() << ")";
205 device->Initialize();
206 delayed_devices_.erase(device->interface_index());
207 CHECK(!GetDevice(device->interface_index()).get());
208 infos_[device->interface_index()].device = device;
209 if (metrics_->IsDeviceRegistered(device->interface_index(),
210 device->technology())) {
211 metrics_->NotifyDeviceInitialized(device->interface_index());
212 } else {
213 metrics_->RegisterDevice(device->interface_index(), device->technology());
214 }
215 if (Technology::IsPrimaryConnectivityTechnology(device->technology())) {
216 manager_->RegisterDevice(device);
217 }
218 }
219
DeregisterDevice(const DeviceRefPtr & device)220 void DeviceInfo::DeregisterDevice(const DeviceRefPtr& device) {
221 int interface_index = device->interface_index();
222
223 SLOG(this, 2) << __func__ << "(" << device->link_name() << ", "
224 << interface_index << ")";
225 CHECK((device->technology() == Technology::kCellular) ||
226 (device->technology() == Technology::kWiMax));
227
228 // Release reference to the device
229 map<int, Info>::iterator iter = infos_.find(interface_index);
230 if (iter != infos_.end()) {
231 SLOG(this, 2) << "Removing device from info for index: "
232 << interface_index;
233 manager_->DeregisterDevice(device);
234 // Release the reference to the device, but maintain the mapping
235 // for the index. That will be cleaned up by an RTNL message.
236 iter->second.device = nullptr;
237 }
238 metrics_->DeregisterDevice(device->interface_index());
239 }
240
GetDeviceInfoPath(const string & iface_name,const string & path_name)241 FilePath DeviceInfo::GetDeviceInfoPath(const string& iface_name,
242 const string& path_name) {
243 return device_info_root_.Append(iface_name).Append(path_name);
244 }
245
GetDeviceInfoContents(const string & iface_name,const string & path_name,string * contents_out)246 bool DeviceInfo::GetDeviceInfoContents(const string& iface_name,
247 const string& path_name,
248 string* contents_out) {
249 return base::ReadFileToString(GetDeviceInfoPath(iface_name, path_name),
250 contents_out);
251 }
252
GetDeviceInfoSymbolicLink(const string & iface_name,const string & path_name,FilePath * path_out)253 bool DeviceInfo::GetDeviceInfoSymbolicLink(const string& iface_name,
254 const string& path_name,
255 FilePath* path_out) {
256 return base::ReadSymbolicLink(GetDeviceInfoPath(iface_name, path_name),
257 path_out);
258 }
259
GetDeviceTechnology(const string & iface_name)260 Technology::Identifier DeviceInfo::GetDeviceTechnology(
261 const string& iface_name) {
262 string type_string;
263 int arp_type = ARPHRD_VOID;
264 if (GetDeviceInfoContents(iface_name, kInterfaceType, &type_string) &&
265 base::TrimString(type_string, "\n", &type_string) &&
266 !base::StringToInt(type_string, &arp_type)) {
267 arp_type = ARPHRD_VOID;
268 }
269
270 string contents;
271 if (!GetDeviceInfoContents(iface_name, kInterfaceUevent, &contents)) {
272 LOG(INFO) << StringPrintf("%s: device %s has no uevent file",
273 __func__, iface_name.c_str());
274 return Technology::kUnknown;
275 }
276
277 // If the "uevent" file contains the string "DEVTYPE=wlan\n" at the
278 // start of the file or after a newline, we can safely assume this
279 // is a wifi device.
280 if (contents.find(kInterfaceUeventWifiSignature) != string::npos) {
281 SLOG(this, 2)
282 << StringPrintf("%s: device %s has wifi signature in uevent file",
283 __func__, iface_name.c_str());
284 if (arp_type == ARPHRD_IEEE80211_RADIOTAP) {
285 SLOG(this, 2) << StringPrintf("%s: wifi device %s is in monitor mode",
286 __func__, iface_name.c_str());
287 return Technology::kWiFiMonitor;
288 }
289 return Technology::kWifi;
290 }
291
292 // Special case for pseudo modems which are used for testing
293 if (iface_name.find(kModemPseudoDeviceNamePrefix) == 0) {
294 SLOG(this, 2) << StringPrintf(
295 "%s: device %s is a pseudo modem for testing",
296 __func__, iface_name.c_str());
297 return Technology::kCellular;
298 }
299
300 // Special case for pseudo ethernet devices which are used for testing.
301 if (iface_name.find(kEthernetPseudoDeviceNamePrefix) == 0) {
302 SLOG(this, 2) << StringPrintf(
303 "%s: device %s is a virtual ethernet device for testing",
304 __func__, iface_name.c_str());
305 return Technology::kEthernet;
306 }
307
308 // Special case for devices which should be ignored.
309 if (iface_name.find(kIgnoredDeviceNamePrefix) == 0) {
310 SLOG(this, 2) << StringPrintf(
311 "%s: device %s should be ignored", __func__, iface_name.c_str());
312 return Technology::kUnknown;
313 }
314
315 FilePath driver_path;
316 if (!GetDeviceInfoSymbolicLink(iface_name, kInterfaceDriver, &driver_path)) {
317 SLOG(this, 2) << StringPrintf("%s: device %s has no device symlink",
318 __func__, iface_name.c_str());
319 if (arp_type == ARPHRD_LOOPBACK) {
320 SLOG(this, 2) << StringPrintf("%s: device %s is a loopback device",
321 __func__, iface_name.c_str());
322 return Technology::kLoopback;
323 }
324 if (arp_type == ARPHRD_PPP) {
325 SLOG(this, 2) << StringPrintf("%s: device %s is a ppp device",
326 __func__, iface_name.c_str());
327 return Technology::kPPP;
328 }
329 string tun_flags_str;
330 int tun_flags = 0;
331 if (GetDeviceInfoContents(iface_name, kInterfaceTunFlags, &tun_flags_str) &&
332 base::TrimString(tun_flags_str, "\n", &tun_flags_str) &&
333 base::HexStringToInt(tun_flags_str, &tun_flags) &&
334 (tun_flags & IFF_TUN)) {
335 SLOG(this, 2) << StringPrintf("%s: device %s is tun device",
336 __func__, iface_name.c_str());
337 return Technology::kTunnel;
338 }
339
340 // We don't know what sort of device it is.
341 return Technology::kNoDeviceSymlink;
342 }
343
344 string driver_name(driver_path.BaseName().value());
345 // See if driver for this interface is in a list of known modem driver names.
346 for (size_t modem_idx = 0; modem_idx < arraysize(kModemDrivers);
347 ++modem_idx) {
348 if (driver_name == kModemDrivers[modem_idx]) {
349 SLOG(this, 2)
350 << StringPrintf("%s: device %s is matched with modem driver %s",
351 __func__, iface_name.c_str(), driver_name.c_str());
352 return Technology::kCellular;
353 }
354 }
355
356 if (driver_name == kDriverGdmWiMax) {
357 SLOG(this, 2) << StringPrintf("%s: device %s is a WiMAX device",
358 __func__, iface_name.c_str());
359 return Technology::kWiMax;
360 }
361
362 // For cdc_ether / cdc_ncm devices, make sure it's a modem because this driver
363 // can be used for other ethernet devices.
364 if (driver_name == kDriverCdcEther || driver_name == kDriverCdcNcm) {
365 if (IsCdcEthernetModemDevice(iface_name)) {
366 LOG(INFO) << StringPrintf("%s: device %s is a %s modem device", __func__,
367 iface_name.c_str(), driver_name.c_str());
368 return Technology::kCellular;
369 }
370 SLOG(this, 2) << StringPrintf("%s: device %s is a %s device", __func__,
371 iface_name.c_str(), driver_name.c_str());
372 return Technology::kCDCEthernet;
373 }
374
375 // Special case for the virtio driver, used when run under KVM. See also
376 // the comment in VirtioEthernet::Start.
377 if (driver_name == kDriverVirtioNet) {
378 SLOG(this, 2) << StringPrintf("%s: device %s is virtio ethernet",
379 __func__, iface_name.c_str());
380 return Technology::kVirtioEthernet;
381 }
382
383 SLOG(this, 2) << StringPrintf("%s: device %s, with driver %s, "
384 "is defaulted to type ethernet",
385 __func__, iface_name.c_str(),
386 driver_name.c_str());
387 return Technology::kEthernet;
388 }
389
IsCdcEthernetModemDevice(const std::string & iface_name)390 bool DeviceInfo::IsCdcEthernetModemDevice(const std::string& iface_name) {
391 // A cdc_ether / cdc_ncm device is a modem device if it also exposes tty
392 // interfaces. To determine this, we look for the existence of the tty
393 // interface in the USB device sysfs tree.
394 //
395 // A typical sysfs dir hierarchy for a cdc_ether / cdc_ncm modem USB device is
396 // as follows:
397 //
398 // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2
399 // 1-2:1.0
400 // tty
401 // ttyACM0
402 // 1-2:1.1
403 // net
404 // usb0
405 // 1-2:1.2
406 // tty
407 // ttyACM1
408 // ...
409 //
410 // /sys/class/net/usb0/device symlinks to
411 // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2/1-2:1.1
412 //
413 // Note that some modem devices have the tty directory one level deeper
414 // (eg. E362), so the device tree for the tty interface is:
415 // /sys/devices/pci0000:00/0000:00:1d.7/usb/1-2/1-2:1.0/ttyUSB0/tty/ttyUSB0
416
417 FilePath device_file = GetDeviceInfoPath(iface_name, kInterfaceDevice);
418 FilePath device_path;
419 if (!base::ReadSymbolicLink(device_file, &device_path)) {
420 SLOG(this, 2) << StringPrintf("%s: device %s has no device symlink",
421 __func__, iface_name.c_str());
422 return false;
423 }
424 if (!device_path.IsAbsolute()) {
425 device_path =
426 base::MakeAbsoluteFilePath(device_file.DirName().Append(device_path));
427 }
428
429 // Look for tty interface by enumerating all directories under the parent
430 // USB device and see if there's a subdirectory "tty" inside. In other
431 // words, using the example dir hierarchy above, find
432 // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2/.../tty.
433 // If this exists, then this is a modem device.
434 return HasSubdir(device_path.DirName(), FilePath("tty"));
435 }
436
437 // static
HasSubdir(const FilePath & base_dir,const FilePath & subdir)438 bool DeviceInfo::HasSubdir(const FilePath& base_dir, const FilePath& subdir) {
439 FileEnumerator::FileType type = static_cast<FileEnumerator::FileType>(
440 FileEnumerator::DIRECTORIES | FileEnumerator::SHOW_SYM_LINKS);
441 FileEnumerator dir_enum(base_dir, true, type);
442 for (FilePath curr_dir = dir_enum.Next(); !curr_dir.empty();
443 curr_dir = dir_enum.Next()) {
444 if (curr_dir.BaseName() == subdir)
445 return true;
446 }
447 return false;
448 }
449
CreateDevice(const string & link_name,const string & address,int interface_index,Technology::Identifier technology)450 DeviceRefPtr DeviceInfo::CreateDevice(const string& link_name,
451 const string& address,
452 int interface_index,
453 Technology::Identifier technology) {
454 DeviceRefPtr device;
455 delayed_devices_.erase(interface_index);
456 infos_[interface_index].technology = technology;
457
458 switch (technology) {
459 case Technology::kCellular:
460 #if defined(DISABLE_CELLULAR)
461 LOG(WARNING) << "Cellular support is not implemented. "
462 << "Ignore cellular device " << link_name << " at index "
463 << interface_index << ".";
464 return nullptr;
465 #else
466 // Cellular devices are managed by ModemInfo.
467 SLOG(this, 2) << "Cellular link " << link_name
468 << " at index " << interface_index
469 << " -- notifying ModemInfo.";
470
471 // The MAC address provided by RTNL is not reliable for Gobi 2K modems.
472 // Clear it here, and it will be fetched from the kernel in
473 // GetMACAddress().
474 infos_[interface_index].mac_address.Clear();
475 manager_->modem_info()->OnDeviceInfoAvailable(link_name);
476 break;
477 #endif // DISABLE_CELLULAR
478 case Technology::kEthernet:
479 device = new Ethernet(control_interface_, dispatcher_, metrics_,
480 manager_, link_name, address, interface_index);
481 device->EnableIPv6Privacy();
482 break;
483 case Technology::kVirtioEthernet:
484 device = new VirtioEthernet(control_interface_, dispatcher_, metrics_,
485 manager_, link_name, address,
486 interface_index);
487 device->EnableIPv6Privacy();
488 break;
489 case Technology::kWifi:
490 #if defined(DISABLE_WIFI)
491 LOG(WARNING) << "WiFi support is not implemented. Ignore WiFi link "
492 << link_name << " at index " << interface_index << ".";
493 return nullptr;
494 #else
495 // Defer creating this device until we get information about the
496 // type of WiFi interface.
497 GetWiFiInterfaceInfo(interface_index);
498 break;
499 #endif // DISABLE_WIFI
500 case Technology::kWiMax:
501 #if defined(DISABLE_WIMAX)
502 LOG(WARNING) << "WiMax support is not implemented. Ignore WiMax link "
503 << link_name << " at index " << interface_index << ".";
504 return nullptr;
505 #else
506 // WiMax devices are managed by WiMaxProvider.
507 SLOG(this, 2) << "WiMax link " << link_name
508 << " at index " << interface_index
509 << " -- notifying WiMaxProvider.";
510 // The MAC address provided by RTNL may not be the final value as the
511 // WiMAX device may change the address after initialization. Clear it
512 // here, and it will be fetched from the kernel when
513 // WiMaxProvider::CreateDevice() is called after the WiMAX device DBus
514 // object is created by the WiMAX manager daemon.
515 infos_[interface_index].mac_address.Clear();
516 manager_->wimax_provider()->OnDeviceInfoAvailable(link_name);
517 break;
518 #endif // DISABLE_WIMAX
519 case Technology::kPPP:
520 case Technology::kTunnel:
521 // Tunnel and PPP devices are managed by the VPN code (PPP for
522 // l2tpipsec). Notify the VPN Provider of the interface's presence.
523 // Since CreateDevice is only called once in the lifetime of an
524 // interface index, this notification will only occur the first
525 // time the device is seen.
526 SLOG(this, 2) << "Tunnel / PPP link " << link_name
527 << " at index " << interface_index
528 << " -- notifying VPNProvider.";
529 if (!manager_->vpn_provider()->OnDeviceInfoAvailable(link_name,
530 interface_index) &&
531 technology == Technology::kTunnel) {
532 // If VPN does not know anything about this tunnel, it is probably
533 // left over from a previous instance and should not exist.
534 SLOG(this, 2) << "Tunnel link is unused. Deleting.";
535 DeleteInterface(interface_index);
536 }
537 break;
538 case Technology::kLoopback:
539 // Loopback devices are largely ignored, but we should make sure the
540 // link is enabled.
541 SLOG(this, 2) << "Bringing up loopback device " << link_name
542 << " at index " << interface_index;
543 rtnl_handler_->SetInterfaceFlags(interface_index, IFF_UP, IFF_UP);
544 return nullptr;
545 case Technology::kCDCEthernet:
546 // CDCEthernet devices are of indeterminate type when they are
547 // initially created. Some time later, tty devices may or may
548 // not appear under the same USB device root, which will identify
549 // it as a modem. Alternatively, ModemManager may discover the
550 // device and create and register a Cellular device. In either
551 // case, we should delay creating a Device until we can make a
552 // better determination of what type this Device should be.
553 case Technology::kNoDeviceSymlink: // FALLTHROUGH
554 // The same is true for devices that do not report a device
555 // symlink. It has been observed that tunnel devices may not
556 // immediately contain a tun_flags component in their
557 // /sys/class/net entry.
558 LOG(INFO) << "Delaying creation of device for " << link_name
559 << " at index " << interface_index;
560 DelayDeviceCreation(interface_index);
561 return nullptr;
562 default:
563 // We will not manage this device in shill. Do not create a device
564 // object or do anything to change its state. We create a stub object
565 // which is useful for testing.
566 return new DeviceStub(control_interface_, dispatcher_, metrics_,
567 manager_, link_name, address, interface_index,
568 technology);
569 }
570
571 // Reset the routing table and addresses.
572 routing_table_->FlushRoutes(interface_index);
573 FlushAddresses(interface_index);
574
575 manager_->UpdateUninitializedTechnologies();
576
577 return device;
578 }
579
580 // static
GetLinkNameFromMessage(const RTNLMessage & msg,string * link_name)581 bool DeviceInfo::GetLinkNameFromMessage(const RTNLMessage& msg,
582 string* link_name) {
583 if (!msg.HasAttribute(IFLA_IFNAME))
584 return false;
585
586 ByteString link_name_bytes(msg.GetAttribute(IFLA_IFNAME));
587 link_name->assign(reinterpret_cast<const char*>(
588 link_name_bytes.GetConstData()));
589
590 return true;
591 }
592
IsRenamedBlacklistedDevice(const RTNLMessage & msg)593 bool DeviceInfo::IsRenamedBlacklistedDevice(const RTNLMessage& msg) {
594 int interface_index = msg.interface_index();
595 const Info* info = GetInfo(interface_index);
596 if (!info)
597 return false;
598
599 if (!info->device || info->device->technology() != Technology::kBlacklisted)
600 return false;
601
602 string interface_name;
603 if (!GetLinkNameFromMessage(msg, &interface_name))
604 return false;
605
606 if (interface_name == info->name)
607 return false;
608
609 LOG(INFO) << __func__ << ": interface index " << interface_index
610 << " renamed from " << info->name << " to " << interface_name;
611 return true;
612 }
613
614
AddLinkMsgHandler(const RTNLMessage & msg)615 void DeviceInfo::AddLinkMsgHandler(const RTNLMessage& msg) {
616 DCHECK(msg.type() == RTNLMessage::kTypeLink &&
617 msg.mode() == RTNLMessage::kModeAdd);
618 int dev_index = msg.interface_index();
619 Technology::Identifier technology = Technology::kUnknown;
620 unsigned int flags = msg.link_status().flags;
621 unsigned int change = msg.link_status().change;
622
623 if (IsRenamedBlacklistedDevice(msg)) {
624 // Treat renamed blacklisted devices as new devices.
625 RemoveInfo(dev_index);
626 }
627
628 bool new_device =
629 !ContainsKey(infos_, dev_index) || infos_[dev_index].has_addresses_only;
630 SLOG(this, 2) << __func__ << "(index=" << dev_index
631 << std::showbase << std::hex
632 << ", flags=" << flags << ", change=" << change << ")"
633 << std::dec << std::noshowbase
634 << ", new_device=" << new_device;
635 infos_[dev_index].has_addresses_only = false;
636 infos_[dev_index].flags = flags;
637
638 RetrieveLinkStatistics(dev_index, msg);
639
640 DeviceRefPtr device = GetDevice(dev_index);
641 if (new_device) {
642 CHECK(!device);
643 string link_name;
644 if (!GetLinkNameFromMessage(msg, &link_name)) {
645 LOG(ERROR) << "Add Link message does not contain a link name!";
646 return;
647 }
648 SLOG(this, 2) << "add link index " << dev_index << " name " << link_name;
649 infos_[dev_index].name = link_name;
650 indices_[link_name] = dev_index;
651
652 if (!link_name.empty()) {
653 if (IsDeviceBlackListed(link_name)) {
654 technology = Technology::kBlacklisted;
655 } else if (!manager_->DeviceManagementAllowed(link_name)) {
656 technology = Technology::kBlacklisted;
657 AddDeviceToBlackList(link_name);
658 } else {
659 technology = GetDeviceTechnology(link_name);
660 }
661 }
662 string address;
663 if (msg.HasAttribute(IFLA_ADDRESS)) {
664 infos_[dev_index].mac_address = msg.GetAttribute(IFLA_ADDRESS);
665 address =
666 base::ToLowerASCII(infos_[dev_index].mac_address.HexEncode());
667 SLOG(this, 2) << "link index " << dev_index << " address "
668 << infos_[dev_index].mac_address.HexEncode();
669 } else if (technology != Technology::kTunnel &&
670 technology != Technology::kPPP &&
671 technology != Technology::kNoDeviceSymlink) {
672 LOG(ERROR) << "Add Link message for link '" << link_name
673 << "' does not have IFLA_ADDRESS!";
674 return;
675 }
676 metrics_->RegisterDevice(dev_index, technology);
677 device = CreateDevice(link_name, address, dev_index, technology);
678 if (device) {
679 RegisterDevice(device);
680 }
681 }
682 if (device) {
683 device->LinkEvent(flags, change);
684 }
685 }
686
DelLinkMsgHandler(const RTNLMessage & msg)687 void DeviceInfo::DelLinkMsgHandler(const RTNLMessage& msg) {
688 SLOG(this, 2) << __func__ << "(index=" << msg.interface_index() << ")";
689
690 DCHECK(msg.type() == RTNLMessage::kTypeLink &&
691 msg.mode() == RTNLMessage::kModeDelete);
692 SLOG(this, 2) << __func__ << "(index=" << msg.interface_index()
693 << std::showbase << std::hex
694 << ", flags=" << msg.link_status().flags
695 << ", change=" << msg.link_status().change << ")";
696 RemoveInfo(msg.interface_index());
697 }
698
GetDevice(int interface_index) const699 DeviceRefPtr DeviceInfo::GetDevice(int interface_index) const {
700 const Info* info = GetInfo(interface_index);
701 return info ? info->device : nullptr;
702 }
703
GetIndex(const string & interface_name) const704 int DeviceInfo::GetIndex(const string& interface_name) const {
705 map<string, int>::const_iterator it = indices_.find(interface_name);
706 return it == indices_.end() ? -1 : it->second;
707 }
708
GetMACAddress(int interface_index,ByteString * address) const709 bool DeviceInfo::GetMACAddress(int interface_index, ByteString* address) const {
710 const Info* info = GetInfo(interface_index);
711 if (!info) {
712 return false;
713 }
714 // |mac_address| from RTNL is not used for some devices, in which case it will
715 // be empty here.
716 if (!info->mac_address.IsEmpty()) {
717 *address = info->mac_address;
718 return true;
719 }
720
721 // Ask the kernel for the MAC address.
722 *address = GetMACAddressFromKernel(interface_index);
723 return !address->IsEmpty();
724 }
725
GetMACAddressFromKernel(int interface_index) const726 ByteString DeviceInfo::GetMACAddressFromKernel(int interface_index) const {
727 const Info* info = GetInfo(interface_index);
728 if (!info) {
729 return ByteString();
730 }
731
732 const int fd = sockets_->Socket(PF_INET, SOCK_DGRAM, 0);
733 if (fd < 0) {
734 PLOG(ERROR) << __func__ << ": Unable to open socket";
735 return ByteString();
736 }
737
738 ScopedSocketCloser socket_closer(sockets_.get(), fd);
739 struct ifreq ifr;
740 memset(&ifr, 0, sizeof(ifr));
741 ifr.ifr_ifindex = interface_index;
742 strcpy(ifr.ifr_ifrn.ifrn_name, info->name.c_str()); // NOLINT(runtime/printf)
743 int err = sockets_->Ioctl(fd, SIOCGIFHWADDR, &ifr);
744 if (err < 0) {
745 PLOG(ERROR) << __func__ << ": Unable to read MAC address";
746 return ByteString();
747 }
748
749 return ByteString(ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
750 }
751
GetMACAddressOfPeer(int interface_index,const IPAddress & peer,ByteString * mac_address) const752 bool DeviceInfo::GetMACAddressOfPeer(int interface_index,
753 const IPAddress& peer,
754 ByteString* mac_address) const {
755 const Info* info = GetInfo(interface_index);
756 if (!info || !peer.IsValid()) {
757 return false;
758 }
759
760 if (peer.family() != IPAddress::kFamilyIPv4) {
761 NOTIMPLEMENTED() << ": only implemented for IPv4";
762 return false;
763 }
764
765 const int fd = sockets_->Socket(PF_INET, SOCK_DGRAM, 0);
766 if (fd < 0) {
767 PLOG(ERROR) << __func__ << ": Unable to open socket";
768 return false;
769 }
770
771 ScopedSocketCloser socket_closer(sockets_.get(), fd);
772 struct arpreq areq;
773 memset(&areq, 0, sizeof(areq));
774
775 strncpy(areq.arp_dev, info->name.c_str(), sizeof(areq.arp_dev) - 1);
776 areq.arp_dev[sizeof(areq.arp_dev) - 1] = '\0';
777
778 struct sockaddr_in* protocol_address =
779 reinterpret_cast<struct sockaddr_in*>(&areq.arp_pa);
780 protocol_address->sin_family = AF_INET;
781 CHECK_EQ(sizeof(protocol_address->sin_addr.s_addr), peer.GetLength());
782 memcpy(&protocol_address->sin_addr.s_addr, peer.address().GetConstData(),
783 sizeof(protocol_address->sin_addr.s_addr));
784
785 struct sockaddr_in* hardware_address =
786 reinterpret_cast<struct sockaddr_in*>(&areq.arp_ha);
787 hardware_address->sin_family = ARPHRD_ETHER;
788
789 int err = sockets_->Ioctl(fd, SIOCGARP, &areq);
790 if (err < 0) {
791 PLOG(ERROR) << __func__ << ": Unable to perform ARP lookup";
792 return false;
793 }
794
795 ByteString peer_address(areq.arp_ha.sa_data, IFHWADDRLEN);
796
797 if (peer_address.IsZero()) {
798 LOG(INFO) << __func__ << ": ARP lookup is still in progress";
799 return false;
800 }
801
802 CHECK(mac_address);
803 *mac_address = peer_address;
804 return true;
805 }
806
GetAddresses(int interface_index,vector<AddressData> * addresses) const807 bool DeviceInfo::GetAddresses(int interface_index,
808 vector<AddressData>* addresses) const {
809 const Info* info = GetInfo(interface_index);
810 if (!info) {
811 return false;
812 }
813 *addresses = info->ip_addresses;
814 return true;
815 }
816
FlushAddresses(int interface_index) const817 void DeviceInfo::FlushAddresses(int interface_index) const {
818 SLOG(this, 2) << __func__ << "(" << interface_index << ")";
819 const Info* info = GetInfo(interface_index);
820 if (!info) {
821 return;
822 }
823 for (const auto& address_info : info->ip_addresses) {
824 if (address_info.address.family() == IPAddress::kFamilyIPv4 ||
825 (address_info.scope == RT_SCOPE_UNIVERSE &&
826 (address_info.flags & ~IFA_F_TEMPORARY) == 0)) {
827 SLOG(this, 2) << __func__ << ": removing ip address "
828 << address_info.address.ToString()
829 << " from interface " << interface_index;
830 rtnl_handler_->RemoveInterfaceAddress(interface_index,
831 address_info.address);
832 }
833 }
834 }
835
HasOtherAddress(int interface_index,const IPAddress & this_address) const836 bool DeviceInfo::HasOtherAddress(
837 int interface_index, const IPAddress& this_address) const {
838 SLOG(this, 3) << __func__ << "(" << interface_index << ")";
839 const Info* info = GetInfo(interface_index);
840 if (!info) {
841 return false;
842 }
843 bool has_other_address = false;
844 bool has_this_address = false;
845 for (const auto& local_address : info->ip_addresses) {
846 if (local_address.address.family() != this_address.family()) {
847 continue;
848 }
849 if (local_address.address.address().Equals(this_address.address())) {
850 has_this_address = true;
851 } else if (this_address.family() == IPAddress::kFamilyIPv4) {
852 has_other_address = true;
853 } else if ((local_address.scope == RT_SCOPE_UNIVERSE &&
854 (local_address.flags & IFA_F_TEMPORARY) == 0)) {
855 has_other_address = true;
856 }
857 }
858 return has_other_address && !has_this_address;
859 }
860
GetPrimaryIPv6Address(int interface_index,IPAddress * address)861 bool DeviceInfo::GetPrimaryIPv6Address(int interface_index,
862 IPAddress* address) {
863 const Info* info = GetInfo(interface_index);
864 if (!info) {
865 return false;
866 }
867 bool has_temporary_address = false;
868 bool has_current_address = false;
869 bool has_address = false;
870 for (const auto& local_address : info->ip_addresses) {
871 if (local_address.address.family() != IPAddress::kFamilyIPv6 ||
872 local_address.scope != RT_SCOPE_UNIVERSE) {
873 continue;
874 }
875
876 // Prefer non-deprecated addresses to deprecated addresses to match the
877 // kernel's preference.
878 bool is_current_address =
879 ((local_address.flags & IFA_F_DEPRECATED) == 0);
880 if (has_current_address && !is_current_address) {
881 continue;
882 }
883
884 // Prefer temporary addresses to non-temporary addresses to match the
885 // kernel's preference.
886 bool is_temporary_address = ((local_address.flags & IFA_F_TEMPORARY) != 0);
887 if (has_temporary_address && !is_temporary_address) {
888 continue;
889 }
890
891 *address = local_address.address;
892 has_temporary_address = is_temporary_address;
893 has_current_address = is_current_address;
894 has_address = true;
895 }
896
897 return has_address;
898 }
899
GetIPv6DnsServerAddresses(int interface_index,std::vector<IPAddress> * address_list,uint32_t * life_time)900 bool DeviceInfo::GetIPv6DnsServerAddresses(int interface_index,
901 std::vector<IPAddress>* address_list,
902 uint32_t* life_time) {
903 const Info* info = GetInfo(interface_index);
904 if (!info || info->ipv6_dns_server_addresses.empty()) {
905 return false;
906 }
907
908 // Determine the remaining DNS server life time.
909 if (info->ipv6_dns_server_lifetime_seconds == ND_OPT_LIFETIME_INFINITY) {
910 *life_time = ND_OPT_LIFETIME_INFINITY;
911 } else {
912 time_t cur_time;
913 if (!time_->GetSecondsBoottime(&cur_time)) {
914 NOTREACHED();
915 }
916 uint32_t time_elapsed = static_cast<uint32_t>(
917 cur_time - info->ipv6_dns_server_received_time_seconds);
918 if (time_elapsed >= info->ipv6_dns_server_lifetime_seconds) {
919 *life_time = 0;
920 } else {
921 *life_time = info->ipv6_dns_server_lifetime_seconds - time_elapsed;
922 }
923 }
924 *address_list = info->ipv6_dns_server_addresses;
925 return true;
926 }
927
HasDirectConnectivityTo(int interface_index,const IPAddress & address) const928 bool DeviceInfo::HasDirectConnectivityTo(
929 int interface_index, const IPAddress& address) const {
930 SLOG(this, 3) << __func__ << "(" << interface_index << ")";
931 const Info* info = GetInfo(interface_index);
932 if (!info) {
933 return false;
934 }
935
936 for (const auto& local_address : info->ip_addresses) {
937 if (local_address.address.family() == address.family() &&
938 local_address.address.CanReachAddress(address)) {
939 return true;
940 }
941 }
942
943 return false;
944 }
945
GetFlags(int interface_index,unsigned int * flags) const946 bool DeviceInfo::GetFlags(int interface_index, unsigned int* flags) const {
947 const Info* info = GetInfo(interface_index);
948 if (!info) {
949 return false;
950 }
951 *flags = info->flags;
952 return true;
953 }
954
GetByteCounts(int interface_index,uint64_t * rx_bytes,uint64_t * tx_bytes) const955 bool DeviceInfo::GetByteCounts(int interface_index,
956 uint64_t* rx_bytes,
957 uint64_t* tx_bytes) const {
958 const Info* info = GetInfo(interface_index);
959 if (!info) {
960 return false;
961 }
962 *rx_bytes = info->rx_bytes;
963 *tx_bytes = info->tx_bytes;
964 return true;
965 }
966
CreateTunnelInterface(string * interface_name) const967 bool DeviceInfo::CreateTunnelInterface(string* interface_name) const {
968 int fd = HANDLE_EINTR(open(kTunDeviceName, O_RDWR));
969 if (fd < 0) {
970 PLOG(ERROR) << "failed to open " << kTunDeviceName;
971 return false;
972 }
973 base::ScopedFD scoped_fd(fd);
974
975 struct ifreq ifr;
976 memset(&ifr, 0, sizeof(ifr));
977 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
978 if (HANDLE_EINTR(ioctl(fd, TUNSETIFF, &ifr))) {
979 PLOG(ERROR) << "failed to create tunnel interface";
980 return false;
981 }
982
983 if (HANDLE_EINTR(ioctl(fd, TUNSETPERSIST, 1))) {
984 PLOG(ERROR) << "failed to set tunnel interface to be persistent";
985 return false;
986 }
987
988 *interface_name = string(ifr.ifr_name);
989
990 return true;
991 }
992
OpenTunnelInterface(const std::string & interface_name) const993 int DeviceInfo::OpenTunnelInterface(const std::string& interface_name) const {
994 int fd = HANDLE_EINTR(open(kTunDeviceName, O_RDWR));
995 if (fd < 0) {
996 PLOG(ERROR) << "failed to open " << kTunDeviceName;
997 return -1;
998 }
999
1000 struct ifreq ifr;
1001 memset(&ifr, 0, sizeof(ifr));
1002 strncpy(ifr.ifr_name, interface_name.c_str(), sizeof(ifr.ifr_name));
1003 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
1004 if (HANDLE_EINTR(ioctl(fd, TUNSETIFF, &ifr))) {
1005 PLOG(ERROR) << "failed to set tunnel interface name";
1006 return -1;
1007 }
1008
1009 return fd;
1010 }
1011
DeleteInterface(int interface_index) const1012 bool DeviceInfo::DeleteInterface(int interface_index) const {
1013 return rtnl_handler_->RemoveInterface(interface_index);
1014 }
1015
GetInfo(int interface_index) const1016 const DeviceInfo::Info* DeviceInfo::GetInfo(int interface_index) const {
1017 map<int, Info>::const_iterator iter = infos_.find(interface_index);
1018 if (iter == infos_.end()) {
1019 return nullptr;
1020 }
1021 return &iter->second;
1022 }
1023
RemoveInfo(int interface_index)1024 void DeviceInfo::RemoveInfo(int interface_index) {
1025 map<int, Info>::iterator iter = infos_.find(interface_index);
1026 if (iter != infos_.end()) {
1027 SLOG(this, 2) << "Removing info for device index: " << interface_index;
1028 // Deregister the device if not deregistered yet. Cellular and WiMax devices
1029 // are deregistered through a call to DeviceInfo::DeregisterDevice.
1030 if (iter->second.device.get()) {
1031 manager_->DeregisterDevice(iter->second.device);
1032 metrics_->DeregisterDevice(interface_index);
1033 }
1034 indices_.erase(iter->second.name);
1035 infos_.erase(iter);
1036 delayed_devices_.erase(interface_index);
1037 } else {
1038 SLOG(this, 2) << __func__ << ": Unknown device index: "
1039 << interface_index;
1040 }
1041 }
1042
LinkMsgHandler(const RTNLMessage & msg)1043 void DeviceInfo::LinkMsgHandler(const RTNLMessage& msg) {
1044 DCHECK(msg.type() == RTNLMessage::kTypeLink);
1045 if (msg.mode() == RTNLMessage::kModeAdd) {
1046 AddLinkMsgHandler(msg);
1047 } else if (msg.mode() == RTNLMessage::kModeDelete) {
1048 DelLinkMsgHandler(msg);
1049 } else {
1050 NOTREACHED();
1051 }
1052 }
1053
AddressMsgHandler(const RTNLMessage & msg)1054 void DeviceInfo::AddressMsgHandler(const RTNLMessage& msg) {
1055 SLOG(this, 2) << __func__;
1056 DCHECK(msg.type() == RTNLMessage::kTypeAddress);
1057 int interface_index = msg.interface_index();
1058 if (!ContainsKey(infos_, interface_index)) {
1059 SLOG(this, 2) << "Got advance address information for unknown index "
1060 << interface_index;
1061 infos_[interface_index].has_addresses_only = true;
1062 }
1063 const RTNLMessage::AddressStatus& status = msg.address_status();
1064 IPAddress address(msg.family(),
1065 msg.HasAttribute(IFA_LOCAL) ?
1066 msg.GetAttribute(IFA_LOCAL) : msg.GetAttribute(IFA_ADDRESS),
1067 status.prefix_len);
1068
1069 SLOG_IF(Device, 2, msg.HasAttribute(IFA_LOCAL))
1070 << "Found local address attribute for interface " << interface_index;
1071
1072 vector<AddressData>& address_list = infos_[interface_index].ip_addresses;
1073 vector<AddressData>::iterator iter;
1074 for (iter = address_list.begin(); iter != address_list.end(); ++iter) {
1075 if (address.Equals(iter->address)) {
1076 break;
1077 }
1078 }
1079 if (iter != address_list.end()) {
1080 if (msg.mode() == RTNLMessage::kModeDelete) {
1081 SLOG(this, 2) << "Delete address for interface " << interface_index;
1082 address_list.erase(iter);
1083 } else {
1084 iter->flags = status.flags;
1085 iter->scope = status.scope;
1086 }
1087 } else if (msg.mode() == RTNLMessage::kModeAdd) {
1088 address_list.push_back(AddressData(address, status.flags, status.scope));
1089 SLOG(this, 2) << "Add address " << address.ToString()
1090 << " for interface " << interface_index;
1091 }
1092
1093 DeviceRefPtr device = GetDevice(interface_index);
1094 if (device && address.family() == IPAddress::kFamilyIPv6 &&
1095 status.scope == RT_SCOPE_UNIVERSE) {
1096 device->OnIPv6AddressChanged();
1097 }
1098 }
1099
RdnssMsgHandler(const RTNLMessage & msg)1100 void DeviceInfo::RdnssMsgHandler(const RTNLMessage& msg) {
1101 SLOG(this, 2) << __func__;
1102 DCHECK(msg.type() == RTNLMessage::kTypeRdnss);
1103 int interface_index = msg.interface_index();
1104 if (!ContainsKey(infos_, interface_index)) {
1105 SLOG(this, 2) << "Got RDNSS option for unknown index "
1106 << interface_index;
1107 }
1108
1109 const RTNLMessage::RdnssOption& rdnss_option = msg.rdnss_option();
1110 infos_[interface_index].ipv6_dns_server_lifetime_seconds =
1111 rdnss_option.lifetime;
1112 infos_[interface_index].ipv6_dns_server_addresses = rdnss_option.addresses;
1113 if (!time_->GetSecondsBoottime(
1114 &infos_[interface_index].ipv6_dns_server_received_time_seconds)) {
1115 NOTREACHED();
1116 }
1117
1118 // Notify device of the IPv6 DNS server addresses update.
1119 DeviceRefPtr device = GetDevice(interface_index);
1120 if (device) {
1121 device->OnIPv6DnsServerAddressesChanged();
1122 }
1123 }
1124
DelayDeviceCreation(int interface_index)1125 void DeviceInfo::DelayDeviceCreation(int interface_index) {
1126 delayed_devices_.insert(interface_index);
1127 delayed_devices_callback_.Reset(
1128 Bind(&DeviceInfo::DelayedDeviceCreationTask, AsWeakPtr()));
1129 dispatcher_->PostDelayedTask(delayed_devices_callback_.callback(),
1130 kDelayedDeviceCreationSeconds * 1000);
1131 }
1132
1133 // Re-evaluate the technology type for each delayed device.
DelayedDeviceCreationTask()1134 void DeviceInfo::DelayedDeviceCreationTask() {
1135 while (!delayed_devices_.empty()) {
1136 set<int>::iterator it = delayed_devices_.begin();
1137 int dev_index = *it;
1138 delayed_devices_.erase(it);
1139
1140 DCHECK(ContainsKey(infos_, dev_index));
1141 DCHECK(!GetDevice(dev_index));
1142
1143 const string& link_name = infos_[dev_index].name;
1144 Technology::Identifier technology = GetDeviceTechnology(link_name);
1145
1146 if (technology == Technology::kCDCEthernet) {
1147 LOG(INFO) << "In " << __func__ << ": device " << link_name
1148 << " is now assumed to be regular Ethernet.";
1149 technology = Technology::kEthernet;
1150 } else if (technology == Technology::kNoDeviceSymlink) {
1151 if (manager_->ignore_unknown_ethernet()) {
1152 SLOG(this, 2) << StringPrintf("%s: device %s, without driver name "
1153 "will be ignored",
1154 __func__, link_name.c_str());
1155 technology = Technology::kUnknown;
1156 } else {
1157 // Act the same as if there was a driver symlink, but we did not
1158 // recognize the driver name.
1159 SLOG(this, 2) << StringPrintf("%s: device %s, without driver name "
1160 "is defaulted to type ethernet",
1161 __func__, link_name.c_str());
1162 technology = Technology::kEthernet;
1163 }
1164 } else if (technology != Technology::kCellular &&
1165 technology != Technology::kTunnel) {
1166 LOG(WARNING) << "In " << __func__ << ": device " << link_name
1167 << " is unexpected technology "
1168 << Technology::NameFromIdentifier(technology);
1169 }
1170 string address =
1171 base::ToLowerASCII(infos_[dev_index].mac_address.HexEncode());
1172
1173 if (technology != Technology::kTunnel &&
1174 technology != Technology::kUnknown) {
1175 DCHECK(!address.empty());
1176 }
1177
1178 DeviceRefPtr device = CreateDevice(link_name, address, dev_index,
1179 technology);
1180 if (device) {
1181 RegisterDevice(device);
1182 }
1183 }
1184 }
1185
RetrieveLinkStatistics(int interface_index,const RTNLMessage & msg)1186 void DeviceInfo::RetrieveLinkStatistics(int interface_index,
1187 const RTNLMessage& msg) {
1188 if (!msg.HasAttribute(IFLA_STATS64)) {
1189 return;
1190 }
1191 ByteString stats_bytes(msg.GetAttribute(IFLA_STATS64));
1192 struct rtnl_link_stats64 stats;
1193 if (stats_bytes.GetLength() < sizeof(stats)) {
1194 LOG(WARNING) << "Link statistics size is too small: "
1195 << stats_bytes.GetLength() << " < " << sizeof(stats);
1196 return;
1197 }
1198
1199 memcpy(&stats, stats_bytes.GetConstData(), sizeof(stats));
1200 SLOG(this, 2) << "Link statistics for "
1201 << " interface index " << interface_index << ": "
1202 << "receive: " << stats.rx_bytes << "; "
1203 << "transmit: " << stats.tx_bytes << ".";
1204 infos_[interface_index].rx_bytes = stats.rx_bytes;
1205 infos_[interface_index].tx_bytes = stats.tx_bytes;
1206 }
1207
RequestLinkStatistics()1208 void DeviceInfo::RequestLinkStatistics() {
1209 rtnl_handler_->RequestDump(RTNLHandler::kRequestLink);
1210 dispatcher_->PostDelayedTask(request_link_statistics_callback_.callback(),
1211 kRequestLinkStatisticsIntervalMilliseconds);
1212 }
1213
1214 #if !defined(DISABLE_WIFI)
GetWiFiInterfaceInfo(int interface_index)1215 void DeviceInfo::GetWiFiInterfaceInfo(int interface_index) {
1216 GetInterfaceMessage msg;
1217 if (!msg.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX,
1218 interface_index)) {
1219 LOG(ERROR) << "Unable to set interface index attribute for "
1220 "GetInterface message. Interface type cannot be "
1221 "determined!";
1222 return;
1223 }
1224 netlink_manager_->SendNl80211Message(
1225 &msg,
1226 Bind(&DeviceInfo::OnWiFiInterfaceInfoReceived, AsWeakPtr()),
1227 Bind(&NetlinkManager::OnAckDoNothing),
1228 Bind(&NetlinkManager::OnNetlinkMessageError));
1229 }
1230
OnWiFiInterfaceInfoReceived(const Nl80211Message & msg)1231 void DeviceInfo::OnWiFiInterfaceInfoReceived(const Nl80211Message& msg) {
1232 if (msg.command() != NL80211_CMD_NEW_INTERFACE) {
1233 LOG(ERROR) << "Message is not a new interface response";
1234 return;
1235 }
1236
1237 uint32_t interface_index;
1238 if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFINDEX,
1239 &interface_index)) {
1240 LOG(ERROR) << "Message contains no interface index";
1241 return;
1242 }
1243 uint32_t interface_type;
1244 if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFTYPE,
1245 &interface_type)) {
1246 LOG(ERROR) << "Message contains no interface type";
1247 return;
1248 }
1249 const Info* info = GetInfo(interface_index);
1250 if (!info) {
1251 LOG(ERROR) << "Could not find device info for interface index "
1252 << interface_index;
1253 return;
1254 }
1255 if (info->device) {
1256 LOG(ERROR) << "Device already created for interface index "
1257 << interface_index;
1258 return;
1259 }
1260 if (interface_type != NL80211_IFTYPE_STATION) {
1261 LOG(INFO) << "Ignoring WiFi device "
1262 << info->name
1263 << " at interface index "
1264 << interface_index
1265 << " since it is not in station mode.";
1266 return;
1267 }
1268 LOG(INFO) << "Creating WiFi device for station mode interface "
1269 << info->name
1270 << " at interface index "
1271 << interface_index;
1272 string address = base::ToLowerASCII(info->mac_address.HexEncode());
1273 DeviceRefPtr device =
1274 new WiFi(control_interface_, dispatcher_, metrics_, manager_,
1275 info->name, address, interface_index);
1276 device->EnableIPv6Privacy();
1277 RegisterDevice(device);
1278 }
1279 #endif // DISABLE_WIFI
1280
SetHostname(const std::string & hostname) const1281 bool DeviceInfo::SetHostname(const std::string& hostname) const {
1282 if (sethostname(hostname.c_str(), hostname.length())) {
1283 PLOG(ERROR) << "Failed to set hostname to: " << hostname;
1284 return false;
1285 }
1286
1287 return true;
1288 }
1289
1290 } // namespace shill
1291