• 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 "wificond/net/netlink_utils.h"
18 
19 #include <bitset>
20 #include <map>
21 #include <string>
22 #include <vector>
23 
24 #include <linux/netlink.h>
25 
26 #include <android-base/logging.h>
27 
28 #include "wificond/net/kernel-header-latest/nl80211.h"
29 #include "wificond/net/mlme_event_handler.h"
30 #include "wificond/net/nl80211_packet.h"
31 
32 using std::make_pair;
33 using std::make_unique;
34 using std::map;
35 using std::move;
36 using std::string;
37 using std::unique_ptr;
38 using std::vector;
39 
40 namespace android {
41 namespace wificond {
42 
43 namespace {
44 
45 uint32_t k2GHzFrequencyLowerBound = 2400;
46 uint32_t k2GHzFrequencyUpperBound = 2500;
47 
48 uint32_t k5GHzFrequencyLowerBound = 5000;
49 // This upper bound will exclude any 5.9Ghz channels which belong to 802.11p
50 // for "vehicular communication systems".
51 uint32_t k5GHzFrequencyUpperBound = 5850;
52 
IsExtFeatureFlagSet(const std::vector<uint8_t> & ext_feature_flags_bytes,enum nl80211_ext_feature_index ext_feature_flag)53 bool IsExtFeatureFlagSet(
54     const std::vector<uint8_t>& ext_feature_flags_bytes,
55     enum nl80211_ext_feature_index ext_feature_flag) {
56   static_assert(NUM_NL80211_EXT_FEATURES <= SIZE_MAX,
57                 "Ext feature values doesn't fit in |size_t|");
58   // TODO:This is an unsafe cast because this assumes that the values
59   // are always unsigned!
60   size_t ext_feature_flag_idx = static_cast<size_t>(ext_feature_flag);
61   size_t ext_feature_flag_byte_pos = ext_feature_flag_idx / 8;
62   size_t ext_feature_flag_bit_pos = ext_feature_flag_idx % 8;
63   if (ext_feature_flag_byte_pos >= ext_feature_flags_bytes.size()) {
64     return false;
65   }
66   uint8_t ext_feature_flag_byte =
67       ext_feature_flags_bytes[ext_feature_flag_byte_pos];
68   return (ext_feature_flag_byte & (1U << ext_feature_flag_bit_pos));
69 }
70 }  // namespace
71 
WiphyFeatures(uint32_t feature_flags,const std::vector<uint8_t> & ext_feature_flags_bytes)72 WiphyFeatures::WiphyFeatures(uint32_t feature_flags,
73                              const std::vector<uint8_t>& ext_feature_flags_bytes)
74     : supports_random_mac_oneshot_scan(
75             feature_flags & NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR),
76         supports_random_mac_sched_scan(
77             feature_flags & NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR) {
78   supports_low_span_oneshot_scan =
79       IsExtFeatureFlagSet(ext_feature_flags_bytes,
80                           NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
81   supports_low_power_oneshot_scan =
82       IsExtFeatureFlagSet(ext_feature_flags_bytes,
83                           NL80211_EXT_FEATURE_LOW_POWER_SCAN);
84   supports_high_accuracy_oneshot_scan =
85       IsExtFeatureFlagSet(ext_feature_flags_bytes,
86                           NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
87 }
88 
NetlinkUtils(NetlinkManager * netlink_manager)89 NetlinkUtils::NetlinkUtils(NetlinkManager* netlink_manager)
90     : netlink_manager_(netlink_manager) {
91   if (!netlink_manager_->IsStarted()) {
92     netlink_manager_->Start();
93   }
94   uint32_t protocol_features = 0;
95   supports_split_wiphy_dump_ = GetProtocolFeatures(&protocol_features) &&
96       (protocol_features & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP);
97 }
98 
~NetlinkUtils()99 NetlinkUtils::~NetlinkUtils() {}
100 
GetWiphyIndex(uint32_t * out_wiphy_index)101 bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index) {
102   NL80211Packet get_wiphy(
103       netlink_manager_->GetFamilyId(),
104       NL80211_CMD_GET_WIPHY,
105       netlink_manager_->GetSequenceNumber(),
106       getpid());
107   get_wiphy.AddFlag(NLM_F_DUMP);
108   vector<unique_ptr<const NL80211Packet>> response;
109   if (!netlink_manager_->SendMessageAndGetResponses(get_wiphy, &response))  {
110     LOG(ERROR) << "NL80211_CMD_GET_WIPHY dump failed";
111     return false;
112   }
113   if (response.empty()) {
114     LOG(DEBUG) << "No wiphy is found";
115     return false;
116   }
117   for (auto& packet : response) {
118     if (packet->GetMessageType() == NLMSG_ERROR) {
119       LOG(ERROR) << "Receive ERROR message: "
120                  << strerror(packet->GetErrorCode());
121       return false;
122     }
123     if (packet->GetMessageType() != netlink_manager_->GetFamilyId()) {
124       LOG(ERROR) << "Wrong message type for new interface message: "
125                  << packet->GetMessageType();
126       return false;
127     }
128     if (packet->GetCommand() != NL80211_CMD_NEW_WIPHY) {
129       LOG(ERROR) << "Wrong command in response to "
130                  << "a wiphy dump request: "
131                  << static_cast<int>(packet->GetCommand());
132       return false;
133     }
134     if (!packet->GetAttributeValue(NL80211_ATTR_WIPHY, out_wiphy_index)) {
135       LOG(ERROR) << "Failed to get wiphy index from reply message";
136       return false;
137     }
138   }
139   return true;
140 }
141 
GetInterfaces(uint32_t wiphy_index,vector<InterfaceInfo> * interface_info)142 bool NetlinkUtils::GetInterfaces(uint32_t wiphy_index,
143                                  vector<InterfaceInfo>* interface_info) {
144   NL80211Packet get_interfaces(
145       netlink_manager_->GetFamilyId(),
146       NL80211_CMD_GET_INTERFACE,
147       netlink_manager_->GetSequenceNumber(),
148       getpid());
149 
150   get_interfaces.AddFlag(NLM_F_DUMP);
151   get_interfaces.AddAttribute(
152       NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_index));
153   vector<unique_ptr<const NL80211Packet>> response;
154   if (!netlink_manager_->SendMessageAndGetResponses(get_interfaces, &response)) {
155     LOG(ERROR) << "NL80211_CMD_GET_INTERFACE dump failed";
156     return false;
157   }
158   if (response.empty()) {
159     LOG(ERROR) << "No interface is found";
160     return false;
161   }
162   for (auto& packet : response) {
163     if (packet->GetMessageType() == NLMSG_ERROR) {
164       LOG(ERROR) << "Receive ERROR message: "
165                  << strerror(packet->GetErrorCode());
166       return false;
167     }
168     if (packet->GetMessageType() != netlink_manager_->GetFamilyId()) {
169       LOG(ERROR) << "Wrong message type for new interface message: "
170                  << packet->GetMessageType();
171       return false;
172     }
173     if (packet->GetCommand() != NL80211_CMD_NEW_INTERFACE) {
174       LOG(ERROR) << "Wrong command in response to "
175                  << "an interface dump request: "
176                  << static_cast<int>(packet->GetCommand());
177       return false;
178     }
179 
180     // In some situations, it has been observed that the kernel tells us
181     // about a pseudo interface that does not have a real netdev.  In this
182     // case, responses will have a NL80211_ATTR_WDEV, and not the expected
183     // IFNAME/IFINDEX. In this case we just skip these pseudo interfaces.
184     uint32_t if_index;
185     if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
186       LOG(DEBUG) << "Failed to get interface index";
187       continue;
188     }
189 
190     // Today we don't check NL80211_ATTR_IFTYPE because at this point of time
191     // driver always reports that interface is in STATION mode. Even when we
192     // are asking interfaces infomation on behalf of tethering, it is still so
193     // because hostapd is supposed to set interface to AP mode later.
194 
195     string if_name;
196     if (!packet->GetAttributeValue(NL80211_ATTR_IFNAME, &if_name)) {
197       LOG(WARNING) << "Failed to get interface name";
198       continue;
199     }
200 
201     vector<uint8_t> if_mac_addr;
202     if (!packet->GetAttributeValue(NL80211_ATTR_MAC, &if_mac_addr)) {
203       LOG(WARNING) << "Failed to get interface mac address";
204       continue;
205     }
206 
207     interface_info->emplace_back(if_index, if_name, if_mac_addr);
208   }
209 
210   return true;
211 }
212 
SetInterfaceMode(uint32_t interface_index,InterfaceMode mode)213 bool NetlinkUtils::SetInterfaceMode(uint32_t interface_index,
214                                     InterfaceMode mode) {
215   uint32_t set_to_mode = NL80211_IFTYPE_UNSPECIFIED;
216   if (mode == STATION_MODE) {
217     set_to_mode = NL80211_IFTYPE_STATION;
218   } else {
219     LOG(ERROR) << "Unexpected mode for interface with index: "
220                << interface_index;
221     return false;
222   }
223   NL80211Packet set_interface_mode(
224       netlink_manager_->GetFamilyId(),
225       NL80211_CMD_SET_INTERFACE,
226       netlink_manager_->GetSequenceNumber(),
227       getpid());
228   // Force an ACK response upon success.
229   set_interface_mode.AddFlag(NLM_F_ACK);
230 
231   set_interface_mode.AddAttribute(
232       NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, interface_index));
233   set_interface_mode.AddAttribute(
234       NL80211Attr<uint32_t>(NL80211_ATTR_IFTYPE, set_to_mode));
235 
236   if (!netlink_manager_->SendMessageAndGetAck(set_interface_mode)) {
237     LOG(ERROR) << "NL80211_CMD_SET_INTERFACE failed";
238     return false;
239   }
240 
241   return true;
242 }
243 
GetProtocolFeatures(uint32_t * features)244 bool NetlinkUtils::GetProtocolFeatures(uint32_t* features) {
245   NL80211Packet get_protocol_features(
246       netlink_manager_->GetFamilyId(),
247       NL80211_CMD_GET_PROTOCOL_FEATURES,
248       netlink_manager_->GetSequenceNumber(),
249       getpid());
250   unique_ptr<const NL80211Packet> response;
251   if (!netlink_manager_->SendMessageAndGetSingleResponse(get_protocol_features,
252                                                          &response)) {
253     LOG(ERROR) << "NL80211_CMD_GET_PROTOCOL_FEATURES failed";
254     return false;
255   }
256   if (!response->GetAttributeValue(NL80211_ATTR_PROTOCOL_FEATURES, features)) {
257     LOG(ERROR) << "Failed to get NL80211_ATTR_PROTOCOL_FEATURES";
258     return false;
259   }
260   return true;
261 }
262 
GetWiphyInfo(uint32_t wiphy_index,BandInfo * out_band_info,ScanCapabilities * out_scan_capabilities,WiphyFeatures * out_wiphy_features)263 bool NetlinkUtils::GetWiphyInfo(
264     uint32_t wiphy_index,
265     BandInfo* out_band_info,
266     ScanCapabilities* out_scan_capabilities,
267     WiphyFeatures* out_wiphy_features) {
268   NL80211Packet get_wiphy(
269       netlink_manager_->GetFamilyId(),
270       NL80211_CMD_GET_WIPHY,
271       netlink_manager_->GetSequenceNumber(),
272       getpid());
273   get_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_index));
274   if (supports_split_wiphy_dump_) {
275     get_wiphy.AddFlagAttribute(NL80211_ATTR_SPLIT_WIPHY_DUMP);
276     get_wiphy.AddFlag(NLM_F_DUMP);
277   }
278   vector<unique_ptr<const NL80211Packet>> response;
279   if (!netlink_manager_->SendMessageAndGetResponses(get_wiphy, &response))  {
280     LOG(ERROR) << "NL80211_CMD_GET_WIPHY dump failed";
281     return false;
282   }
283 
284   vector<NL80211Packet> packet_per_wiphy;
285   if (supports_split_wiphy_dump_) {
286     if (!MergePacketsForSplitWiphyDump(response, &packet_per_wiphy)) {
287       LOG(WARNING) << "Failed to merge responses from split wiphy dump";
288     }
289   } else {
290     for (auto& packet : response) {
291       packet_per_wiphy.push_back(move(*(packet.release())));
292     }
293   }
294 
295   for (const auto& packet : packet_per_wiphy) {
296     uint32_t current_wiphy_index;
297     if (!packet.GetAttributeValue(NL80211_ATTR_WIPHY, &current_wiphy_index) ||
298         // Not the wihpy we requested.
299         current_wiphy_index != wiphy_index) {
300       continue;
301     }
302     if (ParseWiphyInfoFromPacket(packet, out_band_info,
303                                  out_scan_capabilities, out_wiphy_features)) {
304       return true;
305     }
306   }
307 
308   LOG(ERROR) << "Failed to find expected wiphy info "
309              << "from NL80211_CMD_GET_WIPHY responses";
310   return false;
311 }
312 
ParseWiphyInfoFromPacket(const NL80211Packet & packet,BandInfo * out_band_info,ScanCapabilities * out_scan_capabilities,WiphyFeatures * out_wiphy_features)313 bool NetlinkUtils::ParseWiphyInfoFromPacket(
314     const NL80211Packet& packet,
315     BandInfo* out_band_info,
316     ScanCapabilities* out_scan_capabilities,
317     WiphyFeatures* out_wiphy_features) {
318   if (packet.GetCommand() != NL80211_CMD_NEW_WIPHY) {
319     LOG(ERROR) << "Wrong command in response to a get wiphy request: "
320                << static_cast<int>(packet.GetCommand());
321     return false;
322   }
323   if (!ParseBandInfo(&packet, out_band_info) ||
324       !ParseScanCapabilities(&packet, out_scan_capabilities)) {
325     return false;
326   }
327   uint32_t feature_flags;
328   if (!packet.GetAttributeValue(NL80211_ATTR_FEATURE_FLAGS,
329                                  &feature_flags)) {
330     LOG(ERROR) << "Failed to get NL80211_ATTR_FEATURE_FLAGS";
331     return false;
332   }
333   std::vector<uint8_t> ext_feature_flags_bytes;
334   if (!packet.GetAttributeValue(NL80211_ATTR_EXT_FEATURES,
335                                 &ext_feature_flags_bytes)) {
336     LOG(WARNING) << "Failed to get NL80211_ATTR_EXT_FEATURES";
337   }
338   *out_wiphy_features = WiphyFeatures(feature_flags,
339                                       ext_feature_flags_bytes);
340   return true;
341 }
342 
ParseScanCapabilities(const NL80211Packet * const packet,ScanCapabilities * out_scan_capabilities)343 bool NetlinkUtils::ParseScanCapabilities(
344     const NL80211Packet* const packet,
345     ScanCapabilities* out_scan_capabilities) {
346   uint8_t max_num_scan_ssids;
347   if (!packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
348                                    &max_num_scan_ssids)) {
349     LOG(ERROR) << "Failed to get the capacity of maximum number of scan ssids";
350     return false;
351   }
352 
353   uint8_t max_num_sched_scan_ssids;
354   if (!packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
355                                  &max_num_sched_scan_ssids)) {
356     LOG(ERROR) << "Failed to get the capacity of "
357                << "maximum number of scheduled scan ssids";
358     return false;
359   }
360 
361   // Use default value 0 for scan plan capabilities if attributes are missing.
362   uint32_t max_num_scan_plans = 0;
363   packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
364                             &max_num_scan_plans);
365   uint32_t max_scan_plan_interval = 0;
366   packet->GetAttributeValue(NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
367                             &max_scan_plan_interval);
368   uint32_t max_scan_plan_iterations = 0;
369   packet->GetAttributeValue(NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
370                             &max_scan_plan_iterations);
371 
372   uint8_t max_match_sets;
373   if (!packet->GetAttributeValue(NL80211_ATTR_MAX_MATCH_SETS,
374                                    &max_match_sets)) {
375     LOG(ERROR) << "Failed to get the capacity of maximum number of match set"
376                << "of a scheduled scan";
377     return false;
378   }
379   *out_scan_capabilities = ScanCapabilities(max_num_scan_ssids,
380                                             max_num_sched_scan_ssids,
381                                             max_match_sets,
382                                             max_num_scan_plans,
383                                             max_scan_plan_interval,
384                                             max_scan_plan_iterations);
385   return true;
386 }
387 
ParseBandInfo(const NL80211Packet * const packet,BandInfo * out_band_info)388 bool NetlinkUtils::ParseBandInfo(const NL80211Packet* const packet,
389                                  BandInfo* out_band_info) {
390 
391   NL80211NestedAttr bands_attr(0);
392   if (!packet->GetAttribute(NL80211_ATTR_WIPHY_BANDS, &bands_attr)) {
393     LOG(ERROR) << "Failed to get NL80211_ATTR_WIPHY_BANDS";
394     return false;
395   }
396   vector<NL80211NestedAttr> bands;
397   if (!bands_attr.GetListOfNestedAttributes(&bands)) {
398     LOG(ERROR) << "Failed to get bands within NL80211_ATTR_WIPHY_BANDS";
399     return false;
400   }
401   vector<uint32_t> frequencies_2g;
402   vector<uint32_t> frequencies_5g;
403   vector<uint32_t> frequencies_dfs;
404   for (unsigned int band_index = 0; band_index < bands.size(); band_index++) {
405     NL80211NestedAttr freqs_attr(0);
406     if (!bands[band_index].GetAttribute(NL80211_BAND_ATTR_FREQS, &freqs_attr)) {
407       LOG(DEBUG) << "Failed to get NL80211_BAND_ATTR_FREQS";
408       continue;
409     }
410     vector<NL80211NestedAttr> freqs;
411     if (!freqs_attr.GetListOfNestedAttributes(&freqs)) {
412       LOG(ERROR) << "Failed to get frequencies within NL80211_BAND_ATTR_FREQS";
413       continue;
414     }
415     for (auto& freq : freqs) {
416       uint32_t frequency_value;
417       if (!freq.GetAttributeValue(NL80211_FREQUENCY_ATTR_FREQ,
418                                   &frequency_value)) {
419         LOG(DEBUG) << "Failed to get NL80211_FREQUENCY_ATTR_FREQ";
420         continue;
421       }
422       // Channel is disabled in current regulatory domain.
423       if (freq.HasAttribute(NL80211_FREQUENCY_ATTR_DISABLED)) {
424         continue;
425       }
426       if (frequency_value > k2GHzFrequencyLowerBound &&
427             frequency_value < k2GHzFrequencyUpperBound) {
428           frequencies_2g.push_back(frequency_value);
429       } else if (frequency_value > k5GHzFrequencyLowerBound &&
430             frequency_value < k5GHzFrequencyUpperBound) {
431         // If this is an available/usable DFS frequency, we should save it to
432         // DFS frequencies list.
433         uint32_t dfs_state;
434         if (freq.GetAttributeValue(NL80211_FREQUENCY_ATTR_DFS_STATE,
435                                    &dfs_state) &&
436             (dfs_state == NL80211_DFS_AVAILABLE ||
437                  dfs_state == NL80211_DFS_USABLE)) {
438           frequencies_dfs.push_back(frequency_value);
439           continue;
440         }
441 
442         // Put non-dfs passive-only channels into the dfs category.
443         // This aligns with what framework always assumes.
444         if (freq.HasAttribute(NL80211_FREQUENCY_ATTR_NO_IR)) {
445           frequencies_dfs.push_back(frequency_value);
446           continue;
447         }
448 
449         // Otherwise, this is a regular 5g frequency.
450         frequencies_5g.push_back(frequency_value);
451       }
452 
453     }
454   }
455   *out_band_info = BandInfo(frequencies_2g, frequencies_5g, frequencies_dfs);
456   return true;
457 }
458 
GetStationInfo(uint32_t interface_index,const vector<uint8_t> & mac_address,StationInfo * out_station_info)459 bool NetlinkUtils::GetStationInfo(uint32_t interface_index,
460                                   const vector<uint8_t>& mac_address,
461                                   StationInfo* out_station_info) {
462   NL80211Packet get_station(
463       netlink_manager_->GetFamilyId(),
464       NL80211_CMD_GET_STATION,
465       netlink_manager_->GetSequenceNumber(),
466       getpid());
467   get_station.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX,
468                                                  interface_index));
469   get_station.AddAttribute(NL80211Attr<vector<uint8_t>>(NL80211_ATTR_MAC,
470                                                         mac_address));
471 
472   unique_ptr<const NL80211Packet> response;
473   if (!netlink_manager_->SendMessageAndGetSingleResponse(get_station,
474                                                          &response)) {
475     LOG(ERROR) << "NL80211_CMD_GET_STATION failed";
476     return false;
477   }
478   if (response->GetCommand() != NL80211_CMD_NEW_STATION) {
479     LOG(ERROR) << "Wrong command in response to a get station request: "
480                << static_cast<int>(response->GetCommand());
481     return false;
482   }
483   NL80211NestedAttr sta_info(0);
484   if (!response->GetAttribute(NL80211_ATTR_STA_INFO, &sta_info)) {
485     LOG(ERROR) << "Failed to get NL80211_ATTR_STA_INFO";
486     return false;
487   }
488   int32_t tx_good, tx_bad;
489   if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_PACKETS, &tx_good)) {
490     LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_PACKETS";
491     return false;
492   }
493   if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_FAILED, &tx_bad)) {
494     LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_FAILED";
495     return false;
496   }
497   int8_t current_rssi;
498   if (!sta_info.GetAttributeValue(NL80211_STA_INFO_SIGNAL, &current_rssi)) {
499     LOG(ERROR) << "Failed to get NL80211_STA_INFO_SIGNAL";
500     return false;
501   }
502   NL80211NestedAttr tx_bitrate_attr(0);
503   if (!sta_info.GetAttribute(NL80211_STA_INFO_TX_BITRATE,
504                             &tx_bitrate_attr)) {
505     LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_BITRATE";
506     return false;
507   }
508   uint32_t tx_bitrate;
509   if (!tx_bitrate_attr.GetAttributeValue(NL80211_RATE_INFO_BITRATE32,
510                                          &tx_bitrate)) {
511     LOG(ERROR) << "Failed to get NL80211_RATE_INFO_BITRATE32";
512     return false;
513   }
514 
515   *out_station_info = StationInfo(tx_good, tx_bad, tx_bitrate, current_rssi);
516   return true;
517 }
518 
519 // This is a helper function for merging split NL80211_CMD_NEW_WIPHY packets.
520 // For example:
521 // First NL80211_CMD_NEW_WIPHY has attribute A with payload 0x1234.
522 // Second NL80211_CMD_NEW_WIPHY has attribute A with payload 0x5678.
523 // The generated NL80211_CMD_NEW_WIPHY will have attribute A with
524 // payload 0x12345678.
525 // NL80211_ATTR_WIPHY, NL80211_ATTR_IFINDEX, and NL80211_ATTR_WDEV
526 // are used for filtering packets so we know which packets should
527 // be merged together.
MergePacketsForSplitWiphyDump(const vector<unique_ptr<const NL80211Packet>> & split_dump_info,vector<NL80211Packet> * packet_per_wiphy)528 bool NetlinkUtils::MergePacketsForSplitWiphyDump(
529     const vector<unique_ptr<const NL80211Packet>>& split_dump_info,
530     vector<NL80211Packet>* packet_per_wiphy) {
531   map<uint32_t, map<int, BaseNL80211Attr>> attr_by_wiphy_and_id;
532 
533   // Construct the map using input packets.
534   for (const auto& packet : split_dump_info) {
535     uint32_t wiphy_index;
536     if (!packet->GetAttributeValue(NL80211_ATTR_WIPHY, &wiphy_index)) {
537       LOG(ERROR) << "Failed to get NL80211_ATTR_WIPHY from wiphy split dump";
538       return false;
539     }
540     vector<BaseNL80211Attr> attributes;
541     if (!packet->GetAllAttributes(&attributes)) {
542       return false;
543     }
544     for (auto& attr : attributes) {
545       int attr_id = attr.GetAttributeId();
546       if (attr_id != NL80211_ATTR_WIPHY &&
547           attr_id != NL80211_ATTR_IFINDEX &&
548               attr_id != NL80211_ATTR_WDEV) {
549           auto attr_id_and_attr =
550               attr_by_wiphy_and_id[wiphy_index].find(attr_id);
551           if (attr_id_and_attr == attr_by_wiphy_and_id[wiphy_index].end()) {
552             attr_by_wiphy_and_id[wiphy_index].
553                 insert(make_pair(attr_id, move(attr)));
554           } else {
555             attr_id_and_attr->second.Merge(attr);
556           }
557       }
558     }
559   }
560 
561   // Generate output packets using the constructed map.
562   for (const auto& wiphy_and_attributes : attr_by_wiphy_and_id) {
563     NL80211Packet new_wiphy(0, NL80211_CMD_NEW_WIPHY, 0, 0);
564     new_wiphy.AddAttribute(
565         NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_and_attributes.first));
566     for (const auto& attr : wiphy_and_attributes.second) {
567       new_wiphy.AddAttribute(attr.second);
568     }
569     packet_per_wiphy->emplace_back(move(new_wiphy));
570   }
571   return true;
572 }
573 
GetCountryCode(string * out_country_code)574 bool NetlinkUtils::GetCountryCode(string* out_country_code) {
575   NL80211Packet get_country_code(
576       netlink_manager_->GetFamilyId(),
577       NL80211_CMD_GET_REG,
578       netlink_manager_->GetSequenceNumber(),
579       getpid());
580   unique_ptr<const NL80211Packet> response;
581   if (!netlink_manager_->SendMessageAndGetSingleResponse(get_country_code,
582                                                          &response)) {
583     LOG(ERROR) << "NL80211_CMD_GET_REG failed";
584     return false;
585   }
586   if (!response->GetAttributeValue(NL80211_ATTR_REG_ALPHA2, out_country_code)) {
587     LOG(ERROR) << "Get NL80211_ATTR_REG_ALPHA2 failed";
588     return false;
589   }
590   return true;
591 }
592 
SubscribeMlmeEvent(uint32_t interface_index,MlmeEventHandler * handler)593 void NetlinkUtils::SubscribeMlmeEvent(uint32_t interface_index,
594                                       MlmeEventHandler* handler) {
595   netlink_manager_->SubscribeMlmeEvent(interface_index, handler);
596 }
597 
UnsubscribeMlmeEvent(uint32_t interface_index)598 void NetlinkUtils::UnsubscribeMlmeEvent(uint32_t interface_index) {
599   netlink_manager_->UnsubscribeMlmeEvent(interface_index);
600 }
601 
SubscribeRegDomainChange(uint32_t wiphy_index,OnRegDomainChangedHandler handler)602 void NetlinkUtils::SubscribeRegDomainChange(
603     uint32_t wiphy_index,
604     OnRegDomainChangedHandler handler) {
605   netlink_manager_->SubscribeRegDomainChange(wiphy_index, handler);
606 }
607 
UnsubscribeRegDomainChange(uint32_t wiphy_index)608 void NetlinkUtils::UnsubscribeRegDomainChange(uint32_t wiphy_index) {
609   netlink_manager_->UnsubscribeRegDomainChange(wiphy_index);
610 }
611 
SubscribeStationEvent(uint32_t interface_index,OnStationEventHandler handler)612 void NetlinkUtils::SubscribeStationEvent(uint32_t interface_index,
613                                          OnStationEventHandler handler) {
614   netlink_manager_->SubscribeStationEvent(interface_index, handler);
615 }
616 
UnsubscribeStationEvent(uint32_t interface_index)617 void NetlinkUtils::UnsubscribeStationEvent(uint32_t interface_index) {
618   netlink_manager_->UnsubscribeStationEvent(interface_index);
619 }
620 
SubscribeChannelSwitchEvent(uint32_t interface_index,OnChannelSwitchEventHandler handler)621 void NetlinkUtils::SubscribeChannelSwitchEvent(uint32_t interface_index,
622                                          OnChannelSwitchEventHandler handler) {
623   netlink_manager_->SubscribeChannelSwitchEvent(interface_index, handler);
624 }
625 
UnsubscribeChannelSwitchEvent(uint32_t interface_index)626 void NetlinkUtils::UnsubscribeChannelSwitchEvent(uint32_t interface_index) {
627   netlink_manager_->UnsubscribeChannelSwitchEvent(interface_index);
628 }
629 
630 
631 }  // namespace wificond
632 }  // namespace android
633