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)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 NL80211Packet get_wiphy(
323 netlink_manager_->GetFamilyId(),
324 NL80211_CMD_GET_WIPHY,
325 netlink_manager_->GetSequenceNumber(),
326 getpid());
327 get_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_index));
328 if (supports_split_wiphy_dump_) {
329 get_wiphy.AddFlagAttribute(NL80211_ATTR_SPLIT_WIPHY_DUMP);
330 get_wiphy.AddFlag(NLM_F_DUMP);
331 }
332 vector<unique_ptr<const NL80211Packet>> response;
333 for (int i = kNl80211CmdRetryCount; i >= 0; i--) {
334 if (netlink_manager_->SendMessageAndGetResponses(get_wiphy, &response)) {
335 break;
336 } else {
337 if (i == 0) {
338 LOG(ERROR) << "NL80211_CMD_GET_WIPHY dump failed";
339 return false;
340 } else {
341 LOG(INFO) << "Failed to get wiphy info, retry again";
342 }
343 }
344 }
345
346 vector<NL80211Packet> packet_per_wiphy;
347 if (supports_split_wiphy_dump_) {
348 if (!MergePacketsForSplitWiphyDump(response, &packet_per_wiphy)) {
349 LOG(WARNING) << "Failed to merge responses from split wiphy dump";
350 }
351 } else {
352 for (auto& packet : response) {
353 packet_per_wiphy.push_back(std::move(*(packet.release())));
354 }
355 }
356
357 for (const auto& packet : packet_per_wiphy) {
358 uint32_t current_wiphy_index;
359 if (!packet.GetAttributeValue(NL80211_ATTR_WIPHY, ¤t_wiphy_index) ||
360 // Not the wihpy we requested.
361 current_wiphy_index != wiphy_index) {
362 continue;
363 }
364 if (ParseWiphyInfoFromPacket(packet, out_band_info,
365 out_scan_capabilities, out_wiphy_features)) {
366 return true;
367 }
368 }
369
370 LOG(ERROR) << "Failed to find expected wiphy info "
371 << "from NL80211_CMD_GET_WIPHY responses";
372 return false;
373 }
374
ParseWiphyInfoFromPacket(const NL80211Packet & packet,BandInfo * out_band_info,ScanCapabilities * out_scan_capabilities,WiphyFeatures * out_wiphy_features)375 bool NetlinkUtils::ParseWiphyInfoFromPacket(
376 const NL80211Packet& packet,
377 BandInfo* out_band_info,
378 ScanCapabilities* out_scan_capabilities,
379 WiphyFeatures* out_wiphy_features) {
380 if (packet.GetCommand() != NL80211_CMD_NEW_WIPHY) {
381 LOG(ERROR) << "Wrong command in response to a get wiphy request: "
382 << static_cast<int>(packet.GetCommand());
383 return false;
384 }
385 if (!ParseBandInfo(&packet, out_band_info) ||
386 !ParseScanCapabilities(&packet, out_scan_capabilities)) {
387 return false;
388 }
389 uint32_t feature_flags;
390 if (!packet.GetAttributeValue(NL80211_ATTR_FEATURE_FLAGS,
391 &feature_flags)) {
392 LOG(ERROR) << "Failed to get NL80211_ATTR_FEATURE_FLAGS";
393 return false;
394 }
395 std::vector<uint8_t> ext_feature_flags_bytes;
396 if (!packet.GetAttributeValue(NL80211_ATTR_EXT_FEATURES,
397 &ext_feature_flags_bytes)) {
398 LOG(WARNING) << "Failed to get NL80211_ATTR_EXT_FEATURES";
399 }
400 *out_wiphy_features = WiphyFeatures(feature_flags,
401 ext_feature_flags_bytes);
402 return true;
403 }
404
ParseScanCapabilities(const NL80211Packet * const packet,ScanCapabilities * out_scan_capabilities)405 bool NetlinkUtils::ParseScanCapabilities(
406 const NL80211Packet* const packet,
407 ScanCapabilities* out_scan_capabilities) {
408 uint8_t max_num_scan_ssids;
409 if (!packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
410 &max_num_scan_ssids)) {
411 LOG(ERROR) << "Failed to get the capacity of maximum number of scan ssids";
412 return false;
413 }
414
415 uint8_t max_num_sched_scan_ssids;
416 if (!packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
417 &max_num_sched_scan_ssids)) {
418 LOG(ERROR) << "Failed to get the capacity of "
419 << "maximum number of scheduled scan ssids";
420 return false;
421 }
422
423 // Use default value 0 for scan plan capabilities if attributes are missing.
424 uint32_t max_num_scan_plans = 0;
425 packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
426 &max_num_scan_plans);
427 uint32_t max_scan_plan_interval = 0;
428 packet->GetAttributeValue(NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
429 &max_scan_plan_interval);
430 uint32_t max_scan_plan_iterations = 0;
431 packet->GetAttributeValue(NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
432 &max_scan_plan_iterations);
433
434 uint8_t max_match_sets;
435 if (!packet->GetAttributeValue(NL80211_ATTR_MAX_MATCH_SETS,
436 &max_match_sets)) {
437 LOG(ERROR) << "Failed to get the capacity of maximum number of match set"
438 << "of a scheduled scan";
439 return false;
440 }
441 *out_scan_capabilities = ScanCapabilities(max_num_scan_ssids,
442 max_num_sched_scan_ssids,
443 max_match_sets,
444 max_num_scan_plans,
445 max_scan_plan_interval,
446 max_scan_plan_iterations);
447 return true;
448 }
449
ParseBandInfo(const NL80211Packet * const packet,BandInfo * out_band_info)450 bool NetlinkUtils::ParseBandInfo(const NL80211Packet* const packet,
451 BandInfo* out_band_info) {
452
453 NL80211NestedAttr bands_attr(0);
454 if (!packet->GetAttribute(NL80211_ATTR_WIPHY_BANDS, &bands_attr)) {
455 LOG(ERROR) << "Failed to get NL80211_ATTR_WIPHY_BANDS";
456 return false;
457 }
458 vector<NL80211NestedAttr> bands;
459 if (!bands_attr.GetListOfNestedAttributes(&bands)) {
460 LOG(ERROR) << "Failed to get bands within NL80211_ATTR_WIPHY_BANDS";
461 return false;
462 }
463
464 *out_band_info = BandInfo();
465 for (auto& band : bands) {
466 NL80211NestedAttr freqs_attr(0);
467 if (band.GetAttribute(NL80211_BAND_ATTR_FREQS, &freqs_attr)) {
468 handleBandFreqAttributes(freqs_attr, out_band_info);
469 }
470 if (band.HasAttribute(NL80211_BAND_ATTR_HT_CAPA)) {
471 out_band_info->is_80211n_supported = true;
472 }
473 if (band.HasAttribute(NL80211_BAND_ATTR_VHT_CAPA)) {
474 out_band_info->is_80211ac_supported = true;
475 }
476
477 NL80211NestedAttr iftype_data_attr(0);
478 if (band.GetAttribute(NL80211_BAND_ATTR_IFTYPE_DATA,
479 &iftype_data_attr)) {
480 ParseIfTypeDataAttributes(iftype_data_attr, out_band_info);
481 }
482 ParseHtVhtPhyCapabilities(band, out_band_info);
483 }
484
485 return true;
486 }
487
ParseIfTypeDataAttributes(const NL80211NestedAttr & iftype_data_attr,BandInfo * out_band_info)488 void NetlinkUtils::ParseIfTypeDataAttributes(
489 const NL80211NestedAttr& iftype_data_attr,
490 BandInfo* out_band_info) {
491 vector<NL80211NestedAttr> attrs;
492 if (!iftype_data_attr.GetListOfNestedAttributes(&attrs) || attrs.empty()) {
493 LOG(ERROR) << "Failed to get the list of attributes under iftype_data_attr";
494 return;
495 }
496
497 NL80211NestedAttr attr = attrs[0];
498 if (attr.HasAttribute(NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY)) {
499 out_band_info->is_80211ax_supported = true;
500 ParseHeCapPhyAttribute(attr, out_band_info);
501 }
502 if (attr.HasAttribute(NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET)) {
503 ParseHeMcsSetAttribute(attr, out_band_info);
504 }
505 if (attr.HasAttribute(NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY)) {
506 out_band_info->is_80211be_supported = true;
507 ParseEhtCapPhyAttribute(attr, out_band_info);
508 }
509 return;
510 }
511
handleBandFreqAttributes(const NL80211NestedAttr & freqs_attr,BandInfo * out_band_info)512 void NetlinkUtils::handleBandFreqAttributes(const NL80211NestedAttr& freqs_attr,
513 BandInfo* out_band_info) {
514 vector<NL80211NestedAttr> freqs;
515 if (!freqs_attr.GetListOfNestedAttributes(&freqs)) {
516 LOG(ERROR) << "Failed to get frequency attributes";
517 return;
518 }
519
520 for (auto& freq : freqs) {
521 uint32_t frequency_value;
522 if (!freq.GetAttributeValue(NL80211_FREQUENCY_ATTR_FREQ,
523 &frequency_value)) {
524 LOG(DEBUG) << "Failed to get NL80211_FREQUENCY_ATTR_FREQ";
525 continue;
526 }
527 // Channel is disabled in current regulatory domain.
528 if (freq.HasAttribute(NL80211_FREQUENCY_ATTR_DISABLED)) {
529 continue;
530 }
531
532 if (frequency_value > k2GHzFrequencyLowerBound &&
533 frequency_value < k2GHzFrequencyUpperBound) {
534 out_band_info->band_2g.push_back(frequency_value);
535 } else if (frequency_value > k5GHzFrequencyLowerBound &&
536 frequency_value <= k5GHzFrequencyUpperBound) {
537 // If this is an available/usable DFS frequency, we should save it to
538 // DFS frequencies list.
539 uint32_t dfs_state;
540 if (freq.GetAttributeValue(NL80211_FREQUENCY_ATTR_DFS_STATE,
541 &dfs_state) &&
542 (dfs_state == NL80211_DFS_AVAILABLE ||
543 dfs_state == NL80211_DFS_USABLE)) {
544 out_band_info->band_dfs.push_back(frequency_value);
545 continue;
546 }
547
548 // Put non-dfs passive-only channels into the dfs category.
549 // This aligns with what framework always assumes.
550 if (freq.HasAttribute(NL80211_FREQUENCY_ATTR_NO_IR)) {
551 out_band_info->band_dfs.push_back(frequency_value);
552 continue;
553 }
554
555 // Otherwise, this is a regular 5g frequency.
556 out_band_info->band_5g.push_back(frequency_value);
557 } else if (frequency_value > k6GHzFrequencyLowerBound &&
558 frequency_value < k6GHzFrequencyUpperBound) {
559 out_band_info->band_6g.push_back(frequency_value);
560 } else if (frequency_value >= k60GHzFrequencyLowerBound &&
561 frequency_value < k60GHzFrequencyUpperBound) {
562 out_band_info->band_60g.push_back(frequency_value);
563 }
564 }
565 }
566
ParseHtVhtPhyCapabilities(const NL80211NestedAttr & band,BandInfo * out_band_info)567 void NetlinkUtils::ParseHtVhtPhyCapabilities(const NL80211NestedAttr& band,
568 BandInfo* out_band_info) {
569 ParseHtMcsSetAttribute(band, out_band_info);
570 ParseVhtMcsSetAttribute(band, out_band_info);
571 ParseVhtCapAttribute(band, out_band_info);
572 }
573
ParseHtMcsSetAttribute(const NL80211NestedAttr & band,BandInfo * out_band_info)574 void NetlinkUtils::ParseHtMcsSetAttribute(const NL80211NestedAttr& band,
575 BandInfo* out_band_info) {
576 vector<uint8_t> ht_mcs_set;
577 if (!band.GetAttributeValue(NL80211_BAND_ATTR_HT_MCS_SET, &ht_mcs_set)) {
578 return;
579 }
580 if (ht_mcs_set.size() < kHtMcsSetNumByte) {
581 LOG(ERROR) << "HT MCS set size is incorrect";
582 return;
583 }
584 pair<uint32_t, uint32_t> max_streams_ht = ParseHtMcsSet(ht_mcs_set);
585 out_band_info->max_tx_streams = std::max(out_band_info->max_tx_streams,
586 max_streams_ht.first);
587 out_band_info->max_rx_streams = std::max(out_band_info->max_rx_streams,
588 max_streams_ht.second);
589 }
590
ParseHtMcsSet(const vector<uint8_t> & ht_mcs_set)591 pair<uint32_t, uint32_t> NetlinkUtils::ParseHtMcsSet(
592 const vector<uint8_t>& ht_mcs_set) {
593 uint32_t max_rx_streams = 1;
594 for (int i = 4; i >= 1; i--) {
595 if (ht_mcs_set[i - 1] > 0) {
596 max_rx_streams = i;
597 break;
598 }
599 }
600
601 uint32_t max_tx_streams = max_rx_streams;
602 uint8_t supported_tx_mcs_set = ht_mcs_set[12];
603 uint8_t tx_mcs_set_defined = supported_tx_mcs_set & 0x1;
604 uint8_t tx_rx_mcs_set_not_equal = (supported_tx_mcs_set >> 1) & 0x1;
605 if (tx_mcs_set_defined && tx_rx_mcs_set_not_equal) {
606 uint8_t max_nss_tx_field_value = (supported_tx_mcs_set >> 2) & 0x3;
607 // The maximum number of Tx streams is 1 more than the field value.
608 max_tx_streams = max_nss_tx_field_value + 1;
609 }
610
611 return std::make_pair(max_tx_streams, max_rx_streams);
612 }
613
ParseVhtMcsSetAttribute(const NL80211NestedAttr & band,BandInfo * out_band_info)614 void NetlinkUtils::ParseVhtMcsSetAttribute(const NL80211NestedAttr& band,
615 BandInfo* out_band_info) {
616 vector<uint8_t> vht_mcs_set;
617 if (!band.GetAttributeValue(NL80211_BAND_ATTR_VHT_MCS_SET, &vht_mcs_set)) {
618 return;
619 }
620 if (vht_mcs_set.size() < kVhtMcsSetNumByte) {
621 LOG(ERROR) << "VHT MCS set size is incorrect";
622 return;
623 }
624 uint16_t vht_mcs_set_rx = (vht_mcs_set[1] << 8) | vht_mcs_set[0];
625 uint32_t max_rx_streams_vht = ParseMcsMap(vht_mcs_set_rx);
626 uint16_t vht_mcs_set_tx = (vht_mcs_set[5] << 8) | vht_mcs_set[4];
627 uint32_t max_tx_streams_vht = ParseMcsMap(vht_mcs_set_tx);
628 out_band_info->max_tx_streams = std::max(out_band_info->max_tx_streams,
629 max_tx_streams_vht);
630 out_band_info->max_rx_streams = std::max(out_band_info->max_rx_streams,
631 max_rx_streams_vht);
632 }
633
ParseHeMcsSetAttribute(const NL80211NestedAttr & attribute,BandInfo * out_band_info)634 void NetlinkUtils::ParseHeMcsSetAttribute(const NL80211NestedAttr& attribute,
635 BandInfo* out_band_info) {
636 vector<uint8_t> he_mcs_set;
637 if (!attribute.GetAttributeValue(
638 NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
639 &he_mcs_set)) {
640 LOG(ERROR) << " HE MCS set is not found ";
641 return;
642 }
643 if (he_mcs_set.size() < kHeMcsSetNumByteMin) {
644 LOG(ERROR) << "HE MCS set size is incorrect";
645 return;
646 }
647 uint16_t he_mcs_map_rx = (he_mcs_set[1] << 8) | he_mcs_set[0];
648 uint32_t max_rx_streams_he = ParseMcsMap(he_mcs_map_rx);
649 uint16_t he_mcs_map_tx = (he_mcs_set[3] << 8) | he_mcs_set[2];
650 uint32_t max_tx_streams_he = ParseMcsMap(he_mcs_map_tx);
651 out_band_info->max_tx_streams = std::max(out_band_info->max_tx_streams,
652 max_tx_streams_he);
653 out_band_info->max_rx_streams = std::max(out_band_info->max_rx_streams,
654 max_rx_streams_he);
655 }
656
ParseMcsMap(uint16_t mcs_map)657 uint32_t NetlinkUtils::ParseMcsMap(uint16_t mcs_map)
658 {
659 uint32_t max_nss = 1;
660 for (int i = kMaxStreams; i >= 1; i--) {
661 uint16_t stream_map = (mcs_map >> ((i - 1) * 2)) & 0x3;
662 // 0x3 means unsupported
663 if (stream_map != 0x3) {
664 max_nss = i;
665 break;
666 }
667 }
668 return max_nss;
669 }
670
ParseVhtCapAttribute(const NL80211NestedAttr & band,BandInfo * out_band_info)671 void NetlinkUtils::ParseVhtCapAttribute(const NL80211NestedAttr& band,
672 BandInfo* out_band_info) {
673 uint32_t vht_cap;
674 if (!band.GetAttributeValue(NL80211_BAND_ATTR_VHT_CAPA, &vht_cap)) {
675 return;
676 }
677
678 if (vht_cap & kVht160MhzBitMask) {
679 out_band_info->is_160_mhz_supported = true;
680 }
681 if (vht_cap & kVht80p80MhzBitMask) {
682 out_band_info->is_80p80_mhz_supported = true;
683 }
684 }
685
ParseHeCapPhyAttribute(const NL80211NestedAttr & attribute,BandInfo * out_band_info)686 void NetlinkUtils::ParseHeCapPhyAttribute(const NL80211NestedAttr& attribute,
687 BandInfo* out_band_info) {
688
689 vector<uint8_t> he_cap_phy;
690 if (!attribute.GetAttributeValue(
691 NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
692 &he_cap_phy)) {
693 LOG(ERROR) << " HE CAP PHY is not found";
694 return;
695 }
696
697 if (he_cap_phy.size() < kHeCapPhyNumByte) {
698 LOG(ERROR) << "HE Cap PHY size is incorrect";
699 return;
700 }
701 if (he_cap_phy[0] & kHe160MhzBitMask) {
702 out_band_info->is_160_mhz_supported = true;
703 }
704 if (he_cap_phy[0] & kHe80p80MhzBitMask) {
705 out_band_info->is_80p80_mhz_supported = true;
706 }
707 }
708
ParseEhtCapPhyAttribute(const NL80211NestedAttr & attribute,BandInfo * out_band_info)709 void NetlinkUtils::ParseEhtCapPhyAttribute(const NL80211NestedAttr& attribute,
710 BandInfo* out_band_info) {
711 vector<uint8_t> eht_cap_phy;
712 if (!attribute.GetAttributeValue(
713 NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY,
714 &eht_cap_phy)) {
715 LOG(ERROR) << " EHT CAP PHY is not found";
716 return;
717 }
718
719 if (eht_cap_phy.size() < kEhtCapPhyNumByte) {
720 LOG(ERROR) << "EHT Cap PHY size is incorrect";
721 return;
722 }
723 if (eht_cap_phy[0] & kEht320MhzBitMask) {
724 out_band_info->is_320_mhz_supported = true;
725 }
726 }
727
GetStationInfo(uint32_t interface_index,const array<uint8_t,ETH_ALEN> & mac_address,StationInfo * out_station_info)728 bool NetlinkUtils::GetStationInfo(uint32_t interface_index,
729 const array<uint8_t, ETH_ALEN>& mac_address,
730 StationInfo* out_station_info) {
731 NL80211Packet get_station(
732 netlink_manager_->GetFamilyId(),
733 NL80211_CMD_GET_STATION,
734 netlink_manager_->GetSequenceNumber(),
735 getpid());
736 get_station.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX,
737 interface_index));
738 get_station.AddAttribute(NL80211Attr<array<uint8_t, ETH_ALEN>>(
739 NL80211_ATTR_MAC, mac_address));
740
741 unique_ptr<const NL80211Packet> response;
742 if (!netlink_manager_->SendMessageAndGetSingleResponse(get_station,
743 &response)) {
744 LOG(ERROR) << "NL80211_CMD_GET_STATION failed";
745 return false;
746 }
747 if (response->GetCommand() != NL80211_CMD_NEW_STATION) {
748 LOG(ERROR) << "Wrong command in response to a get station request: "
749 << static_cast<int>(response->GetCommand());
750 return false;
751 }
752 NL80211NestedAttr sta_info(0);
753 if (!response->GetAttribute(NL80211_ATTR_STA_INFO, &sta_info)) {
754 LOG(ERROR) << "Failed to get NL80211_ATTR_STA_INFO";
755 return false;
756 }
757 int32_t tx_good, tx_bad;
758 if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_PACKETS, &tx_good)) {
759 LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_PACKETS";
760 return false;
761 }
762 if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_FAILED, &tx_bad)) {
763 LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_FAILED";
764 return false;
765 }
766 int8_t current_rssi;
767 if (!sta_info.GetAttributeValue(NL80211_STA_INFO_SIGNAL, ¤t_rssi)) {
768 LOG(ERROR) << "Failed to get NL80211_STA_INFO_SIGNAL";
769 return false;
770 }
771 NL80211NestedAttr tx_bitrate_attr(0);
772 uint32_t tx_bitrate = 0;
773 if (sta_info.GetAttribute(NL80211_STA_INFO_TX_BITRATE,
774 &tx_bitrate_attr)) {
775 if (!tx_bitrate_attr.GetAttributeValue(NL80211_RATE_INFO_BITRATE32,
776 &tx_bitrate)) {
777 // Return invalid tx rate to avoid breaking the get station cmd
778 tx_bitrate = 0;
779 }
780 }
781 NL80211NestedAttr rx_bitrate_attr(0);
782 uint32_t rx_bitrate = 0;
783 if (sta_info.GetAttribute(NL80211_STA_INFO_RX_BITRATE,
784 &rx_bitrate_attr)) {
785 if (!rx_bitrate_attr.GetAttributeValue(NL80211_RATE_INFO_BITRATE32,
786 &rx_bitrate)) {
787 // Return invalid rx rate to avoid breaking the get station cmd
788 rx_bitrate = 0;
789 }
790 }
791 *out_station_info = StationInfo(tx_good, tx_bad, tx_bitrate, current_rssi, rx_bitrate);
792 return true;
793 }
794
795 // This is a helper function for merging split NL80211_CMD_NEW_WIPHY packets.
796 // For example:
797 // First NL80211_CMD_NEW_WIPHY has attribute A with payload 0x1234.
798 // Second NL80211_CMD_NEW_WIPHY has attribute A with payload 0x5678.
799 // The generated NL80211_CMD_NEW_WIPHY will have attribute A with
800 // payload 0x12345678.
801 // NL80211_ATTR_WIPHY, NL80211_ATTR_IFINDEX, and NL80211_ATTR_WDEV
802 // are used for filtering packets so we know which packets should
803 // be merged together.
MergePacketsForSplitWiphyDump(const vector<unique_ptr<const NL80211Packet>> & split_dump_info,vector<NL80211Packet> * packet_per_wiphy)804 bool NetlinkUtils::MergePacketsForSplitWiphyDump(
805 const vector<unique_ptr<const NL80211Packet>>& split_dump_info,
806 vector<NL80211Packet>* packet_per_wiphy) {
807 map<uint32_t, map<int, BaseNL80211Attr>> attr_by_wiphy_and_id;
808
809 // Construct the map using input packets.
810 for (const auto& packet : split_dump_info) {
811 uint32_t wiphy_index;
812 if (!packet->GetAttributeValue(NL80211_ATTR_WIPHY, &wiphy_index)) {
813 LOG(ERROR) << "Failed to get NL80211_ATTR_WIPHY from wiphy split dump";
814 return false;
815 }
816 vector<BaseNL80211Attr> attributes;
817 if (!packet->GetAllAttributes(&attributes)) {
818 return false;
819 }
820 for (auto& attr : attributes) {
821 int attr_id = attr.GetAttributeId();
822 if (attr_id != NL80211_ATTR_WIPHY &&
823 attr_id != NL80211_ATTR_IFINDEX &&
824 attr_id != NL80211_ATTR_WDEV) {
825 auto attr_id_and_attr =
826 attr_by_wiphy_and_id[wiphy_index].find(attr_id);
827 if (attr_id_and_attr == attr_by_wiphy_and_id[wiphy_index].end()) {
828 attr_by_wiphy_and_id[wiphy_index].
829 insert(make_pair(attr_id, std::move(attr)));
830 } else {
831 attr_id_and_attr->second.Merge(attr);
832 }
833 }
834 }
835 }
836
837 // Generate output packets using the constructed map.
838 for (const auto& wiphy_and_attributes : attr_by_wiphy_and_id) {
839 NL80211Packet new_wiphy(0, NL80211_CMD_NEW_WIPHY, 0, 0);
840 new_wiphy.AddAttribute(
841 NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_and_attributes.first));
842 for (const auto& attr : wiphy_and_attributes.second) {
843 new_wiphy.AddAttribute(attr.second);
844 }
845 packet_per_wiphy->emplace_back(std::move(new_wiphy));
846 }
847 return true;
848 }
849
GetCountryCode(string * out_country_code)850 bool NetlinkUtils::GetCountryCode(string* out_country_code) {
851 NL80211Packet get_country_code(
852 netlink_manager_->GetFamilyId(),
853 NL80211_CMD_GET_REG,
854 netlink_manager_->GetSequenceNumber(),
855 getpid());
856 unique_ptr<const NL80211Packet> response;
857 if (!netlink_manager_->SendMessageAndGetSingleResponse(get_country_code,
858 &response)) {
859 LOG(ERROR) << "NL80211_CMD_GET_REG failed";
860 return false;
861 }
862 if (!response->GetAttributeValue(NL80211_ATTR_REG_ALPHA2, out_country_code)) {
863 LOG(ERROR) << "Get NL80211_ATTR_REG_ALPHA2 failed";
864 return false;
865 }
866 return true;
867 }
868
SendMgmtFrame(uint32_t interface_index,const vector<uint8_t> & frame,int32_t mcs,uint64_t * out_cookie)869 bool NetlinkUtils::SendMgmtFrame(uint32_t interface_index,
870 const vector<uint8_t>& frame, int32_t mcs, uint64_t* out_cookie) {
871
872 NL80211Packet send_mgmt_frame(
873 netlink_manager_->GetFamilyId(),
874 NL80211_CMD_FRAME,
875 netlink_manager_->GetSequenceNumber(),
876 getpid());
877
878 send_mgmt_frame.AddAttribute(
879 NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, interface_index));
880
881 send_mgmt_frame.AddAttribute(
882 NL80211Attr<vector<uint8_t>>(NL80211_ATTR_FRAME, frame));
883
884 if (mcs >= 0) {
885 // TODO (b/112029045) if mcs >= 0, add MCS attribute
886 }
887
888 unique_ptr<const NL80211Packet> response;
889 if (!netlink_manager_->SendMessageAndGetSingleResponse(
890 send_mgmt_frame, &response)) {
891 LOG(ERROR) << "NL80211_CMD_FRAME failed";
892 return false;
893 }
894
895 if (!response->GetAttributeValue(NL80211_ATTR_COOKIE, out_cookie)) {
896 LOG(ERROR) << "Get NL80211_ATTR_COOKIE failed";
897 return false;
898 }
899
900 return true;
901 }
902
SubscribeMlmeEvent(uint32_t interface_index,MlmeEventHandler * handler)903 void NetlinkUtils::SubscribeMlmeEvent(uint32_t interface_index,
904 MlmeEventHandler* handler) {
905 netlink_manager_->SubscribeMlmeEvent(interface_index, handler);
906 }
907
UnsubscribeMlmeEvent(uint32_t interface_index)908 void NetlinkUtils::UnsubscribeMlmeEvent(uint32_t interface_index) {
909 netlink_manager_->UnsubscribeMlmeEvent(interface_index);
910 }
911
SubscribeRegDomainChange(uint32_t wiphy_index,OnRegDomainChangedHandler handler)912 void NetlinkUtils::SubscribeRegDomainChange(
913 uint32_t wiphy_index,
914 OnRegDomainChangedHandler handler) {
915 netlink_manager_->SubscribeRegDomainChange(wiphy_index, handler);
916 }
917
UnsubscribeRegDomainChange(uint32_t wiphy_index)918 void NetlinkUtils::UnsubscribeRegDomainChange(uint32_t wiphy_index) {
919 netlink_manager_->UnsubscribeRegDomainChange(wiphy_index);
920 }
921
SubscribeStationEvent(uint32_t interface_index,OnStationEventHandler handler)922 void NetlinkUtils::SubscribeStationEvent(uint32_t interface_index,
923 OnStationEventHandler handler) {
924 netlink_manager_->SubscribeStationEvent(interface_index, handler);
925 }
926
UnsubscribeStationEvent(uint32_t interface_index)927 void NetlinkUtils::UnsubscribeStationEvent(uint32_t interface_index) {
928 netlink_manager_->UnsubscribeStationEvent(interface_index);
929 }
930
SubscribeChannelSwitchEvent(uint32_t interface_index,OnChannelSwitchEventHandler handler)931 void NetlinkUtils::SubscribeChannelSwitchEvent(uint32_t interface_index,
932 OnChannelSwitchEventHandler handler) {
933 netlink_manager_->SubscribeChannelSwitchEvent(interface_index, handler);
934 }
935
UnsubscribeChannelSwitchEvent(uint32_t interface_index)936 void NetlinkUtils::UnsubscribeChannelSwitchEvent(uint32_t interface_index) {
937 netlink_manager_->UnsubscribeChannelSwitchEvent(interface_index);
938 }
939
SubscribeFrameTxStatusEvent(uint32_t interface_index,OnFrameTxStatusEventHandler handler)940 void NetlinkUtils::SubscribeFrameTxStatusEvent(
941 uint32_t interface_index, OnFrameTxStatusEventHandler handler) {
942 netlink_manager_->SubscribeFrameTxStatusEvent(interface_index, handler);
943 }
944
UnsubscribeFrameTxStatusEvent(uint32_t interface_index)945 void NetlinkUtils::UnsubscribeFrameTxStatusEvent(uint32_t interface_index) {
946 netlink_manager_->UnsubscribeFrameTxStatusEvent(interface_index);
947 }
948
949 } // namespace wificond
950 } // namespace android
951