| // Copyright 2018 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SHILL_DEVICE_INFO_H_ |
| #define SHILL_DEVICE_INFO_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include <base/callback.h> |
| #include <base/cancelable_callback.h> |
| #include <base/files/file_path.h> |
| #include <base/memory/weak_ptr.h> |
| #include <base/optional.h> |
| #include <gtest/gtest_prod.h> // for FRIEND_TEST |
| |
| #include "shill/net/byte_string.h" |
| #include "shill/net/ip_address.h" |
| #include "shill/net/shill_time.h" |
| #include "shill/refptr_types.h" |
| #include "shill/technology.h" |
| |
| namespace shill { |
| |
| class EventDispatcher; |
| class Manager; |
| class Metrics; |
| class RoutingTable; |
| class RTNLHandler; |
| class RTNLListener; |
| class RTNLMessage; |
| class Sockets; |
| |
| #if !defined(DISABLE_WIFI) |
| class NetlinkManager; |
| class Nl80211Message; |
| #endif // DISABLE_WIFI |
| |
| class DeviceInfo { |
| public: |
| explicit DeviceInfo(Manager* manager); |
| virtual ~DeviceInfo(); |
| |
| virtual void BlockDevice(const std::string& device_name); |
| virtual void AllowDevice(const std::string& device_name); |
| virtual bool IsDeviceBlocked(const std::string& device_name); |
| void Start(); |
| void Stop(); |
| |
| std::vector<std::string> GetUninitializedTechnologies() const; |
| |
| // Adds |device| to this DeviceInfo instance so that we can handle its link |
| // messages, and registers it with the manager. |
| virtual void RegisterDevice(const DeviceRefPtr& device); |
| // Deregister the Device instance (if any) from interested parties like |
| // Manager and Metrics, and remove the Info corresponding to this |
| // interface. No-op if there is no Info for this interface index. |
| void DeregisterDevice(int interface_index); |
| |
| virtual DeviceRefPtr GetDevice(int interface_index) const; |
| virtual bool GetMacAddress(int interface_index, ByteString* address) const; |
| |
| // Queries the kernel for a MAC address for |interface_index|. Returns an |
| // empty ByteString on failure. |
| virtual ByteString GetMacAddressFromKernel(int interface_index) const; |
| |
| // Queries the kernel for the MAC address of |peer| on |interface_index|. |
| // Returns true and populates |mac_address| on success, otherwise returns |
| // false. |
| virtual bool GetMacAddressOfPeer(int interface_index, |
| const IPAddress& peer, |
| ByteString* mac_address) const; |
| |
| virtual bool GetFlags(int interface_index, unsigned int* flags) const; |
| virtual bool GetByteCounts(int interface_index, |
| uint64_t* rx_bytes, |
| uint64_t* tx_bytes) const; |
| virtual std::vector<IPAddress> GetAddresses(int interface_index) const; |
| |
| // Flush all addresses associated with |interface_index|. |
| virtual void FlushAddresses(int interface_index) const; |
| // Returns whether this interface does not have |this_address| |
| // but has another non-temporary address of the same family. |
| virtual bool HasOtherAddress(int interface_index, |
| const IPAddress& this_address) const; |
| |
| // Get the IPv6 DNS server addresses for |interface_index|. This method |
| // returns true and sets |address_list| and |life_time_seconds| if the IPv6 |
| // DNS server addresses exists. Otherwise, it returns false and leave |
| // |address_list| and |life_time_seconds| unmodified. |life_time_seconds| |
| // indicates the number of the seconds the DNS server is still valid for at |
| // the time of this function call. Value of 0 means the DNS server is not |
| // valid anymore, and value of 0xFFFFFFFF means the DNS server is valid |
| // forever. |
| virtual bool GetIPv6DnsServerAddresses(int interface_index, |
| std::vector<IPAddress>* address_list, |
| uint32_t* life_time_seconds); |
| |
| virtual bool CreateTunnelInterface(std::string* interface_name) const; |
| virtual int OpenTunnelInterface(const std::string& interface_name) const; |
| virtual bool DeleteInterface(int interface_index) const; |
| |
| // Returns the interface index for |interface_name| or -1 if unknown. |
| virtual int GetIndex(const std::string& interface_name) const; |
| |
| // Sets the system hostname to |hostname|. |
| virtual bool SetHostname(const std::string& hostname) const; |
| |
| // Gets the real user ID of the given |user_name| and returns it via |uid|. |
| // Returns true on success. |
| virtual bool GetUserId(const std::string& user_name, uid_t* uid); |
| |
| private: |
| friend class DeviceInfoDelayedCreationTest; |
| friend class DeviceInfoMockedGetUserId; |
| friend class DeviceInfoTechnologyTest; |
| friend class DeviceInfoTest; |
| FRIEND_TEST(CellularTest, StartLinked); |
| FRIEND_TEST(DeviceInfoTest, DeviceRemovedEvent); |
| FRIEND_TEST(DeviceInfoTest, GetUninitializedTechnologies); |
| FRIEND_TEST(DeviceInfoTest, HasSubdir); // For HasSubdir. |
| FRIEND_TEST(DeviceInfoTest, IPv6AddressChanged); // For infos_. |
| FRIEND_TEST(DeviceInfoTest, RequestLinkStatistics); |
| FRIEND_TEST(DeviceInfoTest, StartStop); |
| FRIEND_TEST(DeviceInfoTest, IPv6DnsServerAddressesChanged); // For infos_. |
| FRIEND_TEST(DeviceInfoMockedGetUserId, |
| AddRemoveAllowedInterface); // For rtnl_handler_, routing_table_. |
| |
| struct AddressData { |
| AddressData() : address(IPAddress::kFamilyUnknown), flags(0), scope(0) {} |
| AddressData(const IPAddress& address_in, |
| unsigned char flags_in, |
| unsigned char scope_in) |
| : address(address_in), flags(flags_in), scope(scope_in) {} |
| IPAddress address; |
| unsigned char flags; |
| unsigned char scope; |
| }; |
| |
| struct Info { |
| Info(); |
| |
| DeviceRefPtr device; |
| std::string name; |
| ByteString mac_address; |
| std::vector<AddressData> ip_addresses; |
| std::vector<IPAddress> ipv6_dns_server_addresses; |
| uint32_t ipv6_dns_server_lifetime_seconds; |
| time_t ipv6_dns_server_received_time_seconds; |
| unsigned int flags; |
| uint64_t rx_bytes; |
| uint64_t tx_bytes; |
| |
| // This flag indicates that a link add RTNL message has been received for |
| // this interface. This is used to behave differently for the first link add |
| // message received for this interface index; |device| is unsuitable because |
| // some interfaces may undergo delayed Device creation. |
| bool received_add_link; |
| |
| Technology technology; |
| }; |
| |
| // Create a Device object for the interface named |linkname|, with a |
| // string-form MAC address |address|, whose kernel interface index |
| // is |interface_index| and detected technology is |technology|. |
| virtual DeviceRefPtr CreateDevice(const std::string& link_name, |
| const std::string& address, |
| int interface_index, |
| Technology technology); |
| |
| // Return the ARP type (ARPHRD_* from <net/if_arp.h>) of interface |
| // |iface_name|. |
| int GetDeviceArpType(const std::string& iface_name); |
| // Return the FilePath for a given |path_name| in the device sysinfo for |
| // a specific interface |iface_name|. |
| base::FilePath GetDeviceInfoPath(const std::string& iface_name, |
| const std::string& path_name); |
| // Return the preferred globally scoped IPv6 address for |interface_index|. |
| // If no primary IPv6 address exists, return nullptr. |
| const IPAddress* GetPrimaryIPv6Address(int interface_index); |
| // Return the contents of the device info file |path_name| for interface |
| // |iface_name| in output parameter |contents_out|. Returns true if file |
| // read succeeded, false otherwise. |
| bool GetDeviceInfoContents(const std::string& iface_name, |
| const std::string& path_name, |
| std::string* contents_out); |
| |
| // Return the filepath for the target of the device info symbolic link |
| // |path_name| for interface |iface_name| in output parameter |path_out|. |
| // Returns true if symbolic link read succeeded, false otherwise. |
| bool GetDeviceInfoSymbolicLink(const std::string& iface_name, |
| const std::string& path_name, |
| base::FilePath* path_out); |
| // Classify the device named |iface_name| with RTNL kind |kind|, and return |
| // an identifier indicating its type. |
| virtual Technology GetDeviceTechnology( |
| const std::string& iface_name, const base::Optional<std::string>& kind); |
| // Checks the device specified by |iface_name| to see if it's a modem device. |
| // This method assumes that |iface_name| has already been determined to be |
| // using the cdc_ether / cdc_ncm driver. |
| bool IsCdcEthernetModemDevice(const std::string& iface_name); |
| // Returns true if |base_dir| has a subdirectory named |subdir|. |
| // |subdir| can be an immediate subdirectory of |base_dir| or can be |
| // several levels deep. |
| static bool HasSubdir(const base::FilePath& base_dir, |
| const base::FilePath& subdir); |
| |
| // Returns true and sets |link_name| to the interface name contained |
| // in |msg| if one is provided. Returns false otherwise. |
| bool GetLinkNameFromMessage(const RTNLMessage& msg, std::string* link_name); |
| |
| // Returns true if |msg| pertains to a blocked device whose link name |
| // is now different from the name it was assigned before. |
| bool IsRenamedBlockedDevice(const RTNLMessage& msg); |
| |
| void AddLinkMsgHandler(const RTNLMessage& msg); |
| void DelLinkMsgHandler(const RTNLMessage& msg); |
| void LinkMsgHandler(const RTNLMessage& msg); |
| void AddressMsgHandler(const RTNLMessage& msg); |
| void RdnssMsgHandler(const RTNLMessage& msg); |
| |
| const Info* GetInfo(int interface_index) const; |
| void DelayDeviceCreation(int interface_index); |
| void DelayedDeviceCreationTask(); |
| void RetrieveLinkStatistics(int interface_index, const RTNLMessage& msg); |
| void RequestLinkStatistics(); |
| |
| #if !defined(DISABLE_WIFI) |
| // Use nl80211 to get information on |interface_index|. |
| void GetWiFiInterfaceInfo(int interface_index); |
| void OnWiFiInterfaceInfoReceived(const Nl80211Message& message); |
| void RecordDarkResumeWakeReason(const std::string& wake_reason); |
| #endif // DISABLE_WIFI |
| |
| // Returns whether a device with name |interface_name| is guest. |
| bool IsGuestDevice(const std::string& interface_name); |
| |
| void set_sockets_for_test(std::unique_ptr<Sockets> sockets); |
| |
| EventDispatcher* dispatcher() const; |
| Metrics* metrics() const; |
| |
| Manager* manager_; |
| |
| std::map<int, Info> infos_; // Maps interface index to Info. |
| std::map<std::string, int> indices_; // Maps interface name to index. |
| |
| std::unique_ptr<RTNLListener> link_listener_; |
| std::unique_ptr<RTNLListener> address_listener_; |
| std::unique_ptr<RTNLListener> rdnss_listener_; |
| std::set<std::string> blocked_list_; |
| base::FilePath device_info_root_; |
| |
| // Keep track of devices that require a delayed call to CreateDevice(). |
| base::CancelableClosure delayed_devices_callback_; |
| std::set<int> delayed_devices_; |
| |
| // Maintain a callback for the periodic link statistics poll task. |
| base::CancelableClosure request_link_statistics_callback_; |
| |
| // Cache copy of singleton pointers. |
| RoutingTable* routing_table_; |
| RTNLHandler* rtnl_handler_; |
| #if !defined(DISABLE_WIFI) |
| NetlinkManager* netlink_manager_; |
| #endif // DISABLE_WIFI |
| |
| // A member of the class so that a mock can be injected for testing. |
| std::unique_ptr<Sockets> sockets_; |
| |
| Time* time_; |
| base::WeakPtrFactory<DeviceInfo> weak_factory_{this}; |
| |
| DISALLOW_COPY_AND_ASSIGN(DeviceInfo); |
| }; |
| |
| } // namespace shill |
| |
| #endif // SHILL_DEVICE_INFO_H_ |