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_CONFIG_H_
18 #define SHILL_DHCP_DHCP_CONFIG_H_
19 
20 #include <map>
21 #include <memory>
22 #include <string>
23 #include <vector>
24 
25 #include <base/cancelable_callback.h>
26 #include <base/files/file_path.h>
27 #include <base/memory/weak_ptr.h>
28 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
29 
30 #include "shill/ipconfig.h"
31 #include "shill/key_value_store.h"
32 
33 namespace shill {
34 
35 class ControlInterface;
36 class DHCPProvider;
37 class DHCPProxyInterface;
38 class EventDispatcher;
39 class Metrics;
40 class ProcessManager;
41 
42 // This class provides a DHCP client instance for the device |device_name|.
43 //
44 // The DHPCConfig instance asks the DHCP client to create a lease file
45 // containing the name |lease_file_suffix|.  If this suffix is the same as
46 // |device_name|, the lease is considered to be ephemeral, and the lease
47 // file is removed whenever this DHCPConfig instance is no longer needed.
48 // Otherwise, the lease file persists and will be re-used in future attempts.
49 class DHCPConfig : public IPConfig {
50  public:
51   DHCPConfig(ControlInterface* control_interface,
52              EventDispatcher* dispatcher,
53              DHCPProvider* provider,
54              const std::string& device_name,
55              const std::string& type,
56              const std::string& lease_file_suffix);
57   ~DHCPConfig() override;
58 
59   // Inherited from IPConfig.
60   bool RequestIP() override;
61   bool RenewIP() override;
62   bool ReleaseIP(ReleaseReason reason) override;
63 
64   // If |proxy_| is not initialized already, sets it to a new D-Bus proxy to
65   // |service|.
66   void InitProxy(const std::string& service);
67 
68   // Processes an Event signal from dhcpcd.
69   virtual void ProcessEventSignal(const std::string& reason,
70                                   const KeyValueStore& configuration) = 0;
71 
72   // Processes an Status Change signal from dhcpcd.
73   virtual void ProcessStatusChangeSignal(const std::string& status) = 0;
74 
75   // Set the minimum MTU that this configuration will respect.
set_minimum_mtu(const int minimum_mtu)76   virtual void set_minimum_mtu(const int minimum_mtu) {
77     minimum_mtu_ = minimum_mtu;
78   }
79 
80  protected:
81   // Overrides base clase implementation.
82   void UpdateProperties(const Properties& properties,
83                         bool new_lease_acquired) override;
84   void NotifyFailure() override;
85 
minimum_mtu()86   int minimum_mtu() const { return minimum_mtu_; }
87 
set_is_lease_active(bool active)88   void set_is_lease_active(bool active) { is_lease_active_ = active; }
89 
90   // Return true if the lease file is ephermeral, which means the lease file
91   // should be deleted during cleanup.
92   bool IsEphemeralLease() const;
93 
94   // Cleans up remaining state from a running client, if any, including freeing
95   // its GPid, exit watch callback, and state files.
96   // The file path for the lease file and pid file is different for IPv4
97   // and IPv6. So make this function virtual to have the derived class delete
98   // the files accordingly.
99   virtual void CleanupClientState();
100 
101   // Return true if we should treat acquisition timeout as failure.
ShouldFailOnAcquisitionTimeout()102   virtual bool ShouldFailOnAcquisitionTimeout() { return true; }
103 
104   // Return true if we should keep the lease on disconnect.
ShouldKeepLeaseOnDisconnect()105   virtual bool ShouldKeepLeaseOnDisconnect() { return false; }
106 
107   // Return the list of flags used to start dhcpcd.
108   virtual std::vector<std::string> GetFlags();
109 
root()110   base::FilePath root() const { return root_; }
111 
112  private:
113   friend class DHCPConfigTest;
114   friend class DHCPv4ConfigTest;
115   friend class DHCPv6ConfigTest;
116   FRIEND_TEST(DHCPConfigCallbackTest, NotifyFailure);
117   FRIEND_TEST(DHCPConfigCallbackTest, ProcessAcquisitionTimeout);
118   FRIEND_TEST(DHCPConfigCallbackTest, RequestIPTimeout);
119   FRIEND_TEST(DHCPConfigCallbackTest, StartTimeout);
120   FRIEND_TEST(DHCPConfigCallbackTest, StoppedDuringFailureCallback);
121   FRIEND_TEST(DHCPConfigCallbackTest, StoppedDuringSuccessCallback);
122   FRIEND_TEST(DHCPConfigTest, InitProxy);
123   FRIEND_TEST(DHCPConfigTest, KeepLeaseOnDisconnect);
124   FRIEND_TEST(DHCPConfigTest, ReleaseIP);
125   FRIEND_TEST(DHCPConfigTest, ReleaseIPStaticIPWithLease);
126   FRIEND_TEST(DHCPConfigTest, ReleaseIPStaticIPWithoutLease);
127   FRIEND_TEST(DHCPConfigTest, ReleaseLeaseOnDisconnect);
128   FRIEND_TEST(DHCPConfigTest, RenewIP);
129   FRIEND_TEST(DHCPConfigTest, RequestIP);
130   FRIEND_TEST(DHCPConfigTest, Restart);
131   FRIEND_TEST(DHCPConfigTest, RestartNoClient);
132   FRIEND_TEST(DHCPConfigTest, StartFail);
133   FRIEND_TEST(DHCPConfigTest, StartWithoutLeaseSuffix);
134   FRIEND_TEST(DHCPConfigTest, Stop);
135   FRIEND_TEST(DHCPConfigTest, StopDuringRequestIP);
136   FRIEND_TEST(DHCPProviderTest, CreateIPv4Config);
137 
138   static const int kAcquisitionTimeoutSeconds;
139 
140   static const int kDHCPCDExitPollMilliseconds;
141   static const int kDHCPCDExitWaitMilliseconds;
142   static const char kDHCPCDPath[];
143   static const char kDHCPCDUser[];
144   static const char kDHCPCDGroup[];
145 
146   // Starts dhcpcd, returns true on success and false otherwise.
147   bool Start();
148 
149   // Stops dhcpcd if running.
150   void Stop(const char* reason);
151 
152   // Stops dhcpcd if already running and then starts it. Returns true on success
153   // and false otherwise.
154   bool Restart();
155 
156   // Called when the dhcpcd client process exits.
157   void OnProcessExited(int exit_status);
158 
159   // Initialize a callback that will invoke ProcessAcquisitionTimeout if we
160   // do not get a lease in a reasonable amount of time.
161   void StartAcquisitionTimeout();
162   // Cancel callback created by StartAcquisitionTimeout. One-liner included
163   // for symmetry.
164   void StopAcquisitionTimeout();
165   // Called if we do not get a DHCP lease in a reasonable amount of time.
166   // Informs upper layers of the failure.
167   void ProcessAcquisitionTimeout();
168 
169   // Initialize a callback that will invoke ProcessExpirationTimeout if we
170   // do not renew a lease in a |lease_duration_seconds|.
171   void StartExpirationTimeout(uint32_t lease_duration_seconds);
172   // Cancel callback created by StartExpirationTimeout. One-liner included
173   // for symmetry.
174   void StopExpirationTimeout();
175   // Called if we do not renew a DHCP lease by the time the lease expires.
176   // Informs upper layers of the expiration and restarts the DHCP client.
177   void ProcessExpirationTimeout();
178 
179   // Kills DHCP client process.
180   void KillClient();
181 
182   ControlInterface* control_interface_;
183 
184   DHCPProvider* provider_;
185 
186   // DHCP lease file suffix, used to differentiate the lease of one interface
187   // or network from another.
188   std::string lease_file_suffix_;
189 
190   // The PID of the spawned DHCP client. May be 0 if no client has been spawned
191   // yet or the client has died.
192   int pid_;
193 
194   // Whether a lease has been acquired from the DHCP server or gateway ARP.
195   bool is_lease_active_;
196 
197   // The proxy for communicating with the DHCP client.
198   std::unique_ptr<DHCPProxyInterface> proxy_;
199 
200   // Called if we fail to get a DHCP lease in a timely manner.
201   base::CancelableClosure lease_acquisition_timeout_callback_;
202 
203   // Time to wait for a DHCP lease. Represented as field so that it
204   // can be overriden in tests.
205   unsigned int lease_acquisition_timeout_seconds_;
206 
207   // Called if a DHCP lease expires.
208   base::CancelableClosure lease_expiration_callback_;
209 
210   // The minimum MTU value this configuration will respect.
211   int minimum_mtu_;
212 
213   // Root file path, used for testing.
214   base::FilePath root_;
215 
216   base::WeakPtrFactory<DHCPConfig> weak_ptr_factory_;
217   EventDispatcher* dispatcher_;
218   ProcessManager* process_manager_;
219   Metrics* metrics_;
220 
221   DISALLOW_COPY_AND_ASSIGN(DHCPConfig);
222 };
223 
224 }  // namespace shill
225 
226 #endif  // SHILL_DHCP_DHCP_CONFIG_H_
227