350 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			350 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * Copyright (C) 2016 The Android Open Source Project
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  * you may not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at
 | |
|  *
 | |
|  *      http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an "AS IS" BASIS,
 | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  */
 | |
| 
 | |
| #ifndef WIFICOND_NET_NETLINK_UTILS_H_
 | |
| #define WIFICOND_NET_NETLINK_UTILS_H_
 | |
| 
 | |
| #include <array>
 | |
| #include <functional>
 | |
| #include <string>
 | |
| #include <vector>
 | |
| 
 | |
| #include <linux/if_ether.h>
 | |
| 
 | |
| #include <android-base/macros.h>
 | |
| 
 | |
| #include "wificond/net/kernel-header-latest/nl80211.h"
 | |
| #include "wificond/net/netlink_manager.h"
 | |
| #include "wificond/net/nl80211_packet.h"
 | |
| 
 | |
| namespace android {
 | |
| namespace wificond {
 | |
| 
 | |
| struct InterfaceInfo {
 | |
|   InterfaceInfo() = default;
 | |
|   InterfaceInfo(uint32_t if_index,
 | |
|                 uint32_t wiphy_index,
 | |
|                 const std::string& name,
 | |
|                 const std::array<uint8_t, ETH_ALEN>& mac_address)
 | |
|       : if_index(if_index),
 | |
|         wiphy_index(wiphy_index),
 | |
|         name(name),
 | |
|         mac_address(mac_address) {}
 | |
|   // Index of this interface.
 | |
|   uint32_t if_index;
 | |
|   // Wiphy Index of this interface.
 | |
|   uint32_t wiphy_index;
 | |
|   // Name of this interface.
 | |
|   std::string name;
 | |
|   // MAC address of this interface.
 | |
|   std::array<uint8_t, ETH_ALEN> mac_address;
 | |
| };
 | |
| 
 | |
| struct BandInfo {
 | |
|   BandInfo():
 | |
|       is_80211n_supported(false),
 | |
|       is_80211ac_supported(false),
 | |
|       is_80211ax_supported(false),
 | |
|       is_80211be_supported(false),
 | |
|       is_160_mhz_supported(false),
 | |
|       is_80p80_mhz_supported(false),
 | |
|       is_320_mhz_supported(false),
 | |
|       max_tx_streams(1),
 | |
|       max_rx_streams(1) {};
 | |
|   // Frequencies for 2.4 GHz band.
 | |
|   std::vector<uint32_t> band_2g;
 | |
|   // Frequencies for 5 GHz band without DFS.
 | |
|   std::vector<uint32_t> band_5g;
 | |
|   // Frequencies for DFS.
 | |
|   std::vector<uint32_t> band_dfs;
 | |
|   // Frequencies for 6 GHz band.
 | |
|   std::vector<uint32_t> band_6g;
 | |
|   // Frequencies for 60 GHz band.
 | |
|   std::vector<uint32_t> band_60g;
 | |
|   // support for 802.11n
 | |
|   bool is_80211n_supported;
 | |
|   // support for 802.11ac
 | |
|   bool is_80211ac_supported;
 | |
|   // support for 802.11ax
 | |
|   bool is_80211ax_supported;
 | |
|   // support for 802.11be
 | |
|   bool is_80211be_supported;
 | |
|   // support for 160Mhz channel width
 | |
|   bool is_160_mhz_supported;
 | |
|   // support for 80+80Mhz channel width
 | |
|   bool is_80p80_mhz_supported;
 | |
|   // support for 320Mhz channel width
 | |
|   bool is_320_mhz_supported;
 | |
|   // Max number of transmit spatial streams
 | |
|   uint32_t max_tx_streams;
 | |
|   // Max number of receive spatial streams
 | |
|   uint32_t max_rx_streams;
 | |
| };
 | |
| 
 | |
| struct ScanCapabilities {
 | |
|   ScanCapabilities() = default;
 | |
|   ScanCapabilities(uint8_t max_num_scan_ssids_,
 | |
|                    uint8_t max_num_sched_scan_ssids_,
 | |
|                    uint8_t max_match_sets_,
 | |
|                    uint32_t max_num_scan_plans_,
 | |
|                    uint32_t max_scan_plan_interval_,
 | |
|                    uint32_t max_scan_plan_iterations_)
 | |
|       : max_num_scan_ssids(max_num_scan_ssids_),
 | |
|         max_num_sched_scan_ssids(max_num_sched_scan_ssids_),
 | |
|         max_match_sets(max_match_sets_),
 | |
|         max_num_scan_plans(max_num_scan_plans_),
 | |
|         max_scan_plan_interval(max_scan_plan_interval_),
 | |
|         max_scan_plan_iterations(max_scan_plan_iterations_) {}
 | |
|   // Number of SSIDs you can scan with a single scan request.
 | |
|   uint8_t max_num_scan_ssids;
 | |
|   // Number of SSIDs you can scan with a single scheduled scan request.
 | |
|   uint8_t max_num_sched_scan_ssids;
 | |
|   // Maximum number of sets that can be used with NL80211_ATTR_SCHED_SCAN_MATCH.
 | |
|   uint8_t max_match_sets;
 | |
|   // Maximum number of scan plans that can be specified.
 | |
|   uint32_t max_num_scan_plans;
 | |
|   // Maximum interval in seconds for a particular scan plan that can be
 | |
|   // specified.
 | |
|   uint32_t max_scan_plan_interval;
 | |
|   // Maximum number of iterations for a particular scan plan that can be
 | |
|   // specified.
 | |
|   uint32_t max_scan_plan_iterations;
 | |
| };
 | |
| 
 | |
| struct WiphyFeatures {
 | |
|   WiphyFeatures()
 | |
|       : supports_random_mac_oneshot_scan(false),
 | |
|         supports_random_mac_sched_scan(false),
 | |
|         supports_low_span_oneshot_scan(false),
 | |
|         supports_low_power_oneshot_scan(false),
 | |
|         supports_high_accuracy_oneshot_scan(false),
 | |
|         supports_tx_mgmt_frame_mcs(false) {}
 | |
|   WiphyFeatures(uint32_t feature_flags,
 | |
|                 const std::vector<uint8_t>& ext_feature_flags_bytes);
 | |
|   // This device/driver supports using a random MAC address during scan
 | |
|   // (while not associated).
 | |
|   bool supports_random_mac_oneshot_scan;
 | |
|   // This device/driver supports using a random MAC address for every
 | |
|   // scan iteration during scheduled scan (while not associated).
 | |
|   bool supports_random_mac_sched_scan;
 | |
|   // This device/driver supports performing low-span/low-latency one-shot scans.
 | |
|   bool supports_low_span_oneshot_scan;
 | |
|   // This device/driver supports performing low-power one-shot scans.
 | |
|   bool supports_low_power_oneshot_scan;
 | |
|   // This device/driver supports performing high-accuracy one-shot scans.
 | |
|   bool supports_high_accuracy_oneshot_scan;
 | |
|   // This device/driver supports sending a management frame at a specified MCS.
 | |
|   bool supports_tx_mgmt_frame_mcs;
 | |
|   // This device/driver supports sched_scan for reporting BSSs
 | |
|   // with better RSSI than the current connected BSS
 | |
|   bool supports_ext_sched_scan_relative_rssi;
 | |
|   // There are other flags included in NL80211_ATTR_FEATURE_FLAGS.
 | |
|   // We will add them once we find them useful.
 | |
| };
 | |
| 
 | |
| struct StationInfo {
 | |
|   StationInfo() = default;
 | |
|   StationInfo(uint32_t station_tx_packets_,
 | |
|               uint32_t station_tx_failed_,
 | |
|               uint32_t station_tx_bitrate_,
 | |
|               int8_t current_rssi_,
 | |
|               uint32_t station_rx_bitrate_)
 | |
|       : station_tx_packets(station_tx_packets_),
 | |
|         station_tx_failed(station_tx_failed_),
 | |
|         station_tx_bitrate(station_tx_bitrate_),
 | |
|         current_rssi(current_rssi_),
 | |
|         station_rx_bitrate(station_rx_bitrate_) {}
 | |
|   // Number of successfully transmitted packets.
 | |
|   int32_t station_tx_packets;
 | |
|   // Number of tramsmission failures.
 | |
|   int32_t station_tx_failed;
 | |
|   // Transimission bit rate in 100kbit/s.
 | |
|   uint32_t station_tx_bitrate;
 | |
|   // Current signal strength.
 | |
|   int8_t current_rssi;
 | |
|   // Last Received unicast packet bit rate in 100kbit/s.
 | |
|   uint32_t station_rx_bitrate;
 | |
|   // There are many other counters/parameters included in station info.
 | |
|   // We will add them once we find them useful.
 | |
| };
 | |
| 
 | |
| class MlmeEventHandler;
 | |
| class NetlinkManager;
 | |
| class NL80211Packet;
 | |
| 
 | |
| // Provides NL80211 helper functions.
 | |
| class NetlinkUtils {
 | |
|  public:
 | |
|   // Currently we only support setting the interface to STATION mode.
 | |
|   // This is used for cleaning up interface after KILLING hostapd.
 | |
|   enum InterfaceMode{
 | |
|       STATION_MODE
 | |
|   };
 | |
| 
 | |
|   explicit NetlinkUtils(NetlinkManager* netlink_manager);
 | |
|   virtual ~NetlinkUtils();
 | |
| 
 | |
|   // Get the wiphy index from kernel.
 | |
|   // |*out_wiphy_index| returns the wiphy index from kernel.
 | |
|   // Returns true on success.
 | |
|   virtual bool GetWiphyIndex(uint32_t* out_wiphy_index);
 | |
|   virtual bool GetWiphyIndex(uint32_t* out_wiphy_index,
 | |
|                              const std::string& iface_name);
 | |
| 
 | |
|   // Get wifi interfaces info from kernel.
 | |
|   // |wiphy_index| is the wiphy index we get using GetWiphyIndex().
 | |
|   // |interface_info| returns a vector of InterfaceInfo structs with
 | |
|   // information about all existing interfaces.
 | |
|   // Returns true on success.
 | |
|   virtual bool GetInterfaces(uint32_t wiphy_index,
 | |
|                              std::vector<InterfaceInfo>* interface_info);
 | |
| 
 | |
|   // Set the mode of interface.
 | |
|   // |interface_index| is the interface index.
 | |
|   // |mode| is one of the values in |enum InterfaceMode|.
 | |
|   // Returns true on success.
 | |
|   virtual bool SetInterfaceMode(uint32_t interface_index,
 | |
|                                 InterfaceMode mode);
 | |
| 
 | |
|   // Get wiphy capability information from kernel.
 | |
|   // Returns true on success.
 | |
|   virtual bool GetWiphyInfo(uint32_t wiphy_index,
 | |
|                             BandInfo* out_band_info,
 | |
|                             ScanCapabilities* out_scan_capabilities,
 | |
|                             WiphyFeatures* out_wiphy_features);
 | |
| 
 | |
|   // Get station info from kernel.
 | |
|   // |*out_station_info]| is the struct of available station information.
 | |
|   // Returns true on success.
 | |
|   virtual bool GetStationInfo(uint32_t interface_index,
 | |
|                               const std::array<uint8_t, ETH_ALEN>& mac_address,
 | |
|                               StationInfo* out_station_info);
 | |
| 
 | |
|   // Get a bitmap for nl80211 protocol features,
 | |
|   // i.e. features for the nl80211 protocol rather than device features.
 | |
|   // See enum nl80211_protocol_features in nl80211.h for decoding the bitmap.
 | |
|   // Returns true on success.
 | |
|   virtual bool GetProtocolFeatures(uint32_t* features);
 | |
| 
 | |
|   // Get current alpha2 country code from kernel.
 | |
|   // Returns true on success.
 | |
|   virtual bool GetCountryCode(std::string* out_country_code);
 | |
| 
 | |
|   // Sign up to be notified when there is MLME event.
 | |
|   // Only one handler can be registered per interface index.
 | |
|   // New handler will replace the registered handler if they are for the
 | |
|   // same interface index.
 | |
|   // NetlinkUtils is not going to take ownership of this pointer, and that it
 | |
|   // is the caller's responsibility to make sure that the object exists for the
 | |
|   // duration of the subscription.
 | |
|   virtual void SubscribeMlmeEvent(uint32_t interface_index,
 | |
|                                   MlmeEventHandler* handler);
 | |
| 
 | |
|   // Cancel the sign-up of receiving MLME event notification
 | |
|   // from interface with index |interface_index|.
 | |
|   virtual void UnsubscribeMlmeEvent(uint32_t interface_index);
 | |
| 
 | |
|   // Sign up to be notified when there is an regulatory domain change.
 | |
|   // Only one handler can be registered per wiphy index.
 | |
|   // New handler will replace the registered handler if they are for the
 | |
|   // same wiphy index.
 | |
|   virtual void SubscribeRegDomainChange(uint32_t wiphy_index,
 | |
|                                         OnRegDomainChangedHandler handler);
 | |
| 
 | |
|   // Cancel the sign-up of receiving regulatory domain change notification
 | |
|   // from wiphy with index |wiphy_index|.
 | |
|   virtual void UnsubscribeRegDomainChange(uint32_t wiphy_index);
 | |
| 
 | |
|   // Sign up to be notified when there is a station event.
 | |
|   // Only one handler can be registered per interface index.
 | |
|   // New handler will replace the registered handler if they are for the
 | |
|   // same interface index.
 | |
|   virtual void SubscribeStationEvent(uint32_t interface_index,
 | |
|                                      OnStationEventHandler handler);
 | |
| 
 | |
|   // Cancel the sign-up of receiving station events.
 | |
|   virtual void UnsubscribeStationEvent(uint32_t interface_index);
 | |
| 
 | |
|   // Sign up to be notified when there is a channel switch event.
 | |
|   // Only one handler can be registered per interface index.
 | |
|   // New handler will replace the registered handler if they are for the
 | |
|   // same interface index.
 | |
|   virtual void SubscribeChannelSwitchEvent(uint32_t interface_index,
 | |
|                                            OnChannelSwitchEventHandler handler);
 | |
| 
 | |
|   // Cancel the sign-up of receiving channel switch events.
 | |
|   virtual void UnsubscribeChannelSwitchEvent(uint32_t interface_index);
 | |
| 
 | |
|   // Sign up to be notified of frame tx status events.
 | |
|   virtual void SubscribeFrameTxStatusEvent(
 | |
|       uint32_t interface_index, OnFrameTxStatusEventHandler handler);
 | |
| 
 | |
|   // Cancel the sign-up of receiving frame tx status events.
 | |
|   virtual void UnsubscribeFrameTxStatusEvent(uint32_t interface_index);
 | |
| 
 | |
|   virtual bool SendMgmtFrame(uint32_t interface_index,
 | |
|     const std::vector<uint8_t>& frame, int32_t mcs, uint64_t* out_cookie);
 | |
| 
 | |
|   // Visible for testing.
 | |
|   bool supports_split_wiphy_dump_;
 | |
| 
 | |
|  private:
 | |
|   bool ParseWiphyInfoFromPacket(
 | |
|       const NL80211Packet& packet,
 | |
|       BandInfo* out_band_info,
 | |
|       ScanCapabilities* out_scan_capabilities,
 | |
|       WiphyFeatures* out_wiphy_features);
 | |
|   bool ParseBandInfo(const NL80211Packet* const packet,
 | |
|                      BandInfo* out_band_info);
 | |
|   void ParseIfTypeDataAttributes(const NL80211NestedAttr& iftype_data_attr,
 | |
|                                  BandInfo* out_band_info);
 | |
|   void ParseHtVhtPhyCapabilities(const NL80211NestedAttr& band,
 | |
|                                  BandInfo* out_band_info);
 | |
|   void ParseHtMcsSetAttribute(const NL80211NestedAttr& band,
 | |
|                               BandInfo* out_band_info);
 | |
|   void ParseVhtMcsSetAttribute(const NL80211NestedAttr& band,
 | |
|                                BandInfo* out_band_info);
 | |
|   void ParseHeMcsSetAttribute(const NL80211NestedAttr& attribute,
 | |
|                               BandInfo* out_band_info);
 | |
|   std::pair<uint32_t, uint32_t> ParseHtMcsSet(
 | |
|       const std::vector<uint8_t>& ht_mcs_set);
 | |
|   uint32_t ParseMcsMap(uint16_t mcs_map);
 | |
|   void ParseVhtCapAttribute(const NL80211NestedAttr& band,
 | |
|                             BandInfo* out_band_info);
 | |
|   void ParseHeCapPhyAttribute(const NL80211NestedAttr& attribute,
 | |
|                               BandInfo* out_band_info);
 | |
|   void ParseEhtCapPhyAttribute(const NL80211NestedAttr& attribute,
 | |
|                               BandInfo* out_band_info);
 | |
| 
 | |
|   bool ParseScanCapabilities(const NL80211Packet* const packet,
 | |
|                              ScanCapabilities* out_scan_capabilities);
 | |
| 
 | |
|   bool MergePacketsForSplitWiphyDump(
 | |
|       const std::vector<std::unique_ptr<const NL80211Packet>>& split_dump_info,
 | |
|       std::vector<NL80211Packet>* packet_per_wiphy);
 | |
|   void handleBandFreqAttributes(const NL80211NestedAttr& freqs_attr,
 | |
|       BandInfo* out_band_info);
 | |
| 
 | |
|   NetlinkManager* netlink_manager_;
 | |
| 
 | |
|   DISALLOW_COPY_AND_ASSIGN(NetlinkUtils);
 | |
| };
 | |
| 
 | |
| }  // namespace wificond
 | |
| }  // namespace android
 | |
| 
 | |
| #endif  // WIFICOND_NET_NETLINK_UTILS_H_
 |