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