1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2012 The Android Open Source Project 3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License"); 5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License. 6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at 7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// http://www.apache.org/licenses/LICENSE-2.0 9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software 11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS, 12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and 14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License. 15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 160af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 17cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include "shill/device_info.h" 180af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 190af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart#include <arpa/inet.h> 20cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <fcntl.h> 21cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <linux/if_tun.h> 220af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart#include <linux/netlink.h> 230af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart#include <linux/rtnetlink.h> 24cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <net/if.h> 25cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <net/if_arp.h> 26cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <netinet/ether.h> 27cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <string.h> 28cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <sys/ioctl.h> 29cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <sys/socket.h> 30cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <time.h> 31cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart#include <unistd.h> 32cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 330af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart#include <string> 340af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 353e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood#include <base/bind.h> 36a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/files/file_enumerator.h> 3711c213f3cf64f27a0e42ee6da95e98bd1d4b3202Ben Chan#include <base/files/file_util.h> 386fbf64f493a9aae7d743888039c61a57386203dbBen Chan#include <base/files/scoped_file.h> 393e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood#include <base/stl_util.h> 40a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_number_conversions.h> 41a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_util.h> 42a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/stringprintf.h> 430af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 440af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart#include "shill/control_interface.h" 459be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone#include "shill/device.h" 46a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart#include "shill/device_stub.h" 4787602518c59af2f9e8288d81a1f877dd80f24433Ben Chan#include "shill/ethernet/ethernet.h" 4887602518c59af2f9e8288d81a1f877dd80f24433Ben Chan#include "shill/ethernet/virtio_ethernet.h" 49b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley#include "shill/logging.h" 50b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart#include "shill/manager.h" 518d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/ndisc.h" 528d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/rtnl_handler.h" 538d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/rtnl_listener.h" 548d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/rtnl_message.h" 558d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/shill_time.h" 568d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/sockets.h" 578c116a90d3a3536430b808b15e73275060918434Paul Stewart#include "shill/routing_table.h" 58487b8bfc46a91e29bb23aaf3c59cfe67033bfc8bChris Masone#include "shill/service.h" 592240e8c03451c6b6f21eb8944d8a1c0747ac10b3Ben Chan#include "shill/vpn/vpn_provider.h" 601a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu 611a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI) 621a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#include "shill/net/netlink_attribute.h" 631a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#include "shill/net/netlink_manager.h" 641a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#include "shill/net/nl80211_message.h" 65d6a8b519e3057f52313e502f502a4819a942e089Ben Chan#include "shill/wifi/wifi.h" 661a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif // DISABLE_WIFI 670af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 683e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Bind; 69a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chanusing base::FileEnumerator; 700e1cdeae24dd678a5fe27c840802582c0ca45ec0Albert Chaulkusing base::FilePath; 718f1c835d879f82261a08257eb6f9677e6be51fdaThieu Leusing base::StringPrintf; 723e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Unretained; 73e6193c042652831cac90c3bbf2233877754b1eefDarin Petkovusing std::map; 74050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewartusing std::set; 750af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewartusing std::string; 769a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewartusing std::vector; 770af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 780af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewartnamespace shill { 79b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 80c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinnamespace Logging { 81c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinstatic auto kModuleLogScope = ScopeLogger::kDevice; 82a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartstatic string ObjectID(const DeviceInfo* d) { return "(device_info)"; } 83c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein} 84c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein 85b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart// static 86abc5403270e26fa898181301911a905758f8d758Jason Glasgowconst char DeviceInfo::kModemPseudoDeviceNamePrefix[] = "pseudomodem"; 87e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wileyconst char DeviceInfo::kEthernetPseudoDeviceNamePrefix[] = "pseudoethernet"; 8883d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewartconst char DeviceInfo::kIgnoredDeviceNamePrefix[] = "veth"; 89ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kDeviceInfoRoot[] = "/sys/class/net"; 904e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chanconst char DeviceInfo::kDriverCdcEther[] = "cdc_ether"; 914eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chanconst char DeviceInfo::kDriverCdcNcm[] = "cdc_ncm"; 924e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chanconst char DeviceInfo::kDriverGdmWiMax[] = "gdm_wimax"; 9393a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawalconst char DeviceInfo::kDriverVirtioNet[] = "virtio_net"; 94ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceUevent[] = "uevent"; 959364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewartconst char DeviceInfo::kInterfaceUeventWifiSignature[] = "DEVTYPE=wlan\n"; 96ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceDevice[] = "device"; 97ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceDriver[] = "device/driver"; 98ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceTunFlags[] = "tun_flags"; 99ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewartconst char DeviceInfo::kInterfaceType[] = "type"; 100a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartconst char* DeviceInfo::kModemDrivers[] = { 101b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart "gobi", 102b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart "QCUSBNet2k", 103226d46a2e03d316e8a36f93cb261f708219aef07Ben Chan "GobiNet", 1040f90e0b62322ae95c1a419d5efef47438b4617c9Ben Chan "cdc_mbim", 105226d46a2e03d316e8a36f93cb261f708219aef07Ben Chan "qmi_wwan" 106b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart}; 107cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewartconst char DeviceInfo::kTunDeviceName[] = "/dev/net/tun"; 108050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewartconst int DeviceInfo::kDelayedDeviceCreationSeconds = 5; 109b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chanconst int DeviceInfo::kRequestLinkStatisticsIntervalMilliseconds = 20000; 110b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 111a794cd60a7339d576ea2eed263a4f0a20fb255afPaul StewartDeviceInfo::DeviceInfo(ControlInterface* control_interface, 112a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart EventDispatcher* dispatcher, 113a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart Metrics* metrics, 114a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart Manager* manager) 115a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart : control_interface_(control_interface), 116a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart dispatcher_(dispatcher), 1173426c8fc7a3943f2d8fcb2ec78f0593088b42bedThieu Le metrics_(metrics), 118a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart manager_(manager), 1193e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood link_callback_(Bind(&DeviceInfo::LinkMsgHandler, Unretained(this))), 1203e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood address_callback_(Bind(&DeviceInfo::AddressMsgHandler, Unretained(this))), 1219855170e6e2de08db343640c82795c9b4020a166Peter Qiu rdnss_callback_(Bind(&DeviceInfo::RdnssMsgHandler, Unretained(this))), 122ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart device_info_root_(kDeviceInfoRoot), 1238c116a90d3a3536430b808b15e73275060918434Paul Stewart routing_table_(RoutingTable::GetInstance()), 1244178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain rtnl_handler_(RTNLHandler::GetInstance()), 1251a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI) 1262ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart netlink_manager_(NetlinkManager::GetInstance()), 1271a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif // DISABLE_WIFI 1289855170e6e2de08db343640c82795c9b4020a166Peter Qiu sockets_(new Sockets()), 1299855170e6e2de08db343640c82795c9b4020a166Peter Qiu time_(Time::GetInstance()) { 1300af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 1310af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 132a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul StewartDeviceInfo::~DeviceInfo() {} 1330af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 134a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid DeviceInfo::AddDeviceToBlackList(const string& device_name) { 1358f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal black_list_.insert(device_name); 1367e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu // Remove the current device info if it exist, since it will be out-dated. 1377e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu RemoveInfo(GetIndex(device_name)); 1387e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu // Request link info update to allow device info to be recreated. 139ebd709e7d7519915930404be7120cd8070b432c4Peter Qiu if (manager_->running()) { 140ebd709e7d7519915930404be7120cd8070b432c4Peter Qiu rtnl_handler_->RequestDump(RTNLHandler::kRequestLink); 141ebd709e7d7519915930404be7120cd8070b432c4Peter Qiu } 1427e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu} 1437e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu 144a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid DeviceInfo::RemoveDeviceFromBlackList(const string& device_name) { 1457e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu black_list_.erase(device_name); 1467e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu // Remove the current device info if it exist, since it will be out-dated. 1477e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu RemoveInfo(GetIndex(device_name)); 1487e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu // Request link info update to allow device info to be recreated. 149ebd709e7d7519915930404be7120cd8070b432c4Peter Qiu if (manager_->running()) { 150ebd709e7d7519915930404be7120cd8070b432c4Peter Qiu rtnl_handler_->RequestDump(RTNLHandler::kRequestLink); 151ebd709e7d7519915930404be7120cd8070b432c4Peter Qiu } 1528f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal} 1538f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal 154a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartbool DeviceInfo::IsDeviceBlackListed(const string& device_name) { 1555e628a5c722c196ad240af0ff3c717e9613d3ef5Eric Shienbrood return ContainsKey(black_list_, device_name); 1565e628a5c722c196ad240af0ff3c717e9613d3ef5Eric Shienbrood} 1575e628a5c722c196ad240af0ff3c717e9613d3ef5Eric Shienbrood 158a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewartvoid DeviceInfo::Start() { 159a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart link_listener_.reset( 1603e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood new RTNLListener(RTNLHandler::kRequestLink, link_callback_)); 1619a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart address_listener_.reset( 1623e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood new RTNLListener(RTNLHandler::kRequestAddr, address_callback_)); 1639855170e6e2de08db343640c82795c9b4020a166Peter Qiu rdnss_listener_.reset( 1649855170e6e2de08db343640c82795c9b4020a166Peter Qiu new RTNLListener(RTNLHandler::kRequestRdnss, rdnss_callback_)); 1659a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart rtnl_handler_->RequestDump(RTNLHandler::kRequestLink | 1669a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart RTNLHandler::kRequestAddr); 1671ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart request_link_statistics_callback_.Reset( 1681ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart Bind(&DeviceInfo::RequestLinkStatistics, AsWeakPtr())); 1691ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart dispatcher_->PostDelayedTask(request_link_statistics_callback_.callback(), 170b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan kRequestLinkStatisticsIntervalMilliseconds); 1710af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 1720af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 173a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewartvoid DeviceInfo::Stop() { 1749a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart link_listener_.reset(); 1759a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart address_listener_.reset(); 1768c116a90d3a3536430b808b15e73275060918434Paul Stewart infos_.clear(); 1771ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart request_link_statistics_callback_.Cancel(); 178050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_callback_.Cancel(); 179050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.clear(); 1800af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 1810af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 1825086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chanvector<string> DeviceInfo::GetUninitializedTechnologies() const { 1835086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan set<string> unique_technologies; 184b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray set<Technology::Identifier> initialized_technologies; 185a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart for (const auto& info : infos_) { 1866db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart Technology::Identifier technology = info.second.technology; 1876db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart if (info.second.device) { 188b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray // If there is more than one device for a technology and at least 189b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray // one of them has been initialized, make sure that it doesn't get 190b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray // listed as uninitialized. 191b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray initialized_technologies.insert(technology); 192b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray unique_technologies.erase(Technology::NameFromIdentifier(technology)); 193b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray continue; 194b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray } 195b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray if (Technology::IsPrimaryConnectivityTechnology(technology) && 196b00c13d6444ba67154acffec537bdb466099f7b1Arman Uguray !ContainsKey(initialized_technologies, technology)) 1975086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan unique_technologies.insert(Technology::NameFromIdentifier(technology)); 1985086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan } 1995086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan return vector<string>(unique_technologies.begin(), unique_technologies.end()); 2005086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan} 2015086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan 202a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid DeviceInfo::RegisterDevice(const DeviceRefPtr& device) { 203c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << "(" << device->link_name() << ", " 204c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << device->interface_index() << ")"; 2058ce932a8ebf3af11f17b814c4e544a305607afcaChristopher Grant device->Initialize(); 206050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.erase(device->interface_index()); 207e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov CHECK(!GetDevice(device->interface_index()).get()); 208e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov infos_[device->interface_index()].device = device; 2099abd6749e69712e9ec4ed4a54fbba243f16ae7f3Thieu Le if (metrics_->IsDeviceRegistered(device->interface_index(), 2109abd6749e69712e9ec4ed4a54fbba243f16ae7f3Thieu Le device->technology())) { 2119abd6749e69712e9ec4ed4a54fbba243f16ae7f3Thieu Le metrics_->NotifyDeviceInitialized(device->interface_index()); 2129abd6749e69712e9ec4ed4a54fbba243f16ae7f3Thieu Le } else { 2139abd6749e69712e9ec4ed4a54fbba243f16ae7f3Thieu Le metrics_->RegisterDevice(device->interface_index(), device->technology()); 2149abd6749e69712e9ec4ed4a54fbba243f16ae7f3Thieu Le } 2155086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan if (Technology::IsPrimaryConnectivityTechnology(device->technology())) { 2166f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov manager_->RegisterDevice(device); 2176f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov } 2186f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov} 2196f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov 220a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid DeviceInfo::DeregisterDevice(const DeviceRefPtr& device) { 221e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow int interface_index = device->interface_index(); 222e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow 223c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << "(" << device->link_name() << ", " 224c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << interface_index << ")"; 225da798623389b981130cd1922f880736f1e0e36baJoshua Kroll CHECK((device->technology() == Technology::kCellular) || 226da798623389b981130cd1922f880736f1e0e36baJoshua Kroll (device->technology() == Technology::kWiMax)); 227e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow 228e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow // Release reference to the device 229e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow map<int, Info>::iterator iter = infos_.find(interface_index); 230e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow if (iter != infos_.end()) { 231c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Removing device from info for index: " 232c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << interface_index; 233e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow manager_->DeregisterDevice(device); 234e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow // Release the reference to the device, but maintain the mapping 235e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow // for the index. That will be cleaned up by an RTNL message. 236cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan iter->second.device = nullptr; 237e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow } 238c8078a6c44d0e30b71642856ef46e0cf6c5edb46Thieu Le metrics_->DeregisterDevice(device->interface_index()); 239e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow} 240e908949fa87c32ed97073d3e79fb7f450541cb95Jason Glasgow 241a794cd60a7339d576ea2eed263a4f0a20fb255afPaul StewartFilePath DeviceInfo::GetDeviceInfoPath(const string& iface_name, 242a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const string& path_name) { 243ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart return device_info_root_.Append(iface_name).Append(path_name); 244ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart} 245ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart 246a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartbool DeviceInfo::GetDeviceInfoContents(const string& iface_name, 247a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const string& path_name, 248a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart string* contents_out) { 249a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan return base::ReadFileToString(GetDeviceInfoPath(iface_name, path_name), 250a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan contents_out); 251ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart} 252a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart 253a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartbool DeviceInfo::GetDeviceInfoSymbolicLink(const string& iface_name, 254a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const string& path_name, 255a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart FilePath* path_out) { 256a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan return base::ReadSymbolicLink(GetDeviceInfoPath(iface_name, path_name), 257a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan path_out); 258ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart} 259ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart 260fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul StewartTechnology::Identifier DeviceInfo::GetDeviceTechnology( 261a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const string& iface_name) { 262ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart string type_string; 2632ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart int arp_type = ARPHRD_VOID; 264ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (GetDeviceInfoContents(iface_name, kInterfaceType, &type_string) && 265a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan base::TrimString(type_string, "\n", &type_string) && 266ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart !base::StringToInt(type_string, &arp_type)) { 267ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart arp_type = ARPHRD_VOID; 268ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart } 269ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart 2709364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart string contents; 271ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (!GetDeviceInfoContents(iface_name, kInterfaceUevent, &contents)) { 272050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart LOG(INFO) << StringPrintf("%s: device %s has no uevent file", 273050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart __func__, iface_name.c_str()); 274fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart return Technology::kUnknown; 2759364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart } 276b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 2778f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // If the "uevent" file contains the string "DEVTYPE=wlan\n" at the 2788f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // start of the file or after a newline, we can safely assume this 2798f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // is a wifi device. 2809364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart if (contents.find(kInterfaceUeventWifiSignature) != string::npos) { 281c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) 282fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << StringPrintf("%s: device %s has wifi signature in uevent file", 283fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str()); 284ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (arp_type == ARPHRD_IEEE80211_RADIOTAP) { 285c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << StringPrintf("%s: wifi device %s is in monitor mode", 286c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein __func__, iface_name.c_str()); 2872001a42edf1d42ec828a9baf3157496c20fefd49Paul Stewart return Technology::kWiFiMonitor; 2882001a42edf1d42ec828a9baf3157496c20fefd49Paul Stewart } 289fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart return Technology::kWifi; 2909364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart } 291b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 2927904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow // Special case for pseudo modems which are used for testing 2937904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow if (iface_name.find(kModemPseudoDeviceNamePrefix) == 0) { 294c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << StringPrintf( 2957904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow "%s: device %s is a pseudo modem for testing", 2967904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow __func__, iface_name.c_str()); 2977904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow return Technology::kCellular; 2987904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow } 2997904d1443656999fd0a7faaf247aad05a7b3e0a6Jason Glasgow 300e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley // Special case for pseudo ethernet devices which are used for testing. 301e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley if (iface_name.find(kEthernetPseudoDeviceNamePrefix) == 0) { 302c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << StringPrintf( 303e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley "%s: device %s is a virtual ethernet device for testing", 304e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley __func__, iface_name.c_str()); 305e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley return Technology::kEthernet; 306e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley } 307e049cc5ad0db026c66cf448cecc48330b9e59360Christopher Wiley 30883d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewart // Special case for devices which should be ignored. 30983d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewart if (iface_name.find(kIgnoredDeviceNamePrefix) == 0) { 31083d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewart SLOG(this, 2) << StringPrintf( 31183d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewart "%s: device %s should be ignored", __func__, iface_name.c_str()); 31283d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewart return Technology::kUnknown; 31383d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewart } 31483d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewart 3159364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart FilePath driver_path; 316ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (!GetDeviceInfoSymbolicLink(iface_name, kInterfaceDriver, &driver_path)) { 317c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << StringPrintf("%s: device %s has no device symlink", 318c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein __func__, iface_name.c_str()); 319ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (arp_type == ARPHRD_LOOPBACK) { 320c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << StringPrintf("%s: device %s is a loopback device", 321c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein __func__, iface_name.c_str()); 322e81eb700f66563cb695b6e3682f20ac5a0cdb8c0Paul Stewart return Technology::kLoopback; 323e81eb700f66563cb695b6e3682f20ac5a0cdb8c0Paul Stewart } 324ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (arp_type == ARPHRD_PPP) { 325c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << StringPrintf("%s: device %s is a ppp device", 326c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein __func__, iface_name.c_str()); 327ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart return Technology::kPPP; 328ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart } 329ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart string tun_flags_str; 330cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart int tun_flags = 0; 331ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart if (GetDeviceInfoContents(iface_name, kInterfaceTunFlags, &tun_flags_str) && 332a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan base::TrimString(tun_flags_str, "\n", &tun_flags_str) && 333ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart base::HexStringToInt(tun_flags_str, &tun_flags) && 334cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart (tun_flags & IFF_TUN)) { 335c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << StringPrintf("%s: device %s is tun device", 336c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein __func__, iface_name.c_str()); 337cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return Technology::kTunnel; 338cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 339da8cbeef4735df05dd3a9a069c6ecccf37803e60Paul Stewart 34083d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewart // We don't know what sort of device it is. 341a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart return Technology::kNoDeviceSymlink; 3429364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart } 343b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 3449364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart string driver_name(driver_path.BaseName().value()); 3458f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // See if driver for this interface is in a list of known modem driver names. 3468f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le for (size_t modem_idx = 0; modem_idx < arraysize(kModemDrivers); 3478f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le ++modem_idx) { 3489364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart if (driver_name == kModemDrivers[modem_idx]) { 349c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) 350fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << StringPrintf("%s: device %s is matched with modem driver %s", 351fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan __func__, iface_name.c_str(), driver_name.c_str()); 3529364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart return Technology::kCellular; 3539364c4c9a1e1f4bbb59c8d32ac97c928505fc8cbPaul Stewart } 354b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 3550af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 3564e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan if (driver_name == kDriverGdmWiMax) { 357c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << StringPrintf("%s: device %s is a WiMAX device", 358c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein __func__, iface_name.c_str()); 3594e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan return Technology::kWiMax; 3604e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan } 3614e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan 3624eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // For cdc_ether / cdc_ncm devices, make sure it's a modem because this driver 3638f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // can be used for other ethernet devices. 3644eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan if (driver_name == kDriverCdcEther || driver_name == kDriverCdcNcm) { 3654eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan if (IsCdcEthernetModemDevice(iface_name)) { 3664eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan LOG(INFO) << StringPrintf("%s: device %s is a %s modem device", __func__, 36735ec8408d8b40d74693edc32495b392a525dc238mukesh agrawal iface_name.c_str(), driver_name.c_str()); 368050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart return Technology::kCellular; 369050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } 370c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << StringPrintf("%s: device %s is a %s device", __func__, 371c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein iface_name.c_str(), driver_name.c_str()); 372050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart return Technology::kCDCEthernet; 3738f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le } 374abc5403270e26fa898181301911a905758f8d758Jason Glasgow 37593a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal // Special case for the virtio driver, used when run under KVM. See also 37693a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal // the comment in VirtioEthernet::Start. 37793a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal if (driver_name == kDriverVirtioNet) { 378c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << StringPrintf("%s: device %s is virtio ethernet", 379c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein __func__, iface_name.c_str()); 38093a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal return Technology::kVirtioEthernet; 38193a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal } 38293a29ed675f5c75250d09e192d72fe6804c10111mukesh agrawal 383c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << StringPrintf("%s: device %s, with driver %s, " 384c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein "is defaulted to type ethernet", 385c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein __func__, iface_name.c_str(), 386c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein driver_name.c_str()); 387fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart return Technology::kEthernet; 388b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart} 389b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 390a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartbool DeviceInfo::IsCdcEthernetModemDevice(const std::string& iface_name) { 3914eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // A cdc_ether / cdc_ncm device is a modem device if it also exposes tty 3924eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // interfaces. To determine this, we look for the existence of the tty 3934eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // interface in the USB device sysfs tree. 3948f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 3954eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // A typical sysfs dir hierarchy for a cdc_ether / cdc_ncm modem USB device is 3964eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // as follows: 3978f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 3988f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2 3998f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 1-2:1.0 4008f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // tty 4018f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // ttyACM0 4028f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 1-2:1.1 4038f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // net 4048f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // usb0 4058f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 1-2:1.2 4068f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // tty 4078f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // ttyACM1 4088f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // ... 4098f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // 4108f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // /sys/class/net/usb0/device symlinks to 4118f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2/1-2:1.1 412b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // 413b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // Note that some modem devices have the tty directory one level deeper 414b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // (eg. E362), so the device tree for the tty interface is: 415b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // /sys/devices/pci0000:00/0000:00:1d.7/usb/1-2/1-2:1.0/ttyUSB0/tty/ttyUSB0 4168f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le 417ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart FilePath device_file = GetDeviceInfoPath(iface_name, kInterfaceDevice); 4188f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le FilePath device_path; 419a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan if (!base::ReadSymbolicLink(device_file, &device_path)) { 420c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << StringPrintf("%s: device %s has no device symlink", 421c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein __func__, iface_name.c_str()); 4228f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le return false; 4238f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le } 4248f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le if (!device_path.IsAbsolute()) { 425a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan device_path = 426a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan base::MakeAbsoluteFilePath(device_file.DirName().Append(device_path)); 4278f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le } 4288f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le 4298f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // Look for tty interface by enumerating all directories under the parent 430b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // USB device and see if there's a subdirectory "tty" inside. In other 431b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // words, using the example dir hierarchy above, find 432b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2/.../tty. 4338f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le // If this exists, then this is a modem device. 434b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le return HasSubdir(device_path.DirName(), FilePath("tty")); 4358f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le} 4368f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le 4378f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le// static 438a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartbool DeviceInfo::HasSubdir(const FilePath& base_dir, const FilePath& subdir) { 439a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan FileEnumerator::FileType type = static_cast<FileEnumerator::FileType>( 440a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan FileEnumerator::DIRECTORIES | FileEnumerator::SHOW_SYM_LINKS); 441a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan FileEnumerator dir_enum(base_dir, true, type); 4428f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le for (FilePath curr_dir = dir_enum.Next(); !curr_dir.empty(); 4438f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le curr_dir = dir_enum.Next()) { 444b27beee2e85a1ad3d68a1218c8c4fef4214626e8Thieu Le if (curr_dir.BaseName() == subdir) 4458f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le return true; 4468f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le } 4478f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le return false; 4488f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le} 4498f1c835d879f82261a08257eb6f9677e6be51fdaThieu Le 450a794cd60a7339d576ea2eed263a4f0a20fb255afPaul StewartDeviceRefPtr DeviceInfo::CreateDevice(const string& link_name, 451a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const string& address, 4528c116a90d3a3536430b808b15e73275060918434Paul Stewart int interface_index, 4538c116a90d3a3536430b808b15e73275060918434Paul Stewart Technology::Identifier technology) { 4548c116a90d3a3536430b808b15e73275060918434Paul Stewart DeviceRefPtr device; 455050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.erase(interface_index); 4565086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan infos_[interface_index].technology = technology; 4578c116a90d3a3536430b808b15e73275060918434Paul Stewart 4588c116a90d3a3536430b808b15e73275060918434Paul Stewart switch (technology) { 4598c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kCellular: 4605742b24ab984464701fef0cc7024af2637357b04Ben Chan#if defined(DISABLE_CELLULAR) 4615742b24ab984464701fef0cc7024af2637357b04Ben Chan LOG(WARNING) << "Cellular support is not implemented. " 4625742b24ab984464701fef0cc7024af2637357b04Ben Chan << "Ignore cellular device " << link_name << " at index " 4635742b24ab984464701fef0cc7024af2637357b04Ben Chan << interface_index << "."; 464cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan return nullptr; 4655742b24ab984464701fef0cc7024af2637357b04Ben Chan#else 4668c116a90d3a3536430b808b15e73275060918434Paul Stewart // Cellular devices are managed by ModemInfo. 467c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Cellular link " << link_name 468c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << " at index " << interface_index 469c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << " -- notifying ModemInfo."; 470bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain 471bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain // The MAC address provided by RTNL is not reliable for Gobi 2K modems. 4724b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // Clear it here, and it will be fetched from the kernel in 4734b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // GetMACAddress(). 474bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain infos_[interface_index].mac_address.Clear(); 4758c116a90d3a3536430b808b15e73275060918434Paul Stewart manager_->modem_info()->OnDeviceInfoAvailable(link_name); 4768c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 4775742b24ab984464701fef0cc7024af2637357b04Ben Chan#endif // DISABLE_CELLULAR 4788c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kEthernet: 4798c116a90d3a3536430b808b15e73275060918434Paul Stewart device = new Ethernet(control_interface_, dispatcher_, metrics_, 4808c116a90d3a3536430b808b15e73275060918434Paul Stewart manager_, link_name, address, interface_index); 4818c116a90d3a3536430b808b15e73275060918434Paul Stewart device->EnableIPv6Privacy(); 4828c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 4838c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kVirtioEthernet: 4848c116a90d3a3536430b808b15e73275060918434Paul Stewart device = new VirtioEthernet(control_interface_, dispatcher_, metrics_, 4858c116a90d3a3536430b808b15e73275060918434Paul Stewart manager_, link_name, address, 4868c116a90d3a3536430b808b15e73275060918434Paul Stewart interface_index); 4878c116a90d3a3536430b808b15e73275060918434Paul Stewart device->EnableIPv6Privacy(); 4888c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 4898c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kWifi: 4901a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if defined(DISABLE_WIFI) 4911a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu LOG(WARNING) << "WiFi support is not implemented. Ignore WiFi link " 4921a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu << link_name << " at index " << interface_index << "."; 4931a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu return nullptr; 4941a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#else 4952ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart // Defer creating this device until we get information about the 4962ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart // type of WiFi interface. 4972ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart GetWiFiInterfaceInfo(interface_index); 4988c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 4991a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif // DISABLE_WIFI 5004e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan case Technology::kWiMax: 501520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan#if defined(DISABLE_WIMAX) 502520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan LOG(WARNING) << "WiMax support is not implemented. Ignore WiMax link " 503520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan << link_name << " at index " << interface_index << "."; 504cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan return nullptr; 505520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan#else 506e4b270274cba2a1976c7be6c733bd899e009c1d1Darin Petkov // WiMax devices are managed by WiMaxProvider. 507c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "WiMax link " << link_name 508c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << " at index " << interface_index 509c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << " -- notifying WiMaxProvider."; 5104b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // The MAC address provided by RTNL may not be the final value as the 5114b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // WiMAX device may change the address after initialization. Clear it 5124b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // here, and it will be fetched from the kernel when 5134b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // WiMaxProvider::CreateDevice() is called after the WiMAX device DBus 5144b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan // object is created by the WiMAX manager daemon. 5154b28586abe9edee0179ea7672ac5ea9d9dc13ac7Ben Chan infos_[interface_index].mac_address.Clear(); 516e4b270274cba2a1976c7be6c733bd899e009c1d1Darin Petkov manager_->wimax_provider()->OnDeviceInfoAvailable(link_name); 5174e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan break; 518520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan#endif // DISABLE_WIMAX 5198c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kPPP: 5208c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kTunnel: 5218c116a90d3a3536430b808b15e73275060918434Paul Stewart // Tunnel and PPP devices are managed by the VPN code (PPP for 5228c116a90d3a3536430b808b15e73275060918434Paul Stewart // l2tpipsec). Notify the VPN Provider of the interface's presence. 5238c116a90d3a3536430b808b15e73275060918434Paul Stewart // Since CreateDevice is only called once in the lifetime of an 5248c116a90d3a3536430b808b15e73275060918434Paul Stewart // interface index, this notification will only occur the first 5258c116a90d3a3536430b808b15e73275060918434Paul Stewart // time the device is seen. 526c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Tunnel / PPP link " << link_name 527c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << " at index " << interface_index 528c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << " -- notifying VPNProvider."; 5298c116a90d3a3536430b808b15e73275060918434Paul Stewart if (!manager_->vpn_provider()->OnDeviceInfoAvailable(link_name, 5308c116a90d3a3536430b808b15e73275060918434Paul Stewart interface_index) && 5318c116a90d3a3536430b808b15e73275060918434Paul Stewart technology == Technology::kTunnel) { 5328c116a90d3a3536430b808b15e73275060918434Paul Stewart // If VPN does not know anything about this tunnel, it is probably 5338c116a90d3a3536430b808b15e73275060918434Paul Stewart // left over from a previous instance and should not exist. 534c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Tunnel link is unused. Deleting."; 5358c116a90d3a3536430b808b15e73275060918434Paul Stewart DeleteInterface(interface_index); 5368c116a90d3a3536430b808b15e73275060918434Paul Stewart } 5378c116a90d3a3536430b808b15e73275060918434Paul Stewart break; 5388c116a90d3a3536430b808b15e73275060918434Paul Stewart case Technology::kLoopback: 5398c116a90d3a3536430b808b15e73275060918434Paul Stewart // Loopback devices are largely ignored, but we should make sure the 5408c116a90d3a3536430b808b15e73275060918434Paul Stewart // link is enabled. 541c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Bringing up loopback device " << link_name 542c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << " at index " << interface_index; 5438c116a90d3a3536430b808b15e73275060918434Paul Stewart rtnl_handler_->SetInterfaceFlags(interface_index, IFF_UP, IFF_UP); 544cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan return nullptr; 545050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart case Technology::kCDCEthernet: 5464eb4ddf7f26286e6b4d112f014718336559dfb7aBen Chan // CDCEthernet devices are of indeterminate type when they are 547050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // initially created. Some time later, tty devices may or may 548050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // not appear under the same USB device root, which will identify 549050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // it as a modem. Alternatively, ModemManager may discover the 550050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // device and create and register a Cellular device. In either 551050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // case, we should delay creating a Device until we can make a 552050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart // better determination of what type this Device should be. 553a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart case Technology::kNoDeviceSymlink: // FALLTHROUGH 554a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart // The same is true for devices that do not report a device 555a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart // symlink. It has been observed that tunnel devices may not 556a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart // immediately contain a tun_flags component in their 557a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart // /sys/class/net entry. 558050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart LOG(INFO) << "Delaying creation of device for " << link_name 559050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart << " at index " << interface_index; 560050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DelayDeviceCreation(interface_index); 561cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan return nullptr; 5628c116a90d3a3536430b808b15e73275060918434Paul Stewart default: 5638c116a90d3a3536430b808b15e73275060918434Paul Stewart // We will not manage this device in shill. Do not create a device 5648c116a90d3a3536430b808b15e73275060918434Paul Stewart // object or do anything to change its state. We create a stub object 5658c116a90d3a3536430b808b15e73275060918434Paul Stewart // which is useful for testing. 5668c116a90d3a3536430b808b15e73275060918434Paul Stewart return new DeviceStub(control_interface_, dispatcher_, metrics_, 5678c116a90d3a3536430b808b15e73275060918434Paul Stewart manager_, link_name, address, interface_index, 5684e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan technology); 5698c116a90d3a3536430b808b15e73275060918434Paul Stewart } 5708c116a90d3a3536430b808b15e73275060918434Paul Stewart 5718c116a90d3a3536430b808b15e73275060918434Paul Stewart // Reset the routing table and addresses. 5728c116a90d3a3536430b808b15e73275060918434Paul Stewart routing_table_->FlushRoutes(interface_index); 5738c116a90d3a3536430b808b15e73275060918434Paul Stewart FlushAddresses(interface_index); 5748c116a90d3a3536430b808b15e73275060918434Paul Stewart 5755086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan manager_->UpdateUninitializedTechnologies(); 5765086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan 5778c116a90d3a3536430b808b15e73275060918434Paul Stewart return device; 5788c116a90d3a3536430b808b15e73275060918434Paul Stewart} 5798c116a90d3a3536430b808b15e73275060918434Paul Stewart 580d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart// static 581d84f367304e8eec21f235392c57bfc1a30540609Paul Stewartbool DeviceInfo::GetLinkNameFromMessage(const RTNLMessage& msg, 582d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart string* link_name) { 583d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart if (!msg.HasAttribute(IFLA_IFNAME)) 584d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart return false; 585d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart 586d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart ByteString link_name_bytes(msg.GetAttribute(IFLA_IFNAME)); 587d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart link_name->assign(reinterpret_cast<const char*>( 588d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart link_name_bytes.GetConstData())); 589d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart 590d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart return true; 591d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart} 592d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart 593d84f367304e8eec21f235392c57bfc1a30540609Paul Stewartbool DeviceInfo::IsRenamedBlacklistedDevice(const RTNLMessage& msg) { 594d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart int interface_index = msg.interface_index(); 595d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart const Info* info = GetInfo(interface_index); 596d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart if (!info) 597d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart return false; 598d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart 599d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart if (!info->device || info->device->technology() != Technology::kBlacklisted) 600d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart return false; 601d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart 602d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart string interface_name; 603d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart if (!GetLinkNameFromMessage(msg, &interface_name)) 604d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart return false; 605d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart 606d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart if (interface_name == info->name) 607d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart return false; 608d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart 609d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart LOG(INFO) << __func__ << ": interface index " << interface_index 610d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart << " renamed from " << info->name << " to " << interface_name; 611d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart return true; 612d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart} 613d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart 614d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart 615a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid DeviceInfo::AddLinkMsgHandler(const RTNLMessage& msg) { 6169a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart DCHECK(msg.type() == RTNLMessage::kTypeLink && 6179a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart msg.mode() == RTNLMessage::kModeAdd); 6182aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone int dev_index = msg.interface_index(); 619fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart Technology::Identifier technology = Technology::kUnknown; 620e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov unsigned int flags = msg.link_status().flags; 621e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov unsigned int change = msg.link_status().change; 622d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart 623d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart if (IsRenamedBlacklistedDevice(msg)) { 624d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart // Treat renamed blacklisted devices as new devices. 625d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart RemoveInfo(dev_index); 626d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart } 627d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart 6288c116a90d3a3536430b808b15e73275060918434Paul Stewart bool new_device = 6298c116a90d3a3536430b808b15e73275060918434Paul Stewart !ContainsKey(infos_, dev_index) || infos_[dev_index].has_addresses_only; 630c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << "(index=" << dev_index 631c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << std::showbase << std::hex 632c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << ", flags=" << flags << ", change=" << change << ")" 633c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << std::dec << std::noshowbase 634c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << ", new_device=" << new_device; 6358c116a90d3a3536430b808b15e73275060918434Paul Stewart infos_[dev_index].has_addresses_only = false; 636e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov infos_[dev_index].flags = flags; 637f1ce5d27adbfcaf9c46e650252b46e02b0d8addaPaul Stewart 6381ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart RetrieveLinkStatistics(dev_index, msg); 6391ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 6406f9eaa30b850ee4a22e71fd1b6ab13c873ec7110Darin Petkov DeviceRefPtr device = GetDevice(dev_index); 6418c116a90d3a3536430b808b15e73275060918434Paul Stewart if (new_device) { 6428c116a90d3a3536430b808b15e73275060918434Paul Stewart CHECK(!device); 643d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart string link_name; 644d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart if (!GetLinkNameFromMessage(msg, &link_name)) { 645d84f367304e8eec21f235392c57bfc1a30540609Paul Stewart LOG(ERROR) << "Add Link message does not contain a link name!"; 6462aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone return; 647b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 648c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "add link index " << dev_index << " name " << link_name; 649f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov infos_[dev_index].name = link_name; 650f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov indices_[link_name] = dev_index; 651a3c56f9f49e6c72ff55cc1224cccd60538e9b788Paul Stewart 6522aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone if (!link_name.empty()) { 653c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant if (IsDeviceBlackListed(link_name)) { 654fdd1607e26db6c10585f7eefa0e02546274ea8f5Paul Stewart technology = Technology::kBlacklisted; 655c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant } else if (!manager_->DeviceManagementAllowed(link_name)) { 656c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant technology = Technology::kBlacklisted; 657c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant AddDeviceToBlackList(link_name); 6588f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal } else { 6598f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal technology = GetDeviceTechnology(link_name); 6608f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal } 661633ac6f0d56a62f8fd21ba7d9a15818fe080fb2fDarin Petkov } 662cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart string address; 663cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart if (msg.HasAttribute(IFLA_ADDRESS)) { 664cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart infos_[dev_index].mac_address = msg.GetAttribute(IFLA_ADDRESS); 6650353c22fb3bfb443b5eeb7fe08b9e9b5dd2c5e3bBen Chan address = 6663a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko base::ToLowerASCII(infos_[dev_index].mac_address.HexEncode()); 667c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "link index " << dev_index << " address " 668c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << infos_[dev_index].mac_address.HexEncode(); 669ca876ee6b11b38a3df7a8ab03efe9ed0bcab41d8Paul Stewart } else if (technology != Technology::kTunnel && 670a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart technology != Technology::kPPP && 671a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart technology != Technology::kNoDeviceSymlink) { 6726813e7624f1047872eeceec14db45373e30e268emukesh agrawal LOG(ERROR) << "Add Link message for link '" << link_name 6736813e7624f1047872eeceec14db45373e30e268emukesh agrawal << "' does not have IFLA_ADDRESS!"; 674cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return; 675cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 676c8078a6c44d0e30b71642856ef46e0cf6c5edb46Thieu Le metrics_->RegisterDevice(dev_index, technology); 6778c116a90d3a3536430b808b15e73275060918434Paul Stewart device = CreateDevice(link_name, address, dev_index, technology); 6788c116a90d3a3536430b808b15e73275060918434Paul Stewart if (device) { 6798c116a90d3a3536430b808b15e73275060918434Paul Stewart RegisterDevice(device); 680b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 681b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 6828c116a90d3a3536430b808b15e73275060918434Paul Stewart if (device) { 6838c116a90d3a3536430b808b15e73275060918434Paul Stewart device->LinkEvent(flags, change); 6848c116a90d3a3536430b808b15e73275060918434Paul Stewart } 685b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart} 686b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 687a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid DeviceInfo::DelLinkMsgHandler(const RTNLMessage& msg) { 688c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << "(index=" << msg.interface_index() << ")"; 68947009f8d7a6fbc257a1bb1288a01405d034bd13fmukesh agrawal 6909a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart DCHECK(msg.type() == RTNLMessage::kTypeLink && 6919a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart msg.mode() == RTNLMessage::kModeDelete); 692c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << "(index=" << msg.interface_index() 693c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << std::showbase << std::hex 694fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << ", flags=" << msg.link_status().flags 695fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan << ", change=" << msg.link_status().change << ")"; 696e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov RemoveInfo(msg.interface_index()); 697e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov} 698e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov 699e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin PetkovDeviceRefPtr DeviceInfo::GetDevice(int interface_index) const { 700a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Info* info = GetInfo(interface_index); 701cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan return info ? info->device : nullptr; 70267d8ecfd1d6ff5ea75b9d5c7167d9c16891d3d4bDarin Petkov} 703b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart 704a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartint DeviceInfo::GetIndex(const string& interface_name) const { 705f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov map<string, int>::const_iterator it = indices_.find(interface_name); 706f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov return it == indices_.end() ? -1 : it->second; 707f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov} 708f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov 709a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartbool DeviceInfo::GetMACAddress(int interface_index, ByteString* address) const { 710a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Info* info = GetInfo(interface_index); 711e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov if (!info) { 712e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov return false; 713e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov } 714bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain // |mac_address| from RTNL is not used for some devices, in which case it will 715bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain // be empty here. 716bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain if (!info->mac_address.IsEmpty()) { 717bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain *address = info->mac_address; 718bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain return true; 719bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain } 720bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain 721bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain // Ask the kernel for the MAC address. 722bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain *address = GetMACAddressFromKernel(interface_index); 723bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain return !address->IsEmpty(); 724bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain} 725bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain 726bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary MorainByteString DeviceInfo::GetMACAddressFromKernel(int interface_index) const { 727a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Info* info = GetInfo(interface_index); 7284178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain if (!info) { 7294178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain return ByteString(); 7304178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain } 7314178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain 7324178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain const int fd = sockets_->Socket(PF_INET, SOCK_DGRAM, 0); 733bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain if (fd < 0) { 734fc93327b9bb58605b3fce1d67d6980d1a4752b7eNingyuan Wang PLOG(ERROR) << __func__ << ": Unable to open socket"; 7354178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain return ByteString(); 736bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain } 7374178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain 7384178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain ScopedSocketCloser socket_closer(sockets_.get(), fd); 739bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain struct ifreq ifr; 740bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain memset(&ifr, 0, sizeof(ifr)); 741bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain ifr.ifr_ifindex = interface_index; 7428a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko strcpy(ifr.ifr_ifrn.ifrn_name, info->name.c_str()); // NOLINT(runtime/printf) 7434178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain int err = sockets_->Ioctl(fd, SIOCGIFHWADDR, &ifr); 744bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain if (err < 0) { 745fc93327b9bb58605b3fce1d67d6980d1a4752b7eNingyuan Wang PLOG(ERROR) << __func__ << ": Unable to read MAC address"; 7464178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain return ByteString(); 747bf74a67a6dec2f438e6826a3f39c4e1100d1f016Gary Morain } 7484178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain 7494178023c4d627410777bdc259bfc7a31f2a4b8e9Gary Morain return ByteString(ifr.ifr_hwaddr.sa_data, IFHWADDRLEN); 750e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov} 751e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov 7526950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewartbool DeviceInfo::GetMACAddressOfPeer(int interface_index, 753a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const IPAddress& peer, 754a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart ByteString* mac_address) const { 755a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Info* info = GetInfo(interface_index); 7566950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart if (!info || !peer.IsValid()) { 7576950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart return false; 7586950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart } 7596950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 7606950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart if (peer.family() != IPAddress::kFamilyIPv4) { 7616950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart NOTIMPLEMENTED() << ": only implemented for IPv4"; 7626950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart return false; 7636950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart } 7646950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 7656950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart const int fd = sockets_->Socket(PF_INET, SOCK_DGRAM, 0); 7666950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart if (fd < 0) { 767fc93327b9bb58605b3fce1d67d6980d1a4752b7eNingyuan Wang PLOG(ERROR) << __func__ << ": Unable to open socket"; 7686950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart return false; 7696950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart } 7706950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 7716950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart ScopedSocketCloser socket_closer(sockets_.get(), fd); 7726950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart struct arpreq areq; 7736950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart memset(&areq, 0, sizeof(areq)); 7746950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 7756950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart strncpy(areq.arp_dev, info->name.c_str(), sizeof(areq.arp_dev) - 1); 7766950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart areq.arp_dev[sizeof(areq.arp_dev) - 1] = '\0'; 7776950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 778a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart struct sockaddr_in* protocol_address = 779a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart reinterpret_cast<struct sockaddr_in*>(&areq.arp_pa); 7806950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart protocol_address->sin_family = AF_INET; 7816950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart CHECK_EQ(sizeof(protocol_address->sin_addr.s_addr), peer.GetLength()); 7826950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart memcpy(&protocol_address->sin_addr.s_addr, peer.address().GetConstData(), 7836950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart sizeof(protocol_address->sin_addr.s_addr)); 7846950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 785a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart struct sockaddr_in* hardware_address = 786a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart reinterpret_cast<struct sockaddr_in*>(&areq.arp_ha); 7876950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart hardware_address->sin_family = ARPHRD_ETHER; 7886950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 7896950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart int err = sockets_->Ioctl(fd, SIOCGARP, &areq); 7906950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart if (err < 0) { 791fc93327b9bb58605b3fce1d67d6980d1a4752b7eNingyuan Wang PLOG(ERROR) << __func__ << ": Unable to perform ARP lookup"; 7926950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart return false; 7936950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart } 7946950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 7956950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart ByteString peer_address(areq.arp_ha.sa_data, IFHWADDRLEN); 7966950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 7976950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart if (peer_address.IsZero()) { 7986950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart LOG(INFO) << __func__ << ": ARP lookup is still in progress"; 7996950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart return false; 8006950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart } 8016950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 8026950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart CHECK(mac_address); 8036950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart *mac_address = peer_address; 8046950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart return true; 8056950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart} 8066950ba51e9a35b91687103fdc451e1539cdfb35dPaul Stewart 8079a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewartbool DeviceInfo::GetAddresses(int interface_index, 808a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart vector<AddressData>* addresses) const { 809a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Info* info = GetInfo(interface_index); 8109a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (!info) { 8119a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart return false; 8129a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 8139a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart *addresses = info->ip_addresses; 8149a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart return true; 8159a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart} 8169a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 8179a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewartvoid DeviceInfo::FlushAddresses(int interface_index) const { 818c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << "(" << interface_index << ")"; 819a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Info* info = GetInfo(interface_index); 8209a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (!info) { 8219a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart return; 8229a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 823a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart for (const auto& address_info : info->ip_addresses) { 8246db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart if (address_info.address.family() == IPAddress::kFamilyIPv4 || 8256db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart (address_info.scope == RT_SCOPE_UNIVERSE && 8266db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart (address_info.flags & ~IFA_F_TEMPORARY) == 0)) { 827c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << ": removing ip address " 828c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << address_info.address.ToString() 829c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << " from interface " << interface_index; 8306db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart rtnl_handler_->RemoveInterfaceAddress(interface_index, 8316db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart address_info.address); 8329a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 8339a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 8349a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart} 8359a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 83605a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewartbool DeviceInfo::HasOtherAddress( 837a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart int interface_index, const IPAddress& this_address) const { 838c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 3) << __func__ << "(" << interface_index << ")"; 839a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Info* info = GetInfo(interface_index); 84005a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart if (!info) { 84105a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart return false; 84205a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } 84305a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart bool has_other_address = false; 84405a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart bool has_this_address = false; 845a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart for (const auto& local_address : info->ip_addresses) { 846a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart if (local_address.address.family() != this_address.family()) { 84705a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart continue; 84805a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } 849a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart if (local_address.address.address().Equals(this_address.address())) { 85005a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart has_this_address = true; 85105a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } else if (this_address.family() == IPAddress::kFamilyIPv4) { 85205a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart has_other_address = true; 853a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart } else if ((local_address.scope == RT_SCOPE_UNIVERSE && 854a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart (local_address.flags & IFA_F_TEMPORARY) == 0)) { 85505a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart has_other_address = true; 85605a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } 85705a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart } 85805a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart return has_other_address && !has_this_address; 85905a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart} 86005a42c23f1d37daa8689fc4240034e62ed89f8fcPaul Stewart 861d55f6ae45047f984457508d78c70abcd837307eaPaul Stewartbool DeviceInfo::GetPrimaryIPv6Address(int interface_index, 862a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart IPAddress* address) { 863a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Info* info = GetInfo(interface_index); 864d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart if (!info) { 865d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart return false; 866d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart } 867d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart bool has_temporary_address = false; 868241e3f317fe3089dd7dcb4e7c5a34430926d4e2ePaul Stewart bool has_current_address = false; 869d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart bool has_address = false; 870a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart for (const auto& local_address : info->ip_addresses) { 871d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart if (local_address.address.family() != IPAddress::kFamilyIPv6 || 872d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart local_address.scope != RT_SCOPE_UNIVERSE) { 873d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart continue; 874d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart } 875d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart 876241e3f317fe3089dd7dcb4e7c5a34430926d4e2ePaul Stewart // Prefer non-deprecated addresses to deprecated addresses to match the 877241e3f317fe3089dd7dcb4e7c5a34430926d4e2ePaul Stewart // kernel's preference. 878241e3f317fe3089dd7dcb4e7c5a34430926d4e2ePaul Stewart bool is_current_address = 879241e3f317fe3089dd7dcb4e7c5a34430926d4e2ePaul Stewart ((local_address.flags & IFA_F_DEPRECATED) == 0); 880241e3f317fe3089dd7dcb4e7c5a34430926d4e2ePaul Stewart if (has_current_address && !is_current_address) { 881241e3f317fe3089dd7dcb4e7c5a34430926d4e2ePaul Stewart continue; 882241e3f317fe3089dd7dcb4e7c5a34430926d4e2ePaul Stewart } 883241e3f317fe3089dd7dcb4e7c5a34430926d4e2ePaul Stewart 884d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart // Prefer temporary addresses to non-temporary addresses to match the 885d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart // kernel's preference. 886d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart bool is_temporary_address = ((local_address.flags & IFA_F_TEMPORARY) != 0); 887d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart if (has_temporary_address && !is_temporary_address) { 888d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart continue; 889d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart } 890d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart 891d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart *address = local_address.address; 892d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart has_temporary_address = is_temporary_address; 893241e3f317fe3089dd7dcb4e7c5a34430926d4e2ePaul Stewart has_current_address = is_current_address; 894d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart has_address = true; 895d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart } 896d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart 897d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart return has_address; 898d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart} 899d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart 9009855170e6e2de08db343640c82795c9b4020a166Peter Qiubool DeviceInfo::GetIPv6DnsServerAddresses(int interface_index, 901a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart std::vector<IPAddress>* address_list, 902a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart uint32_t* life_time) { 903a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Info* info = GetInfo(interface_index); 9049855170e6e2de08db343640c82795c9b4020a166Peter Qiu if (!info || info->ipv6_dns_server_addresses.empty()) { 9059855170e6e2de08db343640c82795c9b4020a166Peter Qiu return false; 9069855170e6e2de08db343640c82795c9b4020a166Peter Qiu } 9079855170e6e2de08db343640c82795c9b4020a166Peter Qiu 9089855170e6e2de08db343640c82795c9b4020a166Peter Qiu // Determine the remaining DNS server life time. 9099855170e6e2de08db343640c82795c9b4020a166Peter Qiu if (info->ipv6_dns_server_lifetime_seconds == ND_OPT_LIFETIME_INFINITY) { 9109855170e6e2de08db343640c82795c9b4020a166Peter Qiu *life_time = ND_OPT_LIFETIME_INFINITY; 9119855170e6e2de08db343640c82795c9b4020a166Peter Qiu } else { 9129855170e6e2de08db343640c82795c9b4020a166Peter Qiu time_t cur_time; 9139855170e6e2de08db343640c82795c9b4020a166Peter Qiu if (!time_->GetSecondsBoottime(&cur_time)) { 9149855170e6e2de08db343640c82795c9b4020a166Peter Qiu NOTREACHED(); 9159855170e6e2de08db343640c82795c9b4020a166Peter Qiu } 9167fab89734d88724a288e96a9996b15548c5294c7Ben Chan uint32_t time_elapsed = static_cast<uint32_t>( 9179855170e6e2de08db343640c82795c9b4020a166Peter Qiu cur_time - info->ipv6_dns_server_received_time_seconds); 9189855170e6e2de08db343640c82795c9b4020a166Peter Qiu if (time_elapsed >= info->ipv6_dns_server_lifetime_seconds) { 9199855170e6e2de08db343640c82795c9b4020a166Peter Qiu *life_time = 0; 9209855170e6e2de08db343640c82795c9b4020a166Peter Qiu } else { 9219855170e6e2de08db343640c82795c9b4020a166Peter Qiu *life_time = info->ipv6_dns_server_lifetime_seconds - time_elapsed; 9229855170e6e2de08db343640c82795c9b4020a166Peter Qiu } 9239855170e6e2de08db343640c82795c9b4020a166Peter Qiu } 9249855170e6e2de08db343640c82795c9b4020a166Peter Qiu *address_list = info->ipv6_dns_server_addresses; 9259855170e6e2de08db343640c82795c9b4020a166Peter Qiu return true; 9269855170e6e2de08db343640c82795c9b4020a166Peter Qiu} 9279855170e6e2de08db343640c82795c9b4020a166Peter Qiu 928a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewartbool DeviceInfo::HasDirectConnectivityTo( 929a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart int interface_index, const IPAddress& address) const { 930c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 3) << __func__ << "(" << interface_index << ")"; 931a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Info* info = GetInfo(interface_index); 932a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart if (!info) { 933a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart return false; 934a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart } 935a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart 936a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart for (const auto& local_address : info->ip_addresses) { 937a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart if (local_address.address.family() == address.family() && 938a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart local_address.address.CanReachAddress(address)) { 939a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart return true; 940a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart } 941a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart } 942a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart 943a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart return false; 944a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart} 945a0db0fff6ae05e1ba3facfdf3d5049ca1a277be4Paul Stewart 946a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartbool DeviceInfo::GetFlags(int interface_index, unsigned int* flags) const { 947a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Info* info = GetInfo(interface_index); 948e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov if (!info) { 949e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov return false; 950e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov } 951e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov *flags = info->flags; 952e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov return true; 953e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov} 954e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov 9551ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewartbool DeviceInfo::GetByteCounts(int interface_index, 956a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart uint64_t* rx_bytes, 957a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart uint64_t* tx_bytes) const { 958a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Info* info = GetInfo(interface_index); 9591ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart if (!info) { 9601ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart return false; 9611ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart } 9621ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart *rx_bytes = info->rx_bytes; 9631ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart *tx_bytes = info->tx_bytes; 9641ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart return true; 9651ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart} 9661ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 967a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartbool DeviceInfo::CreateTunnelInterface(string* interface_name) const { 968cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart int fd = HANDLE_EINTR(open(kTunDeviceName, O_RDWR)); 969cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart if (fd < 0) { 970cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart PLOG(ERROR) << "failed to open " << kTunDeviceName; 971cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return false; 972cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 9736fbf64f493a9aae7d743888039c61a57386203dbBen Chan base::ScopedFD scoped_fd(fd); 974cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 975cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart struct ifreq ifr; 976cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart memset(&ifr, 0, sizeof(ifr)); 977cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart ifr.ifr_flags = IFF_TUN | IFF_NO_PI; 978cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart if (HANDLE_EINTR(ioctl(fd, TUNSETIFF, &ifr))) { 979cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart PLOG(ERROR) << "failed to create tunnel interface"; 980cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return false; 981cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 982cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 983cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart if (HANDLE_EINTR(ioctl(fd, TUNSETPERSIST, 1))) { 984cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart PLOG(ERROR) << "failed to set tunnel interface to be persistent"; 985cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return false; 986cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart } 987cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 988cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart *interface_name = string(ifr.ifr_name); 989cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 990cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return true; 991cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart} 992cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 993a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartint DeviceInfo::OpenTunnelInterface(const std::string& interface_name) const { 994127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi int fd = HANDLE_EINTR(open(kTunDeviceName, O_RDWR)); 995127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (fd < 0) { 996127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi PLOG(ERROR) << "failed to open " << kTunDeviceName; 997127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return -1; 998127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 999127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 1000127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi struct ifreq ifr; 1001127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi memset(&ifr, 0, sizeof(ifr)); 1002127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi strncpy(ifr.ifr_name, interface_name.c_str(), sizeof(ifr.ifr_name)); 1003127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi ifr.ifr_flags = IFF_TUN | IFF_NO_PI; 1004127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi if (HANDLE_EINTR(ioctl(fd, TUNSETIFF, &ifr))) { 1005127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi PLOG(ERROR) << "failed to set tunnel interface name"; 1006127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return -1; 1007127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi } 1008127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 1009127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi return fd; 1010127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi} 1011127b341755731bd6ecc19e44b63c23c79e0b7cd1Prabhu Kaliamoorthi 1012ca6abd4635507fa5b8f4b8819a37819fb560c464Paul Stewartbool DeviceInfo::DeleteInterface(int interface_index) const { 1013cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart return rtnl_handler_->RemoveInterface(interface_index); 1014cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart} 1015cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart 1016a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartconst DeviceInfo::Info* DeviceInfo::GetInfo(int interface_index) const { 1017e3e1cfaadc69ea67db55f11e55f404b11a70e354Darin Petkov map<int, Info>::const_iterator iter = infos_.find(interface_index); 1018e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov if (iter == infos_.end()) { 1019cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan return nullptr; 1020e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov } 1021e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov return &iter->second; 1022e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov} 1023e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov 1024e6193c042652831cac90c3bbf2233877754b1eefDarin Petkovvoid DeviceInfo::RemoveInfo(int interface_index) { 1025e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov map<int, Info>::iterator iter = infos_.find(interface_index); 1026e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov if (iter != infos_.end()) { 1027c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Removing info for device index: " << interface_index; 10289f5159e07028a01e1353d68bc19da9817a6785fePeter Qiu // Deregister the device if not deregistered yet. Cellular and WiMax devices 10299f5159e07028a01e1353d68bc19da9817a6785fePeter Qiu // are deregistered through a call to DeviceInfo::DeregisterDevice. 1030e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov if (iter->second.device.get()) { 1031e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov manager_->DeregisterDevice(iter->second.device); 10329f5159e07028a01e1353d68bc19da9817a6785fePeter Qiu metrics_->DeregisterDevice(interface_index); 1033e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov } 1034f8046b8f975417255baf5cc7cdd025c63aa2f918Darin Petkov indices_.erase(iter->second.name); 1035e6193c042652831cac90c3bbf2233877754b1eefDarin Petkov infos_.erase(iter); 1036050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.erase(interface_index); 103747009f8d7a6fbc257a1bb1288a01405d034bd13fmukesh agrawal } else { 1038c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << ": Unknown device index: " 1039c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << interface_index; 1040b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 10410af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 10420af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 1043a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid DeviceInfo::LinkMsgHandler(const RTNLMessage& msg) { 10449a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart DCHECK(msg.type() == RTNLMessage::kTypeLink); 10459a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (msg.mode() == RTNLMessage::kModeAdd) { 10462aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone AddLinkMsgHandler(msg); 10479a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else if (msg.mode() == RTNLMessage::kModeDelete) { 10482aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone DelLinkMsgHandler(msg); 10492aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone } else { 10502aa9707f114ab8166f45df5726bf05278df2aef6Chris Masone NOTREACHED(); 1051b50f0b9837c398b8edd5dc568eb01bdcff9a4d65Paul Stewart } 10520af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} 10530af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart 1054a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid DeviceInfo::AddressMsgHandler(const RTNLMessage& msg) { 1055c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 10569a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart DCHECK(msg.type() == RTNLMessage::kTypeAddress); 10579a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart int interface_index = msg.interface_index(); 10589a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (!ContainsKey(infos_, interface_index)) { 1059c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Got advance address information for unknown index " 1060c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << interface_index; 10618c116a90d3a3536430b808b15e73275060918434Paul Stewart infos_[interface_index].has_addresses_only = true; 10629a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 1063a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const RTNLMessage::AddressStatus& status = msg.address_status(); 10649a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart IPAddress address(msg.family(), 1065682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan msg.HasAttribute(IFA_LOCAL) ? 1066682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan msg.GetAttribute(IFA_LOCAL) : msg.GetAttribute(IFA_ADDRESS), 10679a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart status.prefix_len); 10689a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 1069682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan SLOG_IF(Device, 2, msg.HasAttribute(IFA_LOCAL)) 1070682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan << "Found local address attribute for interface " << interface_index; 1071682c5d4738cbdffc1ec88573a4a339840cc4fb25Ben Chan 1072a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart vector<AddressData>& address_list = infos_[interface_index].ip_addresses; 10739a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart vector<AddressData>::iterator iter; 10749a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart for (iter = address_list.begin(); iter != address_list.end(); ++iter) { 10759a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (address.Equals(iter->address)) { 10769a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart break; 10779a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 10789a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 10799a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (iter != address_list.end()) { 10809a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (msg.mode() == RTNLMessage::kModeDelete) { 1081c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Delete address for interface " << interface_index; 10829a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart address_list.erase(iter); 10839a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else { 10849a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart iter->flags = status.flags; 10859a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart iter->scope = status.scope; 10869a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 10879a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else if (msg.mode() == RTNLMessage::kModeAdd) { 10889a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart address_list.push_back(AddressData(address, status.flags, status.scope)); 1089c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Add address " << address.ToString() 1090c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << " for interface " << interface_index; 10919a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } 1092d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart 1093d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart DeviceRefPtr device = GetDevice(interface_index); 1094d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart if (device && address.family() == IPAddress::kFamilyIPv6 && 1095d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart status.scope == RT_SCOPE_UNIVERSE) { 1096d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart device->OnIPv6AddressChanged(); 1097d55f6ae45047f984457508d78c70abcd837307eaPaul Stewart } 10989a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart} 10999a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart 1100a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid DeviceInfo::RdnssMsgHandler(const RTNLMessage& msg) { 1101c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 11029855170e6e2de08db343640c82795c9b4020a166Peter Qiu DCHECK(msg.type() == RTNLMessage::kTypeRdnss); 11039855170e6e2de08db343640c82795c9b4020a166Peter Qiu int interface_index = msg.interface_index(); 11049855170e6e2de08db343640c82795c9b4020a166Peter Qiu if (!ContainsKey(infos_, interface_index)) { 1105c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Got RDNSS option for unknown index " 1106c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << interface_index; 11079855170e6e2de08db343640c82795c9b4020a166Peter Qiu } 11089855170e6e2de08db343640c82795c9b4020a166Peter Qiu 1109a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const RTNLMessage::RdnssOption& rdnss_option = msg.rdnss_option(); 11109855170e6e2de08db343640c82795c9b4020a166Peter Qiu infos_[interface_index].ipv6_dns_server_lifetime_seconds = 11119855170e6e2de08db343640c82795c9b4020a166Peter Qiu rdnss_option.lifetime; 11129855170e6e2de08db343640c82795c9b4020a166Peter Qiu infos_[interface_index].ipv6_dns_server_addresses = rdnss_option.addresses; 11139855170e6e2de08db343640c82795c9b4020a166Peter Qiu if (!time_->GetSecondsBoottime( 11149855170e6e2de08db343640c82795c9b4020a166Peter Qiu &infos_[interface_index].ipv6_dns_server_received_time_seconds)) { 11159855170e6e2de08db343640c82795c9b4020a166Peter Qiu NOTREACHED(); 11169855170e6e2de08db343640c82795c9b4020a166Peter Qiu } 11179855170e6e2de08db343640c82795c9b4020a166Peter Qiu 11189855170e6e2de08db343640c82795c9b4020a166Peter Qiu // Notify device of the IPv6 DNS server addresses update. 11199855170e6e2de08db343640c82795c9b4020a166Peter Qiu DeviceRefPtr device = GetDevice(interface_index); 11209855170e6e2de08db343640c82795c9b4020a166Peter Qiu if (device) { 11219855170e6e2de08db343640c82795c9b4020a166Peter Qiu device->OnIPv6DnsServerAddressesChanged(); 11229855170e6e2de08db343640c82795c9b4020a166Peter Qiu } 11239855170e6e2de08db343640c82795c9b4020a166Peter Qiu} 11249855170e6e2de08db343640c82795c9b4020a166Peter Qiu 1125050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewartvoid DeviceInfo::DelayDeviceCreation(int interface_index) { 1126050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.insert(interface_index); 1127050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_callback_.Reset( 1128050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart Bind(&DeviceInfo::DelayedDeviceCreationTask, AsWeakPtr())); 1129050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart dispatcher_->PostDelayedTask(delayed_devices_callback_.callback(), 1130050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart kDelayedDeviceCreationSeconds * 1000); 1131050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart} 1132050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 1133050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart// Re-evaluate the technology type for each delayed device. 1134050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewartvoid DeviceInfo::DelayedDeviceCreationTask() { 1135050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart while (!delayed_devices_.empty()) { 1136050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart set<int>::iterator it = delayed_devices_.begin(); 1137050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart int dev_index = *it; 1138050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart delayed_devices_.erase(it); 1139050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 1140050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DCHECK(ContainsKey(infos_, dev_index)); 1141050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DCHECK(!GetDevice(dev_index)); 1142050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 1143a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const string& link_name = infos_[dev_index].name; 1144050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart Technology::Identifier technology = GetDeviceTechnology(link_name); 1145050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 1146050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart if (technology == Technology::kCDCEthernet) { 1147050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart LOG(INFO) << "In " << __func__ << ": device " << link_name 1148050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart << " is now assumed to be regular Ethernet."; 1149050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart technology = Technology::kEthernet; 1150a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart } else if (technology == Technology::kNoDeviceSymlink) { 1151a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart if (manager_->ignore_unknown_ethernet()) { 1152a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart SLOG(this, 2) << StringPrintf("%s: device %s, without driver name " 1153a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart "will be ignored", 1154a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart __func__, link_name.c_str()); 1155a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart technology = Technology::kUnknown; 1156a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart } else { 1157a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart // Act the same as if there was a driver symlink, but we did not 1158a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart // recognize the driver name. 1159a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart SLOG(this, 2) << StringPrintf("%s: device %s, without driver name " 1160a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart "is defaulted to type ethernet", 1161a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart __func__, link_name.c_str()); 1162a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart technology = Technology::kEthernet; 1163a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart } 1164a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart } else if (technology != Technology::kCellular && 1165a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart technology != Technology::kTunnel) { 1166050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart LOG(WARNING) << "In " << __func__ << ": device " << link_name 1167050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart << " is unexpected technology " 1168050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart << Technology::NameFromIdentifier(technology); 1169050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } 1170050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart string address = 11713a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko base::ToLowerASCII(infos_[dev_index].mac_address.HexEncode()); 1172a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart 1173d92c35390c2309645b82f37c6172e4fae606b095Christopher Grant if (technology != Technology::kTunnel && 1174d92c35390c2309645b82f37c6172e4fae606b095Christopher Grant technology != Technology::kUnknown) { 1175a551451a88ec3a4746021c84c646dcf8206b2531Paul Stewart DCHECK(!address.empty()); 1176d92c35390c2309645b82f37c6172e4fae606b095Christopher Grant } 1177050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 1178050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart DeviceRefPtr device = CreateDevice(link_name, address, dev_index, 1179050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart technology); 1180050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart if (device) { 1181050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart RegisterDevice(device); 1182050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } 1183050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart } 1184050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart} 1185050cfc068fda2bd77df2ba08f7b2897bf0e0a6e0Paul Stewart 11861ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewartvoid DeviceInfo::RetrieveLinkStatistics(int interface_index, 1187a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const RTNLMessage& msg) { 11881ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart if (!msg.HasAttribute(IFLA_STATS64)) { 11891ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart return; 11901ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart } 11911ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart ByteString stats_bytes(msg.GetAttribute(IFLA_STATS64)); 11921ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart struct rtnl_link_stats64 stats; 11931ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart if (stats_bytes.GetLength() < sizeof(stats)) { 11941ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart LOG(WARNING) << "Link statistics size is too small: " 11951ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart << stats_bytes.GetLength() << " < " << sizeof(stats); 11961ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart return; 11971ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart } 11981ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 11991ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart memcpy(&stats, stats_bytes.GetConstData(), sizeof(stats)); 1200c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Link statistics for " 1201c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << " interface index " << interface_index << ": " 1202c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << "receive: " << stats.rx_bytes << "; " 1203c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << "transmit: " << stats.tx_bytes << "."; 12041ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart infos_[interface_index].rx_bytes = stats.rx_bytes; 12051ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart infos_[interface_index].tx_bytes = stats.tx_bytes; 12061ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart} 12071ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 12081ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewartvoid DeviceInfo::RequestLinkStatistics() { 12091ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart rtnl_handler_->RequestDump(RTNLHandler::kRequestLink); 12101ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart dispatcher_->PostDelayedTask(request_link_statistics_callback_.callback(), 1211b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan kRequestLinkStatisticsIntervalMilliseconds); 12121ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart} 12131ac4e84148e03752d99aecea4f743abb094f28b0Paul Stewart 12141a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI) 12152ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewartvoid DeviceInfo::GetWiFiInterfaceInfo(int interface_index) { 12162ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart GetInterfaceMessage msg; 12172ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart if (!msg.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX, 12182ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart interface_index)) { 12192ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(ERROR) << "Unable to set interface index attribute for " 12202ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart "GetInterface message. Interface type cannot be " 12212ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart "determined!"; 12222ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 12232ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 12247347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie netlink_manager_->SendNl80211Message( 12257347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie &msg, 12267347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie Bind(&DeviceInfo::OnWiFiInterfaceInfoReceived, AsWeakPtr()), 12275412de0a46893b44f60fee4058c5b0d744b74b4dSamuel Tan Bind(&NetlinkManager::OnAckDoNothing), 12287347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie Bind(&NetlinkManager::OnNetlinkMessageError)); 12292ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart} 12302ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart 1231a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartvoid DeviceInfo::OnWiFiInterfaceInfoReceived(const Nl80211Message& msg) { 12327347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie if (msg.command() != NL80211_CMD_NEW_INTERFACE) { 12332ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(ERROR) << "Message is not a new interface response"; 12342ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 12352ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 12362ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart 12372ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart uint32_t interface_index; 12387347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFINDEX, 12397347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie &interface_index)) { 12402ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(ERROR) << "Message contains no interface index"; 12412ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 12422ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 12432ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart uint32_t interface_type; 12447347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFTYPE, 12457347bf2b466ae8058e47b29aaf0583390405d866Wade Guthrie &interface_type)) { 12462ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(ERROR) << "Message contains no interface type"; 12472ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 12482ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 1249a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart const Info* info = GetInfo(interface_index); 12502ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart if (!info) { 12512ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(ERROR) << "Could not find device info for interface index " 12522ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << interface_index; 12532ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 12542ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 12552ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart if (info->device) { 12562ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(ERROR) << "Device already created for interface index " 12572ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << interface_index; 12582ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 12592ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 12602ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart if (interface_type != NL80211_IFTYPE_STATION) { 12612ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(INFO) << "Ignoring WiFi device " 12622ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << info->name 12632ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << " at interface index " 12642ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << interface_index 12652ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << " since it is not in station mode."; 12662ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart return; 12672ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart } 12682ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart LOG(INFO) << "Creating WiFi device for station mode interface " 12692ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << info->name 12702ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << " at interface index " 12712ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart << interface_index; 12723a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko string address = base::ToLowerASCII(info->mac_address.HexEncode()); 12732ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart DeviceRefPtr device = 12742ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart new WiFi(control_interface_, dispatcher_, metrics_, manager_, 12752ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart info->name, address, interface_index); 12762ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart device->EnableIPv6Privacy(); 12772ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart RegisterDevice(device); 12782ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart} 12791a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif // DISABLE_WIFI 12802ddf2c63751546aa554335a6733314a3859d5c2ePaul Stewart 1281a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartbool DeviceInfo::SetHostname(const std::string& hostname) const { 1282208a97ed32c62bc11b0a20eaf01833482e8c0fbcPaul Stewart if (sethostname(hostname.c_str(), hostname.length())) { 1283208a97ed32c62bc11b0a20eaf01833482e8c0fbcPaul Stewart PLOG(ERROR) << "Failed to set hostname to: " << hostname; 1284208a97ed32c62bc11b0a20eaf01833482e8c0fbcPaul Stewart return false; 1285208a97ed32c62bc11b0a20eaf01833482e8c0fbcPaul Stewart } 1286208a97ed32c62bc11b0a20eaf01833482e8c0fbcPaul Stewart 1287208a97ed32c62bc11b0a20eaf01833482e8c0fbcPaul Stewart return true; 1288208a97ed32c62bc11b0a20eaf01833482e8c0fbcPaul Stewart} 1289208a97ed32c62bc11b0a20eaf01833482e8c0fbcPaul Stewart 12900af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart} // namespace shill 1291