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; 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 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 132 DeviceInfo::~DeviceInfo() {} 133 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 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 154 bool DeviceInfo::IsDeviceBlackListed(const string& device_name) { 155 return ContainsKey(black_list_, device_name); 156 } 157 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 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 182 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 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 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 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 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 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 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 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 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 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 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 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 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 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 699 DeviceRefPtr DeviceInfo::GetDevice(int interface_index) const { 700 const Info* info = GetInfo(interface_index); 701 return info ? info->device : nullptr; 702 } 703 704 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 709 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 726 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 752 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 807 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 817 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 836 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 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 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 928 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 946 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 955 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 967 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 993 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 1012 bool DeviceInfo::DeleteInterface(int interface_index) const { 1013 return rtnl_handler_->RemoveInterface(interface_index); 1014 } 1015 1016 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 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 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 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 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 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. 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 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 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) 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 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 1281 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