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
35using android::base::unique_fd;
36using std::placeholders::_1;
37using std::string;
38using std::unique_ptr;
39using std::vector;
40
41namespace android {
42namespace wificond {
43
44namespace {
45
46// netlink.h suggests NLMSG_GOODSIZE to be at most 8192 bytes.
47constexpr int kReceiveBufferSize = 8 * 1024;
48constexpr uint32_t kBroadcastSequenceNumber = 0;
49constexpr int kMaximumNetlinkMessageWaitMilliSeconds = 300;
50uint8_t ReceiveBuffer[kReceiveBufferSize];
51
52void AppendPacket(vector<unique_ptr<const NL80211Packet>>* vec,
53                  unique_ptr<const NL80211Packet> packet) {
54  vec->push_back(std::move(packet));
55}
56
57}
58
59NetlinkManager::NetlinkManager(EventLoop* event_loop)
60    : started_(false),
61      event_loop_(event_loop),
62      sequence_number_(0) {
63}
64
65NetlinkManager::~NetlinkManager() {
66}
67
68uint32_t NetlinkManager::GetSequenceNumber() {
69  if (++sequence_number_ == kBroadcastSequenceNumber) {
70    ++sequence_number_;
71  }
72  return sequence_number_;
73}
74
75void 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
149void 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
194bool 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
236bool NetlinkManager::IsStarted() const {
237  return started_;
238}
239
240bool 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
254bool 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
303bool 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
321bool 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
337bool 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
353bool 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
366bool 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
377bool 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
408bool 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
421uint16_t NetlinkManager::GetFamilyId() {
422  return message_types_[NL80211_GENL_NAME].family_id;
423}
424
425bool 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
445bool 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
464void 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
530void 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
575void 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
627void 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
644void 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
688void NetlinkManager::SubscribeStationEvent(
689    uint32_t interface_index,
690    OnStationEventHandler handler) {
691  on_station_event_handler_[interface_index] = handler;
692}
693
694void NetlinkManager::UnsubscribeStationEvent(uint32_t interface_index) {
695  on_station_event_handler_.erase(interface_index);
696}
697
698void NetlinkManager::SubscribeRegDomainChange(
699    uint32_t wiphy_index,
700    OnRegDomainChangedHandler handler) {
701  on_reg_domain_changed_handler_[wiphy_index] = handler;
702}
703
704void NetlinkManager::UnsubscribeRegDomainChange(uint32_t wiphy_index) {
705  on_reg_domain_changed_handler_.erase(wiphy_index);
706}
707
708void NetlinkManager::SubscribeScanResultNotification(
709    uint32_t interface_index,
710    OnScanResultsReadyHandler handler) {
711  on_scan_result_ready_handler_[interface_index] = handler;
712}
713
714void NetlinkManager::UnsubscribeScanResultNotification(
715    uint32_t interface_index) {
716  on_scan_result_ready_handler_.erase(interface_index);
717}
718
719void NetlinkManager::SubscribeMlmeEvent(uint32_t interface_index,
720                                        MlmeEventHandler* handler) {
721  on_mlme_event_handler_[interface_index] = handler;
722}
723
724void NetlinkManager::UnsubscribeMlmeEvent(uint32_t interface_index) {
725  on_mlme_event_handler_.erase(interface_index);
726}
727
728void NetlinkManager::SubscribeSchedScanResultNotification(
729      uint32_t interface_index,
730      OnSchedScanResultsReadyHandler handler) {
731  on_sched_scan_result_ready_handler_[interface_index] = handler;
732}
733
734void 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