blob: 97d7deb6e26f676cb01a0773f7403dfec4b1a374 [file] [log] [blame]
Thieu Le94eed562012-02-21 15:57:29 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Darin Petkov50308cd2011-06-01 18:25:07 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef SHILL_DHCP_CONFIG_
6#define SHILL_DHCP_CONFIG_
7
Alex Vakulenko8a532292014-06-16 17:18:44 -07008#include <map>
9#include <string>
10
mukesh agrawalcc0fded2012-05-09 13:40:58 -070011#include <base/cancelable_callback.h>
Ben Chana0ddf462014-02-06 11:32:42 -080012#include <base/files/file_path.h>
Darin Petkovd1b715b2011-06-02 21:21:22 -070013#include <base/memory/scoped_ptr.h>
mukesh agrawalcc0fded2012-05-09 13:40:58 -070014#include <base/memory/weak_ptr.h>
Darin Petkovaceede32011-07-18 15:32:38 -070015#include <dbus-c++/types.h>
Darin Petkov92c43902011-06-09 20:46:06 -070016#include <glib.h>
Darin Petkove7cb7f82011-06-03 13:21:51 -070017#include <gtest/gtest_prod.h> // for FRIEND_TEST
Darin Petkovd1b715b2011-06-02 21:21:22 -070018
Darin Petkov50308cd2011-06-01 18:25:07 -070019#include "shill/ipconfig.h"
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -070020#include "shill/minijail.h"
Darin Petkov50308cd2011-06-01 18:25:07 -070021
22namespace shill {
23
Chris Masone19e30402011-07-19 15:48:47 -070024class ControlInterface;
Darin Petkovd1b715b2011-06-02 21:21:22 -070025class DHCPProvider;
26class DHCPProxyInterface;
Darin Petkova7b89492011-07-27 12:48:17 -070027class EventDispatcher;
Darin Petkov3258a812011-06-23 11:28:45 -070028class GLib;
Darin Petkovab565bb2011-10-06 02:55:51 -070029class ProxyFactory;
Darin Petkovd1b715b2011-06-02 21:21:22 -070030
Paul Stewartd408fdf2012-05-07 17:15:57 -070031// This class provides a DHCP client instance for the device |device_name|.
32// If |request_hostname| is non-empty, it asks the DHCP server to register
33// this hostname on our behalf, for purposes of administration or creating
34// a dynamic DNS entry.
35//
36// The DHPCConfig instance asks the DHCP client to create a lease file
37// containing the name |lease_file_suffix|. If this suffix is the same as
38// |device_name|, the lease is considered to be ephemeral, and the lease
39// file is removed whenever this DHCPConfig instance is no longer needed.
40// Otherwise, the lease file persists and will be re-used in future attempts.
Eric Shienbrood9a245532012-03-07 14:20:39 -050041class DHCPConfig : public IPConfig {
Darin Petkov50308cd2011-06-01 18:25:07 -070042 public:
Darin Petkove7cb7f82011-06-03 13:21:51 -070043 typedef std::map<std::string, DBus::Variant> Configuration;
44
Darin Petkov14c29ec2012-03-02 11:34:19 +010045 static const int kMinMTU;
46
Chris Masone19e30402011-07-19 15:48:47 -070047 DHCPConfig(ControlInterface *control_interface,
Darin Petkova7b89492011-07-27 12:48:17 -070048 EventDispatcher *dispatcher,
Chris Masone19e30402011-07-19 15:48:47 -070049 DHCPProvider *provider,
Darin Petkovf65e9282011-06-21 14:29:56 -070050 const std::string &device_name,
Paul Stewartd32f4842012-01-11 16:08:13 -080051 const std::string &request_hostname,
Paul Stewartd408fdf2012-05-07 17:15:57 -070052 const std::string &lease_file_suffix,
53 bool arp_gateway,
Paul Stewart75a68b92013-10-24 10:50:27 -070054 bool is_minimal_config,
Darin Petkov3258a812011-06-23 11:28:45 -070055 GLib *glib);
Darin Petkov50308cd2011-06-01 18:25:07 -070056 virtual ~DHCPConfig();
57
Darin Petkovd1b715b2011-06-02 21:21:22 -070058 // Inherited from IPConfig.
Darin Petkov92c43902011-06-09 20:46:06 -070059 virtual bool RequestIP();
60 virtual bool RenewIP();
Paul Stewart217c61d2013-06-13 15:12:02 -070061 virtual bool ReleaseIP(ReleaseReason reason);
Darin Petkovd1b715b2011-06-02 21:21:22 -070062
63 // If |proxy_| is not initialized already, sets it to a new D-Bus proxy to
64 // |service|.
Darin Petkova7b89492011-07-27 12:48:17 -070065 void InitProxy(const std::string &service);
Darin Petkovd1b715b2011-06-02 21:21:22 -070066
Darin Petkove7cb7f82011-06-03 13:21:51 -070067 // Processes an Event signal from dhcpcd.
68 void ProcessEventSignal(const std::string &reason,
69 const Configuration &configuration);
70
mukesh agrawalcc0fded2012-05-09 13:40:58 -070071 protected:
72 // Overrides base clase implementation.
Paul Stewartc5099532013-12-12 07:53:15 -080073 virtual void UpdateProperties(const Properties &properties);
74 virtual void NotifyFailure();
mukesh agrawalcc0fded2012-05-09 13:40:58 -070075
Darin Petkov50308cd2011-06-01 18:25:07 -070076 private:
Darin Petkov98dd6a02011-06-10 15:12:57 -070077 friend class DHCPConfigTest;
Paul Stewartc5099532013-12-12 07:53:15 -080078 FRIEND_TEST(DHCPConfigCallbackTest, ProcessEventSignalFail);
79 FRIEND_TEST(DHCPConfigCallbackTest, ProcessEventSignalGatewayArp);
80 FRIEND_TEST(DHCPConfigCallbackTest, ProcessEventSignalGatewayArpNak);
81 FRIEND_TEST(DHCPConfigCallbackTest, ProcessEventSignalSuccess);
82 FRIEND_TEST(DHCPConfigCallbackTest, ProcessEventSignalUnknown);
83 FRIEND_TEST(DHCPConfigCallbackTest, RequestIPTimeout);
84 FRIEND_TEST(DHCPConfigCallbackTest, StartTimeout);
Paul Stewart475c0722014-04-18 08:52:00 -070085 FRIEND_TEST(DHCPConfigCallbackTest, StoppedDuringFailureCallback);
86 FRIEND_TEST(DHCPConfigCallbackTest, StoppedDuringSuccessCallback);
Darin Petkove7cb7f82011-06-03 13:21:51 -070087 FRIEND_TEST(DHCPConfigTest, GetIPv4AddressString);
Darin Petkova7b89492011-07-27 12:48:17 -070088 FRIEND_TEST(DHCPConfigTest, InitProxy);
Paul Stewart65bcd082012-11-16 09:37:14 -080089 FRIEND_TEST(DHCPConfigTest, ParseClasslessStaticRoutes);
Darin Petkove7cb7f82011-06-03 13:21:51 -070090 FRIEND_TEST(DHCPConfigTest, ParseConfiguration);
Darin Petkov98dd6a02011-06-10 15:12:57 -070091 FRIEND_TEST(DHCPConfigTest, ReleaseIP);
Paul Stewarta02ee492012-05-16 10:04:53 -070092 FRIEND_TEST(DHCPConfigTest, ReleaseIPArpGW);
Paul Stewart217c61d2013-06-13 15:12:02 -070093 FRIEND_TEST(DHCPConfigTest, ReleaseIPStaticIPWithLease);
94 FRIEND_TEST(DHCPConfigTest, ReleaseIPStaticIPWithoutLease);
Darin Petkov98dd6a02011-06-10 15:12:57 -070095 FRIEND_TEST(DHCPConfigTest, RenewIP);
96 FRIEND_TEST(DHCPConfigTest, RequestIP);
97 FRIEND_TEST(DHCPConfigTest, Restart);
98 FRIEND_TEST(DHCPConfigTest, RestartNoClient);
Darin Petkov92c43902011-06-09 20:46:06 -070099 FRIEND_TEST(DHCPConfigTest, StartFail);
Paul Stewartd32f4842012-01-11 16:08:13 -0800100 FRIEND_TEST(DHCPConfigTest, StartWithHostname);
Paul Stewart75a68b92013-10-24 10:50:27 -0700101 FRIEND_TEST(DHCPConfigTest, StartWithMinimalConfig);
Paul Stewartd408fdf2012-05-07 17:15:57 -0700102 FRIEND_TEST(DHCPConfigTest, StartWithoutArpGateway);
Paul Stewartd32f4842012-01-11 16:08:13 -0800103 FRIEND_TEST(DHCPConfigTest, StartWithoutHostname);
Paul Stewartd408fdf2012-05-07 17:15:57 -0700104 FRIEND_TEST(DHCPConfigTest, StartWithoutLeaseSuffix);
Darin Petkov98dd6a02011-06-10 15:12:57 -0700105 FRIEND_TEST(DHCPConfigTest, Stop);
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700106 FRIEND_TEST(DHCPConfigTest, StopDuringRequestIP);
Darin Petkov98dd6a02011-06-10 15:12:57 -0700107 FRIEND_TEST(DHCPProviderTest, CreateConfig);
Darin Petkove7cb7f82011-06-03 13:21:51 -0700108
Paul Stewart1f916e42013-12-23 09:52:54 -0800109 static const int kAcquisitionTimeoutSeconds;
110
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700111 static const char kConfigurationKeyBroadcastAddress[];
Paul Stewart65bcd082012-11-16 09:37:14 -0800112 static const char kConfigurationKeyClasslessStaticRoutes[];
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700113 static const char kConfigurationKeyDNS[];
114 static const char kConfigurationKeyDomainName[];
115 static const char kConfigurationKeyDomainSearch[];
116 static const char kConfigurationKeyIPAddress[];
Paul Stewart1f916e42013-12-23 09:52:54 -0800117 static const char kConfigurationKeyLeaseTime[];
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700118 static const char kConfigurationKeyMTU[];
119 static const char kConfigurationKeyRouters[];
120 static const char kConfigurationKeySubnetCIDR[];
Paul Stewartc3fdba92013-12-02 11:12:38 -0800121 static const char kConfigurationKeyVendorEncapsulatedOptions[];
Paul Stewarta63f5212013-06-25 15:29:40 -0700122 static const char kConfigurationKeyWebProxyAutoDiscoveryUrl[];
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700123
Thieu Le94eed562012-02-21 15:57:29 -0800124 static const int kDHCPCDExitPollMilliseconds;
125 static const int kDHCPCDExitWaitMilliseconds;
Darin Petkovd1b715b2011-06-02 21:21:22 -0700126 static const char kDHCPCDPath[];
Darin Petkov92c43902011-06-09 20:46:06 -0700127 static const char kDHCPCDPathFormatPID[];
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700128 static const char kDHCPCDUser[];
Paul Stewart75a68b92013-10-24 10:50:27 -0700129 static const char kDHCPCDMinimalConfig[];
Darin Petkovd1b715b2011-06-02 21:21:22 -0700130
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700131 static const char kReasonBound[];
132 static const char kReasonFail[];
Paul Stewart94571f12013-09-10 17:26:07 -0700133 static const char kReasonGatewayArp[];
134 static const char kReasonNak[];
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700135 static const char kReasonRebind[];
136 static const char kReasonReboot[];
137 static const char kReasonRenew[];
138
Chris Masone0756f232011-07-21 17:24:00 -0700139 static const char kType[];
140
Darin Petkovd1b715b2011-06-02 21:21:22 -0700141 // Starts dhcpcd, returns true on success and false otherwise.
142 bool Start();
143
Darin Petkov92c43902011-06-09 20:46:06 -0700144 // Stops dhcpcd if running.
mukesh agrawal1835e772013-01-15 18:35:03 -0800145 void Stop(const char *reason);
Darin Petkov92c43902011-06-09 20:46:06 -0700146
Darin Petkov98dd6a02011-06-10 15:12:57 -0700147 // Stops dhcpcd if already running and then starts it. Returns true on success
148 // and false otherwise.
149 bool Restart();
150
Paul Stewart65bcd082012-11-16 09:37:14 -0800151 // Parses |classless_routes| into |properties|. Sets the default gateway
152 // if one is supplied and |properties| does not already contain one. It
153 // also sets the "routes" parameter of the IPConfig properties for all
154 // routes not converted into the default gateway. Returns true on
155 // success, and false otherwise.
156 static bool ParseClasslessStaticRoutes(const std::string &classless_routes,
157 IPConfig::Properties *properties);
158
Darin Petkove7cb7f82011-06-03 13:21:51 -0700159 // Parses |configuration| into |properties|. Returns true on success, and
160 // false otherwise.
mukesh agrawal28fd88e2013-05-02 14:06:10 -0700161 static bool ParseConfiguration(const Configuration &configuration,
162 IPConfig::Properties *properties);
Darin Petkove7cb7f82011-06-03 13:21:51 -0700163
164 // Returns the string representation of the IP address |address|, or an
165 // empty string on failure.
mukesh agrawal28fd88e2013-05-02 14:06:10 -0700166 static std::string GetIPv4AddressString(unsigned int address);
Darin Petkove7cb7f82011-06-03 13:21:51 -0700167
Darin Petkov92c43902011-06-09 20:46:06 -0700168 // Called when the dhcpcd client process exits.
169 static void ChildWatchCallback(GPid pid, gint status, gpointer data);
170
Darin Petkov98dd6a02011-06-10 15:12:57 -0700171 // Cleans up remaining state from a running client, if any, including freeing
172 // its GPid, exit watch callback, and state files.
Darin Petkov92c43902011-06-09 20:46:06 -0700173 void CleanupClientState();
174
Paul Stewart1f916e42013-12-23 09:52:54 -0800175 // Initialize a callback that will invoke ProcessAcquisitionTimeout if we
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700176 // do not get a lease in a reasonable amount of time.
Paul Stewart1f916e42013-12-23 09:52:54 -0800177 void StartAcquisitionTimeout();
178 // Cancel callback created by StartAcquisitionTimeout. One-liner included
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700179 // for symmetry.
Paul Stewart1f916e42013-12-23 09:52:54 -0800180 void StopAcquisitionTimeout();
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700181 // Called if we do not get a DHCP lease in a reasonable amount of time.
182 // Informs upper layers of the failure.
Paul Stewart1f916e42013-12-23 09:52:54 -0800183 void ProcessAcquisitionTimeout();
184
185 // Initialize a callback that will invoke ProcessExpirationTimeout if we
186 // do not renew a lease in a |lease_duration_seconds|.
187 void StartExpirationTimeout(uint32 lease_duration_seconds);
188 // Cancel callback created by StartExpirationTimeout. One-liner included
189 // for symmetry.
190 void StopExpirationTimeout();
191 // Called if we do not renew a DHCP lease by the time the lease expires.
192 // Informs upper layers of the expiration and restarts the DHCP client.
193 void ProcessExpirationTimeout();
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700194
Paul Stewartc5099532013-12-12 07:53:15 -0800195 // Kills DHCP client process.
Darin Petkov3fe17662013-02-04 14:19:08 +0100196 void KillClient();
197
Darin Petkovab565bb2011-10-06 02:55:51 -0700198 // Store cached copies of singletons for speed/ease of testing.
199 ProxyFactory *proxy_factory_;
200
Darin Petkovd1b715b2011-06-02 21:21:22 -0700201 DHCPProvider *provider_;
202
Paul Stewartd32f4842012-01-11 16:08:13 -0800203 // Hostname to be used in the request. This will be passed to the DHCP
204 // server in the request.
205 std::string request_hostname_;
206
Paul Stewartd408fdf2012-05-07 17:15:57 -0700207 // DHCP lease file suffix, used to differentiate the lease of one interface
208 // or network from another.
209 std::string lease_file_suffix_;
210
211 // Specifies whether to supply an argument to the DHCP client to validate
212 // the acquired IP address using an ARP request to the gateway IP address.
213 bool arp_gateway_;
214
Paul Stewart75a68b92013-10-24 10:50:27 -0700215 // Specifies whether to configure the the DHCP client to request the bare
216 // minimum of options in order to escape any MTU issues with the packet size
217 // of the DHCP server's reply.
218 bool is_minimal_config_;
219
Darin Petkovd1b715b2011-06-02 21:21:22 -0700220 // The PID of the spawned DHCP client. May be 0 if no client has been spawned
221 // yet or the client has died.
Darin Petkov92c43902011-06-09 20:46:06 -0700222 int pid_;
223
224 // Child exit watch callback source tag.
225 unsigned int child_watch_tag_;
Darin Petkovd1b715b2011-06-02 21:21:22 -0700226
Paul Stewart217c61d2013-06-13 15:12:02 -0700227 // Whether a lease has been acquired from the DHCP server or gateway ARP.
228 bool is_lease_active_;
229
Paul Stewart94571f12013-09-10 17:26:07 -0700230 // Whether it is valid to retain the lease acquired via gateway ARP.
231 bool is_gateway_arp_active_;
232
Darin Petkovd1b715b2011-06-02 21:21:22 -0700233 // The proxy for communicating with the DHCP client.
234 scoped_ptr<DHCPProxyInterface> proxy_;
235
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700236 // Called if we fail to get a DHCP lease in a timely manner.
237 base::CancelableClosure lease_acquisition_timeout_callback_;
238
239 // Time to wait for a DHCP lease. Represented as field so that it
240 // can be overriden in tests.
241 unsigned int lease_acquisition_timeout_seconds_;
242
Paul Stewart1f916e42013-12-23 09:52:54 -0800243 // Called if a DHCP lease expires.
244 base::CancelableClosure lease_expiration_callback_;
245
Darin Petkov92c43902011-06-09 20:46:06 -0700246 // Root file path, used for testing.
Albert Chaulk0e1cdea2013-02-27 15:32:55 -0800247 base::FilePath root_;
Darin Petkov92c43902011-06-09 20:46:06 -0700248
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700249 base::WeakPtrFactory<DHCPConfig> weak_ptr_factory_;
Darin Petkova7b89492011-07-27 12:48:17 -0700250 EventDispatcher *dispatcher_;
Darin Petkov3258a812011-06-23 11:28:45 -0700251 GLib *glib_;
Darin Petkovf7897bc2011-06-08 17:13:36 -0700252
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700253 Minijail *minijail_;
254
Darin Petkov50308cd2011-06-01 18:25:07 -0700255 DISALLOW_COPY_AND_ASSIGN(DHCPConfig);
256};
257
258} // namespace shill
259
260#endif // SHILL_DHCP_CONFIG_