• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AppendPacket(vector<unique_ptr<const NL80211Packet>> * vec,unique_ptr<const NL80211Packet> packet)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 
NetlinkManager(EventLoop * event_loop)59 NetlinkManager::NetlinkManager(EventLoop* event_loop)
60     : started_(false),
61       event_loop_(event_loop),
62       sequence_number_(0) {
63 }
64 
~NetlinkManager()65 NetlinkManager::~NetlinkManager() {
66 }
67 
GetSequenceNumber()68 uint32_t NetlinkManager::GetSequenceNumber() {
69   if (++sequence_number_ == kBroadcastSequenceNumber) {
70     ++sequence_number_;
71   }
72   return sequence_number_;
73 }
74 
ReceivePacketAndRunHandler(int fd)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 
OnNewFamily(unique_ptr<const NL80211Packet> packet)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 
Start()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 
IsStarted() const236 bool NetlinkManager::IsStarted() const {
237   return started_;
238 }
239 
RegisterHandlerAndSendMessage(const NL80211Packet & packet,std::function<void (unique_ptr<const NL80211Packet>)> handler)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 
SendMessageAndGetResponses(const NL80211Packet & packet,vector<unique_ptr<const NL80211Packet>> * response)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 
SendMessageAndGetSingleResponse(const NL80211Packet & packet,unique_ptr<const NL80211Packet> * response)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 
SendMessageAndGetSingleResponseOrError(const NL80211Packet & packet,unique_ptr<const NL80211Packet> * response)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 
SendMessageAndGetAckOrError(const NL80211Packet & packet,int * error_code)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 
SendMessageAndGetAck(const NL80211Packet & packet)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 
SendMessageInternal(const NL80211Packet & packet,int fd)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 
SetupSocket(unique_fd * netlink_fd)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 
WatchSocket(unique_fd * netlink_fd)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 
GetFamilyId()421 uint16_t NetlinkManager::GetFamilyId() {
422   return message_types_[NL80211_GENL_NAME].family_id;
423 }
424 
DiscoverFamilyId()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 
SubscribeToEvents(const string & group)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 
BroadcastHandler(unique_ptr<const NL80211Packet> packet)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 
OnRegChangeEvent(unique_ptr<const NL80211Packet> packet)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 
OnMlmeEvent(unique_ptr<const NL80211Packet> packet)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 
OnSchedScanResultsReady(unique_ptr<const NL80211Packet> packet)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 
OnScanResultsReady(unique_ptr<const NL80211Packet> packet)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 
SubscribeStationEvent(uint32_t interface_index,OnStationEventHandler handler)688 void NetlinkManager::SubscribeStationEvent(
689     uint32_t interface_index,
690     OnStationEventHandler handler) {
691   on_station_event_handler_[interface_index] = handler;
692 }
693 
UnsubscribeStationEvent(uint32_t interface_index)694 void NetlinkManager::UnsubscribeStationEvent(uint32_t interface_index) {
695   on_station_event_handler_.erase(interface_index);
696 }
697 
SubscribeRegDomainChange(uint32_t wiphy_index,OnRegDomainChangedHandler handler)698 void NetlinkManager::SubscribeRegDomainChange(
699     uint32_t wiphy_index,
700     OnRegDomainChangedHandler handler) {
701   on_reg_domain_changed_handler_[wiphy_index] = handler;
702 }
703 
UnsubscribeRegDomainChange(uint32_t wiphy_index)704 void NetlinkManager::UnsubscribeRegDomainChange(uint32_t wiphy_index) {
705   on_reg_domain_changed_handler_.erase(wiphy_index);
706 }
707 
SubscribeScanResultNotification(uint32_t interface_index,OnScanResultsReadyHandler handler)708 void NetlinkManager::SubscribeScanResultNotification(
709     uint32_t interface_index,
710     OnScanResultsReadyHandler handler) {
711   on_scan_result_ready_handler_[interface_index] = handler;
712 }
713 
UnsubscribeScanResultNotification(uint32_t interface_index)714 void NetlinkManager::UnsubscribeScanResultNotification(
715     uint32_t interface_index) {
716   on_scan_result_ready_handler_.erase(interface_index);
717 }
718 
SubscribeMlmeEvent(uint32_t interface_index,MlmeEventHandler * handler)719 void NetlinkManager::SubscribeMlmeEvent(uint32_t interface_index,
720                                         MlmeEventHandler* handler) {
721   on_mlme_event_handler_[interface_index] = handler;
722 }
723 
UnsubscribeMlmeEvent(uint32_t interface_index)724 void NetlinkManager::UnsubscribeMlmeEvent(uint32_t interface_index) {
725   on_mlme_event_handler_.erase(interface_index);
726 }
727 
SubscribeSchedScanResultNotification(uint32_t interface_index,OnSchedScanResultsReadyHandler handler)728 void NetlinkManager::SubscribeSchedScanResultNotification(
729       uint32_t interface_index,
730       OnSchedScanResultsReadyHandler handler) {
731   on_sched_scan_result_ready_handler_[interface_index] = handler;
732 }
733 
UnsubscribeSchedScanResultNotification(uint32_t interface_index)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