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, ¤t_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, ¤t_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