Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2016 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 "net/netlink_manager.h"
     18 
     19 #include <string>
     20 #include <vector>
     21 
     22 #include <linux/netlink.h>
     23 #include <linux/nl80211.h>
     24 #include <poll.h>
     25 #include <sys/socket.h>
     26 
     27 #include <android-base/logging.h>
     28 #include <utils/Timers.h>
     29 
     30 #include "net/mlme_event.h"
     31 #include "net/mlme_event_handler.h"
     32 #include "net/nl80211_attribute.h"
     33 #include "net/nl80211_packet.h"
     34 
     35 using android::base::unique_fd;
     36 using std::placeholders::_1;
     37 using std::string;
     38 using std::unique_ptr;
     39 using std::vector;
     40 
     41 namespace android {
     42 namespace wificond {
     43 
     44 namespace {
     45 
     46 // netlink.h suggests NLMSG_GOODSIZE to be at most 8192 bytes.
     47 constexpr int kReceiveBufferSize = 8 * 1024;
     48 constexpr uint32_t kBroadcastSequenceNumber = 0;
     49 constexpr int kMaximumNetlinkMessageWaitMilliSeconds = 300;
     50 uint8_t ReceiveBuffer[kReceiveBufferSize];
     51 
     52 void AppendPacket(vector<unique_ptr<const NL80211Packet>>* vec,
     53                   unique_ptr<const NL80211Packet> packet) {
     54   vec->push_back(std::move(packet));
     55 }
     56 
     57 }
     58 
     59 NetlinkManager::NetlinkManager(EventLoop* event_loop)
     60     : started_(false),
     61       event_loop_(event_loop),
     62       sequence_number_(0) {
     63 }
     64 
     65 NetlinkManager::~NetlinkManager() {
     66 }
     67 
     68 uint32_t NetlinkManager::GetSequenceNumber() {
     69   if (++sequence_number_ == kBroadcastSequenceNumber) {
     70     ++sequence_number_;
     71   }
     72   return sequence_number_;
     73 }
     74 
     75 void NetlinkManager::ReceivePacketAndRunHandler(int fd) {
     76   ssize_t len = read(fd, ReceiveBuffer, kReceiveBufferSize);
     77   if (len == -1) {
     78     LOG(ERROR) << "Failed to read packet from buffer";
     79     return;
     80   }
     81   if (len == 0) {
     82     return;
     83   }
     84   // There might be multiple message in one datagram payload.
     85   uint8_t* ptr = ReceiveBuffer;
     86   while (ptr < ReceiveBuffer + len) {
     87     // peek at the header.
     88     if (ptr + sizeof(nlmsghdr) > ReceiveBuffer + len) {
     89       LOG(ERROR) << "payload is broken.";
     90       return;
     91     }
     92     const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(ptr);
     93     unique_ptr<NL80211Packet> packet(
     94         new NL80211Packet(vector<uint8_t>(ptr, ptr + nl_header->nlmsg_len)));
     95     ptr += nl_header->nlmsg_len;
     96     if (!packet->IsValid()) {
     97       LOG(ERROR) << "Receive invalid packet";
     98       return;
     99     }
    100     // Some document says message from kernel should have port id equal 0.
    101     // However in practice this is not always true so we don't check that.
    102 
    103     uint32_t sequence_number = packet->GetMessageSequence();
    104 
    105     // Handle multicasts.
    106     if (sequence_number == kBroadcastSequenceNumber) {
    107       BroadcastHandler(std::move(packet));
    108       continue;
    109     }
    110 
    111     auto itr = message_handlers_.find(sequence_number);
    112     // There is no handler for this sequence number.
    113     if (itr == message_handlers_.end()) {
    114       LOG(WARNING) << "No handler for message: " << sequence_number;
    115       return;
    116     }
    117     // A multipart message is terminated by NLMSG_DONE.
    118     // In this case we don't need to run the handler.
    119     // NLMSG_NOOP means no operation, message must be discarded.
    120     uint32_t message_type =  packet->GetMessageType();
    121     if (message_type == NLMSG_DONE || message_type == NLMSG_NOOP) {
    122       message_handlers_.erase(itr);
    123       return;
    124     }
    125     if (message_type == NLMSG_OVERRUN) {
    126       LOG(ERROR) << "Get message overrun notification";
    127       message_handlers_.erase(itr);
    128       return;
    129     }
    130 
    131     // In case we receive a NLMSG_ERROR message:
    132     // NLMSG_ERROR could be either an error or an ACK.
    133     // It is an ACK message only when error code field is set to 0.
    134     // An ACK could be return when we explicitly request that with NLM_F_ACK.
    135     // An ERROR could be received on NLM_F_ACK or other failure cases.
    136     // We should still run handler in this case, leaving it for the caller
    137     // to decide what to do with the packet.
    138 
    139     bool is_multi = packet->IsMulti();
    140     // Run the handler.
    141     itr->second(std::move(packet));
    142     // Remove handler after processing.
    143     if (!is_multi) {
    144       message_handlers_.erase(itr);
    145     }
    146   }
    147 }
    148 
    149 void NetlinkManager::OnNewFamily(unique_ptr<const NL80211Packet> packet) {
    150   if (packet->GetMessageType() != GENL_ID_CTRL) {
    151     LOG(ERROR) << "Wrong message type for new family message";
    152     return;
    153   }
    154   if (packet->GetCommand() != CTRL_CMD_NEWFAMILY) {
    155     LOG(ERROR) << "Wrong command for new family message";
    156     return;
    157   }
    158   uint16_t family_id;
    159   if (!packet->GetAttributeValue(CTRL_ATTR_FAMILY_ID, &family_id)) {
    160     LOG(ERROR) << "Failed to get family id";
    161     return;
    162   }
    163   string family_name;
    164   if (!packet->GetAttributeValue(CTRL_ATTR_FAMILY_NAME, &family_name)) {
    165     LOG(ERROR) << "Failed to get family name";
    166     return;
    167   }
    168   if (family_name != NL80211_GENL_NAME) {
    169     LOG(WARNING) << "Ignoring none nl80211 netlink families";
    170   }
    171   MessageType nl80211_type(family_id);
    172   message_types_[family_name] = nl80211_type;
    173   // Exract multicast groups.
    174   NL80211NestedAttr multicast_groups(0);
    175   if (packet->GetAttribute(CTRL_ATTR_MCAST_GROUPS, &multicast_groups)) {
    176     vector<NL80211NestedAttr> groups;
    177     if (!multicast_groups.GetListOfNestedAttributes(&groups)) {
    178       return;
    179     }
    180     for (auto& group : groups) {
    181       string group_name;
    182       uint32_t group_id;
    183       if (!group.GetAttributeValue(CTRL_ATTR_MCAST_GRP_NAME, &group_name)) {
    184         LOG(ERROR) << "Failed to get group name";
    185       }
    186       if (!group.GetAttributeValue(CTRL_ATTR_MCAST_GRP_ID, &group_id)) {
    187         LOG(ERROR) << "Failed to get group id";
    188       }
    189       message_types_[family_name].groups[group_name] = group_id;
    190     }
    191   }
    192 }
    193 
    194 bool NetlinkManager::Start() {
    195   if (started_) {
    196     LOG(DEBUG) << "NetlinkManager is already started";
    197     return true;
    198   }
    199   bool setup_rt = SetupSocket(&sync_netlink_fd_);
    200   if (!setup_rt) {
    201     LOG(ERROR) << "Failed to setup synchronous netlink socket";
    202     return false;
    203   }
    204 
    205   setup_rt = SetupSocket(&async_netlink_fd_);
    206   if (!setup_rt) {
    207     LOG(ERROR) << "Failed to setup asynchronous netlink socket";
    208     return false;
    209   }
    210 
    211   // Request family id for nl80211 messages.
    212   if (!DiscoverFamilyId()) {
    213     return false;
    214   }
    215   // Watch socket.
    216   if (!WatchSocket(&async_netlink_fd_)) {
    217     return false;
    218   }
    219   // Subscribe kernel NL80211 broadcast of regulatory changes.
    220   if (!SubscribeToEvents(NL80211_MULTICAST_GROUP_REG)) {
    221     return false;
    222   }
    223   // Subscribe kernel NL80211 broadcast of scanning events.
    224   if (!SubscribeToEvents(NL80211_MULTICAST_GROUP_SCAN)) {
    225     return false;
    226   }
    227   // Subscribe kernel NL80211 broadcast of MLME events.
    228   if (!SubscribeToEvents(NL80211_MULTICAST_GROUP_MLME)) {
    229     return false;
    230   }
    231 
    232   started_ = true;
    233   return true;
    234 }
    235 
    236 bool NetlinkManager::IsStarted() const {
    237   return started_;
    238 }
    239 
    240 bool NetlinkManager::RegisterHandlerAndSendMessage(
    241     const NL80211Packet& packet,
    242     std::function<void(unique_ptr<const NL80211Packet>)> handler) {
    243   if (packet.IsDump()) {
    244     LOG(ERROR) << "Do not use asynchronous interface for dump request !";
    245     return false;
    246   }
    247   if (!SendMessageInternal(packet, async_netlink_fd_.get())) {
    248     return false;
    249   }
    250   message_handlers_[packet.GetMessageSequence()] = handler;
    251   return true;
    252 }
    253 
    254 bool NetlinkManager::SendMessageAndGetResponses(
    255     const NL80211Packet& packet,
    256     vector<unique_ptr<const NL80211Packet>>* response) {
    257   if (!SendMessageInternal(packet, sync_netlink_fd_.get())) {
    258     return false;
    259   }
    260   // Polling netlink socket, waiting for GetFamily reply.
    261   struct pollfd netlink_output;
    262   memset(&netlink_output, 0, sizeof(netlink_output));
    263   netlink_output.fd = sync_netlink_fd_.get();
    264   netlink_output.events = POLLIN;
    265 
    266   uint32_t sequence = packet.GetMessageSequence();
    267 
    268   int time_remaining = kMaximumNetlinkMessageWaitMilliSeconds;
    269   // Multipart messages may come with seperated datagrams, ending with a
    270   // NLMSG_DONE message.
    271   // ReceivePacketAndRunHandler() will remove the handler after receiving a
    272   // NLMSG_DONE message.
    273   message_handlers_[sequence] = std::bind(AppendPacket, response, _1);
    274 
    275   while (time_remaining > 0 &&
    276       message_handlers_.find(sequence) != message_handlers_.end()) {
    277     nsecs_t interval = systemTime(SYSTEM_TIME_MONOTONIC);
    278     int poll_return = poll(&netlink_output,
    279                            1,
    280                            time_remaining);
    281 
    282     if (poll_return == 0) {
    283       LOG(ERROR) << "Failed to poll netlink fd: time out ";
    284       message_handlers_.erase(sequence);
    285       return false;
    286     } else if (poll_return == -1) {
    287       LOG(ERROR) << "Failed to poll netlink fd: " << strerror(errno);
    288       message_handlers_.erase(sequence);
    289       return false;
    290     }
    291     ReceivePacketAndRunHandler(sync_netlink_fd_.get());
    292     interval = systemTime(SYSTEM_TIME_MONOTONIC) - interval;
    293     time_remaining -= static_cast<int>(ns2ms(interval));
    294   }
    295   if (time_remaining <= 0) {
    296     LOG(ERROR) << "Timeout waiting for netlink reply messages";
    297     message_handlers_.erase(sequence);
    298     return false;
    299   }
    300   return true;
    301 }
    302 
    303 bool NetlinkManager::SendMessageAndGetSingleResponse(
    304     const NL80211Packet& packet,
    305     unique_ptr<const NL80211Packet>* response) {
    306   unique_ptr<const NL80211Packet> response_or_error;
    307   if (!SendMessageAndGetSingleResponseOrError(packet, &response_or_error)) {
    308     return false;
    309   }
    310   if (response_or_error->GetMessageType() == NLMSG_ERROR) {
    311     // We use ERROR because we are not expecting to receive a ACK here.
    312     // In that case the caller should use |SendMessageAndGetAckOrError|.
    313     LOG(ERROR) << "Received error message: "
    314                << strerror(response_or_error->GetErrorCode());
    315     return false;
    316   }
    317   *response = std::move(response_or_error);
    318   return true;
    319 }
    320 
    321 bool NetlinkManager::SendMessageAndGetSingleResponseOrError(
    322     const NL80211Packet& packet,
    323     unique_ptr<const NL80211Packet>* response) {
    324   vector<unique_ptr<const NL80211Packet>> response_vec;
    325   if (!SendMessageAndGetResponses(packet, &response_vec)) {
    326     return false;
    327   }
    328   if (response_vec.size() != 1) {
    329     LOG(ERROR) << "Unexpected response size: " << response_vec.size();
    330     return false;
    331   }
    332 
    333   *response = std::move(response_vec[0]);
    334   return true;
    335 }
    336 
    337 bool NetlinkManager::SendMessageAndGetAckOrError(const NL80211Packet& packet,
    338                                                  int* error_code) {
    339   unique_ptr<const NL80211Packet> response;
    340   if (!SendMessageAndGetSingleResponseOrError(packet, &response)) {
    341     return false;
    342   }
    343   uint16_t type = response->GetMessageType();
    344   if (type != NLMSG_ERROR) {
    345     LOG(ERROR) << "Receive unexpected message type :" << type;
    346     return false;
    347   }
    348 
    349   *error_code = response->GetErrorCode();
    350   return true;
    351 }
    352 
    353 bool NetlinkManager::SendMessageAndGetAck(const NL80211Packet& packet) {
    354   int error_code;
    355   if (!SendMessageAndGetAckOrError(packet, &error_code)) {
    356     return false;
    357   }
    358   if (error_code != 0) {
    359     LOG(ERROR) << "Received error messsage: " << strerror(error_code);
    360     return false;
    361   }
    362 
    363   return true;
    364 }
    365 
    366 bool NetlinkManager::SendMessageInternal(const NL80211Packet& packet, int fd) {
    367   const vector<uint8_t>& data = packet.GetConstData();
    368   ssize_t bytes_sent =
    369       TEMP_FAILURE_RETRY(send(fd, data.data(), data.size(), 0));
    370   if (bytes_sent == -1) {
    371     LOG(ERROR) << "Failed to send netlink message: " << strerror(errno);
    372     return false;
    373   }
    374   return true;
    375 }
    376 
    377 bool NetlinkManager::SetupSocket(unique_fd* netlink_fd) {
    378   struct sockaddr_nl nladdr;
    379 
    380   memset(&nladdr, 0, sizeof(nladdr));
    381   nladdr.nl_family = AF_NETLINK;
    382 
    383   netlink_fd->reset(
    384       socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_GENERIC));
    385   if (netlink_fd->get() < 0) {
    386     LOG(ERROR) << "Failed to create netlink socket: " << strerror(errno);
    387     return false;
    388   }
    389   // Set maximum receive buffer size.
    390   // Datagram which is larger than this size will be discarded.
    391   if (setsockopt(netlink_fd->get(),
    392                  SOL_SOCKET,
    393                  SO_RCVBUFFORCE,
    394                  &kReceiveBufferSize,
    395                  sizeof(kReceiveBufferSize)) < 0) {
    396     LOG(ERROR) << "Failed to set uevent socket SO_RCVBUFFORCE option: " << strerror(errno);
    397     return false;
    398   }
    399   if (bind(netlink_fd->get(),
    400            reinterpret_cast<struct sockaddr*>(&nladdr),
    401            sizeof(nladdr)) < 0) {
    402     LOG(ERROR) << "Failed to bind netlink socket: " << strerror(errno);
    403     return false;
    404   }
    405   return true;
    406 }
    407 
    408 bool NetlinkManager::WatchSocket(unique_fd* netlink_fd) {
    409   // Watch socket
    410   bool watch_fd_rt = event_loop_->WatchFileDescriptor(
    411       netlink_fd->get(),
    412       EventLoop::kModeInput,
    413       std::bind(&NetlinkManager::ReceivePacketAndRunHandler, this, _1));
    414   if (!watch_fd_rt) {
    415     LOG(ERROR) << "Failed to watch fd: " << netlink_fd->get();
    416     return false;
    417   }
    418   return true;
    419 }
    420 
    421 uint16_t NetlinkManager::GetFamilyId() {
    422   return message_types_[NL80211_GENL_NAME].family_id;
    423 }
    424 
    425 bool NetlinkManager::DiscoverFamilyId() {
    426   NL80211Packet get_family_request(GENL_ID_CTRL,
    427                                    CTRL_CMD_GETFAMILY,
    428                                    GetSequenceNumber(),
    429                                    getpid());
    430   NL80211Attr<string> family_name(CTRL_ATTR_FAMILY_NAME, NL80211_GENL_NAME);
    431   get_family_request.AddAttribute(family_name);
    432   unique_ptr<const NL80211Packet> response;
    433   if (!SendMessageAndGetSingleResponse(get_family_request, &response)) {
    434     LOG(ERROR) << "Failed to get NL80211 family info";
    435     return false;
    436   }
    437   OnNewFamily(std::move(response));
    438   if (message_types_.find(NL80211_GENL_NAME) == message_types_.end()) {
    439     LOG(ERROR) << "Failed to get NL80211 family id";
    440     return false;
    441   }
    442   return true;
    443 }
    444 
    445 bool NetlinkManager::SubscribeToEvents(const string& group) {
    446   auto groups = message_types_[NL80211_GENL_NAME].groups;
    447   if (groups.find(group) == groups.end()) {
    448     LOG(ERROR) << "Failed to subscribe: group " << group << " doesn't exist";
    449     return false;
    450   }
    451   uint32_t group_id = groups[group];
    452   int err = setsockopt(async_netlink_fd_.get(),
    453                        SOL_NETLINK,
    454                        NETLINK_ADD_MEMBERSHIP,
    455                        &group_id,
    456                        sizeof(group_id));
    457   if (err < 0) {
    458     LOG(ERROR) << "Failed to setsockopt: " << strerror(errno);
    459     return false;
    460   }
    461   return true;
    462 }
    463 
    464 void NetlinkManager::BroadcastHandler(unique_ptr<const NL80211Packet> packet) {
    465   if (packet->GetMessageType() != GetFamilyId()) {
    466     LOG(ERROR) << "Wrong family id for multicast message";
    467     return;
    468   }
    469   uint32_t command = packet->GetCommand();
    470 
    471   if (command == NL80211_CMD_NEW_SCAN_RESULTS ||
    472       // Scan was aborted, for unspecified reasons.partial scan results may be
    473       // available.
    474       command == NL80211_CMD_SCAN_ABORTED) {
    475     OnScanResultsReady(std::move(packet));
    476     return;
    477   }
    478 
    479   if (command == NL80211_CMD_SCHED_SCAN_RESULTS ||
    480       command == NL80211_CMD_SCHED_SCAN_STOPPED) {
    481     OnSchedScanResultsReady(std::move(packet));
    482     return;
    483   }
    484 
    485 
    486   // Driver which supports SME uses both NL80211_CMD_AUTHENTICATE and
    487   // NL80211_CMD_ASSOCIATE, otherwise it uses NL80211_CMD_CONNECT
    488   // to notify a combination of authentication and association processses.
    489   // Currently we monitor CONNECT/ASSOCIATE/ROAM event for up-to-date
    490   // frequency and bssid.
    491   // TODO(nywang): Handle other MLME events, which help us track the
    492   // connection state better.
    493   if (command == NL80211_CMD_CONNECT ||
    494       command == NL80211_CMD_ASSOCIATE ||
    495       command == NL80211_CMD_ROAM ||
    496       command == NL80211_CMD_DISCONNECT ||
    497       command == NL80211_CMD_DISASSOCIATE) {
    498       OnMlmeEvent(std::move(packet));
    499      return;
    500   }
    501   if (command == NL80211_CMD_REG_CHANGE) {
    502     OnRegChangeEvent(std::move(packet));
    503     return;
    504   }
    505   // Station eventsFor AP mode.
    506   if (command == NL80211_CMD_NEW_STATION ||
    507       command == NL80211_CMD_DEL_STATION) {
    508     uint32_t if_index;
    509     if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
    510       LOG(WARNING) << "Failed to get interface index from station event";
    511       return;
    512     }
    513     const auto handler = on_station_event_handler_.find(if_index);
    514     if (handler != on_station_event_handler_.end()) {
    515       vector<uint8_t> mac_address;
    516       if (!packet->GetAttributeValue(NL80211_ATTR_MAC, &mac_address)) {
    517         LOG(WARNING) << "Failed to get mac address from station event";
    518         return;
    519       }
    520       if (command == NL80211_CMD_NEW_STATION) {
    521         handler->second(NEW_STATION, mac_address);
    522       } else {
    523         handler->second(DEL_STATION, mac_address);
    524       }
    525     }
    526     return;
    527   }
    528 }
    529 
    530 void NetlinkManager::OnRegChangeEvent(unique_ptr<const NL80211Packet> packet) {
    531   uint32_t wiphy_index;
    532   if (!packet->GetAttributeValue(NL80211_ATTR_WIPHY, &wiphy_index)) {
    533     LOG(ERROR) << "Failed to get wiphy index from reg changed message";
    534     return;
    535   }
    536 
    537   uint8_t reg_type;
    538   if (!packet->GetAttributeValue(NL80211_ATTR_REG_TYPE, &reg_type)) {
    539     LOG(ERROR) << "Failed to get NL80211_ATTR_REG_TYPE";
    540   }
    541 
    542   string country_code;
    543   // NL80211_REGDOM_TYPE_COUNTRY means the regulatory domain set is one that
    544   // pertains to a specific country
    545   if (reg_type == NL80211_REGDOM_TYPE_COUNTRY) {
    546     if (!packet->GetAttributeValue(NL80211_ATTR_REG_ALPHA2, &country_code)) {
    547       LOG(ERROR) << "Failed to get NL80211_ATTR_REG_ALPHA2";
    548       return;
    549     }
    550   } else if (reg_type == NL80211_REGDOM_TYPE_WORLD ||
    551       reg_type == NL80211_REGDOM_TYPE_CUSTOM_WORLD ||
    552       reg_type == NL80211_REGDOM_TYPE_INTERSECTION) {
    553     // NL80211_REGDOM_TYPE_WORLD refers to the world regulartory domain.
    554     // NL80211_REGDOM_TYPE_CUSTOM_WORLD refers to the driver specific world
    555     // regulartory domain.
    556     // NL80211_REGDOM_TYPE_INTERSECTION refers to an intersection between two
    557     // regulatory domains:
    558     // The previously set regulatory domain on the system and the last accepted
    559     // regulatory domain request to be processed.
    560     country_code = "";
    561   } else {
    562     LOG(ERROR) << "Unknown type of regulatory domain change: " << (int)reg_type;
    563     return;
    564   }
    565 
    566   const auto handler = on_reg_domain_changed_handler_.find(wiphy_index);
    567   if (handler == on_reg_domain_changed_handler_.end()) {
    568     LOG(DEBUG) << "No handler for country code changed event from wiphy"
    569                << "with index: " << wiphy_index;
    570     return;
    571   }
    572   handler->second(country_code);
    573 }
    574 
    575 void NetlinkManager::OnMlmeEvent(unique_ptr<const NL80211Packet> packet) {
    576   uint32_t if_index;
    577 
    578   if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
    579     LOG(ERROR) << "Failed to get interface index from a MLME event message";
    580     return;
    581   }
    582   const auto handler = on_mlme_event_handler_.find(if_index);
    583   if (handler == on_mlme_event_handler_.end()) {
    584     LOG(DEBUG) << "No handler for mlme event from interface"
    585                << " with index: " << if_index;
    586     return;
    587   }
    588   uint32_t command = packet->GetCommand();
    589   if (command == NL80211_CMD_CONNECT) {
    590     auto event = MlmeConnectEvent::InitFromPacket(packet.get());
    591     if (event != nullptr) {
    592       handler->second->OnConnect(std::move(event));
    593     }
    594     return;
    595   }
    596   if (command == NL80211_CMD_ASSOCIATE) {
    597     auto event = MlmeAssociateEvent::InitFromPacket(packet.get());
    598     if (event != nullptr) {
    599       handler->second->OnAssociate(std::move(event));
    600     }
    601     return;
    602   }
    603   if (command == NL80211_CMD_ROAM) {
    604     auto event = MlmeRoamEvent::InitFromPacket(packet.get());
    605     if (event != nullptr) {
    606       handler->second->OnRoam(std::move(event));
    607     }
    608     return;
    609   }
    610   if (command == NL80211_CMD_DISCONNECT) {
    611     auto event = MlmeDisconnectEvent::InitFromPacket(packet.get());
    612     if (event != nullptr) {
    613       handler->second->OnDisconnect(std::move(event));
    614     }
    615     return;
    616   }
    617   if (command == NL80211_CMD_DISASSOCIATE) {
    618     auto event = MlmeDisassociateEvent::InitFromPacket(packet.get());
    619     if (event != nullptr) {
    620       handler->second->OnDisassociate(std::move(event));
    621     }
    622     return;
    623   }
    624 
    625 }
    626 
    627 void NetlinkManager::OnSchedScanResultsReady(unique_ptr<const NL80211Packet> packet) {
    628   uint32_t if_index;
    629   if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
    630     LOG(ERROR) << "Failed to get interface index from scan result notification";
    631     return;
    632   }
    633 
    634   const auto handler = on_sched_scan_result_ready_handler_.find(if_index);
    635   if (handler == on_sched_scan_result_ready_handler_.end()) {
    636     LOG(DEBUG) << "No handler for scheduled scan result notification from"
    637                << " interface with index: " << if_index;
    638     return;
    639   }
    640   // Run scan result notification handler.
    641   handler->second(if_index, packet->GetCommand() == NL80211_CMD_SCHED_SCAN_STOPPED);
    642 }
    643 
    644 void NetlinkManager::OnScanResultsReady(unique_ptr<const NL80211Packet> packet) {
    645   uint32_t if_index;
    646   if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
    647     LOG(ERROR) << "Failed to get interface index from scan result notification";
    648     return;
    649   }
    650   bool aborted = false;
    651   if (packet->GetCommand() == NL80211_CMD_SCAN_ABORTED) {
    652     aborted = true;
    653   }
    654 
    655   const auto handler = on_scan_result_ready_handler_.find(if_index);
    656   if (handler == on_scan_result_ready_handler_.end()) {
    657     LOG(WARNING) << "No handler for scan result notification from interface"
    658                  << " with index: " << if_index;
    659     return;
    660   }
    661 
    662   vector<vector<uint8_t>> ssids;
    663   NL80211NestedAttr ssids_attr(0);
    664   if (!packet->GetAttribute(NL80211_ATTR_SCAN_SSIDS, &ssids_attr)) {
    665     if (!aborted) {
    666       LOG(WARNING) << "Failed to get scan ssids from scan result notification";
    667     }
    668   } else {
    669     if (!ssids_attr.GetListOfAttributeValues(&ssids)) {
    670       return;
    671     }
    672   }
    673   vector<uint32_t> freqs;
    674   NL80211NestedAttr freqs_attr(0);
    675   if (!packet->GetAttribute(NL80211_ATTR_SCAN_FREQUENCIES, &freqs_attr)) {
    676     if (!aborted) {
    677       LOG(WARNING) << "Failed to get scan freqs from scan result notification";
    678     }
    679   } else {
    680     if (!freqs_attr.GetListOfAttributeValues(&freqs)) {
    681       return;
    682     }
    683   }
    684   // Run scan result notification handler.
    685   handler->second(if_index, aborted, ssids, freqs);
    686 }
    687 
    688 void NetlinkManager::SubscribeStationEvent(
    689     uint32_t interface_index,
    690     OnStationEventHandler handler) {
    691   on_station_event_handler_[interface_index] = handler;
    692 }
    693 
    694 void NetlinkManager::UnsubscribeStationEvent(uint32_t interface_index) {
    695   on_station_event_handler_.erase(interface_index);
    696 }
    697 
    698 void NetlinkManager::SubscribeRegDomainChange(
    699     uint32_t wiphy_index,
    700     OnRegDomainChangedHandler handler) {
    701   on_reg_domain_changed_handler_[wiphy_index] = handler;
    702 }
    703 
    704 void NetlinkManager::UnsubscribeRegDomainChange(uint32_t wiphy_index) {
    705   on_reg_domain_changed_handler_.erase(wiphy_index);
    706 }
    707 
    708 void NetlinkManager::SubscribeScanResultNotification(
    709     uint32_t interface_index,
    710     OnScanResultsReadyHandler handler) {
    711   on_scan_result_ready_handler_[interface_index] = handler;
    712 }
    713 
    714 void NetlinkManager::UnsubscribeScanResultNotification(
    715     uint32_t interface_index) {
    716   on_scan_result_ready_handler_.erase(interface_index);
    717 }
    718 
    719 void NetlinkManager::SubscribeMlmeEvent(uint32_t interface_index,
    720                                         MlmeEventHandler* handler) {
    721   on_mlme_event_handler_[interface_index] = handler;
    722 }
    723 
    724 void NetlinkManager::UnsubscribeMlmeEvent(uint32_t interface_index) {
    725   on_mlme_event_handler_.erase(interface_index);
    726 }
    727 
    728 void NetlinkManager::SubscribeSchedScanResultNotification(
    729       uint32_t interface_index,
    730       OnSchedScanResultsReadyHandler handler) {
    731   on_sched_scan_result_ready_handler_[interface_index] = handler;
    732 }
    733 
    734 void NetlinkManager::UnsubscribeSchedScanResultNotification(
    735     uint32_t interface_index) {
    736   on_sched_scan_result_ready_handler_.erase(interface_index);
    737 }
    738 
    739 }  // namespace wificond
    740 }  // namespace android
    741