1326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// 2326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// Copyright (C) 2014 The Android Open Source Project 3326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// 4326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// Licensed under the Apache License, Version 2.0 (the "License"); 5326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// you may not use this file except in compliance with the License. 6326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// You may obtain a copy of the License at 7326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// 8326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// http://www.apache.org/licenses/LICENSE-2.0 9326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// 10326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// Unless required by applicable law or agreed to in writing, software 11326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// distributed under the License is distributed on an "AS IS" BASIS, 12326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// See the License for the specific language governing permissions and 14326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// limitations under the License. 15326b6cfba5ab73c9e41a7585d1bc95871631122aPeter Qiu// 16fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 17fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include "apmanager/device_info.h" 18fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 19fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <linux/rtnetlink.h> 20fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 21fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <string> 22fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 23fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <base/bind.h> 24fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <base/files/file_util.h> 25fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <base/logging.h> 2674cfdc9a3fb1a1052512971b9c48f5fb5fd9e5fcNathan Bullock#include <shill/net/ndisc.h> 27fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <shill/net/netlink_attribute.h> 28fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <shill/net/netlink_manager.h> 29fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <shill/net/nl80211_message.h> 30fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <shill/net/rtnl_handler.h> 31fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <shill/net/rtnl_listener.h> 32fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include <shill/net/rtnl_message.h> 33fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 34f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu#include "apmanager/control_interface.h" 35fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu#include "apmanager/manager.h" 36fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 37fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing base::Bind; 38fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing shill::ByteString; 39fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing shill::NetlinkManager; 40fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing shill::NetlinkMessage; 41fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing shill::Nl80211Message; 42fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing shill::RTNLHandler; 43fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing shill::RTNLMessage; 44fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing shill::RTNLListener; 45fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing std::map; 46fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuusing std::string; 47fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 48fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiunamespace apmanager { 49fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 50fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuconst char DeviceInfo::kDeviceInfoRoot[] = "/sys/class/net"; 51fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuconst char DeviceInfo::kInterfaceUevent[] = "uevent"; 52fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuconst char DeviceInfo::kInterfaceUeventWifiSignature[] = "DEVTYPE=wlan\n"; 53fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 54fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter QiuDeviceInfo::DeviceInfo(Manager* manager) 55fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu : link_callback_(Bind(&DeviceInfo::LinkMsgHandler, Unretained(this))), 56fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu device_info_root_(kDeviceInfoRoot), 57fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu manager_(manager), 58fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu netlink_manager_(NetlinkManager::GetInstance()), 59f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu rtnl_handler_(RTNLHandler::GetInstance()), 60f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu device_identifier_(0) { 61fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 62fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 63fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter QiuDeviceInfo::~DeviceInfo() {} 64fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 65fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuvoid DeviceInfo::Start() { 66fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Start netlink manager. 67fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu netlink_manager_->Init(); 68fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu uint16_t nl80211_family_id = netlink_manager_->GetFamily( 69fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu Nl80211Message::kMessageTypeString, 70fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu Bind(&Nl80211Message::CreateMessage)); 71fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (nl80211_family_id == NetlinkMessage::kIllegalMessageType) { 72fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(FATAL) << "Didn't get a legal message type for 'nl80211' messages."; 73fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 74fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu Nl80211Message::SetMessageType(nl80211_family_id); 75fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu netlink_manager_->Start(); 76fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 77fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Start enumerating WiFi devices (PHYs). 78fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu EnumerateDevices(); 79fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 80fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Start RTNL for monitoring network interfaces. 8174cfdc9a3fb1a1052512971b9c48f5fb5fd9e5fcNathan Bullock rtnl_handler_->Start(RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE | 8274cfdc9a3fb1a1052512971b9c48f5fb5fd9e5fcNathan Bullock RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE | 8374cfdc9a3fb1a1052512971b9c48f5fb5fd9e5fcNathan Bullock RTMGRP_ND_USEROPT); 84fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu link_listener_.reset( 85fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu new RTNLListener(RTNLHandler::kRequestLink, link_callback_)); 861ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu // Request link infos. 871ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu rtnl_handler_->RequestDump(RTNLHandler::kRequestLink); 88fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 89fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 90fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuvoid DeviceInfo::Stop() { 91fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu link_listener_.reset(); 92fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 93fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 94fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuvoid DeviceInfo::EnumerateDevices() { 95fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu shill::GetWiphyMessage get_wiphy; 96fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu get_wiphy.attributes()->SetFlagAttributeValue(NL80211_ATTR_SPLIT_WIPHY_DUMP, 97fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu true); 98fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu get_wiphy.AddFlag(NLM_F_DUMP); 99fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu netlink_manager_->SendNl80211Message( 100fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu &get_wiphy, 101fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu Bind(&DeviceInfo::OnWiFiPhyInfoReceived, AsWeakPtr()), 102fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu Bind(&NetlinkManager::OnAckDoNothing), 103fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu Bind(&NetlinkManager::OnNetlinkMessageError)); 104fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 105fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 106fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuvoid DeviceInfo::OnWiFiPhyInfoReceived(const shill::Nl80211Message& msg) { 107fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Verify NL80211_CMD_NEW_WIPHY. 108fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (msg.command() != shill::NewWiphyMessage::kCommand) { 109fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(ERROR) << "Received unexpected command:" 110fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu << msg.command(); 111fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return; 112fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 113fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 1141ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu string device_name; 1151ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu if (!msg.const_attributes()->GetStringAttributeValue(NL80211_ATTR_WIPHY_NAME, 1161ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu &device_name)) { 1171ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_WIPHY_NAME"; 1181ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu return; 1191ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu } 1201ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu 1211ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu if (GetDevice(device_name)) { 1221ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu LOG(INFO) << "Device " << device_name << " already enumerated."; 1231ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu return; 1241ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu } 1251ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu 126f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu scoped_refptr<Device> device = 127f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu new Device(manager_, device_name, device_identifier_++); 1281ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu device->ParseWiphyCapability(msg); 129fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 130fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Register device 131fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu RegisterDevice(device); 132fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 133fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 134fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuvoid DeviceInfo::LinkMsgHandler(const RTNLMessage& msg) { 135fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu DCHECK(msg.type() == RTNLMessage::kTypeLink); 136fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 137fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Get interface name. 138fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (!msg.HasAttribute(IFLA_IFNAME)) { 139fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(ERROR) << "Link event message does not have IFLA_IFNAME!"; 140fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return; 141fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 142fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu ByteString b(msg.GetAttribute(IFLA_IFNAME)); 143fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu string iface_name(reinterpret_cast<const char*>(b.GetConstData())); 144fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 145fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu int dev_index = msg.interface_index(); 146fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (msg.mode() == RTNLMessage::kModeAdd) { 147fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu AddLinkMsgHandler(iface_name, dev_index); 148fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } else if (msg.mode() == RTNLMessage::kModeDelete) { 149fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu DelLinkMsgHandler(iface_name, dev_index); 150fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } else { 151fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu NOTREACHED(); 152fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 153fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 154fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 155fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuvoid DeviceInfo::AddLinkMsgHandler(const string& iface_name, int iface_index) { 156fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Ignore non-wifi interfaces. 157fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (!IsWifiInterface(iface_name)) { 158fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(INFO) << "Ignore link event for non-wifi interface: " << iface_name; 159fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return; 160fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 161fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 162fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Return if interface already existed. Could receive multiple add link event 163fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // for a single interface. 164fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (interface_infos_.find(iface_index) != interface_infos_.end()) { 165fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(INFO) << "AddLinkMsgHandler: interface " << iface_name 166fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu << " is already added"; 167fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return; 168fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 169fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 170fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Add interface. 171fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu Device::WiFiInterface wifi_interface; 172fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu wifi_interface.iface_name = iface_name; 173fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu wifi_interface.iface_index = iface_index; 174fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu interface_infos_[iface_index] = wifi_interface; 175fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 176fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Get interface info. 177fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu GetWiFiInterfaceInfo(iface_index); 178fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 179fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 180fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuvoid DeviceInfo::DelLinkMsgHandler(const string& iface_name, int iface_index) { 181fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(INFO) << "DelLinkMsgHandler iface_name: " << iface_name 182fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu << "iface_index: " << iface_index; 183fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu map<uint32_t, Device::WiFiInterface>::iterator iter = 184fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu interface_infos_.find(iface_index); 185fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (iter != interface_infos_.end()) { 186fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Deregister interface from the Device. 187fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu scoped_refptr<Device> device = GetDevice(iter->second.device_name); 188fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (device) { 189fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu device->DeregisterInterface(iter->second); 190fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 191fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu interface_infos_.erase(iter); 192fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 193fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 194fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 195fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiubool DeviceInfo::IsWifiInterface(const string& iface_name) { 196fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu string contents; 197fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (!GetDeviceInfoContents(iface_name, kInterfaceUevent, &contents)) { 198fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(INFO) << "Interface " << iface_name << " has no uevent file"; 199fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return false; 200fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 201fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 202fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (contents.find(kInterfaceUeventWifiSignature) == string::npos) { 203fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(INFO) << "Interface " << iface_name << " is not a WiFi interface"; 204fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return false; 205fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 206fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 207fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return true; 208fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 209fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 210fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiubool DeviceInfo::GetDeviceInfoContents(const string& iface_name, 211fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu const string& path_name, 212fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu string* contents_out) { 213fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return base::ReadFileToString( 214fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu device_info_root_.Append(iface_name).Append(path_name), 215fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu contents_out); 216fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 217fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 218fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuvoid DeviceInfo::GetWiFiInterfaceInfo(int interface_index) { 219fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu shill::GetInterfaceMessage msg; 220fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (!msg.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX, 221fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu interface_index)) { 222fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(ERROR) << "Unable to set interface index attribute for " 223fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu "GetInterface message. Interface type cannot be " 224fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu "determined!"; 225fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return; 226fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 227fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 228fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu netlink_manager_->SendNl80211Message( 229fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu &msg, 230fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu Bind(&DeviceInfo::OnWiFiInterfaceInfoReceived, AsWeakPtr()), 231fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu Bind(&NetlinkManager::OnAckDoNothing), 232fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu Bind(&NetlinkManager::OnNetlinkMessageError)); 233fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 234fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 235fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuvoid DeviceInfo::OnWiFiInterfaceInfoReceived(const shill::Nl80211Message& msg) { 236fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (msg.command() != NL80211_CMD_NEW_INTERFACE) { 237fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(ERROR) << "Message is not a new interface response"; 238fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return; 239fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 240fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 241fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu uint32_t interface_index; 242fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFINDEX, 243fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu &interface_index)) { 244fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(ERROR) << "Message contains no interface index"; 245fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return; 246fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 247fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu uint32_t interface_type; 248fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFTYPE, 249fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu &interface_type)) { 250fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(ERROR) << "Message contains no interface type"; 251fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return; 252fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 253fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 254fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu map<uint32_t, Device::WiFiInterface>::iterator iter = 255fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu interface_infos_.find(interface_index); 256fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (iter == interface_infos_.end()) { 257fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(ERROR) << "Receive WiFi interface info for non-exist interface: " 258fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu << interface_index; 259fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return; 260fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 261fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu iter->second.iface_type = interface_type; 262fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 263fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Request PHY info, to know which Device to register this interface to. 264fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu GetWiFiInterfacePhyInfo(interface_index); 265fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 266fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 267fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuvoid DeviceInfo::GetWiFiInterfacePhyInfo(uint32_t iface_index) { 268fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu shill::GetWiphyMessage get_wiphy; 269fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu get_wiphy.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX, 270fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu iface_index); 271fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu netlink_manager_->SendNl80211Message( 272fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu &get_wiphy, 273fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu Bind(&DeviceInfo::OnWiFiInterfacePhyInfoReceived, 274fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu AsWeakPtr(), 275fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu iface_index), 276fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu Bind(&NetlinkManager::OnAckDoNothing), 277fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu Bind(&NetlinkManager::OnNetlinkMessageError)); 278fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 279fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 280fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuvoid DeviceInfo::OnWiFiInterfacePhyInfoReceived( 281fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu uint32_t iface_index, const shill::Nl80211Message& msg) { 282fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Verify NL80211_CMD_NEW_WIPHY. 283fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (msg.command() != shill::NewWiphyMessage::kCommand) { 284fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(ERROR) << "Received unexpected command:" 285fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu << msg.command(); 286fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return; 287fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 288fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 289fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu map<uint32_t, Device::WiFiInterface>::iterator iter = 290fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu interface_infos_.find(iface_index); 291fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (iter == interface_infos_.end()) { 292fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Interface is gone by the time we received its PHY info. 293fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(ERROR) << "Interface [" << iface_index 294fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu << "] is deleted when PHY info is received"; 295fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return; 296fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 297fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 298fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu string device_name; 299fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (!msg.const_attributes()->GetStringAttributeValue(NL80211_ATTR_WIPHY_NAME, 300fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu &device_name)) { 301fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_WIPHY_NAME"; 302fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return; 303fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 304fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 305fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu scoped_refptr<Device> device = GetDevice(device_name); 3061ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu // Create device if it is not enumerated yet. 307fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (!device) { 308f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu device = 309f933540bb968efa2744ee48b40ab713ccd358d51Peter Qiu new Device(manager_, device_name, device_identifier_++); 3101ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu device->ParseWiphyCapability(msg); 3111ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu 3121ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu // Register device 3131ff67a70eb6dea94ba8a6a836add9810536bec31Peter Qiu RegisterDevice(device); 314fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 315fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu iter->second.device_name = device_name; 316fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 317fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu device->RegisterInterface(iter->second); 318fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 319fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 320fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuvoid DeviceInfo::RegisterDevice(scoped_refptr<Device> device) { 321fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (!device) { 322fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return; 323fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 324fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu devices_[device->GetDeviceName()] = device; 325fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu // Register device with manager. 326fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu manager_->RegisterDevice(device); 327fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 328fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 329fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiuscoped_refptr<Device> DeviceInfo::GetDevice(const string& device_name) { 330fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu map<string, scoped_refptr<Device>>::iterator iter = 331fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu devices_.find(device_name); 332fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu if (iter == devices_.end()) { 333fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return nullptr; 334fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu } 335fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu return iter->second; 336fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} 337fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu 338fb39ba4b2ef92f0c9d19f6910a350cd8a14405a0Peter Qiu} // namespace apmanager 339