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