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::string;
41 using std::unique_ptr;
42 using std::vector;
43
44 namespace android {
45 namespace wificond {
46
47 namespace {
48
49 uint32_t k2GHzFrequencyLowerBound = 2400;
50 uint32_t k2GHzFrequencyUpperBound = 2500;
51
52 uint32_t k5GHzFrequencyLowerBound = 5000;
53 // This upper bound will exclude any 5.9Ghz channels which belong to 802.11p
54 // for "vehicular communication systems".
55 uint32_t k5GHzFrequencyUpperBound = 5850;
56
IsExtFeatureFlagSet(const std::vector<uint8_t> & ext_feature_flags_bytes,enum nl80211_ext_feature_index ext_feature_flag)57 bool IsExtFeatureFlagSet(
58 const std::vector<uint8_t>& ext_feature_flags_bytes,
59 enum nl80211_ext_feature_index ext_feature_flag) {
60 static_assert(NUM_NL80211_EXT_FEATURES <= SIZE_MAX,
61 "Ext feature values doesn't fit in |size_t|");
62 // TODO:This is an unsafe cast because this assumes that the values
63 // are always unsigned!
64 size_t ext_feature_flag_idx = static_cast<size_t>(ext_feature_flag);
65 size_t ext_feature_flag_byte_pos = ext_feature_flag_idx / 8;
66 size_t ext_feature_flag_bit_pos = ext_feature_flag_idx % 8;
67 if (ext_feature_flag_byte_pos >= ext_feature_flags_bytes.size()) {
68 return false;
69 }
70 uint8_t ext_feature_flag_byte =
71 ext_feature_flags_bytes[ext_feature_flag_byte_pos];
72 return (ext_feature_flag_byte & (1U << ext_feature_flag_bit_pos));
73 }
74 } // namespace
75
WiphyFeatures(uint32_t feature_flags,const std::vector<uint8_t> & ext_feature_flags_bytes)76 WiphyFeatures::WiphyFeatures(uint32_t feature_flags,
77 const std::vector<uint8_t>& ext_feature_flags_bytes)
78 : supports_random_mac_oneshot_scan(
79 feature_flags & NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR),
80 supports_random_mac_sched_scan(
81 feature_flags & NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR) {
82 supports_low_span_oneshot_scan =
83 IsExtFeatureFlagSet(ext_feature_flags_bytes,
84 NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
85 supports_low_power_oneshot_scan =
86 IsExtFeatureFlagSet(ext_feature_flags_bytes,
87 NL80211_EXT_FEATURE_LOW_POWER_SCAN);
88 supports_high_accuracy_oneshot_scan =
89 IsExtFeatureFlagSet(ext_feature_flags_bytes,
90 NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
91 // TODO (b/112029045) check if sending frame at specified MCS is supported
92 supports_tx_mgmt_frame_mcs = false;
93 supports_ext_sched_scan_relative_rssi =
94 IsExtFeatureFlagSet(ext_feature_flags_bytes,
95 NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI);
96 }
97
NetlinkUtils(NetlinkManager * netlink_manager)98 NetlinkUtils::NetlinkUtils(NetlinkManager* netlink_manager)
99 : netlink_manager_(netlink_manager) {
100 if (!netlink_manager_->IsStarted()) {
101 netlink_manager_->Start();
102 }
103 uint32_t protocol_features = 0;
104 supports_split_wiphy_dump_ = GetProtocolFeatures(&protocol_features) &&
105 (protocol_features & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP);
106 }
107
~NetlinkUtils()108 NetlinkUtils::~NetlinkUtils() {}
109
GetWiphyIndex(uint32_t * out_wiphy_index,const std::string & iface_name)110 bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index,
111 const std::string& iface_name) {
112 NL80211Packet get_wiphy(
113 netlink_manager_->GetFamilyId(),
114 NL80211_CMD_GET_WIPHY,
115 netlink_manager_->GetSequenceNumber(),
116 getpid());
117 get_wiphy.AddFlag(NLM_F_DUMP);
118 if (!iface_name.empty()) {
119 int ifindex = if_nametoindex(iface_name.c_str());
120 get_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, ifindex));
121 }
122 vector<unique_ptr<const NL80211Packet>> response;
123 if (!netlink_manager_->SendMessageAndGetResponses(get_wiphy, &response)) {
124 LOG(ERROR) << "NL80211_CMD_GET_WIPHY dump failed";
125 return false;
126 }
127 if (response.empty()) {
128 LOG(DEBUG) << "No wiphy is found";
129 return false;
130 }
131 for (auto& packet : response) {
132 if (packet->GetMessageType() == NLMSG_ERROR) {
133 LOG(ERROR) << "Receive ERROR message: "
134 << strerror(packet->GetErrorCode());
135 return false;
136 }
137 if (packet->GetMessageType() != netlink_manager_->GetFamilyId()) {
138 LOG(ERROR) << "Wrong message type for new interface message: "
139 << packet->GetMessageType();
140 return false;
141 }
142 if (packet->GetCommand() != NL80211_CMD_NEW_WIPHY) {
143 LOG(ERROR) << "Wrong command in response to "
144 << "a wiphy dump request: "
145 << static_cast<int>(packet->GetCommand());
146 return false;
147 }
148 if (!packet->GetAttributeValue(NL80211_ATTR_WIPHY, out_wiphy_index)) {
149 LOG(ERROR) << "Failed to get wiphy index from reply message";
150 return false;
151 }
152 }
153 return true;
154 }
155
GetWiphyIndex(uint32_t * out_wiphy_index)156 bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index) {
157 return GetWiphyIndex(out_wiphy_index, "");
158 }
159
GetInterfaces(uint32_t wiphy_index,vector<InterfaceInfo> * interface_info)160 bool NetlinkUtils::GetInterfaces(uint32_t wiphy_index,
161 vector<InterfaceInfo>* interface_info) {
162 NL80211Packet get_interfaces(
163 netlink_manager_->GetFamilyId(),
164 NL80211_CMD_GET_INTERFACE,
165 netlink_manager_->GetSequenceNumber(),
166 getpid());
167
168 get_interfaces.AddFlag(NLM_F_DUMP);
169 get_interfaces.AddAttribute(
170 NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_index));
171 vector<unique_ptr<const NL80211Packet>> response;
172 if (!netlink_manager_->SendMessageAndGetResponses(get_interfaces, &response)) {
173 LOG(ERROR) << "NL80211_CMD_GET_INTERFACE dump failed";
174 return false;
175 }
176 if (response.empty()) {
177 LOG(ERROR) << "No interface is found";
178 return false;
179 }
180 for (auto& packet : response) {
181 if (packet->GetMessageType() == NLMSG_ERROR) {
182 LOG(ERROR) << "Receive ERROR message: "
183 << strerror(packet->GetErrorCode());
184 return false;
185 }
186 if (packet->GetMessageType() != netlink_manager_->GetFamilyId()) {
187 LOG(ERROR) << "Wrong message type for new interface message: "
188 << packet->GetMessageType();
189 return false;
190 }
191 if (packet->GetCommand() != NL80211_CMD_NEW_INTERFACE) {
192 LOG(ERROR) << "Wrong command in response to "
193 << "an interface dump request: "
194 << static_cast<int>(packet->GetCommand());
195 return false;
196 }
197
198 // In some situations, it has been observed that the kernel tells us
199 // about a pseudo interface that does not have a real netdev. In this
200 // case, responses will have a NL80211_ATTR_WDEV, and not the expected
201 // IFNAME/IFINDEX. In this case we just skip these pseudo interfaces.
202 uint32_t if_index;
203 if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
204 LOG(DEBUG) << "Failed to get interface index";
205 continue;
206 }
207
208 // Today we don't check NL80211_ATTR_IFTYPE because at this point of time
209 // driver always reports that interface is in STATION mode. Even when we
210 // are asking interfaces infomation on behalf of tethering, it is still so
211 // because hostapd is supposed to set interface to AP mode later.
212
213 string if_name;
214 if (!packet->GetAttributeValue(NL80211_ATTR_IFNAME, &if_name)) {
215 LOG(WARNING) << "Failed to get interface name";
216 continue;
217 }
218
219 array<uint8_t, ETH_ALEN> if_mac_addr;
220 if (!packet->GetAttributeValue(NL80211_ATTR_MAC, &if_mac_addr)) {
221 LOG(WARNING) << "Failed to get interface mac address";
222 continue;
223 }
224
225 interface_info->emplace_back(if_index, if_name, if_mac_addr);
226 }
227
228 return true;
229 }
230
SetInterfaceMode(uint32_t interface_index,InterfaceMode mode)231 bool NetlinkUtils::SetInterfaceMode(uint32_t interface_index,
232 InterfaceMode mode) {
233 uint32_t set_to_mode = NL80211_IFTYPE_UNSPECIFIED;
234 if (mode == STATION_MODE) {
235 set_to_mode = NL80211_IFTYPE_STATION;
236 } else {
237 LOG(ERROR) << "Unexpected mode for interface with index: "
238 << interface_index;
239 return false;
240 }
241 NL80211Packet set_interface_mode(
242 netlink_manager_->GetFamilyId(),
243 NL80211_CMD_SET_INTERFACE,
244 netlink_manager_->GetSequenceNumber(),
245 getpid());
246 // Force an ACK response upon success.
247 set_interface_mode.AddFlag(NLM_F_ACK);
248
249 set_interface_mode.AddAttribute(
250 NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, interface_index));
251 set_interface_mode.AddAttribute(
252 NL80211Attr<uint32_t>(NL80211_ATTR_IFTYPE, set_to_mode));
253
254 if (!netlink_manager_->SendMessageAndGetAck(set_interface_mode)) {
255 LOG(ERROR) << "NL80211_CMD_SET_INTERFACE failed";
256 return false;
257 }
258
259 return true;
260 }
261
GetProtocolFeatures(uint32_t * features)262 bool NetlinkUtils::GetProtocolFeatures(uint32_t* features) {
263 NL80211Packet get_protocol_features(
264 netlink_manager_->GetFamilyId(),
265 NL80211_CMD_GET_PROTOCOL_FEATURES,
266 netlink_manager_->GetSequenceNumber(),
267 getpid());
268 unique_ptr<const NL80211Packet> response;
269 if (!netlink_manager_->SendMessageAndGetSingleResponse(get_protocol_features,
270 &response)) {
271 LOG(ERROR) << "NL80211_CMD_GET_PROTOCOL_FEATURES failed";
272 return false;
273 }
274 if (!response->GetAttributeValue(NL80211_ATTR_PROTOCOL_FEATURES, features)) {
275 LOG(ERROR) << "Failed to get NL80211_ATTR_PROTOCOL_FEATURES";
276 return false;
277 }
278 return true;
279 }
280
GetWiphyInfo(uint32_t wiphy_index,BandInfo * out_band_info,ScanCapabilities * out_scan_capabilities,WiphyFeatures * out_wiphy_features)281 bool NetlinkUtils::GetWiphyInfo(
282 uint32_t wiphy_index,
283 BandInfo* out_band_info,
284 ScanCapabilities* out_scan_capabilities,
285 WiphyFeatures* out_wiphy_features) {
286 NL80211Packet get_wiphy(
287 netlink_manager_->GetFamilyId(),
288 NL80211_CMD_GET_WIPHY,
289 netlink_manager_->GetSequenceNumber(),
290 getpid());
291 get_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_index));
292 if (supports_split_wiphy_dump_) {
293 get_wiphy.AddFlagAttribute(NL80211_ATTR_SPLIT_WIPHY_DUMP);
294 get_wiphy.AddFlag(NLM_F_DUMP);
295 }
296 vector<unique_ptr<const NL80211Packet>> response;
297 if (!netlink_manager_->SendMessageAndGetResponses(get_wiphy, &response)) {
298 LOG(ERROR) << "NL80211_CMD_GET_WIPHY dump failed";
299 return false;
300 }
301
302 vector<NL80211Packet> packet_per_wiphy;
303 if (supports_split_wiphy_dump_) {
304 if (!MergePacketsForSplitWiphyDump(response, &packet_per_wiphy)) {
305 LOG(WARNING) << "Failed to merge responses from split wiphy dump";
306 }
307 } else {
308 for (auto& packet : response) {
309 packet_per_wiphy.push_back(move(*(packet.release())));
310 }
311 }
312
313 for (const auto& packet : packet_per_wiphy) {
314 uint32_t current_wiphy_index;
315 if (!packet.GetAttributeValue(NL80211_ATTR_WIPHY, ¤t_wiphy_index) ||
316 // Not the wihpy we requested.
317 current_wiphy_index != wiphy_index) {
318 continue;
319 }
320 if (ParseWiphyInfoFromPacket(packet, out_band_info,
321 out_scan_capabilities, out_wiphy_features)) {
322 return true;
323 }
324 }
325
326 LOG(ERROR) << "Failed to find expected wiphy info "
327 << "from NL80211_CMD_GET_WIPHY responses";
328 return false;
329 }
330
ParseWiphyInfoFromPacket(const NL80211Packet & packet,BandInfo * out_band_info,ScanCapabilities * out_scan_capabilities,WiphyFeatures * out_wiphy_features)331 bool NetlinkUtils::ParseWiphyInfoFromPacket(
332 const NL80211Packet& packet,
333 BandInfo* out_band_info,
334 ScanCapabilities* out_scan_capabilities,
335 WiphyFeatures* out_wiphy_features) {
336 if (packet.GetCommand() != NL80211_CMD_NEW_WIPHY) {
337 LOG(ERROR) << "Wrong command in response to a get wiphy request: "
338 << static_cast<int>(packet.GetCommand());
339 return false;
340 }
341 if (!ParseBandInfo(&packet, out_band_info) ||
342 !ParseScanCapabilities(&packet, out_scan_capabilities)) {
343 return false;
344 }
345 uint32_t feature_flags;
346 if (!packet.GetAttributeValue(NL80211_ATTR_FEATURE_FLAGS,
347 &feature_flags)) {
348 LOG(ERROR) << "Failed to get NL80211_ATTR_FEATURE_FLAGS";
349 return false;
350 }
351 std::vector<uint8_t> ext_feature_flags_bytes;
352 if (!packet.GetAttributeValue(NL80211_ATTR_EXT_FEATURES,
353 &ext_feature_flags_bytes)) {
354 LOG(WARNING) << "Failed to get NL80211_ATTR_EXT_FEATURES";
355 }
356 *out_wiphy_features = WiphyFeatures(feature_flags,
357 ext_feature_flags_bytes);
358 return true;
359 }
360
ParseScanCapabilities(const NL80211Packet * const packet,ScanCapabilities * out_scan_capabilities)361 bool NetlinkUtils::ParseScanCapabilities(
362 const NL80211Packet* const packet,
363 ScanCapabilities* out_scan_capabilities) {
364 uint8_t max_num_scan_ssids;
365 if (!packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
366 &max_num_scan_ssids)) {
367 LOG(ERROR) << "Failed to get the capacity of maximum number of scan ssids";
368 return false;
369 }
370
371 uint8_t max_num_sched_scan_ssids;
372 if (!packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
373 &max_num_sched_scan_ssids)) {
374 LOG(ERROR) << "Failed to get the capacity of "
375 << "maximum number of scheduled scan ssids";
376 return false;
377 }
378
379 // Use default value 0 for scan plan capabilities if attributes are missing.
380 uint32_t max_num_scan_plans = 0;
381 packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
382 &max_num_scan_plans);
383 uint32_t max_scan_plan_interval = 0;
384 packet->GetAttributeValue(NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
385 &max_scan_plan_interval);
386 uint32_t max_scan_plan_iterations = 0;
387 packet->GetAttributeValue(NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
388 &max_scan_plan_iterations);
389
390 uint8_t max_match_sets;
391 if (!packet->GetAttributeValue(NL80211_ATTR_MAX_MATCH_SETS,
392 &max_match_sets)) {
393 LOG(ERROR) << "Failed to get the capacity of maximum number of match set"
394 << "of a scheduled scan";
395 return false;
396 }
397 *out_scan_capabilities = ScanCapabilities(max_num_scan_ssids,
398 max_num_sched_scan_ssids,
399 max_match_sets,
400 max_num_scan_plans,
401 max_scan_plan_interval,
402 max_scan_plan_iterations);
403 return true;
404 }
405
ParseBandInfo(const NL80211Packet * const packet,BandInfo * out_band_info)406 bool NetlinkUtils::ParseBandInfo(const NL80211Packet* const packet,
407 BandInfo* out_band_info) {
408
409 NL80211NestedAttr bands_attr(0);
410 if (!packet->GetAttribute(NL80211_ATTR_WIPHY_BANDS, &bands_attr)) {
411 LOG(ERROR) << "Failed to get NL80211_ATTR_WIPHY_BANDS";
412 return false;
413 }
414 vector<NL80211NestedAttr> bands;
415 if (!bands_attr.GetListOfNestedAttributes(&bands)) {
416 LOG(ERROR) << "Failed to get bands within NL80211_ATTR_WIPHY_BANDS";
417 return false;
418 }
419 vector<uint32_t> frequencies_2g;
420 vector<uint32_t> frequencies_5g;
421 vector<uint32_t> frequencies_dfs;
422 for (unsigned int band_index = 0; band_index < bands.size(); band_index++) {
423 NL80211NestedAttr freqs_attr(0);
424 if (!bands[band_index].GetAttribute(NL80211_BAND_ATTR_FREQS, &freqs_attr)) {
425 LOG(DEBUG) << "Failed to get NL80211_BAND_ATTR_FREQS";
426 continue;
427 }
428 vector<NL80211NestedAttr> freqs;
429 if (!freqs_attr.GetListOfNestedAttributes(&freqs)) {
430 LOG(ERROR) << "Failed to get frequencies within NL80211_BAND_ATTR_FREQS";
431 continue;
432 }
433 for (auto& freq : freqs) {
434 uint32_t frequency_value;
435 if (!freq.GetAttributeValue(NL80211_FREQUENCY_ATTR_FREQ,
436 &frequency_value)) {
437 LOG(DEBUG) << "Failed to get NL80211_FREQUENCY_ATTR_FREQ";
438 continue;
439 }
440 // Channel is disabled in current regulatory domain.
441 if (freq.HasAttribute(NL80211_FREQUENCY_ATTR_DISABLED)) {
442 continue;
443 }
444 if (frequency_value > k2GHzFrequencyLowerBound &&
445 frequency_value < k2GHzFrequencyUpperBound) {
446 frequencies_2g.push_back(frequency_value);
447 } else if (frequency_value > k5GHzFrequencyLowerBound &&
448 frequency_value < k5GHzFrequencyUpperBound) {
449 // If this is an available/usable DFS frequency, we should save it to
450 // DFS frequencies list.
451 uint32_t dfs_state;
452 if (freq.GetAttributeValue(NL80211_FREQUENCY_ATTR_DFS_STATE,
453 &dfs_state) &&
454 (dfs_state == NL80211_DFS_AVAILABLE ||
455 dfs_state == NL80211_DFS_USABLE)) {
456 frequencies_dfs.push_back(frequency_value);
457 continue;
458 }
459
460 // Put non-dfs passive-only channels into the dfs category.
461 // This aligns with what framework always assumes.
462 if (freq.HasAttribute(NL80211_FREQUENCY_ATTR_NO_IR)) {
463 frequencies_dfs.push_back(frequency_value);
464 continue;
465 }
466
467 // Otherwise, this is a regular 5g frequency.
468 frequencies_5g.push_back(frequency_value);
469 }
470
471 }
472 }
473 *out_band_info = BandInfo(frequencies_2g, frequencies_5g, frequencies_dfs);
474 return true;
475 }
476
GetStationInfo(uint32_t interface_index,const array<uint8_t,ETH_ALEN> & mac_address,StationInfo * out_station_info)477 bool NetlinkUtils::GetStationInfo(uint32_t interface_index,
478 const array<uint8_t, ETH_ALEN>& mac_address,
479 StationInfo* out_station_info) {
480 NL80211Packet get_station(
481 netlink_manager_->GetFamilyId(),
482 NL80211_CMD_GET_STATION,
483 netlink_manager_->GetSequenceNumber(),
484 getpid());
485 get_station.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX,
486 interface_index));
487 get_station.AddAttribute(NL80211Attr<array<uint8_t, ETH_ALEN>>(
488 NL80211_ATTR_MAC, mac_address));
489
490 unique_ptr<const NL80211Packet> response;
491 if (!netlink_manager_->SendMessageAndGetSingleResponse(get_station,
492 &response)) {
493 LOG(ERROR) << "NL80211_CMD_GET_STATION failed";
494 return false;
495 }
496 if (response->GetCommand() != NL80211_CMD_NEW_STATION) {
497 LOG(ERROR) << "Wrong command in response to a get station request: "
498 << static_cast<int>(response->GetCommand());
499 return false;
500 }
501 NL80211NestedAttr sta_info(0);
502 if (!response->GetAttribute(NL80211_ATTR_STA_INFO, &sta_info)) {
503 LOG(ERROR) << "Failed to get NL80211_ATTR_STA_INFO";
504 return false;
505 }
506 int32_t tx_good, tx_bad;
507 if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_PACKETS, &tx_good)) {
508 LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_PACKETS";
509 return false;
510 }
511 if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_FAILED, &tx_bad)) {
512 LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_FAILED";
513 return false;
514 }
515 int8_t current_rssi;
516 if (!sta_info.GetAttributeValue(NL80211_STA_INFO_SIGNAL, ¤t_rssi)) {
517 LOG(ERROR) << "Failed to get NL80211_STA_INFO_SIGNAL";
518 return false;
519 }
520 NL80211NestedAttr tx_bitrate_attr(0);
521 uint32_t tx_bitrate = 0;
522 if (sta_info.GetAttribute(NL80211_STA_INFO_TX_BITRATE,
523 &tx_bitrate_attr)) {
524 if (!tx_bitrate_attr.GetAttributeValue(NL80211_RATE_INFO_BITRATE32,
525 &tx_bitrate)) {
526 // Return invalid tx rate to avoid breaking the get station cmd
527 tx_bitrate = 0;
528 }
529 }
530 NL80211NestedAttr rx_bitrate_attr(0);
531 uint32_t rx_bitrate = 0;
532 if (sta_info.GetAttribute(NL80211_STA_INFO_RX_BITRATE,
533 &rx_bitrate_attr)) {
534 if (!rx_bitrate_attr.GetAttributeValue(NL80211_RATE_INFO_BITRATE32,
535 &rx_bitrate)) {
536 // Return invalid rx rate to avoid breaking the get station cmd
537 rx_bitrate = 0;
538 }
539 }
540 *out_station_info = StationInfo(tx_good, tx_bad, tx_bitrate, current_rssi, rx_bitrate);
541 return true;
542 }
543
544 // This is a helper function for merging split NL80211_CMD_NEW_WIPHY packets.
545 // For example:
546 // First NL80211_CMD_NEW_WIPHY has attribute A with payload 0x1234.
547 // Second NL80211_CMD_NEW_WIPHY has attribute A with payload 0x5678.
548 // The generated NL80211_CMD_NEW_WIPHY will have attribute A with
549 // payload 0x12345678.
550 // NL80211_ATTR_WIPHY, NL80211_ATTR_IFINDEX, and NL80211_ATTR_WDEV
551 // are used for filtering packets so we know which packets should
552 // be merged together.
MergePacketsForSplitWiphyDump(const vector<unique_ptr<const NL80211Packet>> & split_dump_info,vector<NL80211Packet> * packet_per_wiphy)553 bool NetlinkUtils::MergePacketsForSplitWiphyDump(
554 const vector<unique_ptr<const NL80211Packet>>& split_dump_info,
555 vector<NL80211Packet>* packet_per_wiphy) {
556 map<uint32_t, map<int, BaseNL80211Attr>> attr_by_wiphy_and_id;
557
558 // Construct the map using input packets.
559 for (const auto& packet : split_dump_info) {
560 uint32_t wiphy_index;
561 if (!packet->GetAttributeValue(NL80211_ATTR_WIPHY, &wiphy_index)) {
562 LOG(ERROR) << "Failed to get NL80211_ATTR_WIPHY from wiphy split dump";
563 return false;
564 }
565 vector<BaseNL80211Attr> attributes;
566 if (!packet->GetAllAttributes(&attributes)) {
567 return false;
568 }
569 for (auto& attr : attributes) {
570 int attr_id = attr.GetAttributeId();
571 if (attr_id != NL80211_ATTR_WIPHY &&
572 attr_id != NL80211_ATTR_IFINDEX &&
573 attr_id != NL80211_ATTR_WDEV) {
574 auto attr_id_and_attr =
575 attr_by_wiphy_and_id[wiphy_index].find(attr_id);
576 if (attr_id_and_attr == attr_by_wiphy_and_id[wiphy_index].end()) {
577 attr_by_wiphy_and_id[wiphy_index].
578 insert(make_pair(attr_id, move(attr)));
579 } else {
580 attr_id_and_attr->second.Merge(attr);
581 }
582 }
583 }
584 }
585
586 // Generate output packets using the constructed map.
587 for (const auto& wiphy_and_attributes : attr_by_wiphy_and_id) {
588 NL80211Packet new_wiphy(0, NL80211_CMD_NEW_WIPHY, 0, 0);
589 new_wiphy.AddAttribute(
590 NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_and_attributes.first));
591 for (const auto& attr : wiphy_and_attributes.second) {
592 new_wiphy.AddAttribute(attr.second);
593 }
594 packet_per_wiphy->emplace_back(move(new_wiphy));
595 }
596 return true;
597 }
598
GetCountryCode(string * out_country_code)599 bool NetlinkUtils::GetCountryCode(string* out_country_code) {
600 NL80211Packet get_country_code(
601 netlink_manager_->GetFamilyId(),
602 NL80211_CMD_GET_REG,
603 netlink_manager_->GetSequenceNumber(),
604 getpid());
605 unique_ptr<const NL80211Packet> response;
606 if (!netlink_manager_->SendMessageAndGetSingleResponse(get_country_code,
607 &response)) {
608 LOG(ERROR) << "NL80211_CMD_GET_REG failed";
609 return false;
610 }
611 if (!response->GetAttributeValue(NL80211_ATTR_REG_ALPHA2, out_country_code)) {
612 LOG(ERROR) << "Get NL80211_ATTR_REG_ALPHA2 failed";
613 return false;
614 }
615 return true;
616 }
617
SendMgmtFrame(uint32_t interface_index,const vector<uint8_t> & frame,int32_t mcs,uint64_t * out_cookie)618 bool NetlinkUtils::SendMgmtFrame(uint32_t interface_index,
619 const vector<uint8_t>& frame, int32_t mcs, uint64_t* out_cookie) {
620
621 NL80211Packet send_mgmt_frame(
622 netlink_manager_->GetFamilyId(),
623 NL80211_CMD_FRAME,
624 netlink_manager_->GetSequenceNumber(),
625 getpid());
626
627 send_mgmt_frame.AddAttribute(
628 NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, interface_index));
629
630 send_mgmt_frame.AddAttribute(
631 NL80211Attr<vector<uint8_t>>(NL80211_ATTR_FRAME, frame));
632
633 if (mcs >= 0) {
634 // TODO (b/112029045) if mcs >= 0, add MCS attribute
635 }
636
637 unique_ptr<const NL80211Packet> response;
638 if (!netlink_manager_->SendMessageAndGetSingleResponse(
639 send_mgmt_frame, &response)) {
640 LOG(ERROR) << "NL80211_CMD_FRAME failed";
641 return false;
642 }
643
644 if (!response->GetAttributeValue(NL80211_ATTR_COOKIE, out_cookie)) {
645 LOG(ERROR) << "Get NL80211_ATTR_COOKIE failed";
646 return false;
647 }
648
649 return true;
650 }
651
SubscribeMlmeEvent(uint32_t interface_index,MlmeEventHandler * handler)652 void NetlinkUtils::SubscribeMlmeEvent(uint32_t interface_index,
653 MlmeEventHandler* handler) {
654 netlink_manager_->SubscribeMlmeEvent(interface_index, handler);
655 }
656
UnsubscribeMlmeEvent(uint32_t interface_index)657 void NetlinkUtils::UnsubscribeMlmeEvent(uint32_t interface_index) {
658 netlink_manager_->UnsubscribeMlmeEvent(interface_index);
659 }
660
SubscribeRegDomainChange(uint32_t wiphy_index,OnRegDomainChangedHandler handler)661 void NetlinkUtils::SubscribeRegDomainChange(
662 uint32_t wiphy_index,
663 OnRegDomainChangedHandler handler) {
664 netlink_manager_->SubscribeRegDomainChange(wiphy_index, handler);
665 }
666
UnsubscribeRegDomainChange(uint32_t wiphy_index)667 void NetlinkUtils::UnsubscribeRegDomainChange(uint32_t wiphy_index) {
668 netlink_manager_->UnsubscribeRegDomainChange(wiphy_index);
669 }
670
SubscribeStationEvent(uint32_t interface_index,OnStationEventHandler handler)671 void NetlinkUtils::SubscribeStationEvent(uint32_t interface_index,
672 OnStationEventHandler handler) {
673 netlink_manager_->SubscribeStationEvent(interface_index, handler);
674 }
675
UnsubscribeStationEvent(uint32_t interface_index)676 void NetlinkUtils::UnsubscribeStationEvent(uint32_t interface_index) {
677 netlink_manager_->UnsubscribeStationEvent(interface_index);
678 }
679
SubscribeChannelSwitchEvent(uint32_t interface_index,OnChannelSwitchEventHandler handler)680 void NetlinkUtils::SubscribeChannelSwitchEvent(uint32_t interface_index,
681 OnChannelSwitchEventHandler handler) {
682 netlink_manager_->SubscribeChannelSwitchEvent(interface_index, handler);
683 }
684
UnsubscribeChannelSwitchEvent(uint32_t interface_index)685 void NetlinkUtils::UnsubscribeChannelSwitchEvent(uint32_t interface_index) {
686 netlink_manager_->UnsubscribeChannelSwitchEvent(interface_index);
687 }
688
SubscribeFrameTxStatusEvent(uint32_t interface_index,OnFrameTxStatusEventHandler handler)689 void NetlinkUtils::SubscribeFrameTxStatusEvent(
690 uint32_t interface_index, OnFrameTxStatusEventHandler handler) {
691 netlink_manager_->SubscribeFrameTxStatusEvent(interface_index, handler);
692 }
693
UnsubscribeFrameTxStatusEvent(uint32_t interface_index)694 void NetlinkUtils::UnsubscribeFrameTxStatusEvent(uint32_t interface_index) {
695 netlink_manager_->UnsubscribeFrameTxStatusEvent(interface_index);
696 }
697
698 } // namespace wificond
699 } // namespace android
700