• 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 <array>
20 #include <algorithm>
21 #include <bitset>
22 #include <map>
23 #include <string>
24 #include <vector>
25 
26 #include <net/if.h>
27 #include <linux/netlink.h>
28 
29 #include <android-base/logging.h>
30 
31 #include "wificond/net/kernel-header-latest/nl80211.h"
32 #include "wificond/net/mlme_event_handler.h"
33 #include "wificond/net/nl80211_packet.h"
34 
35 using std::array;
36 using std::make_pair;
37 using std::make_unique;
38 using std::map;
39 using std::move;
40 using std::pair;
41 using std::string;
42 using std::unique_ptr;
43 using std::vector;
44 
45 namespace android {
46 namespace wificond {
47 
48 namespace {
49 
50 uint32_t k2GHzFrequencyLowerBound = 2400;
51 uint32_t k2GHzFrequencyUpperBound = 2500;
52 
53 uint32_t k5GHzFrequencyLowerBound = 5000;
54 // This upper bound will exclude any 5.9Ghz channels which belong to 802.11p
55 // for "vehicular communication systems".
56 uint32_t k5GHzFrequencyUpperBound = 5865;
57 
58 uint32_t k6GHzFrequencyLowerBound = 5925;
59 uint32_t k6GHzFrequencyUpperBound = 7125;
60 
61 constexpr uint8_t kHtMcsSetNumByte = 16;
62 constexpr uint8_t kVhtMcsSetNumByte = 8;
63 constexpr uint8_t kHeMcsSetNumByteMin = 4;
64 constexpr uint8_t kMaxStreams = 8;
65 constexpr uint8_t kVht160MhzBitMask = 0x4;
66 constexpr uint8_t kVht80p80MhzBitMask = 0x8;
67 // Some old Linux kernel versions set it to 9.
68 // 9 is OK because only 1st byte is used
69 constexpr uint8_t kHeCapPhyNumByte = 9; // Should be 11
70 constexpr uint8_t kHe160MhzBitMask = 0x8;
71 constexpr uint8_t kHe80p80MhzBitMask = 0x10;
72 
IsExtFeatureFlagSet(const std::vector<uint8_t> & ext_feature_flags_bytes,enum nl80211_ext_feature_index ext_feature_flag)73 bool IsExtFeatureFlagSet(
74     const std::vector<uint8_t>& ext_feature_flags_bytes,
75     enum nl80211_ext_feature_index ext_feature_flag) {
76   static_assert(NUM_NL80211_EXT_FEATURES <= SIZE_MAX,
77                 "Ext feature values doesn't fit in |size_t|");
78   // TODO:This is an unsafe cast because this assumes that the values
79   // are always unsigned!
80   size_t ext_feature_flag_idx = static_cast<size_t>(ext_feature_flag);
81   size_t ext_feature_flag_byte_pos = ext_feature_flag_idx / 8;
82   size_t ext_feature_flag_bit_pos = ext_feature_flag_idx % 8;
83   if (ext_feature_flag_byte_pos >= ext_feature_flags_bytes.size()) {
84     return false;
85   }
86   uint8_t ext_feature_flag_byte =
87       ext_feature_flags_bytes[ext_feature_flag_byte_pos];
88   return (ext_feature_flag_byte & (1U << ext_feature_flag_bit_pos));
89 }
90 }  // namespace
91 
WiphyFeatures(uint32_t feature_flags,const std::vector<uint8_t> & ext_feature_flags_bytes)92 WiphyFeatures::WiphyFeatures(uint32_t feature_flags,
93                              const std::vector<uint8_t>& ext_feature_flags_bytes)
94     : supports_random_mac_oneshot_scan(
95             feature_flags & NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR),
96         supports_random_mac_sched_scan(
97             feature_flags & NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR) {
98   supports_low_span_oneshot_scan =
99       IsExtFeatureFlagSet(ext_feature_flags_bytes,
100                           NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
101   supports_low_power_oneshot_scan =
102       IsExtFeatureFlagSet(ext_feature_flags_bytes,
103                           NL80211_EXT_FEATURE_LOW_POWER_SCAN);
104   supports_high_accuracy_oneshot_scan =
105       IsExtFeatureFlagSet(ext_feature_flags_bytes,
106                           NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
107   // TODO (b/112029045) check if sending frame at specified MCS is supported
108   supports_tx_mgmt_frame_mcs = false;
109   supports_ext_sched_scan_relative_rssi =
110       IsExtFeatureFlagSet(ext_feature_flags_bytes,
111                           NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI);
112 }
113 
NetlinkUtils(NetlinkManager * netlink_manager)114 NetlinkUtils::NetlinkUtils(NetlinkManager* netlink_manager)
115     : netlink_manager_(netlink_manager) {
116   if (!netlink_manager_->IsStarted()) {
117     netlink_manager_->Start();
118   }
119   uint32_t protocol_features = 0;
120   supports_split_wiphy_dump_ = GetProtocolFeatures(&protocol_features) &&
121       (protocol_features & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP);
122 }
123 
~NetlinkUtils()124 NetlinkUtils::~NetlinkUtils() {}
125 
GetWiphyIndex(uint32_t * out_wiphy_index,const std::string & iface_name)126 bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index,
127                                  const std::string& iface_name) {
128   NL80211Packet get_wiphy(
129       netlink_manager_->GetFamilyId(),
130       NL80211_CMD_GET_WIPHY,
131       netlink_manager_->GetSequenceNumber(),
132       getpid());
133   get_wiphy.AddFlag(NLM_F_DUMP);
134   if (!iface_name.empty()) {
135     int ifindex = if_nametoindex(iface_name.c_str());
136     get_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, ifindex));
137   }
138   vector<unique_ptr<const NL80211Packet>> response;
139   if (!netlink_manager_->SendMessageAndGetResponses(get_wiphy, &response))  {
140     LOG(ERROR) << "NL80211_CMD_GET_WIPHY dump failed";
141     return false;
142   }
143   if (response.empty()) {
144     LOG(DEBUG) << "No wiphy is found";
145     return false;
146   }
147   for (auto& packet : response) {
148     if (packet->GetMessageType() == NLMSG_ERROR) {
149       LOG(ERROR) << "Receive ERROR message: "
150                  << strerror(packet->GetErrorCode());
151       return false;
152     }
153     if (packet->GetMessageType() != netlink_manager_->GetFamilyId()) {
154       LOG(ERROR) << "Wrong message type for new interface message: "
155                  << packet->GetMessageType();
156       return false;
157     }
158     if (packet->GetCommand() != NL80211_CMD_NEW_WIPHY) {
159       LOG(ERROR) << "Wrong command in response to "
160                  << "a wiphy dump request: "
161                  << static_cast<int>(packet->GetCommand());
162       return false;
163     }
164     if (!packet->GetAttributeValue(NL80211_ATTR_WIPHY, out_wiphy_index)) {
165       LOG(ERROR) << "Failed to get wiphy index from reply message";
166       return false;
167     }
168   }
169   return true;
170 }
171 
GetWiphyIndex(uint32_t * out_wiphy_index)172 bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index) {
173   return GetWiphyIndex(out_wiphy_index, "");
174 }
175 
GetInterfaces(uint32_t wiphy_index,vector<InterfaceInfo> * interface_info)176 bool NetlinkUtils::GetInterfaces(uint32_t wiphy_index,
177                                  vector<InterfaceInfo>* interface_info) {
178   NL80211Packet get_interfaces(
179       netlink_manager_->GetFamilyId(),
180       NL80211_CMD_GET_INTERFACE,
181       netlink_manager_->GetSequenceNumber(),
182       getpid());
183 
184   get_interfaces.AddFlag(NLM_F_DUMP);
185   get_interfaces.AddAttribute(
186       NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_index));
187   vector<unique_ptr<const NL80211Packet>> response;
188   if (!netlink_manager_->SendMessageAndGetResponses(get_interfaces, &response)) {
189     LOG(ERROR) << "NL80211_CMD_GET_INTERFACE dump failed";
190     return false;
191   }
192   if (response.empty()) {
193     LOG(ERROR) << "No interface is found";
194     return false;
195   }
196   for (auto& packet : response) {
197     if (packet->GetMessageType() == NLMSG_ERROR) {
198       LOG(ERROR) << "Receive ERROR message: "
199                  << strerror(packet->GetErrorCode());
200       return false;
201     }
202     if (packet->GetMessageType() != netlink_manager_->GetFamilyId()) {
203       LOG(ERROR) << "Wrong message type for new interface message: "
204                  << packet->GetMessageType();
205       return false;
206     }
207     if (packet->GetCommand() != NL80211_CMD_NEW_INTERFACE) {
208       LOG(ERROR) << "Wrong command in response to "
209                  << "an interface dump request: "
210                  << static_cast<int>(packet->GetCommand());
211       return false;
212     }
213 
214     // In some situations, it has been observed that the kernel tells us
215     // about a pseudo interface that does not have a real netdev.  In this
216     // case, responses will have a NL80211_ATTR_WDEV, and not the expected
217     // IFNAME/IFINDEX. In this case we just skip these pseudo interfaces.
218     uint32_t if_index;
219     if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
220       LOG(DEBUG) << "Failed to get interface index";
221       continue;
222     }
223 
224     // Today we don't check NL80211_ATTR_IFTYPE because at this point of time
225     // driver always reports that interface is in STATION mode. Even when we
226     // are asking interfaces infomation on behalf of tethering, it is still so
227     // because hostapd is supposed to set interface to AP mode later.
228 
229     string if_name;
230     if (!packet->GetAttributeValue(NL80211_ATTR_IFNAME, &if_name)) {
231       LOG(WARNING) << "Failed to get interface name";
232       continue;
233     }
234 
235     array<uint8_t, ETH_ALEN> if_mac_addr;
236     if (!packet->GetAttributeValue(NL80211_ATTR_MAC, &if_mac_addr)) {
237       LOG(WARNING) << "Failed to get interface mac address";
238       continue;
239     }
240 
241     interface_info->emplace_back(if_index, if_name, if_mac_addr);
242   }
243 
244   return true;
245 }
246 
SetInterfaceMode(uint32_t interface_index,InterfaceMode mode)247 bool NetlinkUtils::SetInterfaceMode(uint32_t interface_index,
248                                     InterfaceMode mode) {
249   uint32_t set_to_mode = NL80211_IFTYPE_UNSPECIFIED;
250   if (mode == STATION_MODE) {
251     set_to_mode = NL80211_IFTYPE_STATION;
252   } else {
253     LOG(ERROR) << "Unexpected mode for interface with index: "
254                << interface_index;
255     return false;
256   }
257   NL80211Packet set_interface_mode(
258       netlink_manager_->GetFamilyId(),
259       NL80211_CMD_SET_INTERFACE,
260       netlink_manager_->GetSequenceNumber(),
261       getpid());
262   // Force an ACK response upon success.
263   set_interface_mode.AddFlag(NLM_F_ACK);
264 
265   set_interface_mode.AddAttribute(
266       NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, interface_index));
267   set_interface_mode.AddAttribute(
268       NL80211Attr<uint32_t>(NL80211_ATTR_IFTYPE, set_to_mode));
269 
270   if (!netlink_manager_->SendMessageAndGetAck(set_interface_mode)) {
271     LOG(ERROR) << "NL80211_CMD_SET_INTERFACE failed";
272     return false;
273   }
274 
275   return true;
276 }
277 
GetProtocolFeatures(uint32_t * features)278 bool NetlinkUtils::GetProtocolFeatures(uint32_t* features) {
279   NL80211Packet get_protocol_features(
280       netlink_manager_->GetFamilyId(),
281       NL80211_CMD_GET_PROTOCOL_FEATURES,
282       netlink_manager_->GetSequenceNumber(),
283       getpid());
284   unique_ptr<const NL80211Packet> response;
285   if (!netlink_manager_->SendMessageAndGetSingleResponse(get_protocol_features,
286                                                          &response)) {
287     LOG(ERROR) << "NL80211_CMD_GET_PROTOCOL_FEATURES failed";
288     return false;
289   }
290   if (!response->GetAttributeValue(NL80211_ATTR_PROTOCOL_FEATURES, features)) {
291     LOG(ERROR) << "Failed to get NL80211_ATTR_PROTOCOL_FEATURES";
292     return false;
293   }
294   return true;
295 }
296 
GetWiphyInfo(uint32_t wiphy_index,BandInfo * out_band_info,ScanCapabilities * out_scan_capabilities,WiphyFeatures * out_wiphy_features)297 bool NetlinkUtils::GetWiphyInfo(
298     uint32_t wiphy_index,
299     BandInfo* out_band_info,
300     ScanCapabilities* out_scan_capabilities,
301     WiphyFeatures* out_wiphy_features) {
302   NL80211Packet get_wiphy(
303       netlink_manager_->GetFamilyId(),
304       NL80211_CMD_GET_WIPHY,
305       netlink_manager_->GetSequenceNumber(),
306       getpid());
307   get_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_index));
308   if (supports_split_wiphy_dump_) {
309     get_wiphy.AddFlagAttribute(NL80211_ATTR_SPLIT_WIPHY_DUMP);
310     get_wiphy.AddFlag(NLM_F_DUMP);
311   }
312   vector<unique_ptr<const NL80211Packet>> response;
313   if (!netlink_manager_->SendMessageAndGetResponses(get_wiphy, &response))  {
314     LOG(ERROR) << "NL80211_CMD_GET_WIPHY dump failed";
315     return false;
316   }
317 
318   vector<NL80211Packet> packet_per_wiphy;
319   if (supports_split_wiphy_dump_) {
320     if (!MergePacketsForSplitWiphyDump(response, &packet_per_wiphy)) {
321       LOG(WARNING) << "Failed to merge responses from split wiphy dump";
322     }
323   } else {
324     for (auto& packet : response) {
325       packet_per_wiphy.push_back(move(*(packet.release())));
326     }
327   }
328 
329   for (const auto& packet : packet_per_wiphy) {
330     uint32_t current_wiphy_index;
331     if (!packet.GetAttributeValue(NL80211_ATTR_WIPHY, &current_wiphy_index) ||
332         // Not the wihpy we requested.
333         current_wiphy_index != wiphy_index) {
334       continue;
335     }
336     if (ParseWiphyInfoFromPacket(packet, out_band_info,
337                                  out_scan_capabilities, out_wiphy_features)) {
338       return true;
339     }
340   }
341 
342   LOG(ERROR) << "Failed to find expected wiphy info "
343              << "from NL80211_CMD_GET_WIPHY responses";
344   return false;
345 }
346 
ParseWiphyInfoFromPacket(const NL80211Packet & packet,BandInfo * out_band_info,ScanCapabilities * out_scan_capabilities,WiphyFeatures * out_wiphy_features)347 bool NetlinkUtils::ParseWiphyInfoFromPacket(
348     const NL80211Packet& packet,
349     BandInfo* out_band_info,
350     ScanCapabilities* out_scan_capabilities,
351     WiphyFeatures* out_wiphy_features) {
352   if (packet.GetCommand() != NL80211_CMD_NEW_WIPHY) {
353     LOG(ERROR) << "Wrong command in response to a get wiphy request: "
354                << static_cast<int>(packet.GetCommand());
355     return false;
356   }
357   if (!ParseBandInfo(&packet, out_band_info) ||
358       !ParseScanCapabilities(&packet, out_scan_capabilities)) {
359     return false;
360   }
361   uint32_t feature_flags;
362   if (!packet.GetAttributeValue(NL80211_ATTR_FEATURE_FLAGS,
363                                  &feature_flags)) {
364     LOG(ERROR) << "Failed to get NL80211_ATTR_FEATURE_FLAGS";
365     return false;
366   }
367   std::vector<uint8_t> ext_feature_flags_bytes;
368   if (!packet.GetAttributeValue(NL80211_ATTR_EXT_FEATURES,
369                                 &ext_feature_flags_bytes)) {
370     LOG(WARNING) << "Failed to get NL80211_ATTR_EXT_FEATURES";
371   }
372   *out_wiphy_features = WiphyFeatures(feature_flags,
373                                       ext_feature_flags_bytes);
374   return true;
375 }
376 
ParseScanCapabilities(const NL80211Packet * const packet,ScanCapabilities * out_scan_capabilities)377 bool NetlinkUtils::ParseScanCapabilities(
378     const NL80211Packet* const packet,
379     ScanCapabilities* out_scan_capabilities) {
380   uint8_t max_num_scan_ssids;
381   if (!packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
382                                    &max_num_scan_ssids)) {
383     LOG(ERROR) << "Failed to get the capacity of maximum number of scan ssids";
384     return false;
385   }
386 
387   uint8_t max_num_sched_scan_ssids;
388   if (!packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
389                                  &max_num_sched_scan_ssids)) {
390     LOG(ERROR) << "Failed to get the capacity of "
391                << "maximum number of scheduled scan ssids";
392     return false;
393   }
394 
395   // Use default value 0 for scan plan capabilities if attributes are missing.
396   uint32_t max_num_scan_plans = 0;
397   packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
398                             &max_num_scan_plans);
399   uint32_t max_scan_plan_interval = 0;
400   packet->GetAttributeValue(NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
401                             &max_scan_plan_interval);
402   uint32_t max_scan_plan_iterations = 0;
403   packet->GetAttributeValue(NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
404                             &max_scan_plan_iterations);
405 
406   uint8_t max_match_sets;
407   if (!packet->GetAttributeValue(NL80211_ATTR_MAX_MATCH_SETS,
408                                    &max_match_sets)) {
409     LOG(ERROR) << "Failed to get the capacity of maximum number of match set"
410                << "of a scheduled scan";
411     return false;
412   }
413   *out_scan_capabilities = ScanCapabilities(max_num_scan_ssids,
414                                             max_num_sched_scan_ssids,
415                                             max_match_sets,
416                                             max_num_scan_plans,
417                                             max_scan_plan_interval,
418                                             max_scan_plan_iterations);
419   return true;
420 }
421 
ParseBandInfo(const NL80211Packet * const packet,BandInfo * out_band_info)422 bool NetlinkUtils::ParseBandInfo(const NL80211Packet* const packet,
423                                  BandInfo* out_band_info) {
424 
425   NL80211NestedAttr bands_attr(0);
426   if (!packet->GetAttribute(NL80211_ATTR_WIPHY_BANDS, &bands_attr)) {
427     LOG(ERROR) << "Failed to get NL80211_ATTR_WIPHY_BANDS";
428     return false;
429   }
430   vector<NL80211NestedAttr> bands;
431   if (!bands_attr.GetListOfNestedAttributes(&bands)) {
432     LOG(ERROR) << "Failed to get bands within NL80211_ATTR_WIPHY_BANDS";
433     return false;
434   }
435 
436   *out_band_info = BandInfo();
437   for (auto& band : bands) {
438     NL80211NestedAttr freqs_attr(0);
439     if (band.GetAttribute(NL80211_BAND_ATTR_FREQS, &freqs_attr)) {
440       handleBandFreqAttributes(freqs_attr, out_band_info);
441     }
442     if (band.HasAttribute(NL80211_BAND_ATTR_HT_CAPA)) {
443       out_band_info->is_80211n_supported = true;
444     }
445     if (band.HasAttribute(NL80211_BAND_ATTR_VHT_CAPA)) {
446       out_band_info->is_80211ac_supported = true;
447     }
448 
449     NL80211NestedAttr iftype_data_attr(0);
450     if (band.GetAttribute(NL80211_BAND_ATTR_IFTYPE_DATA,
451         &iftype_data_attr)) {
452       ParseIfTypeDataAttributes(iftype_data_attr, out_band_info);
453     }
454     ParseHtVhtPhyCapabilities(band, out_band_info);
455   }
456 
457   return true;
458 }
459 
ParseIfTypeDataAttributes(const NL80211NestedAttr & iftype_data_attr,BandInfo * out_band_info)460 void NetlinkUtils::ParseIfTypeDataAttributes(
461     const NL80211NestedAttr& iftype_data_attr,
462     BandInfo* out_band_info) {
463   vector<NL80211NestedAttr> attrs;
464   if (!iftype_data_attr.GetListOfNestedAttributes(&attrs) || attrs.empty()) {
465     LOG(ERROR) << "Failed to get the list of attributes under iftype_data_attr";
466     return;
467   }
468   NL80211NestedAttr attr = attrs[0];
469   if (attr.HasAttribute(NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY)) {
470     out_band_info->is_80211ax_supported = true;
471     ParseHeCapPhyAttribute(attr, out_band_info);
472   }
473   if (attr.HasAttribute(NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET)) {
474     ParseHeMcsSetAttribute(attr, out_band_info);
475   }
476   return;
477 }
478 
handleBandFreqAttributes(const NL80211NestedAttr & freqs_attr,BandInfo * out_band_info)479 void NetlinkUtils::handleBandFreqAttributes(const NL80211NestedAttr& freqs_attr,
480                                             BandInfo* out_band_info) {
481   vector<NL80211NestedAttr> freqs;
482   if (!freqs_attr.GetListOfNestedAttributes(&freqs)) {
483     LOG(ERROR) << "Failed to get frequency attributes";
484     return;
485   }
486 
487   for (auto& freq : freqs) {
488     uint32_t frequency_value;
489     if (!freq.GetAttributeValue(NL80211_FREQUENCY_ATTR_FREQ,
490                                 &frequency_value)) {
491       LOG(DEBUG) << "Failed to get NL80211_FREQUENCY_ATTR_FREQ";
492       continue;
493     }
494     // Channel is disabled in current regulatory domain.
495     if (freq.HasAttribute(NL80211_FREQUENCY_ATTR_DISABLED)) {
496       continue;
497     }
498 
499     if (frequency_value > k2GHzFrequencyLowerBound &&
500         frequency_value < k2GHzFrequencyUpperBound) {
501       out_band_info->band_2g.push_back(frequency_value);
502     } else if (frequency_value > k5GHzFrequencyLowerBound &&
503         frequency_value <= k5GHzFrequencyUpperBound) {
504       // If this is an available/usable DFS frequency, we should save it to
505       // DFS frequencies list.
506       uint32_t dfs_state;
507       if (freq.GetAttributeValue(NL80211_FREQUENCY_ATTR_DFS_STATE,
508                                  &dfs_state) &&
509         (dfs_state == NL80211_DFS_AVAILABLE ||
510             dfs_state == NL80211_DFS_USABLE)) {
511         out_band_info->band_dfs.push_back(frequency_value);
512         continue;
513       }
514 
515       // Put non-dfs passive-only channels into the dfs category.
516       // This aligns with what framework always assumes.
517       if (freq.HasAttribute(NL80211_FREQUENCY_ATTR_NO_IR)) {
518         out_band_info->band_dfs.push_back(frequency_value);
519         continue;
520       }
521 
522       // Otherwise, this is a regular 5g frequency.
523       out_band_info->band_5g.push_back(frequency_value);
524     } else if (frequency_value > k6GHzFrequencyLowerBound &&
525         frequency_value < k6GHzFrequencyUpperBound) {
526       out_band_info->band_6g.push_back(frequency_value);
527     }
528   }
529 }
530 
ParseHtVhtPhyCapabilities(const NL80211NestedAttr & band,BandInfo * out_band_info)531 void NetlinkUtils::ParseHtVhtPhyCapabilities(const NL80211NestedAttr& band,
532                                              BandInfo* out_band_info) {
533   ParseHtMcsSetAttribute(band, out_band_info);
534   ParseVhtMcsSetAttribute(band, out_band_info);
535   ParseVhtCapAttribute(band, out_band_info);
536 }
537 
ParseHtMcsSetAttribute(const NL80211NestedAttr & band,BandInfo * out_band_info)538 void NetlinkUtils::ParseHtMcsSetAttribute(const NL80211NestedAttr& band,
539                                           BandInfo* out_band_info) {
540   vector<uint8_t> ht_mcs_set;
541   if (!band.GetAttributeValue(NL80211_BAND_ATTR_HT_MCS_SET, &ht_mcs_set)) {
542     return;
543   }
544   if (ht_mcs_set.size() < kHtMcsSetNumByte) {
545     LOG(ERROR) << "HT MCS set size is incorrect";
546     return;
547   }
548   pair<uint32_t, uint32_t> max_streams_ht = ParseHtMcsSet(ht_mcs_set);
549   out_band_info->max_tx_streams = std::max(out_band_info->max_tx_streams,
550                                            max_streams_ht.first);
551   out_band_info->max_rx_streams = std::max(out_band_info->max_rx_streams,
552                                            max_streams_ht.second);
553 }
554 
ParseHtMcsSet(const vector<uint8_t> & ht_mcs_set)555 pair<uint32_t, uint32_t> NetlinkUtils::ParseHtMcsSet(
556     const vector<uint8_t>& ht_mcs_set) {
557   uint32_t max_rx_streams = 1;
558   for (int i = 4; i >= 1; i--) {
559     if (ht_mcs_set[i - 1] > 0) {
560       max_rx_streams = i;
561       break;
562     }
563   }
564 
565   uint32_t max_tx_streams = max_rx_streams;
566   uint8_t supported_tx_mcs_set = ht_mcs_set[12];
567   uint8_t tx_mcs_set_defined = supported_tx_mcs_set & 0x1;
568   uint8_t tx_rx_mcs_set_not_equal = (supported_tx_mcs_set >> 1) & 0x1;
569   if (tx_mcs_set_defined && tx_rx_mcs_set_not_equal) {
570     uint8_t max_nss_tx_field_value = (supported_tx_mcs_set >> 2) & 0x3;
571     // The maximum number of Tx streams is 1 more than the field value.
572     max_tx_streams = max_nss_tx_field_value + 1;
573   }
574 
575   return std::make_pair(max_tx_streams, max_rx_streams);
576 }
577 
ParseVhtMcsSetAttribute(const NL80211NestedAttr & band,BandInfo * out_band_info)578 void NetlinkUtils::ParseVhtMcsSetAttribute(const NL80211NestedAttr& band,
579                                            BandInfo* out_band_info) {
580   vector<uint8_t> vht_mcs_set;
581   if (!band.GetAttributeValue(NL80211_BAND_ATTR_VHT_MCS_SET, &vht_mcs_set)) {
582     return;
583   }
584   if (vht_mcs_set.size() < kVhtMcsSetNumByte) {
585     LOG(ERROR) << "VHT MCS set size is incorrect";
586     return;
587   }
588   uint16_t vht_mcs_set_rx = (vht_mcs_set[1] << 8) | vht_mcs_set[0];
589   uint32_t max_rx_streams_vht = ParseMcsMap(vht_mcs_set_rx);
590   uint16_t vht_mcs_set_tx = (vht_mcs_set[5] << 8) | vht_mcs_set[4];
591   uint32_t max_tx_streams_vht = ParseMcsMap(vht_mcs_set_tx);
592   out_band_info->max_tx_streams = std::max(out_band_info->max_tx_streams,
593                                            max_tx_streams_vht);
594   out_band_info->max_rx_streams = std::max(out_band_info->max_rx_streams,
595                                            max_rx_streams_vht);
596 }
597 
ParseHeMcsSetAttribute(const NL80211NestedAttr & attribute,BandInfo * out_band_info)598 void NetlinkUtils::ParseHeMcsSetAttribute(const NL80211NestedAttr& attribute,
599                                           BandInfo* out_band_info) {
600   vector<uint8_t> he_mcs_set;
601   if (!attribute.GetAttributeValue(
602       NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
603       &he_mcs_set)) {
604     LOG(ERROR) << " HE MCS set is not found ";
605     return;
606   }
607   if (he_mcs_set.size() < kHeMcsSetNumByteMin) {
608     LOG(ERROR) << "HE MCS set size is incorrect";
609     return;
610   }
611   uint16_t he_mcs_map_rx = (he_mcs_set[1] << 8) | he_mcs_set[0];
612   uint32_t max_rx_streams_he = ParseMcsMap(he_mcs_map_rx);
613   uint16_t he_mcs_map_tx = (he_mcs_set[3] << 8) | he_mcs_set[2];
614   uint32_t max_tx_streams_he = ParseMcsMap(he_mcs_map_tx);
615   out_band_info->max_tx_streams = std::max(out_band_info->max_tx_streams,
616                                            max_tx_streams_he);
617   out_band_info->max_rx_streams = std::max(out_band_info->max_rx_streams,
618                                            max_rx_streams_he);
619 }
620 
ParseMcsMap(uint16_t mcs_map)621 uint32_t NetlinkUtils::ParseMcsMap(uint16_t mcs_map)
622 {
623   uint32_t max_nss = 1;
624   for (int i = kMaxStreams; i >= 1; i--) {
625     uint16_t stream_map = (mcs_map >> ((i - 1) * 2)) & 0x3;
626     // 0x3 means unsupported
627     if (stream_map != 0x3) {
628       max_nss = i;
629       break;
630     }
631   }
632   return max_nss;
633 }
634 
ParseVhtCapAttribute(const NL80211NestedAttr & band,BandInfo * out_band_info)635 void NetlinkUtils::ParseVhtCapAttribute(const NL80211NestedAttr& band,
636                                         BandInfo* out_band_info) {
637   uint32_t vht_cap;
638   if (!band.GetAttributeValue(NL80211_BAND_ATTR_VHT_CAPA, &vht_cap)) {
639     return;
640   }
641 
642   if (vht_cap & kVht160MhzBitMask) {
643     out_band_info->is_160_mhz_supported = true;
644   }
645   if (vht_cap & kVht80p80MhzBitMask) {
646     out_band_info->is_80p80_mhz_supported = true;
647   }
648 
649 }
650 
ParseHeCapPhyAttribute(const NL80211NestedAttr & attribute,BandInfo * out_band_info)651 void NetlinkUtils::ParseHeCapPhyAttribute(const NL80211NestedAttr& attribute,
652                                           BandInfo* out_band_info) {
653 
654   vector<uint8_t> he_cap_phy;
655   if (!attribute.GetAttributeValue(
656       NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
657       &he_cap_phy)) {
658     LOG(ERROR) << " HE CAP PHY is not found";
659     return;
660   }
661 
662   if (he_cap_phy.size() < kHeCapPhyNumByte) {
663     LOG(ERROR) << "HE Cap PHY size is incorrect";
664     return;
665   }
666   if (he_cap_phy[0] & kHe160MhzBitMask) {
667     out_band_info->is_160_mhz_supported = true;
668   }
669   if (he_cap_phy[0] & kHe80p80MhzBitMask) {
670     out_band_info->is_80p80_mhz_supported = true;
671   }
672 }
673 
GetStationInfo(uint32_t interface_index,const array<uint8_t,ETH_ALEN> & mac_address,StationInfo * out_station_info)674 bool NetlinkUtils::GetStationInfo(uint32_t interface_index,
675                                   const array<uint8_t, ETH_ALEN>& mac_address,
676                                   StationInfo* out_station_info) {
677   NL80211Packet get_station(
678       netlink_manager_->GetFamilyId(),
679       NL80211_CMD_GET_STATION,
680       netlink_manager_->GetSequenceNumber(),
681       getpid());
682   get_station.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX,
683                                                  interface_index));
684   get_station.AddAttribute(NL80211Attr<array<uint8_t, ETH_ALEN>>(
685       NL80211_ATTR_MAC, mac_address));
686 
687   unique_ptr<const NL80211Packet> response;
688   if (!netlink_manager_->SendMessageAndGetSingleResponse(get_station,
689                                                          &response)) {
690     LOG(ERROR) << "NL80211_CMD_GET_STATION failed";
691     return false;
692   }
693   if (response->GetCommand() != NL80211_CMD_NEW_STATION) {
694     LOG(ERROR) << "Wrong command in response to a get station request: "
695                << static_cast<int>(response->GetCommand());
696     return false;
697   }
698   NL80211NestedAttr sta_info(0);
699   if (!response->GetAttribute(NL80211_ATTR_STA_INFO, &sta_info)) {
700     LOG(ERROR) << "Failed to get NL80211_ATTR_STA_INFO";
701     return false;
702   }
703   int32_t tx_good, tx_bad;
704   if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_PACKETS, &tx_good)) {
705     LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_PACKETS";
706     return false;
707   }
708   if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_FAILED, &tx_bad)) {
709     LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_FAILED";
710     return false;
711   }
712   int8_t current_rssi;
713   if (!sta_info.GetAttributeValue(NL80211_STA_INFO_SIGNAL, &current_rssi)) {
714     LOG(ERROR) << "Failed to get NL80211_STA_INFO_SIGNAL";
715     return false;
716   }
717   NL80211NestedAttr tx_bitrate_attr(0);
718   uint32_t tx_bitrate = 0;
719   if (sta_info.GetAttribute(NL80211_STA_INFO_TX_BITRATE,
720                             &tx_bitrate_attr)) {
721     if (!tx_bitrate_attr.GetAttributeValue(NL80211_RATE_INFO_BITRATE32,
722                                          &tx_bitrate)) {
723       // Return invalid tx rate to avoid breaking the get station cmd
724       tx_bitrate = 0;
725     }
726   }
727   NL80211NestedAttr rx_bitrate_attr(0);
728   uint32_t rx_bitrate = 0;
729   if (sta_info.GetAttribute(NL80211_STA_INFO_RX_BITRATE,
730                             &rx_bitrate_attr)) {
731     if (!rx_bitrate_attr.GetAttributeValue(NL80211_RATE_INFO_BITRATE32,
732                                          &rx_bitrate)) {
733       // Return invalid rx rate to avoid breaking the get station cmd
734       rx_bitrate = 0;
735     }
736   }
737   *out_station_info = StationInfo(tx_good, tx_bad, tx_bitrate, current_rssi, rx_bitrate);
738   return true;
739 }
740 
741 // This is a helper function for merging split NL80211_CMD_NEW_WIPHY packets.
742 // For example:
743 // First NL80211_CMD_NEW_WIPHY has attribute A with payload 0x1234.
744 // Second NL80211_CMD_NEW_WIPHY has attribute A with payload 0x5678.
745 // The generated NL80211_CMD_NEW_WIPHY will have attribute A with
746 // payload 0x12345678.
747 // NL80211_ATTR_WIPHY, NL80211_ATTR_IFINDEX, and NL80211_ATTR_WDEV
748 // are used for filtering packets so we know which packets should
749 // be merged together.
MergePacketsForSplitWiphyDump(const vector<unique_ptr<const NL80211Packet>> & split_dump_info,vector<NL80211Packet> * packet_per_wiphy)750 bool NetlinkUtils::MergePacketsForSplitWiphyDump(
751     const vector<unique_ptr<const NL80211Packet>>& split_dump_info,
752     vector<NL80211Packet>* packet_per_wiphy) {
753   map<uint32_t, map<int, BaseNL80211Attr>> attr_by_wiphy_and_id;
754 
755   // Construct the map using input packets.
756   for (const auto& packet : split_dump_info) {
757     uint32_t wiphy_index;
758     if (!packet->GetAttributeValue(NL80211_ATTR_WIPHY, &wiphy_index)) {
759       LOG(ERROR) << "Failed to get NL80211_ATTR_WIPHY from wiphy split dump";
760       return false;
761     }
762     vector<BaseNL80211Attr> attributes;
763     if (!packet->GetAllAttributes(&attributes)) {
764       return false;
765     }
766     for (auto& attr : attributes) {
767       int attr_id = attr.GetAttributeId();
768       if (attr_id != NL80211_ATTR_WIPHY &&
769           attr_id != NL80211_ATTR_IFINDEX &&
770               attr_id != NL80211_ATTR_WDEV) {
771           auto attr_id_and_attr =
772               attr_by_wiphy_and_id[wiphy_index].find(attr_id);
773           if (attr_id_and_attr == attr_by_wiphy_and_id[wiphy_index].end()) {
774             attr_by_wiphy_and_id[wiphy_index].
775                 insert(make_pair(attr_id, move(attr)));
776           } else {
777             attr_id_and_attr->second.Merge(attr);
778           }
779       }
780     }
781   }
782 
783   // Generate output packets using the constructed map.
784   for (const auto& wiphy_and_attributes : attr_by_wiphy_and_id) {
785     NL80211Packet new_wiphy(0, NL80211_CMD_NEW_WIPHY, 0, 0);
786     new_wiphy.AddAttribute(
787         NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_and_attributes.first));
788     for (const auto& attr : wiphy_and_attributes.second) {
789       new_wiphy.AddAttribute(attr.second);
790     }
791     packet_per_wiphy->emplace_back(move(new_wiphy));
792   }
793   return true;
794 }
795 
GetCountryCode(string * out_country_code)796 bool NetlinkUtils::GetCountryCode(string* out_country_code) {
797   NL80211Packet get_country_code(
798       netlink_manager_->GetFamilyId(),
799       NL80211_CMD_GET_REG,
800       netlink_manager_->GetSequenceNumber(),
801       getpid());
802   unique_ptr<const NL80211Packet> response;
803   if (!netlink_manager_->SendMessageAndGetSingleResponse(get_country_code,
804                                                          &response)) {
805     LOG(ERROR) << "NL80211_CMD_GET_REG failed";
806     return false;
807   }
808   if (!response->GetAttributeValue(NL80211_ATTR_REG_ALPHA2, out_country_code)) {
809     LOG(ERROR) << "Get NL80211_ATTR_REG_ALPHA2 failed";
810     return false;
811   }
812   return true;
813 }
814 
SendMgmtFrame(uint32_t interface_index,const vector<uint8_t> & frame,int32_t mcs,uint64_t * out_cookie)815 bool NetlinkUtils::SendMgmtFrame(uint32_t interface_index,
816     const vector<uint8_t>& frame, int32_t mcs, uint64_t* out_cookie) {
817 
818   NL80211Packet send_mgmt_frame(
819       netlink_manager_->GetFamilyId(),
820       NL80211_CMD_FRAME,
821       netlink_manager_->GetSequenceNumber(),
822       getpid());
823 
824   send_mgmt_frame.AddAttribute(
825       NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, interface_index));
826 
827   send_mgmt_frame.AddAttribute(
828       NL80211Attr<vector<uint8_t>>(NL80211_ATTR_FRAME, frame));
829 
830   if (mcs >= 0) {
831     // TODO (b/112029045) if mcs >= 0, add MCS attribute
832   }
833 
834   unique_ptr<const NL80211Packet> response;
835   if (!netlink_manager_->SendMessageAndGetSingleResponse(
836       send_mgmt_frame, &response)) {
837     LOG(ERROR) << "NL80211_CMD_FRAME failed";
838     return false;
839   }
840 
841   if (!response->GetAttributeValue(NL80211_ATTR_COOKIE, out_cookie)) {
842     LOG(ERROR) << "Get NL80211_ATTR_COOKIE failed";
843     return false;
844   }
845 
846   return true;
847 }
848 
SubscribeMlmeEvent(uint32_t interface_index,MlmeEventHandler * handler)849 void NetlinkUtils::SubscribeMlmeEvent(uint32_t interface_index,
850                                       MlmeEventHandler* handler) {
851   netlink_manager_->SubscribeMlmeEvent(interface_index, handler);
852 }
853 
UnsubscribeMlmeEvent(uint32_t interface_index)854 void NetlinkUtils::UnsubscribeMlmeEvent(uint32_t interface_index) {
855   netlink_manager_->UnsubscribeMlmeEvent(interface_index);
856 }
857 
SubscribeRegDomainChange(uint32_t wiphy_index,OnRegDomainChangedHandler handler)858 void NetlinkUtils::SubscribeRegDomainChange(
859     uint32_t wiphy_index,
860     OnRegDomainChangedHandler handler) {
861   netlink_manager_->SubscribeRegDomainChange(wiphy_index, handler);
862 }
863 
UnsubscribeRegDomainChange(uint32_t wiphy_index)864 void NetlinkUtils::UnsubscribeRegDomainChange(uint32_t wiphy_index) {
865   netlink_manager_->UnsubscribeRegDomainChange(wiphy_index);
866 }
867 
SubscribeStationEvent(uint32_t interface_index,OnStationEventHandler handler)868 void NetlinkUtils::SubscribeStationEvent(uint32_t interface_index,
869                                          OnStationEventHandler handler) {
870   netlink_manager_->SubscribeStationEvent(interface_index, handler);
871 }
872 
UnsubscribeStationEvent(uint32_t interface_index)873 void NetlinkUtils::UnsubscribeStationEvent(uint32_t interface_index) {
874   netlink_manager_->UnsubscribeStationEvent(interface_index);
875 }
876 
SubscribeChannelSwitchEvent(uint32_t interface_index,OnChannelSwitchEventHandler handler)877 void NetlinkUtils::SubscribeChannelSwitchEvent(uint32_t interface_index,
878                                          OnChannelSwitchEventHandler handler) {
879   netlink_manager_->SubscribeChannelSwitchEvent(interface_index, handler);
880 }
881 
UnsubscribeChannelSwitchEvent(uint32_t interface_index)882 void NetlinkUtils::UnsubscribeChannelSwitchEvent(uint32_t interface_index) {
883   netlink_manager_->UnsubscribeChannelSwitchEvent(interface_index);
884 }
885 
SubscribeFrameTxStatusEvent(uint32_t interface_index,OnFrameTxStatusEventHandler handler)886 void NetlinkUtils::SubscribeFrameTxStatusEvent(
887     uint32_t interface_index, OnFrameTxStatusEventHandler handler) {
888   netlink_manager_->SubscribeFrameTxStatusEvent(interface_index, handler);
889 }
890 
UnsubscribeFrameTxStatusEvent(uint32_t interface_index)891 void NetlinkUtils::UnsubscribeFrameTxStatusEvent(uint32_t interface_index) {
892   netlink_manager_->UnsubscribeFrameTxStatusEvent(interface_index);
893 }
894 
895 }  // namespace wificond
896 }  // namespace android
897