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
33namespace shill {
34
35class ControlInterface;
36class DHCPProvider;
37class DHCPProxyInterface;
38class EventDispatcher;
39class Metrics;
40class 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.
49class 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.
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
86  int minimum_mtu() const { return minimum_mtu_; }
87
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.
102  virtual bool ShouldFailOnAcquisitionTimeout() { return true; }
103
104  // Return true if we should keep the lease on disconnect.
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
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