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