350 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			350 lines
		
	
	
		
			15 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_MANAGER_H_
 | |
| #define WIFICOND_NET_NETLINK_MANAGER_H_
 | |
| 
 | |
| #include <array>
 | |
| #include <functional>
 | |
| #include <map>
 | |
| #include <memory>
 | |
| 
 | |
| #include <linux/if_ether.h>
 | |
| 
 | |
| #include <android-base/macros.h>
 | |
| #include <android-base/unique_fd.h>
 | |
| #include <libnlinterceptor/libnlinterceptor.h>
 | |
| 
 | |
| #include "event_loop.h"
 | |
| 
 | |
| namespace android {
 | |
| namespace wificond {
 | |
| 
 | |
| class MlmeEventHandler;
 | |
| class NL80211Packet;
 | |
| 
 | |
| // Encapsulates all the different things we know about a specific message
 | |
| // type like its name, and its id.
 | |
| struct MessageType {
 | |
|    // This constructor is needed by map[key] operation.
 | |
|    MessageType() {};
 | |
|    explicit MessageType(uint16_t id) {
 | |
|      family_id = id;
 | |
|    };
 | |
|    uint16_t family_id;
 | |
|    // Multicast groups supported by the family.  The string and mapping to
 | |
|    // a group id are extracted from the CTRL_CMD_NEWFAMILY message.
 | |
|    std::map<std::string, uint32_t> groups;
 | |
| };
 | |
| 
 | |
| // This describes a type of function handling scan results ready notification.
 | |
| // |interface_index| is the index of interface which the scan results
 | |
| // are from.
 | |
| // |aborted| is a boolean indicating if this scan was aborted or not.
 | |
| // According to nl80211.h document, part of the scan result might still be
 | |
| // available even when the scan was aborted.
 | |
| // |ssids| is a vector of scan ssids associated with the corresponding
 | |
| // scan request.
 | |
| // |frequencies| is a vector of scan frequencies associated with the
 | |
| // corresponding scan request.
 | |
| typedef std::function<void(
 | |
|     uint32_t interface_index,
 | |
|     bool aborted,
 | |
|     std::vector<std::vector<uint8_t>>& ssids,
 | |
|     std::vector<uint32_t>& frequencies)> OnScanResultsReadyHandler;
 | |
| 
 | |
| // This describes a type of function handling scheduled scan results ready
 | |
| // notification. This can also be used for notificating the stopping of a
 | |
| // scheduled scan.
 | |
| // |interface_index| is the index of interface which the scan results
 | |
| // are from.
 | |
| // |scan_stopped| is a boolean indicating if this scheduled scan was stopped
 | |
| // or not.
 | |
| typedef std::function<void(
 | |
|     uint32_t interface_index,
 | |
|     bool scan_stopped)> OnSchedScanResultsReadyHandler;
 | |
| 
 | |
| // This describes a type of function handling regulatory domain change
 | |
| // notification.
 | |
| // If the regulatory domain set is one that pertains to a specific country,
 | |
| // |country_code| will be set accordingly.
 | |
| // If the regulatory domain set does not pertain to a specific country,
 | |
| // |country_code| will be an empty string. This could be a world regulatory
 | |
| // domain or a intersection regulatory domain.
 | |
| // See details in defination of |nl80211_reg_type| from nl80211.h.
 | |
| typedef std::function<void(
 | |
|     uint32_t wiphy_index, std::string& country_code)> OnRegDomainChangedHandler;
 | |
| 
 | |
| // Enum used for identifying channel bandwidth.
 | |
| // This is used by function |OnChannelSwitchEventHandler|.
 | |
| enum ChannelBandwidth {
 | |
|     BW_INVALID,
 | |
|     BW_20_NOHT,
 | |
|     BW_20,
 | |
|     BW_40,
 | |
|     BW_80,
 | |
|     BW_80P80,
 | |
|     BW_160,
 | |
|     BW_320,
 | |
| };
 | |
| 
 | |
| // This describes a type of function handling channel switch notification.
 | |
| // |frequency| represents the frequence of the channel in MHz.
 | |
| typedef std::function<void(
 | |
|     uint32_t frequency, ChannelBandwidth bandwidth)> OnChannelSwitchEventHandler;
 | |
| 
 | |
| // Enum used for identifying the type of a station event.
 | |
| // This is used by function |OnStationEventHandler|.
 | |
| enum StationEvent {
 | |
|     NEW_STATION,
 | |
|     DEL_STATION
 | |
| };
 | |
| 
 | |
| // This describes a type of function handling station events.
 | |
| // |event| specifies the type of this event.
 | |
| // |mac_address| is the station mac address associated with this event.
 | |
| typedef std::function<void(
 | |
|     StationEvent event,
 | |
|     const std::array<uint8_t, ETH_ALEN>& mac_address)> OnStationEventHandler;
 | |
| 
 | |
| // This describes a type of function handling frame tx status events.
 | |
| // |cookie| specifies the cookie of the transmitted frame that this status
 | |
| // event corresponds to.
 | |
| // |was_acked| reports whether the transmitted frame was ACKed.
 | |
| typedef std::function<void(
 | |
|     uint64_t cookie, bool was_acked)> OnFrameTxStatusEventHandler;
 | |
| 
 | |
| class NetlinkManager {
 | |
|  public:
 | |
|   explicit NetlinkManager(EventLoop* event_loop);
 | |
|   virtual ~NetlinkManager();
 | |
|   // Initialize netlink manager.
 | |
|   // This includes setting up socket and requesting nl80211 family id from kernel.
 | |
|   // Returns true on success.
 | |
|   virtual bool Start();
 | |
|   // Returns true if this netlink manager object is started.
 | |
|   virtual bool IsStarted() const;
 | |
|   // Returns a sequence number available for use.
 | |
|   virtual uint32_t GetSequenceNumber();
 | |
|   // Get NL80211 netlink family id,
 | |
|   virtual uint16_t GetFamilyId();
 | |
| 
 | |
|   // Send |packet| to kernel.
 | |
|   // This works in an asynchronous way.
 | |
|   // |handler| will be run when we receive a valid reply from kernel.
 | |
|   // Do not use this asynchronous interface to send a dump request.
 | |
|   // Returns true on success.
 | |
|   virtual bool RegisterHandlerAndSendMessage(const NL80211Packet& packet,
 | |
|       std::function<void(std::unique_ptr<const NL80211Packet>)> handler);
 | |
|   // Synchronous version of |RegisterHandlerAndSendMessage|.
 | |
|   // Returns true on successfully receiving an valid reply.
 | |
|   // Reply packets will be stored in |*response|.
 | |
|   virtual bool SendMessageAndGetResponses(
 | |
|       const NL80211Packet& packet,
 | |
|       std::vector<std::unique_ptr<const NL80211Packet>>* response);
 | |
|   // Wrapper of |SendMessageAndGetResponses| for messages with a single
 | |
|   // response.
 | |
|   // Returns true on successfully receiving an valid reply.
 | |
|   // This will returns false if a NLMSG_ERROR is received.
 | |
|   // Reply packet will be stored in |*response|.
 | |
|   virtual bool SendMessageAndGetSingleResponse(
 | |
|       const NL80211Packet& packet,
 | |
|       std::unique_ptr<const NL80211Packet>* response);
 | |
| 
 | |
|   // Wrapper of |SendMessageAndGetResponses| for messages with a single
 | |
|   // response.
 | |
|   // Returns true on successfully receiving an valid reply.
 | |
|   // This will returns true if a NLMSG_ERROR is received.
 | |
|   // This is useful when the caller needs the error code from kernel.
 | |
|   // Reply packet will be stored in |*response|.
 | |
|   virtual bool SendMessageAndGetSingleResponseOrError(
 | |
|       const NL80211Packet& packet,
 | |
|       std::unique_ptr<const NL80211Packet>* response);
 | |
| 
 | |
|   // Wrapper of |SendMessageAndGetResponses| for messages that trigger
 | |
|   // only a NLMSG_ERROR response
 | |
|   // Returns true if the message is successfully sent and a NLMSG_ERROR response
 | |
|   // comes back, regardless of the error code.
 | |
|   // Error code will be stored in |*error_code|
 | |
|   virtual bool SendMessageAndGetAckOrError(const NL80211Packet& packet,
 | |
|                                            int* error_code);
 | |
|   // Wrapper of |SendMessageAndGetResponses| that returns true iff the response
 | |
|   // is an ACK.
 | |
|   virtual bool SendMessageAndGetAck(const NL80211Packet& packet);
 | |
| 
 | |
|   // Sign up to receive and log multicast events of a specific type.
 | |
|   // |group| is one of the string NL80211_MULTICAST_GROUP_* in nl80211.h.
 | |
|   virtual bool SubscribeToEvents(const std::string& group);
 | |
| 
 | |
|   // Sign up to be notified when new scan results are available.
 | |
|   // |handler| will be called when the kernel signals to wificond that a scan
 | |
|   // has been completed on the given |interface_index|.  See the declaration of
 | |
|   // OnScanResultsReadyHandler for documentation on the semantics of this
 | |
|   // callback.
 | |
|   // 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 SubscribeScanResultNotification(
 | |
|       uint32_t interface_index,
 | |
|       OnScanResultsReadyHandler handler);
 | |
| 
 | |
|   // Cancel the sign-up of receiving new scan result notification from
 | |
|   // interface with index |interface_index|.
 | |
|   virtual void UnsubscribeScanResultNotification(uint32_t interface_index);
 | |
| 
 | |
|   // 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.
 | |
|   // NetlinkManager 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 new scan results are available.
 | |
|   // |handler| will be called when the kernel signals to wificond that a
 | |
|   // scheduled scan has been completed on the given |interface_index|.
 | |
|   // See the declaration of OnSchedScanResultsReadyHandler for documentation
 | |
|   // on the semantics of this callback.
 | |
|   // 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 SubscribeSchedScanResultNotification(
 | |
|       uint32_t interface_index,
 | |
|       OnSchedScanResultsReadyHandler handler);
 | |
| 
 | |
|   // Cancel the sign-up of receiving new scheduled scan result notification from
 | |
|   // interface with index |interface_index|.
 | |
|   virtual void UnsubscribeSchedScanResultNotification(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 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);
 | |
| 
 | |
|  private:
 | |
|   bool SetupSocket(android::base::unique_fd* netlink_fd,
 | |
|                    android::nlinterceptor::InterceptedSocket* nl_destination);
 | |
|   bool WatchSocket(android::base::unique_fd* netlink_fd);
 | |
|   void ReceivePacketAndRunHandler(int fd);
 | |
|   bool DiscoverFamilyId();
 | |
|   bool SendMessageInternal(const NL80211Packet& packet, int fd,
 | |
|                            android::nlinterceptor::InterceptedSocket nl_destination);
 | |
|   void BroadcastHandler(std::unique_ptr<const NL80211Packet> packet);
 | |
|   void OnRegChangeEvent(std::unique_ptr<const NL80211Packet> packet);
 | |
|   void OnMlmeEvent(std::unique_ptr<const NL80211Packet> packet);
 | |
|   void OnScanResultsReady(std::unique_ptr<const NL80211Packet> packet);
 | |
|   void OnSchedScanResultsReady(std::unique_ptr<const NL80211Packet> packet);
 | |
|   void OnChannelSwitchEvent(std::unique_ptr<const NL80211Packet> packet);
 | |
|   void OnFrameTxStatusEvent(std::unique_ptr<const NL80211Packet> packet);
 | |
| 
 | |
|   // This handler revceives mapping from NL80211 family name to family id,
 | |
|   // as well as mapping from group name to group id.
 | |
|   // These mappings are allocated by kernel.
 | |
|   void OnNewFamily(std::unique_ptr<const NL80211Packet> packet);
 | |
| 
 | |
|   bool started_;
 | |
|   // We use different sockets for synchronous and asynchronous interfaces.
 | |
|   // Kernel will reply error message when we start a new request in the
 | |
|   // middle of a dump request.
 | |
|   // Using different sockets help us avoid the complexity of message
 | |
|   // rescheduling.
 | |
|   android::base::unique_fd sync_netlink_fd_;
 | |
|   android::base::unique_fd async_netlink_fd_;
 | |
| 
 | |
|   // Each netlink socket will either communicate directly with the kernel (pid = 0), or will be
 | |
|   // assigned a Netlink Interceptor socket, and will have a non-zero pid to which messages should be
 | |
|   // sent.
 | |
|   android::nlinterceptor::InterceptedSocket sync_netlink_destination_ = {NETLINK_GENERIC, 0};
 | |
|   android::nlinterceptor::InterceptedSocket async_netlink_destination_ = {NETLINK_GENERIC, 0};
 | |
|   EventLoop* event_loop_;
 | |
| 
 | |
|   // This is a collection of message handlers, for each sequence number.
 | |
|   std::map<uint32_t,
 | |
|       std::function<void(std::unique_ptr<const NL80211Packet>)>> message_handlers_;
 | |
| 
 | |
|   // A mapping from interface index to the handler registered to receive
 | |
|   // scan results notifications.
 | |
|   std::map<uint32_t, OnScanResultsReadyHandler> on_scan_result_ready_handler_;
 | |
|   // A mapping from interface index to the handler registered to receive
 | |
|   // scheduled scan results notifications.
 | |
|   std::map<uint32_t, OnSchedScanResultsReadyHandler>
 | |
|       on_sched_scan_result_ready_handler_;
 | |
| 
 | |
|   std::map<uint32_t, MlmeEventHandler*> on_mlme_event_handler_;
 | |
| 
 | |
|   // A mapping from wiphy index to the handler registered to receive
 | |
|   // regulatory domain change notifications.
 | |
|   std::map<uint32_t, OnRegDomainChangedHandler> on_reg_domain_changed_handler_;
 | |
|   std::map<uint32_t, OnStationEventHandler> on_station_event_handler_;
 | |
|   std::map<uint32_t, OnChannelSwitchEventHandler> on_channel_switch_event_handler_;
 | |
| 
 | |
|   // mapping from interface_index to frame tx status event handler
 | |
|   std::map<uint32_t, OnFrameTxStatusEventHandler>
 | |
|       on_frame_tx_status_event_handler_;
 | |
| 
 | |
|   // Mapping from family name to family id, and group name to group id.
 | |
|   std::map<std::string, MessageType> message_types_;
 | |
| 
 | |
|   uint32_t sequence_number_;
 | |
| 
 | |
|   DISALLOW_COPY_AND_ASSIGN(NetlinkManager);
 | |
| };
 | |
| 
 | |
| }  // namespace wificond
 | |
| }  // namespace android
 | |
| 
 | |
| #endif  // WIFICOND_NET_NETLINK_MANAGER_H_
 |