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