device_info.cc revision 4b28586abe9edee0179ea7672ac5ea9d9dc13ac7
141c0e0accae6602dbc9fc31f336dabee7af1b170Darin Petkov// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 20af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart// Use of this source code is governed by a BSD-style license that can be 30af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart// found in the LICENSE file. 40af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 5cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include "shill/device_info.h" 60af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 70af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart#include <arpa/inet.h> 8cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <fcntl.h> 9cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <linux/if_tun.h> 100af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart#include <linux/netlink.h> 110af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart#include <linux/rtnetlink.h> 12cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <net/if.h> 13cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <net/if_arp.h> 14cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <netinet/ether.h> 15cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <string.h> 16cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <sys/ioctl.h> 17cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <sys/socket.h> 18cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <time.h> 19cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <unistd.h> 20cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 210af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart#include <string> 220af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 233e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood#include <base/bind.h> 24bf1861b28b61d2338116e4416ac8f2a45f7045cePaul Stewart#include <base/file_util.h> 25487b8bfc46a91e29bb23aaf3c59cfe67033bfc8bChris Masone#include <base/memory/scoped_ptr.h> 263e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood#include <base/stl_util.h> 272001a42edf1d42ec828a9baf3157496c20fefd49Paul Stewart#include <base/string_number_conversions.h> 28877ff9894e21c4c78b63777025f6c8d577ccd855Chris Masone#include <base/string_util.h> 29b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart#include <base/stringprintf.h> 300af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 310af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart#include "shill/control_interface.h" 329be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone#include "shill/device.h" 33a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart#include "shill/device_stub.h" 34b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart#include "shill/ethernet.h" 35b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley#include "shill/logging.h" 36b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart#include "shill/manager.h" 378c116a90d3a3536430b808b15e73275060918434Paul Stewart#include "shill/routing_table.h" 38a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart#include "shill/rtnl_handler.h" 39a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart#include "shill/rtnl_listener.h" 402aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone#include "shill/rtnl_message.h" 41487b8bfc46a91e29bb23aaf3c59cfe67033bfc8bChris Masone#include "shill/service.h" 424178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain#include "shill/sockets.h" 4393a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal#include "shill/virtio_ethernet.h" 44b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart#include "shill/wifi.h" 450af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 463e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Bind; 478f1c835d879f82261a08257eb6f9677e6be51fdaThieu Leusing base::StringPrintf; 483e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Unretained; 49e6193c042652831cac90c3bbf2233877754b1eefDarin Petkovusing std::map; 50050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewartusing std::set; 510af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewartusing std::string; 529a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewartusing std::vector; 530af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 540af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewartnamespace shill { 55b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 56b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart// static 57abc5403270e26fa898181301911a905758f8d758Jason Glasgowconst char DeviceInfo::kModemPseudoDeviceNamePrefix[] = "pseudomodem"; 58e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wileyconst char DeviceInfo::kEthernetPseudoDeviceNamePrefix[] = "pseudoethernet"; 59ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kDeviceInfoRoot[] = "/sys/class/net"; 604e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chanconst char DeviceInfo::kDriverCdcEther[] = "cdc_ether"; 614e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chanconst char DeviceInfo::kDriverGdmWiMax[] = "gdm_wimax"; 6293a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawalconst char DeviceInfo::kDriverVirtioNet[] = "virtio_net"; 63ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceUevent[] = "uevent"; 649364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewartconst char DeviceInfo::kInterfaceUeventWifiSignature[] = "DEVTYPE=wlan\n"; 65ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceDevice[] = "device"; 66ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceDriver[] = "device/driver"; 67ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceTunFlags[] = "tun_flags"; 68ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceType[] = "type"; 69b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewartconst char *DeviceInfo::kModemDrivers[] = { 70b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart "gobi", 71b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart "QCUSBNet2k", 72226d46a2e03d316e8a36f93cb261f708219aef07Ben Chan "GobiNet", 73226d46a2e03d316e8a36f93cb261f708219aef07Ben Chan "qmi_wwan" 74b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart}; 75cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewartconst char DeviceInfo::kTunDeviceName[] = "/dev/net/tun"; 76050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewartconst int DeviceInfo::kDelayedDeviceCreationSeconds = 5; 771ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewartconst int DeviceInfo::kRequestLinkStatisticsIntervalSeconds = 60; 78b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 79b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul StewartDeviceInfo::DeviceInfo(ControlInterface *control_interface, 80b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart EventDispatcher *dispatcher, 813426c8fc7a3943f2d8fcb2ec78f0593088b42bedThieu Le Metrics *metrics, 82b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart Manager *manager) 83a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart : control_interface_(control_interface), 84a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart dispatcher_(dispatcher), 853426c8fc7a3943f2d8fcb2ec78f0593088b42bedThieu Le metrics_(metrics), 86a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart manager_(manager), 873e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood link_callback_(Bind(&DeviceInfo::LinkMsgHandler, Unretained(this))), 883e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood address_callback_(Bind(&DeviceInfo::AddressMsgHandler, Unretained(this))), 899a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart link_listener_(NULL), 909a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart address_listener_(NULL), 91ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart device_info_root_(kDeviceInfoRoot), 928c116a90d3a3536430b808b15e73275060918434Paul Stewart routing_table_(RoutingTable::GetInstance()), 934178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain rtnl_handler_(RTNLHandler::GetInstance()), 944178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain sockets_(new Sockets()) { 950af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 960af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 97a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul StewartDeviceInfo::~DeviceInfo() {} 980af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 998f317b600a218afe05f2d73c59204bb98269a950mukesh agrawalvoid DeviceInfo::AddDeviceToBlackList(const string &device_name) { 1008f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal black_list_.insert(device_name); 1018f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal} 1028f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal 1035e628a5c722c196ad240af0ff3c717e9613d3ef5Eric Shienbroodbool DeviceInfo::IsDeviceBlackListed(const string &device_name) { 1045e628a5c722c196ad240af0ff3c717e9613d3ef5Eric Shienbrood return ContainsKey(black_list_, device_name); 1055e628a5c722c196ad240af0ff3c717e9613d3ef5Eric Shienbrood} 1065e628a5c722c196ad240af0ff3c717e9613d3ef5Eric Shienbrood 107a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewartvoid DeviceInfo::Start() { 108a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart link_listener_.reset( 1093e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood new RTNLListener(RTNLHandler::kRequestLink, link_callback_)); 1109a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart address_listener_.reset( 1113e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood new RTNLListener(RTNLHandler::kRequestAddr, address_callback_)); 1129a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart rtnl_handler_->RequestDump(RTNLHandler::kRequestLink | 1139a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart RTNLHandler::kRequestAddr); 1141ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart request_link_statistics_callback_.Reset( 1151ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart Bind(&DeviceInfo::RequestLinkStatistics, AsWeakPtr())); 1161ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart dispatcher_->PostDelayedTask(request_link_statistics_callback_.callback(), 1171ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart kRequestLinkStatisticsIntervalSeconds * 1000); 1180af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 1190af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 120a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewartvoid DeviceInfo::Stop() { 1219a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart link_listener_.reset(); 1229a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart address_listener_.reset(); 1238c116a90d3a3536430b808b15e73275060918434Paul Stewart infos_.clear(); 1241ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart request_link_statistics_callback_.Cancel(); 125050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_callback_.Cancel(); 126050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.clear(); 1270af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 1280af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 1296f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkovvoid DeviceInfo::RegisterDevice(const DeviceRefPtr &device) { 130fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << "(" << device->link_name() << ", " 131fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << device->interface_index() << ")"; 132050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.erase(device->interface_index()); 133e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov CHECK(!GetDevice(device->interface_index()).get()); 134e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov infos_[device->interface_index()].device = device; 135da798623389b981130cd1922f880736f1e0e36baJoshua Kroll if ((device->technology() == Technology::kCellular) || 136da798623389b981130cd1922f880736f1e0e36baJoshua Kroll (device->technology() == Technology::kEthernet) || 137da798623389b981130cd1922f880736f1e0e36baJoshua Kroll (device->technology() == Technology::kWifi) || 138da798623389b981130cd1922f880736f1e0e36baJoshua Kroll (device->technology() == Technology::kWiMax)) { 1396f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov manager_->RegisterDevice(device); 1406f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov } 1416f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov} 1426f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov 143e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgowvoid DeviceInfo::DeregisterDevice(const DeviceRefPtr &device) { 144e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow int interface_index = device->interface_index(); 145e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow 146fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << "(" << device->link_name() << ", " 147fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << interface_index << ")"; 148da798623389b981130cd1922f880736f1e0e36baJoshua Kroll CHECK((device->technology() == Technology::kCellular) || 149da798623389b981130cd1922f880736f1e0e36baJoshua Kroll (device->technology() == Technology::kWiMax)); 150e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow 151e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow // Release reference to the device 152e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow map<int, Info>::iterator iter = infos_.find(interface_index); 153e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow if (iter != infos_.end()) { 154fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << "Removing device from info for index: " 155fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << interface_index; 156e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow manager_->DeregisterDevice(device); 157e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow // Release the reference to the device, but maintain the mapping 158e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow // for the index. That will be cleaned up by an RTNL message. 159e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow iter->second.device = NULL; 160e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow } 161e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow} 162e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow 163ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul StewartFilePath DeviceInfo::GetDeviceInfoPath(const string &iface_name, 164ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart const string &path_name) { 165ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart return device_info_root_.Append(iface_name).Append(path_name); 166ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart} 167ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart 168ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartbool DeviceInfo::GetDeviceInfoContents(const string &iface_name, 169ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart const string &path_name, 170ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart string *contents_out) { 171ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart return file_util::ReadFileToString(GetDeviceInfoPath(iface_name, path_name), 172ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart contents_out); 173ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart} 174ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartbool DeviceInfo::GetDeviceInfoSymbolicLink(const string &iface_name, 1754e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan const string &path_name, 1764e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan FilePath *path_out) { 177ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart return file_util::ReadSymbolicLink(GetDeviceInfoPath(iface_name, path_name), 178ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart path_out); 179ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart} 180ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart 181fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul StewartTechnology::Identifier DeviceInfo::GetDeviceTechnology( 182fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart const string &iface_name) { 183ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart string type_string; 184ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart int arp_type = ARPHRD_VOID;; 185ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (GetDeviceInfoContents(iface_name, kInterfaceType, &type_string) && 186ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart TrimString(type_string, "\n", &type_string) && 187ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart !base::StringToInt(type_string, &arp_type)) { 188ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart arp_type = ARPHRD_VOID; 189ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart } 190ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart 1919364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart string contents; 192ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (!GetDeviceInfoContents(iface_name, kInterfaceUevent, &contents)) { 193050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart LOG(INFO) << StringPrintf("%s: device %s has no uevent file", 194050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart __func__, iface_name.c_str()); 195fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart return Technology::kUnknown; 1969364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart } 197b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 1988f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // If the "uevent" file contains the string "DEVTYPE=wlan\n" at the 1998f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // start of the file or after a newline, we can safely assume this 2008f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // is a wifi device. 2019364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart if (contents.find(kInterfaceUeventWifiSignature) != string::npos) { 202fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) 203fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << StringPrintf("%s: device %s has wifi signature in uevent file", 204fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 205ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (arp_type == ARPHRD_IEEE80211_RADIOTAP) { 206fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: wifi device %s is in monitor mode", 207fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 2082001a42edf1d42ec828a9baf3157496c20fefd49Paul Stewart return Technology::kWiFiMonitor; 2092001a42edf1d42ec828a9baf3157496c20fefd49Paul Stewart } 210fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart return Technology::kWifi; 2119364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart } 212b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 2137904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow // Special case for pseudo modems which are used for testing 2147904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow if (iface_name.find(kModemPseudoDeviceNamePrefix) == 0) { 2157904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow SLOG(Device, 2) << StringPrintf( 2167904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow "%s: device %s is a pseudo modem for testing", 2177904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow __func__, iface_name.c_str()); 2187904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow return Technology::kCellular; 2197904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow } 2207904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow 221e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley // Special case for pseudo ethernet devices which are used for testing. 222e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley if (iface_name.find(kEthernetPseudoDeviceNamePrefix) == 0) { 223e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley SLOG(Device, 2) << StringPrintf( 224e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley "%s: device %s is a virtual ethernet device for testing", 225e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley __func__, iface_name.c_str()); 226e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley return Technology::kEthernet; 227e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley } 228e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley 2299364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart FilePath driver_path; 230ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (!GetDeviceInfoSymbolicLink(iface_name, kInterfaceDriver, &driver_path)) { 231fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s has no device symlink", 232fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 233ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (arp_type == ARPHRD_LOOPBACK) { 234fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s is a loopback device", 235fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 236e81eb700f66563cb695b6e3682f20ac5a0cdb8c0Paul Stewart return Technology::kLoopback; 237e81eb700f66563cb695b6e3682f20ac5a0cdb8c0Paul Stewart } 238ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (arp_type == ARPHRD_PPP) { 239ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart SLOG(Device, 2) << StringPrintf("%s: device %s is a ppp device", 240ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart __func__, iface_name.c_str()); 241ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart return Technology::kPPP; 242ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart } 243ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart string tun_flags_str; 244cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart int tun_flags = 0; 245ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (GetDeviceInfoContents(iface_name, kInterfaceTunFlags, &tun_flags_str) && 246ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart TrimString(tun_flags_str, "\n", &tun_flags_str) && 247ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart base::HexStringToInt(tun_flags_str, &tun_flags) && 248cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart (tun_flags & IFF_TUN)) { 249fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s is tun device", 250fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 251cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return Technology::kTunnel; 252cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 253e81eb700f66563cb695b6e3682f20ac5a0cdb8c0Paul Stewart return Technology::kUnknown; 2549364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart } 255b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 2569364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart string driver_name(driver_path.BaseName().value()); 2578f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // See if driver for this interface is in a list of known modem driver names. 2588f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le for (size_t modem_idx = 0; modem_idx < arraysize(kModemDrivers); 2598f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le ++modem_idx) { 2609364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart if (driver_name == kModemDrivers[modem_idx]) { 261fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) 262fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << StringPrintf("%s: device %s is matched with modem driver %s", 263fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str(), driver_name.c_str()); 2649364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart return Technology::kCellular; 2659364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart } 266b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 2670af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 2684e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan if (driver_name == kDriverGdmWiMax) { 2694e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s is a WiMAX device", 2704e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan __func__, iface_name.c_str()); 2714e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan return Technology::kWiMax; 2724e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan } 2734e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan 2748f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // For cdc_ether devices, make sure it's a modem because this driver 2758f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // can be used for other ethernet devices. 276050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart if (driver_name == kDriverCdcEther) { 277050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart if (IsCdcEtherModemDevice(iface_name)) { 278050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart LOG(INFO) << StringPrintf("%s: device %s is a modem cdc_ether " 279050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart "device", __func__, iface_name.c_str()); 280050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart return Technology::kCellular; 281050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } 282050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart SLOG(Device, 2) << StringPrintf("%s: device %s is a cdc_ether " 283050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart "device", __func__, iface_name.c_str()); 284050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart return Technology::kCDCEthernet; 2858f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le } 286abc5403270e26fa898181301911a905758f8d758Jason Glasgow 28793a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal // Special case for the virtio driver, used when run under KVM. See also 28893a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal // the comment in VirtioEthernet::Start. 28993a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal if (driver_name == kDriverVirtioNet) { 290fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s is virtio ethernet", 291fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 29293a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal return Technology::kVirtioEthernet; 29393a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal } 29493a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal 295fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s, with driver %s, " 296fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan "is defaulted to type ethernet", 297fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str(), 298fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan driver_name.c_str()); 299fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart return Technology::kEthernet; 300b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart} 301b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 3028f1c835d879f82261a08257eb6f9677e6be51fdaThieu Lebool DeviceInfo::IsCdcEtherModemDevice(const std::string &iface_name) { 3038f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // A cdc_ether device is a modem device if it also exposes tty interfaces. 3048f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // To determine this, we look for the existence of the tty interface in the 3058f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // USB device sysfs tree. 3068f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 3078f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // A typical sysfs dir hierarchy for a cdc_ether modem USB device is as 3088f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // follows: 3098f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 3108f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2 3118f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 1-2:1.0 3128f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // tty 3138f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // ttyACM0 3148f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 1-2:1.1 3158f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // net 3168f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // usb0 3178f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 1-2:1.2 3188f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // tty 3198f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // ttyACM1 3208f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // ... 3218f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 3228f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // /sys/class/net/usb0/device symlinks to 3238f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2/1-2:1.1 324b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // 325b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // Note that some modem devices have the tty directory one level deeper 326b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // (eg. E362), so the device tree for the tty interface is: 327b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // /sys/devices/pci0000:00/0000:00:1d.7/usb/1-2/1-2:1.0/ttyUSB0/tty/ttyUSB0 3288f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le 329ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart FilePath device_file = GetDeviceInfoPath(iface_name, kInterfaceDevice); 3308f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le FilePath device_path; 3318f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le if (!file_util::ReadSymbolicLink(device_file, &device_path)) { 332fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s has no device symlink", 333fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 3348f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le return false; 3358f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le } 3368f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le if (!device_path.IsAbsolute()) { 3378f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le device_path = device_file.DirName().Append(device_path); 3388f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le file_util::AbsolutePath(&device_path); 3398f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le } 3408f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le 3418f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // Look for tty interface by enumerating all directories under the parent 342b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // USB device and see if there's a subdirectory "tty" inside. In other 343b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // words, using the example dir hierarchy above, find 344b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2/.../tty. 3458f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // If this exists, then this is a modem device. 346b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le return HasSubdir(device_path.DirName(), FilePath("tty")); 3478f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le} 3488f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le 3498f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le// static 350b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Lebool DeviceInfo::HasSubdir(const FilePath &base_dir, const FilePath &subdir) { 351b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le file_util::FileEnumerator::FileType type = 352b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le static_cast<file_util::FileEnumerator::FileType>( 353b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le file_util::FileEnumerator::DIRECTORIES | 354b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le file_util::FileEnumerator::SHOW_SYM_LINKS); 355b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le file_util::FileEnumerator dir_enum(base_dir, true, type); 3568f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le for (FilePath curr_dir = dir_enum.Next(); !curr_dir.empty(); 3578f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le curr_dir = dir_enum.Next()) { 358b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le if (curr_dir.BaseName() == subdir) 3598f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le return true; 3608f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le } 3618f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le return false; 3628f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le} 3638f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le 3648c116a90d3a3536430b808b15e73275060918434Paul StewartDeviceRefPtr DeviceInfo::CreateDevice(const string &link_name, 3658c116a90d3a3536430b808b15e73275060918434Paul Stewart const string &address, 3668c116a90d3a3536430b808b15e73275060918434Paul Stewart int interface_index, 3678c116a90d3a3536430b808b15e73275060918434Paul Stewart Technology::Identifier technology) { 3688c116a90d3a3536430b808b15e73275060918434Paul Stewart DeviceRefPtr device; 369050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.erase(interface_index); 3708c116a90d3a3536430b808b15e73275060918434Paul Stewart 3718c116a90d3a3536430b808b15e73275060918434Paul Stewart switch (technology) { 3728c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kCellular: 3738c116a90d3a3536430b808b15e73275060918434Paul Stewart // Cellular devices are managed by ModemInfo. 3748c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << "Cellular link " << link_name 3758c116a90d3a3536430b808b15e73275060918434Paul Stewart << " at index " << interface_index 3768c116a90d3a3536430b808b15e73275060918434Paul Stewart << " -- notifying ModemInfo."; 377bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain 378bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain // The MAC address provided by RTNL is not reliable for Gobi 2K modems. 3794b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // Clear it here, and it will be fetched from the kernel in 3804b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // GetMACAddress(). 381bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain infos_[interface_index].mac_address.Clear(); 3828c116a90d3a3536430b808b15e73275060918434Paul Stewart manager_->modem_info()->OnDeviceInfoAvailable(link_name); 3838c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 3848c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kEthernet: 3858c116a90d3a3536430b808b15e73275060918434Paul Stewart device = new Ethernet(control_interface_, dispatcher_, metrics_, 3868c116a90d3a3536430b808b15e73275060918434Paul Stewart manager_, link_name, address, interface_index); 3878c116a90d3a3536430b808b15e73275060918434Paul Stewart device->EnableIPv6Privacy(); 3888c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 3898c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kVirtioEthernet: 3908c116a90d3a3536430b808b15e73275060918434Paul Stewart device = new VirtioEthernet(control_interface_, dispatcher_, metrics_, 3918c116a90d3a3536430b808b15e73275060918434Paul Stewart manager_, link_name, address, 3928c116a90d3a3536430b808b15e73275060918434Paul Stewart interface_index); 3938c116a90d3a3536430b808b15e73275060918434Paul Stewart device->EnableIPv6Privacy(); 3948c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 3958c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kWifi: 3968c116a90d3a3536430b808b15e73275060918434Paul Stewart device = new WiFi(control_interface_, dispatcher_, metrics_, manager_, 3978c116a90d3a3536430b808b15e73275060918434Paul Stewart link_name, address, interface_index); 3988c116a90d3a3536430b808b15e73275060918434Paul Stewart device->EnableIPv6Privacy(); 3998c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 4004e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan case Technology::kWiMax: 401e4b270274cba2a1976c7be6c733bd899e009c1d1Darin Petkov // WiMax devices are managed by WiMaxProvider. 402e4b270274cba2a1976c7be6c733bd899e009c1d1Darin Petkov SLOG(Device, 2) << "WiMax link " << link_name 403e4b270274cba2a1976c7be6c733bd899e009c1d1Darin Petkov << " at index " << interface_index 404e4b270274cba2a1976c7be6c733bd899e009c1d1Darin Petkov << " -- notifying WiMaxProvider."; 4054b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // The MAC address provided by RTNL may not be the final value as the 4064b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // WiMAX device may change the address after initialization. Clear it 4074b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // here, and it will be fetched from the kernel when 4084b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // WiMaxProvider::CreateDevice() is called after the WiMAX device DBus 4094b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // object is created by the WiMAX manager daemon. 4104b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan infos_[interface_index].mac_address.Clear(); 411e4b270274cba2a1976c7be6c733bd899e009c1d1Darin Petkov manager_->wimax_provider()->OnDeviceInfoAvailable(link_name); 4124e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan break; 4138c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kPPP: 4148c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kTunnel: 4158c116a90d3a3536430b808b15e73275060918434Paul Stewart // Tunnel and PPP devices are managed by the VPN code (PPP for 4168c116a90d3a3536430b808b15e73275060918434Paul Stewart // l2tpipsec). Notify the VPN Provider of the interface's presence. 4178c116a90d3a3536430b808b15e73275060918434Paul Stewart // Since CreateDevice is only called once in the lifetime of an 4188c116a90d3a3536430b808b15e73275060918434Paul Stewart // interface index, this notification will only occur the first 4198c116a90d3a3536430b808b15e73275060918434Paul Stewart // time the device is seen. 4208c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << "Tunnel / PPP link " << link_name 4218c116a90d3a3536430b808b15e73275060918434Paul Stewart << " at index " << interface_index 4228c116a90d3a3536430b808b15e73275060918434Paul Stewart << " -- notifying VPNProvider."; 4238c116a90d3a3536430b808b15e73275060918434Paul Stewart if (!manager_->vpn_provider()->OnDeviceInfoAvailable(link_name, 4248c116a90d3a3536430b808b15e73275060918434Paul Stewart interface_index) && 4258c116a90d3a3536430b808b15e73275060918434Paul Stewart technology == Technology::kTunnel) { 4268c116a90d3a3536430b808b15e73275060918434Paul Stewart // If VPN does not know anything about this tunnel, it is probably 4278c116a90d3a3536430b808b15e73275060918434Paul Stewart // left over from a previous instance and should not exist. 4288c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << "Tunnel link is unused. Deleting."; 4298c116a90d3a3536430b808b15e73275060918434Paul Stewart DeleteInterface(interface_index); 4308c116a90d3a3536430b808b15e73275060918434Paul Stewart } 4318c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 4328c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kLoopback: 4338c116a90d3a3536430b808b15e73275060918434Paul Stewart // Loopback devices are largely ignored, but we should make sure the 4348c116a90d3a3536430b808b15e73275060918434Paul Stewart // link is enabled. 4358c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << "Bringing up loopback device " << link_name 4368c116a90d3a3536430b808b15e73275060918434Paul Stewart << " at index " << interface_index; 4378c116a90d3a3536430b808b15e73275060918434Paul Stewart rtnl_handler_->SetInterfaceFlags(interface_index, IFF_UP, IFF_UP); 4388c116a90d3a3536430b808b15e73275060918434Paul Stewart return NULL; 439050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart case Technology::kCDCEthernet: 440050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // CDCEnternet devices are of indeterminate type when they are 441050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // initially created. Some time later, tty devices may or may 442050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // not appear under the same USB device root, which will identify 443050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // it as a modem. Alternatively, ModemManager may discover the 444050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // device and create and register a Cellular device. In either 445050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // case, we should delay creating a Device until we can make a 446050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // better determination of what type this Device should be. 447050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart LOG(INFO) << "Delaying creation of device for " << link_name 448050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart << " at index " << interface_index; 449050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DelayDeviceCreation(interface_index); 450050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart return NULL; 4518c116a90d3a3536430b808b15e73275060918434Paul Stewart default: 4528c116a90d3a3536430b808b15e73275060918434Paul Stewart // We will not manage this device in shill. Do not create a device 4538c116a90d3a3536430b808b15e73275060918434Paul Stewart // object or do anything to change its state. We create a stub object 4548c116a90d3a3536430b808b15e73275060918434Paul Stewart // which is useful for testing. 4558c116a90d3a3536430b808b15e73275060918434Paul Stewart return new DeviceStub(control_interface_, dispatcher_, metrics_, 4568c116a90d3a3536430b808b15e73275060918434Paul Stewart manager_, link_name, address, interface_index, 4574e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan technology); 4588c116a90d3a3536430b808b15e73275060918434Paul Stewart } 4598c116a90d3a3536430b808b15e73275060918434Paul Stewart 4608c116a90d3a3536430b808b15e73275060918434Paul Stewart // Reset the routing table and addresses. 4618c116a90d3a3536430b808b15e73275060918434Paul Stewart routing_table_->FlushRoutes(interface_index); 4628c116a90d3a3536430b808b15e73275060918434Paul Stewart FlushAddresses(interface_index); 4638c116a90d3a3536430b808b15e73275060918434Paul Stewart 4648c116a90d3a3536430b808b15e73275060918434Paul Stewart return device; 4658c116a90d3a3536430b808b15e73275060918434Paul Stewart} 4668c116a90d3a3536430b808b15e73275060918434Paul Stewart 4672aa9707f114ab8166f45df5726bf05278df2aef6Chris Masonevoid DeviceInfo::AddLinkMsgHandler(const RTNLMessage &msg) { 4689a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart DCHECK(msg.type() == RTNLMessage::kTypeLink && 4699a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart msg.mode() == RTNLMessage::kModeAdd); 4702aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone int dev_index = msg.interface_index(); 471fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart Technology::Identifier technology = Technology::kUnknown; 472e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov unsigned int flags = msg.link_status().flags; 473e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov unsigned int change = msg.link_status().change; 4748c116a90d3a3536430b808b15e73275060918434Paul Stewart bool new_device = 4758c116a90d3a3536430b808b15e73275060918434Paul Stewart !ContainsKey(infos_, dev_index) || infos_[dev_index].has_addresses_only; 476fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << "(index=" << dev_index 477fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << std::showbase << std::hex 478fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << ", flags=" << flags << ", change=" << change << ")" 479fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << std::dec << std::noshowbase 480fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << ", new_device=" << new_device; 4818c116a90d3a3536430b808b15e73275060918434Paul Stewart infos_[dev_index].has_addresses_only = false; 482e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov infos_[dev_index].flags = flags; 483f1ce5d27adbfcaf9c46e650252b46e02b0d8addaPaul Stewart 4841ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart RetrieveLinkStatistics(dev_index, msg); 4851ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 4866f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov DeviceRefPtr device = GetDevice(dev_index); 4878c116a90d3a3536430b808b15e73275060918434Paul Stewart if (new_device) { 4888c116a90d3a3536430b808b15e73275060918434Paul Stewart CHECK(!device); 4892aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone if (!msg.HasAttribute(IFLA_IFNAME)) { 4902aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone LOG(ERROR) << "Add Link message does not have IFLA_IFNAME!"; 4912aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone return; 492b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 4932aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone ByteString b(msg.GetAttribute(IFLA_IFNAME)); 4942aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone string link_name(reinterpret_cast<const char*>(b.GetConstData())); 495fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << "add link index " << dev_index << " name " << link_name; 496f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov infos_[dev_index].name = link_name; 497f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov indices_[link_name] = dev_index; 498a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart 4992aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone if (!link_name.empty()) { 5008f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal if (ContainsKey(black_list_, link_name)) { 501fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart technology = Technology::kBlacklisted; 5028f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal } else { 5038f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal technology = GetDeviceTechnology(link_name); 5048f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal } 505633ac6f0d56a62f8fd21ba7d9a15818fe080fb2fDarin Petkov } 506cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart string address; 507cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart if (msg.HasAttribute(IFLA_ADDRESS)) { 508cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart infos_[dev_index].mac_address = msg.GetAttribute(IFLA_ADDRESS); 509cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart address = StringToLowerASCII(infos_[dev_index].mac_address.HexEncode()); 510fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << "link index " << dev_index << " address " 511fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << infos_[dev_index].mac_address.HexEncode(); 512ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart } else if (technology != Technology::kTunnel && 513ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart technology != Technology::kPPP) { 514cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart LOG(ERROR) << "Add Link message does not have IFLA_ADDRESS!"; 515cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return; 516cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 5178c116a90d3a3536430b808b15e73275060918434Paul Stewart device = CreateDevice(link_name, address, dev_index, technology); 5188c116a90d3a3536430b808b15e73275060918434Paul Stewart if (device) { 5198c116a90d3a3536430b808b15e73275060918434Paul Stewart RegisterDevice(device); 520b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 521b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 5228c116a90d3a3536430b808b15e73275060918434Paul Stewart if (device) { 5238c116a90d3a3536430b808b15e73275060918434Paul Stewart device->LinkEvent(flags, change); 5248c116a90d3a3536430b808b15e73275060918434Paul Stewart } 525b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart} 526b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 5272aa9707f114ab8166f45df5726bf05278df2aef6Chris Masonevoid DeviceInfo::DelLinkMsgHandler(const RTNLMessage &msg) { 528fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << "(index=" << msg.interface_index() << ")"; 52947009f8d7a6fbc257a1bb1288a01405d034bd13fmukesh agrawal 5309a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart DCHECK(msg.type() == RTNLMessage::kTypeLink && 5319a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart msg.mode() == RTNLMessage::kModeDelete); 532fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << "(index=" << msg.interface_index() 533fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << std::showbase << std::hex 534fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << ", flags=" << msg.link_status().flags 535fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << ", change=" << msg.link_status().change << ")"; 536e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov RemoveInfo(msg.interface_index()); 537e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov} 538e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov 539e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin PetkovDeviceRefPtr DeviceInfo::GetDevice(int interface_index) const { 540e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov const Info *info = GetInfo(interface_index); 541e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov return info ? info->device : NULL; 54267d8ecfd1d6ff5ea75b9d5c7167d9c16891d3d4bDarin Petkov} 543b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 544f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkovint DeviceInfo::GetIndex(const string &interface_name) const { 545f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov map<string, int>::const_iterator it = indices_.find(interface_name); 546f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov return it == indices_.end() ? -1 : it->second; 547f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov} 548f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov 5493285296e6624fa0b1b10699f2fa6466d4be10742Paul Stewartbool DeviceInfo::GetMACAddress(int interface_index, ByteString *address) const { 550e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov const Info *info = GetInfo(interface_index); 551e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov if (!info) { 552e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov return false; 553e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov } 554bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain // |mac_address| from RTNL is not used for some devices, in which case it will 555bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain // be empty here. 556bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain if (!info->mac_address.IsEmpty()) { 557bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain *address = info->mac_address; 558bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain return true; 559bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain } 560bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain 561bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain // Ask the kernel for the MAC address. 562bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain *address = GetMACAddressFromKernel(interface_index); 563bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain return !address->IsEmpty(); 564bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain} 565bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain 566bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary MorainByteString DeviceInfo::GetMACAddressFromKernel(int interface_index) const { 5674178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain const Info *info = GetInfo(interface_index); 5684178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain if (!info) { 5694178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain return ByteString(); 5704178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain } 5714178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain 5724178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain const int fd = sockets_->Socket(PF_INET, SOCK_DGRAM, 0); 573bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain if (fd < 0) { 574bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain LOG(ERROR) << __func__ << ": Unable to open socket: " << fd; 5754178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain return ByteString(); 576bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain } 5774178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain 5784178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain ScopedSocketCloser socket_closer(sockets_.get(), fd); 579bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain struct ifreq ifr; 580bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain memset(&ifr, 0, sizeof(ifr)); 581bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain ifr.ifr_ifindex = interface_index; 5824178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain strcpy(ifr.ifr_ifrn.ifrn_name, info->name.c_str()); 5834178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain int err = sockets_->Ioctl(fd, SIOCGIFHWADDR, &ifr); 584bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain if (err < 0) { 585bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain LOG(ERROR) << __func__ << ": Unable to read MAC address: " << errno; 5864178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain return ByteString(); 587bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain } 5884178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain 5894178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain return ByteString(ifr.ifr_hwaddr.sa_data, IFHWADDRLEN); 590e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov} 591e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov 5929a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewartbool DeviceInfo::GetAddresses(int interface_index, 5939a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart vector<AddressData> *addresses) const { 5949a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart const Info *info = GetInfo(interface_index); 5959a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (!info) { 5969a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart return false; 5979a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 5989a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart *addresses = info->ip_addresses; 5999a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart return true; 6009a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart} 6019a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 6029a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewartvoid DeviceInfo::FlushAddresses(int interface_index) const { 603fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << "(" << interface_index << ")"; 6049a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart const Info *info = GetInfo(interface_index); 6059a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (!info) { 6069a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart return; 6079a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 6089a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart const vector<AddressData> &addresses = info->ip_addresses; 6099a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart vector<AddressData>::const_iterator iter; 6109a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart for (iter = addresses.begin(); iter != addresses.end(); ++iter) { 6117355ce1937c504d836a303ac809bd436272212b3Paul Stewart if (iter->address.family() == IPAddress::kFamilyIPv4 || 6129a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart (iter->scope == RT_SCOPE_UNIVERSE && 6139a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart (iter->flags & ~IFA_F_TEMPORARY) == 0)) { 6148c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << __func__ << ": removing ip address " 6158c116a90d3a3536430b808b15e73275060918434Paul Stewart << iter->address.ToString() 6168c116a90d3a3536430b808b15e73275060918434Paul Stewart << " from interface " << interface_index; 6179a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart rtnl_handler_->RemoveInterfaceAddress(interface_index, iter->address); 6189a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 6199a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 6209a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart} 6219a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 62205a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewartbool DeviceInfo::HasOtherAddress( 62305a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart int interface_index, const IPAddress &this_address) const { 62405a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart SLOG(Device, 3) << __func__ << "(" << interface_index << ")"; 62505a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart const Info *info = GetInfo(interface_index); 62605a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart if (!info) { 62705a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart return false; 62805a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } 62905a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart const vector<AddressData> &addresses = info->ip_addresses; 63005a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart vector<AddressData>::const_iterator iter; 63105a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart bool has_other_address = false; 63205a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart bool has_this_address = false; 63305a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart for (iter = addresses.begin(); iter != addresses.end(); ++iter) { 63405a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart if (iter->address.family() != this_address.family()) { 63505a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart continue; 63605a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } 63705a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart if (iter->address.address().Equals(this_address.address())) { 63805a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart has_this_address = true; 63905a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } else if (this_address.family() == IPAddress::kFamilyIPv4) { 64005a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart has_other_address = true; 64105a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } else if ((iter->scope == RT_SCOPE_UNIVERSE && 64205a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart (iter->flags & IFA_F_TEMPORARY) == 0)) { 64305a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart has_other_address = true; 64405a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } 64505a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } 64605a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart return has_other_address && !has_this_address; 64705a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart} 64805a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart 649e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkovbool DeviceInfo::GetFlags(int interface_index, unsigned int *flags) const { 650e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov const Info *info = GetInfo(interface_index); 651e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov if (!info) { 652e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov return false; 653e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov } 654e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov *flags = info->flags; 655e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov return true; 656e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov} 657e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov 6581ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewartbool DeviceInfo::GetByteCounts(int interface_index, 6591ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart uint64 *rx_bytes, 6601ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart uint64 *tx_bytes) const { 6611ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart const Info *info = GetInfo(interface_index); 6621ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart if (!info) { 6631ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart return false; 6641ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart } 6651ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart *rx_bytes = info->rx_bytes; 6661ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart *tx_bytes = info->tx_bytes; 6671ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart return true; 6681ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart} 6691ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 670ca6abd4635507fa5b8f4b8819a37819fb560c464Paul Stewartbool DeviceInfo::CreateTunnelInterface(string *interface_name) const { 671cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart int fd = HANDLE_EINTR(open(kTunDeviceName, O_RDWR)); 672cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart if (fd < 0) { 673cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart PLOG(ERROR) << "failed to open " << kTunDeviceName; 674cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return false; 675cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 676cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart file_util::ScopedFD scoped_fd(&fd); 677cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 678cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart struct ifreq ifr; 679cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart memset(&ifr, 0, sizeof(ifr)); 680cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart ifr.ifr_flags = IFF_TUN | IFF_NO_PI; 681cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart if (HANDLE_EINTR(ioctl(fd, TUNSETIFF, &ifr))) { 682cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart PLOG(ERROR) << "failed to create tunnel interface"; 683cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return false; 684cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 685cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 686cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart if (HANDLE_EINTR(ioctl(fd, TUNSETPERSIST, 1))) { 687cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart PLOG(ERROR) << "failed to set tunnel interface to be persistent"; 688cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return false; 689cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 690cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 691cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart *interface_name = string(ifr.ifr_name); 692cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 693cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return true; 694cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart} 695cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 696ca6abd4635507fa5b8f4b8819a37819fb560c464Paul Stewartbool DeviceInfo::DeleteInterface(int interface_index) const { 697cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return rtnl_handler_->RemoveInterface(interface_index); 698cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart} 699cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 700e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkovconst DeviceInfo::Info *DeviceInfo::GetInfo(int interface_index) const { 701e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov map<int, Info>::const_iterator iter = infos_.find(interface_index); 702e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov if (iter == infos_.end()) { 703e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov return NULL; 704e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov } 705e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov return &iter->second; 706e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov} 707e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov 708e6193c042652831cac90c3bbf2233877754b1eefDarin Petkovvoid DeviceInfo::RemoveInfo(int interface_index) { 709e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov map<int, Info>::iterator iter = infos_.find(interface_index); 710e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov if (iter != infos_.end()) { 711fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << "Removing info for device index: " << interface_index; 712e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov if (iter->second.device.get()) { 713e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov manager_->DeregisterDevice(iter->second.device); 714e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov } 715f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov indices_.erase(iter->second.name); 716e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov infos_.erase(iter); 717050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.erase(interface_index); 71847009f8d7a6fbc257a1bb1288a01405d034bd13fmukesh agrawal } else { 719fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << ": Unknown device index: " 720fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << interface_index; 721b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 7220af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 7230af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 7242aa9707f114ab8166f45df5726bf05278df2aef6Chris Masonevoid DeviceInfo::LinkMsgHandler(const RTNLMessage &msg) { 7259a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart DCHECK(msg.type() == RTNLMessage::kTypeLink); 7269a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (msg.mode() == RTNLMessage::kModeAdd) { 7272aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone AddLinkMsgHandler(msg); 7289a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else if (msg.mode() == RTNLMessage::kModeDelete) { 7292aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone DelLinkMsgHandler(msg); 7302aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone } else { 7312aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone NOTREACHED(); 732b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 7330af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 7340af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 7359a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewartvoid DeviceInfo::AddressMsgHandler(const RTNLMessage &msg) { 736fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__; 7379a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart DCHECK(msg.type() == RTNLMessage::kTypeAddress); 7389a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart int interface_index = msg.interface_index(); 7399a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (!ContainsKey(infos_, interface_index)) { 7408c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << "Got advance address information for unknown index " 7418c116a90d3a3536430b808b15e73275060918434Paul Stewart << interface_index; 7428c116a90d3a3536430b808b15e73275060918434Paul Stewart infos_[interface_index].has_addresses_only = true; 7439a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 7449a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart const RTNLMessage::AddressStatus &status = msg.address_status(); 7459a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart IPAddress address(msg.family(), 746682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan msg.HasAttribute(IFA_LOCAL) ? 747682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan msg.GetAttribute(IFA_LOCAL) : msg.GetAttribute(IFA_ADDRESS), 7489a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart status.prefix_len); 7499a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 750682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan SLOG_IF(Device, 2, msg.HasAttribute(IFA_LOCAL)) 751682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan << "Found local address attribute for interface " << interface_index; 752682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan 7539a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart vector<AddressData> &address_list = infos_[interface_index].ip_addresses; 7549a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart vector<AddressData>::iterator iter; 7559a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart for (iter = address_list.begin(); iter != address_list.end(); ++iter) { 7569a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (address.Equals(iter->address)) { 7579a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart break; 7589a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 7599a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 7609a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (iter != address_list.end()) { 7619a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (msg.mode() == RTNLMessage::kModeDelete) { 762fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << "Delete address for interface " << interface_index; 7639a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart address_list.erase(iter); 7649a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else { 7659a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart iter->flags = status.flags; 7669a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart iter->scope = status.scope; 7679a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 7689a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else if (msg.mode() == RTNLMessage::kModeAdd) { 7699a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart address_list.push_back(AddressData(address, status.flags, status.scope)); 7708c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << "Add address " << address.ToString() 7718c116a90d3a3536430b808b15e73275060918434Paul Stewart << " for interface " << interface_index; 7729a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 7739a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart} 7749a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 775050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewartvoid DeviceInfo::DelayDeviceCreation(int interface_index) { 776050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.insert(interface_index); 777050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_callback_.Reset( 778050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart Bind(&DeviceInfo::DelayedDeviceCreationTask, AsWeakPtr())); 779050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart dispatcher_->PostDelayedTask(delayed_devices_callback_.callback(), 780050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart kDelayedDeviceCreationSeconds * 1000); 781050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart} 782050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 783050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart// Re-evaluate the technology type for each delayed device. 784050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewartvoid DeviceInfo::DelayedDeviceCreationTask() { 785050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart while (!delayed_devices_.empty()) { 786050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart set<int>::iterator it = delayed_devices_.begin(); 787050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart int dev_index = *it; 788050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.erase(it); 789050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 790050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DCHECK(ContainsKey(infos_, dev_index)); 791050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DCHECK(!GetDevice(dev_index)); 792050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 793050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart const string &link_name = infos_[dev_index].name; 794050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart Technology::Identifier technology = GetDeviceTechnology(link_name); 795050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 796050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart if (technology == Technology::kCDCEthernet) { 797050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart LOG(INFO) << "In " << __func__ << ": device " << link_name 798050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart << " is now assumed to be regular Ethernet."; 799050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart technology = Technology::kEthernet; 800050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } else if (technology != Technology::kCellular) { 801050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart LOG(WARNING) << "In " << __func__ << ": device " << link_name 802050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart << " is unexpected technology " 803050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart << Technology::NameFromIdentifier(technology); 804050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } 805050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart string address = 806050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart StringToLowerASCII(infos_[dev_index].mac_address.HexEncode()); 807050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DCHECK(!address.empty()); 808050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 809050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DeviceRefPtr device = CreateDevice(link_name, address, dev_index, 810050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart technology); 811050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart if (device) { 812050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart RegisterDevice(device); 813050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } 814050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } 815050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart} 816050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 8171ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewartvoid DeviceInfo::RetrieveLinkStatistics(int interface_index, 8181ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart const RTNLMessage &msg) { 8191ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart if (!msg.HasAttribute(IFLA_STATS64)) { 8201ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart return; 8211ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart } 8221ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart ByteString stats_bytes(msg.GetAttribute(IFLA_STATS64)); 8231ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart struct rtnl_link_stats64 stats; 8241ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart if (stats_bytes.GetLength() < sizeof(stats)) { 8251ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart LOG(WARNING) << "Link statistics size is too small: " 8261ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart << stats_bytes.GetLength() << " < " << sizeof(stats); 8271ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart return; 8281ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart } 8291ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 8301ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart memcpy(&stats, stats_bytes.GetConstData(), sizeof(stats)); 8311ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart SLOG(Device, 2) << "Link statistics for " 8321ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart << " interface index " << interface_index << ": " 8331ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart << "receive: " << stats.rx_bytes << "; " 8341ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart << "transmit: " << stats.tx_bytes << "."; 8351ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart infos_[interface_index].rx_bytes = stats.rx_bytes; 8361ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart infos_[interface_index].tx_bytes = stats.tx_bytes; 8371ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart} 8381ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 8391ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewartvoid DeviceInfo::RequestLinkStatistics() { 8401ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart rtnl_handler_->RequestDump(RTNLHandler::kRequestLink); 8411ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart dispatcher_->PostDelayedTask(request_link_statistics_callback_.callback(), 8421ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart kRequestLinkStatisticsIntervalSeconds * 1000); 8431ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart} 8441ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 8450af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} // namespace shill 846