// // Copyright (C) 2012 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 SHILL_DEVICE_INFO_H_ #define SHILL_DEVICE_INFO_H_ #include #include #include #include #include #include #include #include #include #include #include // for FRIEND_TEST #include "shill/device.h" #include "shill/net/byte_string.h" #include "shill/net/ip_address.h" #include "shill/net/rtnl_listener.h" #include "shill/net/shill_time.h" #include "shill/technology.h" namespace shill { class Manager; class Metrics; class RoutingTable; class RTNLHandler; class RTNLMessage; class Sockets; #if !defined(DISABLE_WIFI) class NetlinkManager; class Nl80211Message; #endif // DISABLE_WIFI class DeviceInfo : public base::SupportsWeakPtr { public: 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; }; // Device name prefix for modem pseudo devices used in testing. static const char kModemPseudoDeviceNamePrefix[]; // Device name prefix for virtual ethernet devices used in testing. static const char kEthernetPseudoDeviceNamePrefix[]; // Device name prefix for virtual ethernet devices that should be ignored. static const char kIgnoredDeviceNamePrefix[]; // Time interval for polling for link statistics. static const int kRequestLinkStatisticsIntervalMilliseconds; DeviceInfo(ControlInterface* control_interface, EventDispatcher* dispatcher, Metrics* metrics, Manager* manager); virtual ~DeviceInfo(); virtual void AddDeviceToBlackList(const std::string& device_name); virtual void RemoveDeviceFromBlackList(const std::string& device_name); virtual bool IsDeviceBlackListed(const std::string& device_name); void Start(); void Stop(); std::vector 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); // Remove |device| from this DeviceInfo. This function should only // be called for cellular devices because the lifetime of the // cellular devices is controlled by the Modem object and its // communication to modem manager, rather than by RTNL messages. virtual void DeregisterDevice(const DeviceRefPtr& device); 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 bool GetAddresses(int interface_index, std::vector* addresses) 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 preferred globally scoped IPv6 address for |interface_index|. // This method returns true and sets |address| if a primary IPv6 address // exists. Otherwise it returns false and leaves |address| unmodified. virtual bool GetPrimaryIPv6Address(int interface_index, IPAddress* address); // 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* address_list, uint32_t* life_time_seconds); // Returns true if any of the addresses on |interface_index| are on the // same network prefix as |address|. virtual bool HasDirectConnectivityTo( int interface_index, const IPAddress& address) const; 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; private: friend class DeviceInfoDelayedCreationTest; friend class DeviceInfoTechnologyTest; friend class DeviceInfoTest; FRIEND_TEST(CellularTest, StartLinked); FRIEND_TEST(DeviceInfoTest, CreateDeviceWiMax); 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_. struct Info { Info() : flags(0), rx_bytes(0), tx_bytes(0), has_addresses_only(false), technology(Technology::kUnknown) {} DeviceRefPtr device; std::string name; ByteString mac_address; std::vector ip_addresses; std::vector 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 link information has not been retrieved yet; // only the ip_addresses field is valid. bool has_addresses_only; Technology::Identifier technology; }; // Root of the kernel sysfs directory holding network device info. static const char kDeviceInfoRoot[]; // Name of the "cdc_ether" driver. This driver is not included in the // kModemDrivers list because we need to do additional checking. static const char kDriverCdcEther[]; // Name of the "cdc_ncm" driver. This driver is not included in the // kModemDrivers list because we need to do additional checking. static const char kDriverCdcNcm[]; // Name of the GDM WiMAX driver. static const char kDriverGdmWiMax[]; // Name of the virtio network driver. static const char kDriverVirtioNet[]; // Sysfs path to a device uevent file. static const char kInterfaceUevent[]; // Content of a device uevent file that indicates it is a wifi device. static const char kInterfaceUeventWifiSignature[]; // Sysfs path to a device via its interface name. static const char kInterfaceDevice[]; // Sysfs path to the driver of a device via its interface name. static const char kInterfaceDriver[]; // Sysfs path to the file that is used to determine if this is tun device. static const char kInterfaceTunFlags[]; // Sysfs path to the file that is used to determine if a wifi device is // operating in monitor mode. static const char kInterfaceType[]; // Modem drivers that we support. static const char* kModemDrivers[]; // Path to the tun device. static const char kTunDeviceName[]; // Time to wait before registering devices which need extra time to detect. static const int kDelayedDeviceCreationSeconds; // 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::Identifier technology); // 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 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|, and return an identifier // indicating its type. virtual Technology::Identifier GetDeviceTechnology( const std::string& iface_name); // 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 blacklisted device whose link name // is now different from the name it was assigned before. bool IsRenamedBlacklistedDevice(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 RemoveInfo(int interface_index); 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); #endif // DISABLE_WIFI void set_sockets(Sockets* sockets) { sockets_.reset(sockets); } ControlInterface* control_interface_; EventDispatcher* dispatcher_; Metrics* metrics_; Manager* manager_; std::map infos_; // Maps interface index to Info. std::map indices_; // Maps interface name to index. base::Callback link_callback_; base::Callback address_callback_; base::Callback rdnss_callback_; std::unique_ptr link_listener_; std::unique_ptr address_listener_; std::unique_ptr rdnss_listener_; std::set black_list_; base::FilePath device_info_root_; // Keep track of devices that require a delayed call to CreateDevice(). base::CancelableClosure delayed_devices_callback_; std::set 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_; Time* time_; DISALLOW_COPY_AND_ASSIGN(DeviceInfo); }; } // namespace shill #endif // SHILL_DEVICE_INFO_H_