device_info.cc revision 6db7b24348e69639e19cd6c408388b10d6ee54fe
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> 25a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/files/file_enumerator.h> 26487b8bfc46a91e29bb23aaf3c59cfe67033bfc8bChris Masone#include <base/memory/scoped_ptr.h> 273e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood#include <base/stl_util.h> 28a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_number_conversions.h> 29a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_util.h> 30a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/stringprintf.h> 310af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 320af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart#include "shill/control_interface.h" 339be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone#include "shill/device.h" 34a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart#include "shill/device_stub.h" 35b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart#include "shill/ethernet.h" 36b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley#include "shill/logging.h" 37b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart#include "shill/manager.h" 382ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart#include "shill/netlink_attribute.h" 392ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart#include "shill/netlink_manager.h" 402ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart#include "shill/nl80211_message.h" 418c116a90d3a3536430b808b15e73275060918434Paul Stewart#include "shill/routing_table.h" 42a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart#include "shill/rtnl_handler.h" 43a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart#include "shill/rtnl_listener.h" 442aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone#include "shill/rtnl_message.h" 45487b8bfc46a91e29bb23aaf3c59cfe67033bfc8bChris Masone#include "shill/service.h" 464178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain#include "shill/sockets.h" 4793a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal#include "shill/virtio_ethernet.h" 48c3505a569e3f98ce56e4017300a3ce46bc714e4cDarin Petkov#include "shill/vpn_provider.h" 49b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart#include "shill/wifi.h" 500af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 513e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Bind; 52a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chanusing base::FileEnumerator; 530e1cdeae24dd678a5fe27c840802582c0ca45ec0Albert Chaulkusing base::FilePath; 548f1c835d879f82261a08257eb6f9677e6be51fdaThieu Leusing base::StringPrintf; 553e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Unretained; 56e6193c042652831cac90c3bbf2233877754b1eefDarin Petkovusing std::map; 57050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewartusing std::set; 580af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewartusing std::string; 599a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewartusing std::vector; 600af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 610af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewartnamespace shill { 62b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 63b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart// static 64abc5403270e26fa898181301911a905758f8d758Jason Glasgowconst char DeviceInfo::kModemPseudoDeviceNamePrefix[] = "pseudomodem"; 65e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wileyconst char DeviceInfo::kEthernetPseudoDeviceNamePrefix[] = "pseudoethernet"; 66ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kDeviceInfoRoot[] = "/sys/class/net"; 674e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chanconst char DeviceInfo::kDriverCdcEther[] = "cdc_ether"; 684eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chanconst char DeviceInfo::kDriverCdcNcm[] = "cdc_ncm"; 694e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chanconst char DeviceInfo::kDriverGdmWiMax[] = "gdm_wimax"; 7093a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawalconst char DeviceInfo::kDriverVirtioNet[] = "virtio_net"; 71ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceUevent[] = "uevent"; 729364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewartconst char DeviceInfo::kInterfaceUeventWifiSignature[] = "DEVTYPE=wlan\n"; 73ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceDevice[] = "device"; 74ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceDriver[] = "device/driver"; 75ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceTunFlags[] = "tun_flags"; 76ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceType[] = "type"; 77b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewartconst char *DeviceInfo::kModemDrivers[] = { 78b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart "gobi", 79b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart "QCUSBNet2k", 80226d46a2e03d316e8a36f93cb261f708219aef07Ben Chan "GobiNet", 810f90e0b62322ae95c1a419d5efef47438b4617c9Ben Chan "cdc_mbim", 82226d46a2e03d316e8a36f93cb261f708219aef07Ben Chan "qmi_wwan" 83b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart}; 84cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewartconst char DeviceInfo::kTunDeviceName[] = "/dev/net/tun"; 85050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewartconst int DeviceInfo::kDelayedDeviceCreationSeconds = 5; 86b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chanconst int DeviceInfo::kRequestLinkStatisticsIntervalMilliseconds = 20000; 87b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 88b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul StewartDeviceInfo::DeviceInfo(ControlInterface *control_interface, 89b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart EventDispatcher *dispatcher, 903426c8fc7a3943f2d8fcb2ec78f0593088b42bedThieu Le Metrics *metrics, 91b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart Manager *manager) 92a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart : control_interface_(control_interface), 93a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart dispatcher_(dispatcher), 943426c8fc7a3943f2d8fcb2ec78f0593088b42bedThieu Le metrics_(metrics), 95a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart manager_(manager), 963e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood link_callback_(Bind(&DeviceInfo::LinkMsgHandler, Unretained(this))), 973e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood address_callback_(Bind(&DeviceInfo::AddressMsgHandler, Unretained(this))), 98ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart device_info_root_(kDeviceInfoRoot), 998c116a90d3a3536430b808b15e73275060918434Paul Stewart routing_table_(RoutingTable::GetInstance()), 1004178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain rtnl_handler_(RTNLHandler::GetInstance()), 1012ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart netlink_manager_(NetlinkManager::GetInstance()), 1024178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain sockets_(new Sockets()) { 1030af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 1040af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 105a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul StewartDeviceInfo::~DeviceInfo() {} 1060af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 1078f317b600a218afe05f2d73c59204bb98269a950mukesh agrawalvoid DeviceInfo::AddDeviceToBlackList(const string &device_name) { 1088f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal black_list_.insert(device_name); 1098f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal} 1108f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal 1115e628a5c722c196ad240af0ff3c717e9613d3ef5Eric Shienbroodbool DeviceInfo::IsDeviceBlackListed(const string &device_name) { 1125e628a5c722c196ad240af0ff3c717e9613d3ef5Eric Shienbrood return ContainsKey(black_list_, device_name); 1135e628a5c722c196ad240af0ff3c717e9613d3ef5Eric Shienbrood} 1145e628a5c722c196ad240af0ff3c717e9613d3ef5Eric Shienbrood 115a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewartvoid DeviceInfo::Start() { 116a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart link_listener_.reset( 1173e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood new RTNLListener(RTNLHandler::kRequestLink, link_callback_)); 1189a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart address_listener_.reset( 1193e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood new RTNLListener(RTNLHandler::kRequestAddr, address_callback_)); 1209a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart rtnl_handler_->RequestDump(RTNLHandler::kRequestLink | 1219a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart RTNLHandler::kRequestAddr); 1221ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart request_link_statistics_callback_.Reset( 1231ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart Bind(&DeviceInfo::RequestLinkStatistics, AsWeakPtr())); 1241ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart dispatcher_->PostDelayedTask(request_link_statistics_callback_.callback(), 125b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan kRequestLinkStatisticsIntervalMilliseconds); 1260af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 1270af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 128a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewartvoid DeviceInfo::Stop() { 1299a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart link_listener_.reset(); 1309a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart address_listener_.reset(); 1318c116a90d3a3536430b808b15e73275060918434Paul Stewart infos_.clear(); 1321ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart request_link_statistics_callback_.Cancel(); 133050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_callback_.Cancel(); 134050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.clear(); 1350af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 1360af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 1375086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chanvector<string> DeviceInfo::GetUninitializedTechnologies() const { 1385086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan set<string> unique_technologies; 139b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray set<Technology::Identifier> initialized_technologies; 1406db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart for (const auto &info : infos_) { 1416db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart Technology::Identifier technology = info.second.technology; 1426db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart if (info.second.device) { 143b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray // If there is more than one device for a technology and at least 144b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray // one of them has been initialized, make sure that it doesn't get 145b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray // listed as uninitialized. 146b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray initialized_technologies.insert(technology); 147b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray unique_technologies.erase(Technology::NameFromIdentifier(technology)); 148b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray continue; 149b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray } 150b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray if (Technology::IsPrimaryConnectivityTechnology(technology) && 151b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray !ContainsKey(initialized_technologies, technology)) 1525086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan unique_technologies.insert(Technology::NameFromIdentifier(technology)); 1535086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan } 1545086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan return vector<string>(unique_technologies.begin(), unique_technologies.end()); 1555086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan} 1565086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan 1576f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkovvoid DeviceInfo::RegisterDevice(const DeviceRefPtr &device) { 158fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << "(" << device->link_name() << ", " 159fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << device->interface_index() << ")"; 160050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.erase(device->interface_index()); 161e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov CHECK(!GetDevice(device->interface_index()).get()); 162e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov infos_[device->interface_index()].device = device; 1639abd6749e69712e9ec4ed4a54fbba243f16ae7f3Thieu Le if (metrics_->IsDeviceRegistered(device->interface_index(), 1649abd6749e69712e9ec4ed4a54fbba243f16ae7f3Thieu Le device->technology())) { 1659abd6749e69712e9ec4ed4a54fbba243f16ae7f3Thieu Le metrics_->NotifyDeviceInitialized(device->interface_index()); 1669abd6749e69712e9ec4ed4a54fbba243f16ae7f3Thieu Le } else { 1679abd6749e69712e9ec4ed4a54fbba243f16ae7f3Thieu Le metrics_->RegisterDevice(device->interface_index(), device->technology()); 1689abd6749e69712e9ec4ed4a54fbba243f16ae7f3Thieu Le } 1695086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan if (Technology::IsPrimaryConnectivityTechnology(device->technology())) { 1706f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov manager_->RegisterDevice(device); 1716f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov } 1726f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov} 1736f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov 174e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgowvoid DeviceInfo::DeregisterDevice(const DeviceRefPtr &device) { 175e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow int interface_index = device->interface_index(); 176e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow 177fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << "(" << device->link_name() << ", " 178fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << interface_index << ")"; 179da798623389b981130cd1922f880736f1e0e36baJoshua Kroll CHECK((device->technology() == Technology::kCellular) || 180da798623389b981130cd1922f880736f1e0e36baJoshua Kroll (device->technology() == Technology::kWiMax)); 181e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow 182e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow // Release reference to the device 183e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow map<int, Info>::iterator iter = infos_.find(interface_index); 184e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow if (iter != infos_.end()) { 185fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << "Removing device from info for index: " 186fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << interface_index; 187e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow manager_->DeregisterDevice(device); 188e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow // Release the reference to the device, but maintain the mapping 189e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow // for the index. That will be cleaned up by an RTNL message. 190e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow iter->second.device = NULL; 191e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow } 192c8078a6c44d0e30b71642856ef46e0cf6c5edb46Thieu Le metrics_->DeregisterDevice(device->interface_index()); 193e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow} 194e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow 195ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul StewartFilePath DeviceInfo::GetDeviceInfoPath(const string &iface_name, 196ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart const string &path_name) { 197ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart return device_info_root_.Append(iface_name).Append(path_name); 198ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart} 199ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart 200ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartbool DeviceInfo::GetDeviceInfoContents(const string &iface_name, 201ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart const string &path_name, 202ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart string *contents_out) { 203a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan return base::ReadFileToString(GetDeviceInfoPath(iface_name, path_name), 204a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan contents_out); 205ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart} 206ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartbool DeviceInfo::GetDeviceInfoSymbolicLink(const string &iface_name, 2074e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan const string &path_name, 2084e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan FilePath *path_out) { 209a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan return base::ReadSymbolicLink(GetDeviceInfoPath(iface_name, path_name), 210a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan path_out); 211ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart} 212ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart 213fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul StewartTechnology::Identifier DeviceInfo::GetDeviceTechnology( 214fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart const string &iface_name) { 215ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart string type_string; 2162ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart int arp_type = ARPHRD_VOID; 217ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (GetDeviceInfoContents(iface_name, kInterfaceType, &type_string) && 218a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan base::TrimString(type_string, "\n", &type_string) && 219ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart !base::StringToInt(type_string, &arp_type)) { 220ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart arp_type = ARPHRD_VOID; 221ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart } 222ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart 2239364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart string contents; 224ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (!GetDeviceInfoContents(iface_name, kInterfaceUevent, &contents)) { 225050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart LOG(INFO) << StringPrintf("%s: device %s has no uevent file", 226050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart __func__, iface_name.c_str()); 227fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart return Technology::kUnknown; 2289364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart } 229b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 2308f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // If the "uevent" file contains the string "DEVTYPE=wlan\n" at the 2318f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // start of the file or after a newline, we can safely assume this 2328f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // is a wifi device. 2339364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart if (contents.find(kInterfaceUeventWifiSignature) != string::npos) { 234fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) 235fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << StringPrintf("%s: device %s has wifi signature in uevent file", 236fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 237ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (arp_type == ARPHRD_IEEE80211_RADIOTAP) { 238fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: wifi device %s is in monitor mode", 239fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 2402001a42edf1d42ec828a9baf3157496c20fefd49Paul Stewart return Technology::kWiFiMonitor; 2412001a42edf1d42ec828a9baf3157496c20fefd49Paul Stewart } 242fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart return Technology::kWifi; 2439364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart } 244b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 2457904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow // Special case for pseudo modems which are used for testing 2467904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow if (iface_name.find(kModemPseudoDeviceNamePrefix) == 0) { 2477904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow SLOG(Device, 2) << StringPrintf( 2487904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow "%s: device %s is a pseudo modem for testing", 2497904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow __func__, iface_name.c_str()); 2507904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow return Technology::kCellular; 2517904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow } 2527904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow 253e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley // Special case for pseudo ethernet devices which are used for testing. 254e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley if (iface_name.find(kEthernetPseudoDeviceNamePrefix) == 0) { 255e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley SLOG(Device, 2) << StringPrintf( 256e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley "%s: device %s is a virtual ethernet device for testing", 257e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley __func__, iface_name.c_str()); 258e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley return Technology::kEthernet; 259e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley } 260e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley 2619364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart FilePath driver_path; 262ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (!GetDeviceInfoSymbolicLink(iface_name, kInterfaceDriver, &driver_path)) { 263fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s has no device symlink", 264fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 265ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (arp_type == ARPHRD_LOOPBACK) { 266fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s is a loopback device", 267fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 268e81eb700f66563cb695b6e3682f20ac5a0cdb8c0Paul Stewart return Technology::kLoopback; 269e81eb700f66563cb695b6e3682f20ac5a0cdb8c0Paul Stewart } 270ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (arp_type == ARPHRD_PPP) { 271ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart SLOG(Device, 2) << StringPrintf("%s: device %s is a ppp device", 272ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart __func__, iface_name.c_str()); 273ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart return Technology::kPPP; 274ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart } 275ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart string tun_flags_str; 276cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart int tun_flags = 0; 277ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (GetDeviceInfoContents(iface_name, kInterfaceTunFlags, &tun_flags_str) && 278a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan base::TrimString(tun_flags_str, "\n", &tun_flags_str) && 279ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart base::HexStringToInt(tun_flags_str, &tun_flags) && 280cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart (tun_flags & IFF_TUN)) { 281fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s is tun device", 282fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 283cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return Technology::kTunnel; 284cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 285e81eb700f66563cb695b6e3682f20ac5a0cdb8c0Paul Stewart return Technology::kUnknown; 2869364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart } 287b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 2889364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart string driver_name(driver_path.BaseName().value()); 2898f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // See if driver for this interface is in a list of known modem driver names. 2908f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le for (size_t modem_idx = 0; modem_idx < arraysize(kModemDrivers); 2918f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le ++modem_idx) { 2929364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart if (driver_name == kModemDrivers[modem_idx]) { 293fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) 294fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << StringPrintf("%s: device %s is matched with modem driver %s", 295fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str(), driver_name.c_str()); 2969364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart return Technology::kCellular; 2979364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart } 298b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 2990af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 3004e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan if (driver_name == kDriverGdmWiMax) { 3014e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s is a WiMAX device", 3024e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan __func__, iface_name.c_str()); 3034e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan return Technology::kWiMax; 3044e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan } 3054e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan 3064eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // For cdc_ether / cdc_ncm devices, make sure it's a modem because this driver 3078f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // can be used for other ethernet devices. 3084eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan if (driver_name == kDriverCdcEther || driver_name == kDriverCdcNcm) { 3094eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan if (IsCdcEthernetModemDevice(iface_name)) { 3104eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan LOG(INFO) << StringPrintf("%s: device %s is a %s modem device", __func__, 31135ec8408d8b40d74693edc32495b392a525dc238mukesh agrawal iface_name.c_str(), driver_name.c_str()); 312050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart return Technology::kCellular; 313050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } 3144eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s is a %s device", __func__, 31535ec8408d8b40d74693edc32495b392a525dc238mukesh agrawal iface_name.c_str(), driver_name.c_str()); 316050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart return Technology::kCDCEthernet; 3178f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le } 318abc5403270e26fa898181301911a905758f8d758Jason Glasgow 31993a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal // Special case for the virtio driver, used when run under KVM. See also 32093a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal // the comment in VirtioEthernet::Start. 32193a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal if (driver_name == kDriverVirtioNet) { 322fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s is virtio ethernet", 323fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 32493a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal return Technology::kVirtioEthernet; 32593a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal } 32693a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal 327fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s, with driver %s, " 328fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan "is defaulted to type ethernet", 329fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str(), 330fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan driver_name.c_str()); 331fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart return Technology::kEthernet; 332b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart} 333b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 3344eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chanbool DeviceInfo::IsCdcEthernetModemDevice(const std::string &iface_name) { 3354eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // A cdc_ether / cdc_ncm device is a modem device if it also exposes tty 3364eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // interfaces. To determine this, we look for the existence of the tty 3374eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // interface in the USB device sysfs tree. 3388f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 3394eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // A typical sysfs dir hierarchy for a cdc_ether / cdc_ncm modem USB device is 3404eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // as follows: 3418f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 3428f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2 3438f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 1-2:1.0 3448f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // tty 3458f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // ttyACM0 3468f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 1-2:1.1 3478f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // net 3488f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // usb0 3498f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 1-2:1.2 3508f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // tty 3518f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // ttyACM1 3528f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // ... 3538f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 3548f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // /sys/class/net/usb0/device symlinks to 3558f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2/1-2:1.1 356b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // 357b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // Note that some modem devices have the tty directory one level deeper 358b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // (eg. E362), so the device tree for the tty interface is: 359b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // /sys/devices/pci0000:00/0000:00:1d.7/usb/1-2/1-2:1.0/ttyUSB0/tty/ttyUSB0 3608f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le 361ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart FilePath device_file = GetDeviceInfoPath(iface_name, kInterfaceDevice); 3628f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le FilePath device_path; 363a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan if (!base::ReadSymbolicLink(device_file, &device_path)) { 364fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << StringPrintf("%s: device %s has no device symlink", 365fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 3668f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le return false; 3678f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le } 3688f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le if (!device_path.IsAbsolute()) { 369a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan device_path = 370a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan base::MakeAbsoluteFilePath(device_file.DirName().Append(device_path)); 3718f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le } 3728f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le 3738f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // Look for tty interface by enumerating all directories under the parent 374b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // USB device and see if there's a subdirectory "tty" inside. In other 375b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // words, using the example dir hierarchy above, find 376b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2/.../tty. 3778f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // If this exists, then this is a modem device. 378b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le return HasSubdir(device_path.DirName(), FilePath("tty")); 3798f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le} 3808f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le 3818f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le// static 382b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Lebool DeviceInfo::HasSubdir(const FilePath &base_dir, const FilePath &subdir) { 383a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan FileEnumerator::FileType type = static_cast<FileEnumerator::FileType>( 384a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan FileEnumerator::DIRECTORIES | FileEnumerator::SHOW_SYM_LINKS); 385a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan FileEnumerator dir_enum(base_dir, true, type); 3868f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le for (FilePath curr_dir = dir_enum.Next(); !curr_dir.empty(); 3878f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le curr_dir = dir_enum.Next()) { 388b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le if (curr_dir.BaseName() == subdir) 3898f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le return true; 3908f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le } 3918f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le return false; 3928f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le} 3938f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le 3948c116a90d3a3536430b808b15e73275060918434Paul StewartDeviceRefPtr DeviceInfo::CreateDevice(const string &link_name, 3958c116a90d3a3536430b808b15e73275060918434Paul Stewart const string &address, 3968c116a90d3a3536430b808b15e73275060918434Paul Stewart int interface_index, 3978c116a90d3a3536430b808b15e73275060918434Paul Stewart Technology::Identifier technology) { 3988c116a90d3a3536430b808b15e73275060918434Paul Stewart DeviceRefPtr device; 399050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.erase(interface_index); 4005086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan infos_[interface_index].technology = technology; 4018c116a90d3a3536430b808b15e73275060918434Paul Stewart 4028c116a90d3a3536430b808b15e73275060918434Paul Stewart switch (technology) { 4038c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kCellular: 4045742b24ab984464701fef0cc7024af2637357b04Ben Chan#if defined(DISABLE_CELLULAR) 4055742b24ab984464701fef0cc7024af2637357b04Ben Chan LOG(WARNING) << "Cellular support is not implemented. " 4065742b24ab984464701fef0cc7024af2637357b04Ben Chan << "Ignore cellular device " << link_name << " at index " 4075742b24ab984464701fef0cc7024af2637357b04Ben Chan << interface_index << "."; 4085742b24ab984464701fef0cc7024af2637357b04Ben Chan return NULL; 4095742b24ab984464701fef0cc7024af2637357b04Ben Chan#else 4108c116a90d3a3536430b808b15e73275060918434Paul Stewart // Cellular devices are managed by ModemInfo. 4118c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << "Cellular link " << link_name 4128c116a90d3a3536430b808b15e73275060918434Paul Stewart << " at index " << interface_index 4138c116a90d3a3536430b808b15e73275060918434Paul Stewart << " -- notifying ModemInfo."; 414bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain 415bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain // The MAC address provided by RTNL is not reliable for Gobi 2K modems. 4164b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // Clear it here, and it will be fetched from the kernel in 4174b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // GetMACAddress(). 418bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain infos_[interface_index].mac_address.Clear(); 4198c116a90d3a3536430b808b15e73275060918434Paul Stewart manager_->modem_info()->OnDeviceInfoAvailable(link_name); 4208c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 4215742b24ab984464701fef0cc7024af2637357b04Ben Chan#endif // DISABLE_CELLULAR 4228c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kEthernet: 4238c116a90d3a3536430b808b15e73275060918434Paul Stewart device = new Ethernet(control_interface_, dispatcher_, metrics_, 4248c116a90d3a3536430b808b15e73275060918434Paul Stewart manager_, link_name, address, interface_index); 4258c116a90d3a3536430b808b15e73275060918434Paul Stewart device->EnableIPv6Privacy(); 4268c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 4278c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kVirtioEthernet: 4288c116a90d3a3536430b808b15e73275060918434Paul Stewart device = new VirtioEthernet(control_interface_, dispatcher_, metrics_, 4298c116a90d3a3536430b808b15e73275060918434Paul Stewart manager_, link_name, address, 4308c116a90d3a3536430b808b15e73275060918434Paul Stewart interface_index); 4318c116a90d3a3536430b808b15e73275060918434Paul Stewart device->EnableIPv6Privacy(); 4328c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 4338c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kWifi: 4342ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart // Defer creating this device until we get information about the 4352ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart // type of WiFi interface. 4362ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart GetWiFiInterfaceInfo(interface_index); 4378c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 4384e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan case Technology::kWiMax: 439520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan#if defined(DISABLE_WIMAX) 440520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan LOG(WARNING) << "WiMax support is not implemented. Ignore WiMax link " 441520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan << link_name << " at index " << interface_index << "."; 442520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan return NULL; 443520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan#else 444e4b270274cba2a1976c7be6c733bd899e009c1d1Darin Petkov // WiMax devices are managed by WiMaxProvider. 445e4b270274cba2a1976c7be6c733bd899e009c1d1Darin Petkov SLOG(Device, 2) << "WiMax link " << link_name 446e4b270274cba2a1976c7be6c733bd899e009c1d1Darin Petkov << " at index " << interface_index 447e4b270274cba2a1976c7be6c733bd899e009c1d1Darin Petkov << " -- notifying WiMaxProvider."; 4484b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // The MAC address provided by RTNL may not be the final value as the 4494b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // WiMAX device may change the address after initialization. Clear it 4504b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // here, and it will be fetched from the kernel when 4514b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // WiMaxProvider::CreateDevice() is called after the WiMAX device DBus 4524b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // object is created by the WiMAX manager daemon. 4534b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan infos_[interface_index].mac_address.Clear(); 454e4b270274cba2a1976c7be6c733bd899e009c1d1Darin Petkov manager_->wimax_provider()->OnDeviceInfoAvailable(link_name); 4554e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan break; 456520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan#endif // DISABLE_WIMAX 4578c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kPPP: 4588c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kTunnel: 4598c116a90d3a3536430b808b15e73275060918434Paul Stewart // Tunnel and PPP devices are managed by the VPN code (PPP for 4608c116a90d3a3536430b808b15e73275060918434Paul Stewart // l2tpipsec). Notify the VPN Provider of the interface's presence. 4618c116a90d3a3536430b808b15e73275060918434Paul Stewart // Since CreateDevice is only called once in the lifetime of an 4628c116a90d3a3536430b808b15e73275060918434Paul Stewart // interface index, this notification will only occur the first 4638c116a90d3a3536430b808b15e73275060918434Paul Stewart // time the device is seen. 4648c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << "Tunnel / PPP link " << link_name 4658c116a90d3a3536430b808b15e73275060918434Paul Stewart << " at index " << interface_index 4668c116a90d3a3536430b808b15e73275060918434Paul Stewart << " -- notifying VPNProvider."; 4678c116a90d3a3536430b808b15e73275060918434Paul Stewart if (!manager_->vpn_provider()->OnDeviceInfoAvailable(link_name, 4688c116a90d3a3536430b808b15e73275060918434Paul Stewart interface_index) && 4698c116a90d3a3536430b808b15e73275060918434Paul Stewart technology == Technology::kTunnel) { 4708c116a90d3a3536430b808b15e73275060918434Paul Stewart // If VPN does not know anything about this tunnel, it is probably 4718c116a90d3a3536430b808b15e73275060918434Paul Stewart // left over from a previous instance and should not exist. 4728c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << "Tunnel link is unused. Deleting."; 4738c116a90d3a3536430b808b15e73275060918434Paul Stewart DeleteInterface(interface_index); 4748c116a90d3a3536430b808b15e73275060918434Paul Stewart } 4758c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 4768c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kLoopback: 4778c116a90d3a3536430b808b15e73275060918434Paul Stewart // Loopback devices are largely ignored, but we should make sure the 4788c116a90d3a3536430b808b15e73275060918434Paul Stewart // link is enabled. 4798c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << "Bringing up loopback device " << link_name 4808c116a90d3a3536430b808b15e73275060918434Paul Stewart << " at index " << interface_index; 4818c116a90d3a3536430b808b15e73275060918434Paul Stewart rtnl_handler_->SetInterfaceFlags(interface_index, IFF_UP, IFF_UP); 4828c116a90d3a3536430b808b15e73275060918434Paul Stewart return NULL; 483050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart case Technology::kCDCEthernet: 4844eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // CDCEthernet devices are of indeterminate type when they are 485050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // initially created. Some time later, tty devices may or may 486050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // not appear under the same USB device root, which will identify 487050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // it as a modem. Alternatively, ModemManager may discover the 488050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // device and create and register a Cellular device. In either 489050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // case, we should delay creating a Device until we can make a 490050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // better determination of what type this Device should be. 491050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart LOG(INFO) << "Delaying creation of device for " << link_name 492050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart << " at index " << interface_index; 493050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DelayDeviceCreation(interface_index); 494050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart return NULL; 4958c116a90d3a3536430b808b15e73275060918434Paul Stewart default: 4968c116a90d3a3536430b808b15e73275060918434Paul Stewart // We will not manage this device in shill. Do not create a device 4978c116a90d3a3536430b808b15e73275060918434Paul Stewart // object or do anything to change its state. We create a stub object 4988c116a90d3a3536430b808b15e73275060918434Paul Stewart // which is useful for testing. 4998c116a90d3a3536430b808b15e73275060918434Paul Stewart return new DeviceStub(control_interface_, dispatcher_, metrics_, 5008c116a90d3a3536430b808b15e73275060918434Paul Stewart manager_, link_name, address, interface_index, 5014e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan technology); 5028c116a90d3a3536430b808b15e73275060918434Paul Stewart } 5038c116a90d3a3536430b808b15e73275060918434Paul Stewart 5048c116a90d3a3536430b808b15e73275060918434Paul Stewart // Reset the routing table and addresses. 5058c116a90d3a3536430b808b15e73275060918434Paul Stewart routing_table_->FlushRoutes(interface_index); 5068c116a90d3a3536430b808b15e73275060918434Paul Stewart FlushAddresses(interface_index); 5078c116a90d3a3536430b808b15e73275060918434Paul Stewart 5085086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan manager_->UpdateUninitializedTechnologies(); 5095086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan 5108c116a90d3a3536430b808b15e73275060918434Paul Stewart return device; 5118c116a90d3a3536430b808b15e73275060918434Paul Stewart} 5128c116a90d3a3536430b808b15e73275060918434Paul Stewart 5132aa9707f114ab8166f45df5726bf05278df2aef6Chris Masonevoid DeviceInfo::AddLinkMsgHandler(const RTNLMessage &msg) { 5149a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart DCHECK(msg.type() == RTNLMessage::kTypeLink && 5159a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart msg.mode() == RTNLMessage::kModeAdd); 5162aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone int dev_index = msg.interface_index(); 517fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart Technology::Identifier technology = Technology::kUnknown; 518e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov unsigned int flags = msg.link_status().flags; 519e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov unsigned int change = msg.link_status().change; 5208c116a90d3a3536430b808b15e73275060918434Paul Stewart bool new_device = 5218c116a90d3a3536430b808b15e73275060918434Paul Stewart !ContainsKey(infos_, dev_index) || infos_[dev_index].has_addresses_only; 522fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << "(index=" << dev_index 523fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << std::showbase << std::hex 524fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << ", flags=" << flags << ", change=" << change << ")" 525fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << std::dec << std::noshowbase 526fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << ", new_device=" << new_device; 5278c116a90d3a3536430b808b15e73275060918434Paul Stewart infos_[dev_index].has_addresses_only = false; 528e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov infos_[dev_index].flags = flags; 529f1ce5d27adbfcaf9c46e650252b46e02b0d8addaPaul Stewart 5301ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart RetrieveLinkStatistics(dev_index, msg); 5311ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 5326f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov DeviceRefPtr device = GetDevice(dev_index); 5338c116a90d3a3536430b808b15e73275060918434Paul Stewart if (new_device) { 5348c116a90d3a3536430b808b15e73275060918434Paul Stewart CHECK(!device); 5352aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone if (!msg.HasAttribute(IFLA_IFNAME)) { 5362aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone LOG(ERROR) << "Add Link message does not have IFLA_IFNAME!"; 5372aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone return; 538b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 5392aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone ByteString b(msg.GetAttribute(IFLA_IFNAME)); 5402aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone string link_name(reinterpret_cast<const char*>(b.GetConstData())); 541fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << "add link index " << dev_index << " name " << link_name; 542f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov infos_[dev_index].name = link_name; 543f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov indices_[link_name] = dev_index; 544a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart 5452aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone if (!link_name.empty()) { 5468f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal if (ContainsKey(black_list_, link_name)) { 547fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart technology = Technology::kBlacklisted; 5488f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal } else { 5498f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal technology = GetDeviceTechnology(link_name); 5508f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal } 551633ac6f0d56a62f8fd21ba7d9a15818fe080fb2fDarin Petkov } 552cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart string address; 553cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart if (msg.HasAttribute(IFLA_ADDRESS)) { 554cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart infos_[dev_index].mac_address = msg.GetAttribute(IFLA_ADDRESS); 555cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart address = StringToLowerASCII(infos_[dev_index].mac_address.HexEncode()); 556fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << "link index " << dev_index << " address " 557fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << infos_[dev_index].mac_address.HexEncode(); 558ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart } else if (technology != Technology::kTunnel && 559ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart technology != Technology::kPPP) { 5606813e7624f1047872eeceec14db45373e30e268emukesh agrawal LOG(ERROR) << "Add Link message for link '" << link_name 5616813e7624f1047872eeceec14db45373e30e268emukesh agrawal << "' does not have IFLA_ADDRESS!"; 562cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return; 563cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 564c8078a6c44d0e30b71642856ef46e0cf6c5edb46Thieu Le metrics_->RegisterDevice(dev_index, technology); 5658c116a90d3a3536430b808b15e73275060918434Paul Stewart device = CreateDevice(link_name, address, dev_index, technology); 5668c116a90d3a3536430b808b15e73275060918434Paul Stewart if (device) { 5678c116a90d3a3536430b808b15e73275060918434Paul Stewart RegisterDevice(device); 568b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 569b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 5708c116a90d3a3536430b808b15e73275060918434Paul Stewart if (device) { 5718c116a90d3a3536430b808b15e73275060918434Paul Stewart device->LinkEvent(flags, change); 5728c116a90d3a3536430b808b15e73275060918434Paul Stewart } 573b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart} 574b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 5752aa9707f114ab8166f45df5726bf05278df2aef6Chris Masonevoid DeviceInfo::DelLinkMsgHandler(const RTNLMessage &msg) { 576fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << "(index=" << msg.interface_index() << ")"; 57747009f8d7a6fbc257a1bb1288a01405d034bd13fmukesh agrawal 5789a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart DCHECK(msg.type() == RTNLMessage::kTypeLink && 5799a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart msg.mode() == RTNLMessage::kModeDelete); 580fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << "(index=" << msg.interface_index() 581fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << std::showbase << std::hex 582fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << ", flags=" << msg.link_status().flags 583fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << ", change=" << msg.link_status().change << ")"; 584e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov RemoveInfo(msg.interface_index()); 585e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov} 586e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov 587e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin PetkovDeviceRefPtr DeviceInfo::GetDevice(int interface_index) const { 588e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov const Info *info = GetInfo(interface_index); 589e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov return info ? info->device : NULL; 59067d8ecfd1d6ff5ea75b9d5c7167d9c16891d3d4bDarin Petkov} 591b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 592f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkovint DeviceInfo::GetIndex(const string &interface_name) const { 593f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov map<string, int>::const_iterator it = indices_.find(interface_name); 594f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov return it == indices_.end() ? -1 : it->second; 595f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov} 596f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov 5973285296e6624fa0b1b10699f2fa6466d4be10742Paul Stewartbool DeviceInfo::GetMACAddress(int interface_index, ByteString *address) const { 598e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov const Info *info = GetInfo(interface_index); 599e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov if (!info) { 600e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov return false; 601e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov } 602bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain // |mac_address| from RTNL is not used for some devices, in which case it will 603bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain // be empty here. 604bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain if (!info->mac_address.IsEmpty()) { 605bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain *address = info->mac_address; 606bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain return true; 607bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain } 608bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain 609bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain // Ask the kernel for the MAC address. 610bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain *address = GetMACAddressFromKernel(interface_index); 611bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain return !address->IsEmpty(); 612bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain} 613bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain 614bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary MorainByteString DeviceInfo::GetMACAddressFromKernel(int interface_index) const { 6154178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain const Info *info = GetInfo(interface_index); 6164178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain if (!info) { 6174178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain return ByteString(); 6184178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain } 6194178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain 6204178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain const int fd = sockets_->Socket(PF_INET, SOCK_DGRAM, 0); 621bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain if (fd < 0) { 622bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain LOG(ERROR) << __func__ << ": Unable to open socket: " << fd; 6234178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain return ByteString(); 624bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain } 6254178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain 6264178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain ScopedSocketCloser socket_closer(sockets_.get(), fd); 627bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain struct ifreq ifr; 628bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain memset(&ifr, 0, sizeof(ifr)); 629bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain ifr.ifr_ifindex = interface_index; 6304178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain strcpy(ifr.ifr_ifrn.ifrn_name, info->name.c_str()); 6314178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain int err = sockets_->Ioctl(fd, SIOCGIFHWADDR, &ifr); 632bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain if (err < 0) { 633bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain LOG(ERROR) << __func__ << ": Unable to read MAC address: " << errno; 6344178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain return ByteString(); 635bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain } 6364178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain 6374178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain return ByteString(ifr.ifr_hwaddr.sa_data, IFHWADDRLEN); 638e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov} 639e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov 6406950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewartbool DeviceInfo::GetMACAddressOfPeer(int interface_index, 6416950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart const IPAddress &peer, 6426950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart ByteString *mac_address) const { 6436950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart const Info *info = GetInfo(interface_index); 6446950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart if (!info || !peer.IsValid()) { 6456950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart return false; 6466950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart } 6476950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 6486950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart if (peer.family() != IPAddress::kFamilyIPv4) { 6496950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart NOTIMPLEMENTED() << ": only implemented for IPv4"; 6506950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart return false; 6516950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart } 6526950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 6536950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart const int fd = sockets_->Socket(PF_INET, SOCK_DGRAM, 0); 6546950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart if (fd < 0) { 6556950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart LOG(ERROR) << __func__ << ": Unable to open socket: " << fd; 6566950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart return false; 6576950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart } 6586950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 6596950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart ScopedSocketCloser socket_closer(sockets_.get(), fd); 6606950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart struct arpreq areq; 6616950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart memset(&areq, 0, sizeof(areq)); 6626950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 6636950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart strncpy(areq.arp_dev, info->name.c_str(), sizeof(areq.arp_dev) - 1); 6646950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart areq.arp_dev[sizeof(areq.arp_dev) - 1] = '\0'; 6656950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 6666950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart struct sockaddr_in *protocol_address = 6676950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart reinterpret_cast<struct sockaddr_in *>(&areq.arp_pa); 6686950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart protocol_address->sin_family = AF_INET; 6696950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart CHECK_EQ(sizeof(protocol_address->sin_addr.s_addr), peer.GetLength()); 6706950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart memcpy(&protocol_address->sin_addr.s_addr, peer.address().GetConstData(), 6716950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart sizeof(protocol_address->sin_addr.s_addr)); 6726950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 6736950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart struct sockaddr_in *hardware_address = 6746950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart reinterpret_cast<struct sockaddr_in *>(&areq.arp_ha); 6756950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart hardware_address->sin_family = ARPHRD_ETHER; 6766950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 6776950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart int err = sockets_->Ioctl(fd, SIOCGARP, &areq); 6786950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart if (err < 0) { 6796950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart LOG(ERROR) << __func__ << ": Unable to perform ARP lookup: " << errno; 6806950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart return false; 6816950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart } 6826950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 6836950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart ByteString peer_address(areq.arp_ha.sa_data, IFHWADDRLEN); 6846950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 6856950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart if (peer_address.IsZero()) { 6866950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart LOG(INFO) << __func__ << ": ARP lookup is still in progress"; 6876950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart return false; 6886950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart } 6896950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 6906950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart CHECK(mac_address); 6916950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart *mac_address = peer_address; 6926950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart return true; 6936950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart} 6946950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 6959a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewartbool DeviceInfo::GetAddresses(int interface_index, 6969a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart vector<AddressData> *addresses) const { 6979a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart const Info *info = GetInfo(interface_index); 6989a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (!info) { 6999a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart return false; 7009a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 7019a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart *addresses = info->ip_addresses; 7029a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart return true; 7039a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart} 7049a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 7059a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewartvoid DeviceInfo::FlushAddresses(int interface_index) const { 706fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << "(" << interface_index << ")"; 7079a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart const Info *info = GetInfo(interface_index); 7089a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (!info) { 7099a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart return; 7109a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 7116db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart for (const auto &address_info : info->ip_addresses) { 7126db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart if (address_info.address.family() == IPAddress::kFamilyIPv4 || 7136db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart (address_info.scope == RT_SCOPE_UNIVERSE && 7146db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart (address_info.flags & ~IFA_F_TEMPORARY) == 0)) { 7158c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << __func__ << ": removing ip address " 7166db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart << address_info.address.ToString() 7178c116a90d3a3536430b808b15e73275060918434Paul Stewart << " from interface " << interface_index; 7186db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart rtnl_handler_->RemoveInterfaceAddress(interface_index, 7196db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart address_info.address); 7209a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 7219a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 7229a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart} 7239a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 72405a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewartbool DeviceInfo::HasOtherAddress( 72505a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart int interface_index, const IPAddress &this_address) const { 72605a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart SLOG(Device, 3) << __func__ << "(" << interface_index << ")"; 72705a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart const Info *info = GetInfo(interface_index); 72805a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart if (!info) { 72905a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart return false; 73005a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } 73105a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart bool has_other_address = false; 73205a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart bool has_this_address = false; 733a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart for (const auto &local_address : info->ip_addresses) { 734a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart if (local_address.address.family() != this_address.family()) { 73505a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart continue; 73605a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } 737a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart if (local_address.address.address().Equals(this_address.address())) { 73805a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart has_this_address = true; 73905a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } else if (this_address.family() == IPAddress::kFamilyIPv4) { 74005a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart has_other_address = true; 741a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart } else if ((local_address.scope == RT_SCOPE_UNIVERSE && 742a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart (local_address.flags & IFA_F_TEMPORARY) == 0)) { 74305a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart has_other_address = true; 74405a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } 74505a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } 74605a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart return has_other_address && !has_this_address; 74705a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart} 74805a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart 749d55f6ae45047f984457508d78c70abcd837307eaPaul Stewartbool DeviceInfo::GetPrimaryIPv6Address(int interface_index, 750d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart IPAddress *address) { 751d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart const Info *info = GetInfo(interface_index); 752d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart if (!info) { 753d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart return false; 754d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart } 755d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart bool has_temporary_address = false; 756d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart bool has_address = false; 757d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart for (const auto &local_address : info->ip_addresses) { 758d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart if (local_address.address.family() != IPAddress::kFamilyIPv6 || 759d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart local_address.scope != RT_SCOPE_UNIVERSE) { 760d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart continue; 761d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart } 762d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart 763d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart // Prefer temporary addresses to non-temporary addresses to match the 764d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart // kernel's preference. 765d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart bool is_temporary_address = ((local_address.flags & IFA_F_TEMPORARY) != 0); 766d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart if (has_temporary_address && !is_temporary_address) { 767d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart continue; 768d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart } 769d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart 770d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart *address = local_address.address; 771d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart has_temporary_address = is_temporary_address; 772d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart has_address = true; 773d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart } 774d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart 775d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart return has_address; 776d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart} 777d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart 778a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewartbool DeviceInfo::HasDirectConnectivityTo( 779a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart int interface_index, const IPAddress &address) const { 780a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart SLOG(Device, 3) << __func__ << "(" << interface_index << ")"; 781a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart const Info *info = GetInfo(interface_index); 782a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart if (!info) { 783a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart return false; 784a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart } 785a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart 786a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart for (const auto &local_address : info->ip_addresses) { 787a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart if (local_address.address.family() == address.family() && 788a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart local_address.address.CanReachAddress(address)) { 789a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart return true; 790a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart } 791a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart } 792a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart 793a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart return false; 794a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart} 795a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart 796e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkovbool DeviceInfo::GetFlags(int interface_index, unsigned int *flags) const { 797e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov const Info *info = GetInfo(interface_index); 798e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov if (!info) { 799e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov return false; 800e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov } 801e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov *flags = info->flags; 802e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov return true; 803e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov} 804e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov 8051ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewartbool DeviceInfo::GetByteCounts(int interface_index, 8061ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart uint64 *rx_bytes, 8071ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart uint64 *tx_bytes) const { 8081ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart const Info *info = GetInfo(interface_index); 8091ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart if (!info) { 8101ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart return false; 8111ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart } 8121ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart *rx_bytes = info->rx_bytes; 8131ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart *tx_bytes = info->tx_bytes; 8141ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart return true; 8151ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart} 8161ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 817ca6abd4635507fa5b8f4b8819a37819fb560c464Paul Stewartbool DeviceInfo::CreateTunnelInterface(string *interface_name) const { 818cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart int fd = HANDLE_EINTR(open(kTunDeviceName, O_RDWR)); 819cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart if (fd < 0) { 820cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart PLOG(ERROR) << "failed to open " << kTunDeviceName; 821cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return false; 822cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 823cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart file_util::ScopedFD scoped_fd(&fd); 824cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 825cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart struct ifreq ifr; 826cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart memset(&ifr, 0, sizeof(ifr)); 827cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart ifr.ifr_flags = IFF_TUN | IFF_NO_PI; 828cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart if (HANDLE_EINTR(ioctl(fd, TUNSETIFF, &ifr))) { 829cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart PLOG(ERROR) << "failed to create tunnel interface"; 830cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return false; 831cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 832cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 833cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart if (HANDLE_EINTR(ioctl(fd, TUNSETPERSIST, 1))) { 834cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart PLOG(ERROR) << "failed to set tunnel interface to be persistent"; 835cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return false; 836cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 837cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 838cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart *interface_name = string(ifr.ifr_name); 839cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 840cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return true; 841cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart} 842cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 843ca6abd4635507fa5b8f4b8819a37819fb560c464Paul Stewartbool DeviceInfo::DeleteInterface(int interface_index) const { 844cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return rtnl_handler_->RemoveInterface(interface_index); 845cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart} 846cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 847e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkovconst DeviceInfo::Info *DeviceInfo::GetInfo(int interface_index) const { 848e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov map<int, Info>::const_iterator iter = infos_.find(interface_index); 849e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov if (iter == infos_.end()) { 850e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov return NULL; 851e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov } 852e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov return &iter->second; 853e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov} 854e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov 855e6193c042652831cac90c3bbf2233877754b1eefDarin Petkovvoid DeviceInfo::RemoveInfo(int interface_index) { 856e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov map<int, Info>::iterator iter = infos_.find(interface_index); 857e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov if (iter != infos_.end()) { 858fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << "Removing info for device index: " << interface_index; 859e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov if (iter->second.device.get()) { 860e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov manager_->DeregisterDevice(iter->second.device); 861e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov } 862f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov indices_.erase(iter->second.name); 863e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov infos_.erase(iter); 864050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.erase(interface_index); 86547009f8d7a6fbc257a1bb1288a01405d034bd13fmukesh agrawal } else { 866fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__ << ": Unknown device index: " 867fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << interface_index; 868b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 8690af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 8700af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 8712aa9707f114ab8166f45df5726bf05278df2aef6Chris Masonevoid DeviceInfo::LinkMsgHandler(const RTNLMessage &msg) { 8729a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart DCHECK(msg.type() == RTNLMessage::kTypeLink); 8739a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (msg.mode() == RTNLMessage::kModeAdd) { 8742aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone AddLinkMsgHandler(msg); 8759a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else if (msg.mode() == RTNLMessage::kModeDelete) { 8762aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone DelLinkMsgHandler(msg); 8772aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone } else { 8782aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone NOTREACHED(); 879b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 8800af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 8810af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 8829a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewartvoid DeviceInfo::AddressMsgHandler(const RTNLMessage &msg) { 883fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << __func__; 8849a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart DCHECK(msg.type() == RTNLMessage::kTypeAddress); 8859a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart int interface_index = msg.interface_index(); 8869a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (!ContainsKey(infos_, interface_index)) { 8878c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << "Got advance address information for unknown index " 8888c116a90d3a3536430b808b15e73275060918434Paul Stewart << interface_index; 8898c116a90d3a3536430b808b15e73275060918434Paul Stewart infos_[interface_index].has_addresses_only = true; 8909a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 8919a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart const RTNLMessage::AddressStatus &status = msg.address_status(); 8929a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart IPAddress address(msg.family(), 893682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan msg.HasAttribute(IFA_LOCAL) ? 894682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan msg.GetAttribute(IFA_LOCAL) : msg.GetAttribute(IFA_ADDRESS), 8959a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart status.prefix_len); 8969a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 897682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan SLOG_IF(Device, 2, msg.HasAttribute(IFA_LOCAL)) 898682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan << "Found local address attribute for interface " << interface_index; 899682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan 9009a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart vector<AddressData> &address_list = infos_[interface_index].ip_addresses; 9019a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart vector<AddressData>::iterator iter; 9029a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart for (iter = address_list.begin(); iter != address_list.end(); ++iter) { 9039a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (address.Equals(iter->address)) { 9049a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart break; 9059a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 9069a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 9079a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (iter != address_list.end()) { 9089a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (msg.mode() == RTNLMessage::kModeDelete) { 909fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan SLOG(Device, 2) << "Delete address for interface " << interface_index; 9109a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart address_list.erase(iter); 9119a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else { 9129a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart iter->flags = status.flags; 9139a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart iter->scope = status.scope; 9149a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 9159a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else if (msg.mode() == RTNLMessage::kModeAdd) { 9169a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart address_list.push_back(AddressData(address, status.flags, status.scope)); 9178c116a90d3a3536430b808b15e73275060918434Paul Stewart SLOG(Device, 2) << "Add address " << address.ToString() 9188c116a90d3a3536430b808b15e73275060918434Paul Stewart << " for interface " << interface_index; 9199a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 920d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart 921d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart DeviceRefPtr device = GetDevice(interface_index); 922d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart if (device && address.family() == IPAddress::kFamilyIPv6 && 923d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart status.scope == RT_SCOPE_UNIVERSE) { 924d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart device->OnIPv6AddressChanged(); 925d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart } 9269a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart} 9279a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 928050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewartvoid DeviceInfo::DelayDeviceCreation(int interface_index) { 929050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.insert(interface_index); 930050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_callback_.Reset( 931050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart Bind(&DeviceInfo::DelayedDeviceCreationTask, AsWeakPtr())); 932050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart dispatcher_->PostDelayedTask(delayed_devices_callback_.callback(), 933050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart kDelayedDeviceCreationSeconds * 1000); 934050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart} 935050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 936050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart// Re-evaluate the technology type for each delayed device. 937050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewartvoid DeviceInfo::DelayedDeviceCreationTask() { 938050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart while (!delayed_devices_.empty()) { 939050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart set<int>::iterator it = delayed_devices_.begin(); 940050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart int dev_index = *it; 941050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.erase(it); 942050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 943050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DCHECK(ContainsKey(infos_, dev_index)); 944050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DCHECK(!GetDevice(dev_index)); 945050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 946050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart const string &link_name = infos_[dev_index].name; 947050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart Technology::Identifier technology = GetDeviceTechnology(link_name); 948050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 949050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart if (technology == Technology::kCDCEthernet) { 950050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart LOG(INFO) << "In " << __func__ << ": device " << link_name 951050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart << " is now assumed to be regular Ethernet."; 952050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart technology = Technology::kEthernet; 953050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } else if (technology != Technology::kCellular) { 954050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart LOG(WARNING) << "In " << __func__ << ": device " << link_name 955050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart << " is unexpected technology " 956050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart << Technology::NameFromIdentifier(technology); 957050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } 958050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart string address = 959050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart StringToLowerASCII(infos_[dev_index].mac_address.HexEncode()); 960050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DCHECK(!address.empty()); 961050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 962050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DeviceRefPtr device = CreateDevice(link_name, address, dev_index, 963050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart technology); 964050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart if (device) { 965050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart RegisterDevice(device); 966050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } 967050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } 968050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart} 969050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 9701ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewartvoid DeviceInfo::RetrieveLinkStatistics(int interface_index, 9711ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart const RTNLMessage &msg) { 9721ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart if (!msg.HasAttribute(IFLA_STATS64)) { 9731ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart return; 9741ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart } 9751ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart ByteString stats_bytes(msg.GetAttribute(IFLA_STATS64)); 9761ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart struct rtnl_link_stats64 stats; 9771ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart if (stats_bytes.GetLength() < sizeof(stats)) { 9781ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart LOG(WARNING) << "Link statistics size is too small: " 9791ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart << stats_bytes.GetLength() << " < " << sizeof(stats); 9801ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart return; 9811ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart } 9821ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 9831ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart memcpy(&stats, stats_bytes.GetConstData(), sizeof(stats)); 9841ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart SLOG(Device, 2) << "Link statistics for " 9851ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart << " interface index " << interface_index << ": " 9861ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart << "receive: " << stats.rx_bytes << "; " 9871ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart << "transmit: " << stats.tx_bytes << "."; 9881ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart infos_[interface_index].rx_bytes = stats.rx_bytes; 9891ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart infos_[interface_index].tx_bytes = stats.tx_bytes; 9901ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart} 9911ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 9921ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewartvoid DeviceInfo::RequestLinkStatistics() { 9931ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart rtnl_handler_->RequestDump(RTNLHandler::kRequestLink); 9941ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart dispatcher_->PostDelayedTask(request_link_statistics_callback_.callback(), 995b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan kRequestLinkStatisticsIntervalMilliseconds); 9961ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart} 9971ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 9982ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewartvoid DeviceInfo::GetWiFiInterfaceInfo(int interface_index) { 9992ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart GetInterfaceMessage msg; 10002ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart if (!msg.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX, 10012ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart interface_index)) { 10022ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(ERROR) << "Unable to set interface index attribute for " 10032ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart "GetInterface message. Interface type cannot be " 10042ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart "determined!"; 10052ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 10062ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 10077347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie netlink_manager_->SendNl80211Message( 10087347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie &msg, 10097347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie Bind(&DeviceInfo::OnWiFiInterfaceInfoReceived, AsWeakPtr()), 10107347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie Bind(&NetlinkManager::OnNetlinkMessageError)); 10112ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart} 10122ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart 10137347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrievoid DeviceInfo::OnWiFiInterfaceInfoReceived(const Nl80211Message &msg) { 10147347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie if (msg.command() != NL80211_CMD_NEW_INTERFACE) { 10152ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(ERROR) << "Message is not a new interface response"; 10162ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 10172ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 10182ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart 10192ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart uint32_t interface_index; 10207347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFINDEX, 10217347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie &interface_index)) { 10222ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(ERROR) << "Message contains no interface index"; 10232ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 10242ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 10252ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart uint32_t interface_type; 10267347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFTYPE, 10277347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie &interface_type)) { 10282ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(ERROR) << "Message contains no interface type"; 10292ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 10302ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 10312ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart const Info *info = GetInfo(interface_index); 10322ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart if (!info) { 10332ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(ERROR) << "Could not find device info for interface index " 10342ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << interface_index; 10352ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 10362ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 10372ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart if (info->device) { 10382ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(ERROR) << "Device already created for interface index " 10392ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << interface_index; 10402ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 10412ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 10422ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart if (interface_type != NL80211_IFTYPE_STATION) { 10432ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(INFO) << "Ignoring WiFi device " 10442ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << info->name 10452ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << " at interface index " 10462ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << interface_index 10472ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << " since it is not in station mode."; 10482ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 10492ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 10502ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(INFO) << "Creating WiFi device for station mode interface " 10512ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << info->name 10522ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << " at interface index " 10532ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << interface_index; 10542ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart string address = StringToLowerASCII(info->mac_address.HexEncode()); 10552ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart DeviceRefPtr device = 10562ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart new WiFi(control_interface_, dispatcher_, metrics_, manager_, 10572ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart info->name, address, interface_index); 10582ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart device->EnableIPv6Privacy(); 10592ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart RegisterDevice(device); 10602ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart} 10612ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart 10620af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} // namespace shill 1063