1 // 2 // Copyright (C) 2012 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 #ifndef SHILL_DHCP_DHCP_PROVIDER_H_ 18 #define SHILL_DHCP_DHCP_PROVIDER_H_ 19 20 #include <map> 21 #include <memory> 22 #include <set> 23 #include <string> 24 25 #include <base/files/file_path.h> 26 #include <base/lazy_instance.h> 27 #include <gtest/gtest_prod.h> // for FRIEND_TEST 28 29 #include "shill/dhcp_properties.h" 30 #include "shill/refptr_types.h" 31 32 namespace shill { 33 34 class ControlInterface; 35 class DHCPCDListenerInterface; 36 class EventDispatcher; 37 class Metrics; 38 39 // DHCPProvider is a singleton providing the main DHCP configuration 40 // entrypoint. Once the provider is initialized through its Init method, DHCP 41 // configurations for devices can be obtained through its CreateConfig 42 // method. For example, a single DHCP configuration request can be initiated as: 43 // 44 // DHCPProvider::GetInstance()->CreateIPv4Config(device_name, 45 // lease_file_suffix, 46 // arp_gateway, 47 // dhcp_props)->Request(); 48 class DHCPProvider { 49 public: 50 static constexpr char kDHCPCDPathFormatLease[] = 51 "var/lib/dhcpcd/dhcpcd-%s.lease"; 52 #ifndef DISABLE_DHCPV6 53 static constexpr char kDHCPCDPathFormatLease6[] = 54 "var/lib/dhcpcd/dhcpcd-%s.lease6"; 55 #endif // DISABLE_DHCPV6 56 57 virtual ~DHCPProvider(); 58 59 // This is a singleton -- use DHCPProvider::GetInstance()->Foo(). 60 static DHCPProvider* GetInstance(); 61 62 // Initializes the provider singleton. This method hooks up a D-Bus signal 63 // listener that catches signals from spawned DHCP clients and dispatches them 64 // to the appropriate DHCP configuration instance. 65 virtual void Init(ControlInterface* control_interface, 66 EventDispatcher* dispatcher, 67 Metrics* metrics); 68 69 // Called on shutdown to release |listener_|. 70 void Stop(); 71 72 // Creates a new DHCPv4Config for |device_name|. The DHCP configuration for 73 // the device can then be initiated through DHCPConfig::Request and 74 // DHCPConfig::Renew. If |host_name| is not-empty, it is placed in the DHCP 75 // request to allow the server to map the request to a specific user-named 76 // origin. The DHCP lease file will contain the suffix supplied 77 // in |lease_file_suffix| if non-empty, otherwise |device_name|. If 78 // |arp_gateway| is true, the DHCP client will ARP for the gateway IP 79 // address as an additional safeguard against the issued IP address being 80 // in-use by another station. 81 virtual DHCPConfigRefPtr CreateIPv4Config( 82 const std::string& device_name, 83 const std::string& lease_file_suffix, 84 bool arp_gateway, 85 const DhcpProperties& dhcp_props); 86 87 #ifndef DISABLE_DHCPV6 88 // Create a new DHCPv6Config for |device_name|. 89 virtual DHCPConfigRefPtr CreateIPv6Config( 90 const std::string& device_name, const std::string& lease_file_suffix); 91 #endif 92 93 // Returns the DHCP configuration associated with DHCP client |pid|. Return 94 // nullptr if |pid| is not bound to a configuration. 95 DHCPConfigRefPtr GetConfig(int pid); 96 97 // Binds a |pid| to a DHCP |config|. When a DHCP config spawns a new DHCP 98 // client, it binds itself to that client's |pid|. 99 virtual void BindPID(int pid, const DHCPConfigRefPtr& config); 100 101 // Unbinds a |pid|. This method is used by a DHCP config to signal the 102 // provider that the DHCP client has been terminated. This may result in 103 // destruction of the DHCP config instance if its reference count goes to 0. 104 virtual void UnbindPID(int pid); 105 106 // Destroy lease file associated with this |name|. 107 virtual void DestroyLease(const std::string& name); 108 109 // Returns true if |pid| was recently unbound from the provider. 110 bool IsRecentlyUnbound(int pid); 111 112 protected: 113 DHCPProvider(); 114 115 private: 116 friend struct base::DefaultLazyInstanceTraits<DHCPProvider>; 117 friend class CellularTest; 118 friend class DHCPProviderTest; 119 friend class DeviceInfoTest; 120 friend class DeviceTest; 121 FRIEND_TEST(DHCPProviderTest, CreateIPv4Config); 122 FRIEND_TEST(DHCPProviderTest, DestroyLease); 123 124 typedef std::map<int, DHCPConfigRefPtr> PIDConfigMap; 125 126 // Retire |pid| from the set of recently retired PIDs. 127 void RetireUnboundPID(int pid); 128 129 // A single listener is used to catch signals from all DHCP clients and 130 // dispatch them to the appropriate DHCP configuration instance. 131 std::unique_ptr<DHCPCDListenerInterface> listener_; 132 133 // A map that binds PIDs to DHCP configuration instances. 134 PIDConfigMap configs_; 135 136 base::FilePath root_; 137 ControlInterface* control_interface_; 138 EventDispatcher* dispatcher_; 139 Metrics* metrics_; 140 141 // Track the set of PIDs recently unbound from the provider in case messages 142 // arrive addressed from them. 143 std::set<int> recently_unbound_pids_; 144 145 DISALLOW_COPY_AND_ASSIGN(DHCPProvider); 146 }; 147 148 } // namespace shill 149 150 #endif // SHILL_DHCP_DHCP_PROVIDER_H_ 151