blob: 60e9a03c622c7599a02b520a5a8499e2a792f3de [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
mukesh agrawalcc0fded2012-05-09 13:40:58 -07008#include <base/cancelable_callback.h>
Darin Petkov92c43902011-06-09 20:46:06 -07009#include <base/file_path.h>
Darin Petkovd1b715b2011-06-02 21:21:22 -070010#include <base/memory/scoped_ptr.h>
mukesh agrawalcc0fded2012-05-09 13:40:58 -070011#include <base/memory/weak_ptr.h>
Darin Petkovaceede32011-07-18 15:32:38 -070012#include <dbus-c++/types.h>
Darin Petkov92c43902011-06-09 20:46:06 -070013#include <glib.h>
Darin Petkove7cb7f82011-06-03 13:21:51 -070014#include <gtest/gtest_prod.h> // for FRIEND_TEST
Darin Petkovd1b715b2011-06-02 21:21:22 -070015
Darin Petkov50308cd2011-06-01 18:25:07 -070016#include "shill/ipconfig.h"
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -070017#include "shill/minijail.h"
Darin Petkov50308cd2011-06-01 18:25:07 -070018
19namespace shill {
20
Chris Masone19e30402011-07-19 15:48:47 -070021class ControlInterface;
Darin Petkovd1b715b2011-06-02 21:21:22 -070022class DHCPProvider;
23class DHCPProxyInterface;
Darin Petkova7b89492011-07-27 12:48:17 -070024class EventDispatcher;
Darin Petkov3258a812011-06-23 11:28:45 -070025class GLib;
Darin Petkovab565bb2011-10-06 02:55:51 -070026class ProxyFactory;
Darin Petkovd1b715b2011-06-02 21:21:22 -070027
Paul Stewartd408fdf2012-05-07 17:15:57 -070028// This class provides a DHCP client instance for the device |device_name|.
29// If |request_hostname| is non-empty, it asks the DHCP server to register
30// this hostname on our behalf, for purposes of administration or creating
31// a dynamic DNS entry.
32//
33// The DHPCConfig instance asks the DHCP client to create a lease file
34// containing the name |lease_file_suffix|. If this suffix is the same as
35// |device_name|, the lease is considered to be ephemeral, and the lease
36// file is removed whenever this DHCPConfig instance is no longer needed.
37// Otherwise, the lease file persists and will be re-used in future attempts.
Eric Shienbrood9a245532012-03-07 14:20:39 -050038class DHCPConfig : public IPConfig {
Darin Petkov50308cd2011-06-01 18:25:07 -070039 public:
Darin Petkove7cb7f82011-06-03 13:21:51 -070040 typedef std::map<std::string, DBus::Variant> Configuration;
41
Darin Petkov14c29ec2012-03-02 11:34:19 +010042 static const int kMinMTU;
43
Chris Masone19e30402011-07-19 15:48:47 -070044 DHCPConfig(ControlInterface *control_interface,
Darin Petkova7b89492011-07-27 12:48:17 -070045 EventDispatcher *dispatcher,
Chris Masone19e30402011-07-19 15:48:47 -070046 DHCPProvider *provider,
Darin Petkovf65e9282011-06-21 14:29:56 -070047 const std::string &device_name,
Paul Stewartd32f4842012-01-11 16:08:13 -080048 const std::string &request_hostname,
Paul Stewartd408fdf2012-05-07 17:15:57 -070049 const std::string &lease_file_suffix,
50 bool arp_gateway,
Darin Petkov3258a812011-06-23 11:28:45 -070051 GLib *glib);
Darin Petkov50308cd2011-06-01 18:25:07 -070052 virtual ~DHCPConfig();
53
Darin Petkovd1b715b2011-06-02 21:21:22 -070054 // Inherited from IPConfig.
Darin Petkov92c43902011-06-09 20:46:06 -070055 virtual bool RequestIP();
56 virtual bool RenewIP();
Paul Stewart217c61d2013-06-13 15:12:02 -070057 virtual bool ReleaseIP(ReleaseReason reason);
Darin Petkovd1b715b2011-06-02 21:21:22 -070058
59 // If |proxy_| is not initialized already, sets it to a new D-Bus proxy to
60 // |service|.
Darin Petkova7b89492011-07-27 12:48:17 -070061 void InitProxy(const std::string &service);
Darin Petkovd1b715b2011-06-02 21:21:22 -070062
Darin Petkove7cb7f82011-06-03 13:21:51 -070063 // Processes an Event signal from dhcpcd.
64 void ProcessEventSignal(const std::string &reason,
65 const Configuration &configuration);
66
mukesh agrawalcc0fded2012-05-09 13:40:58 -070067 protected:
68 // Overrides base clase implementation.
69 virtual void UpdateProperties(const Properties &properties, bool success);
70
Darin Petkov50308cd2011-06-01 18:25:07 -070071 private:
Darin Petkov98dd6a02011-06-10 15:12:57 -070072 friend class DHCPConfigTest;
Darin Petkove7cb7f82011-06-03 13:21:51 -070073 FRIEND_TEST(DHCPConfigTest, GetIPv4AddressString);
Darin Petkova7b89492011-07-27 12:48:17 -070074 FRIEND_TEST(DHCPConfigTest, InitProxy);
Paul Stewart65bcd082012-11-16 09:37:14 -080075 FRIEND_TEST(DHCPConfigTest, ParseClasslessStaticRoutes);
Darin Petkove7cb7f82011-06-03 13:21:51 -070076 FRIEND_TEST(DHCPConfigTest, ParseConfiguration);
Darin Petkovf9b0ca82011-06-20 12:10:23 -070077 FRIEND_TEST(DHCPConfigTest, ProcessEventSignalFail);
78 FRIEND_TEST(DHCPConfigTest, ProcessEventSignalSuccess);
79 FRIEND_TEST(DHCPConfigTest, ProcessEventSignalUnknown);
Darin Petkov98dd6a02011-06-10 15:12:57 -070080 FRIEND_TEST(DHCPConfigTest, ReleaseIP);
Paul Stewarta02ee492012-05-16 10:04:53 -070081 FRIEND_TEST(DHCPConfigTest, ReleaseIPArpGW);
Paul Stewart217c61d2013-06-13 15:12:02 -070082 FRIEND_TEST(DHCPConfigTest, ReleaseIPStaticIPWithLease);
83 FRIEND_TEST(DHCPConfigTest, ReleaseIPStaticIPWithoutLease);
Darin Petkov98dd6a02011-06-10 15:12:57 -070084 FRIEND_TEST(DHCPConfigTest, RenewIP);
85 FRIEND_TEST(DHCPConfigTest, RequestIP);
mukesh agrawalcc0fded2012-05-09 13:40:58 -070086 FRIEND_TEST(DHCPConfigTest, RequestIPTimeout);
Darin Petkov98dd6a02011-06-10 15:12:57 -070087 FRIEND_TEST(DHCPConfigTest, Restart);
88 FRIEND_TEST(DHCPConfigTest, RestartNoClient);
Darin Petkov92c43902011-06-09 20:46:06 -070089 FRIEND_TEST(DHCPConfigTest, StartFail);
mukesh agrawalcc0fded2012-05-09 13:40:58 -070090 FRIEND_TEST(DHCPConfigTest, StartTimeout);
Paul Stewartd32f4842012-01-11 16:08:13 -080091 FRIEND_TEST(DHCPConfigTest, StartWithHostname);
Paul Stewartd408fdf2012-05-07 17:15:57 -070092 FRIEND_TEST(DHCPConfigTest, StartWithoutArpGateway);
Paul Stewartd32f4842012-01-11 16:08:13 -080093 FRIEND_TEST(DHCPConfigTest, StartWithoutHostname);
Paul Stewartd408fdf2012-05-07 17:15:57 -070094 FRIEND_TEST(DHCPConfigTest, StartWithoutLeaseSuffix);
Darin Petkov98dd6a02011-06-10 15:12:57 -070095 FRIEND_TEST(DHCPConfigTest, Stop);
mukesh agrawalcc0fded2012-05-09 13:40:58 -070096 FRIEND_TEST(DHCPConfigTest, StopDuringRequestIP);
Darin Petkov98dd6a02011-06-10 15:12:57 -070097 FRIEND_TEST(DHCPProviderTest, CreateConfig);
Darin Petkove7cb7f82011-06-03 13:21:51 -070098
Darin Petkovf9b0ca82011-06-20 12:10:23 -070099 static const char kConfigurationKeyBroadcastAddress[];
Paul Stewart65bcd082012-11-16 09:37:14 -0800100 static const char kConfigurationKeyClasslessStaticRoutes[];
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700101 static const char kConfigurationKeyDNS[];
102 static const char kConfigurationKeyDomainName[];
103 static const char kConfigurationKeyDomainSearch[];
104 static const char kConfigurationKeyIPAddress[];
105 static const char kConfigurationKeyMTU[];
106 static const char kConfigurationKeyRouters[];
107 static const char kConfigurationKeySubnetCIDR[];
Paul Stewarta63f5212013-06-25 15:29:40 -0700108 static const char kConfigurationKeyWebProxyAutoDiscoveryUrl[];
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700109
Thieu Le94eed562012-02-21 15:57:29 -0800110 static const int kDHCPCDExitPollMilliseconds;
111 static const int kDHCPCDExitWaitMilliseconds;
Darin Petkovd1b715b2011-06-02 21:21:22 -0700112 static const char kDHCPCDPath[];
Darin Petkov92c43902011-06-09 20:46:06 -0700113 static const char kDHCPCDPathFormatPID[];
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700114 static const int kDHCPTimeoutSeconds;
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700115 static const char kDHCPCDUser[];
Darin Petkovd1b715b2011-06-02 21:21:22 -0700116
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700117 static const char kReasonBound[];
Paul Stewarta02ee492012-05-16 10:04:53 -0700118 static const char kReasonGatewayArp[];
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700119 static const char kReasonFail[];
120 static const char kReasonRebind[];
121 static const char kReasonReboot[];
122 static const char kReasonRenew[];
123
Chris Masone0756f232011-07-21 17:24:00 -0700124 static const char kType[];
125
Darin Petkovd1b715b2011-06-02 21:21:22 -0700126 // Starts dhcpcd, returns true on success and false otherwise.
127 bool Start();
128
Darin Petkov92c43902011-06-09 20:46:06 -0700129 // Stops dhcpcd if running.
mukesh agrawal1835e772013-01-15 18:35:03 -0800130 void Stop(const char *reason);
Darin Petkov92c43902011-06-09 20:46:06 -0700131
Darin Petkov98dd6a02011-06-10 15:12:57 -0700132 // Stops dhcpcd if already running and then starts it. Returns true on success
133 // and false otherwise.
134 bool Restart();
135
Paul Stewart65bcd082012-11-16 09:37:14 -0800136 // Parses |classless_routes| into |properties|. Sets the default gateway
137 // if one is supplied and |properties| does not already contain one. It
138 // also sets the "routes" parameter of the IPConfig properties for all
139 // routes not converted into the default gateway. Returns true on
140 // success, and false otherwise.
141 static bool ParseClasslessStaticRoutes(const std::string &classless_routes,
142 IPConfig::Properties *properties);
143
Darin Petkove7cb7f82011-06-03 13:21:51 -0700144 // Parses |configuration| into |properties|. Returns true on success, and
145 // false otherwise.
mukesh agrawal28fd88e2013-05-02 14:06:10 -0700146 static bool ParseConfiguration(const Configuration &configuration,
147 IPConfig::Properties *properties);
Darin Petkove7cb7f82011-06-03 13:21:51 -0700148
149 // Returns the string representation of the IP address |address|, or an
150 // empty string on failure.
mukesh agrawal28fd88e2013-05-02 14:06:10 -0700151 static std::string GetIPv4AddressString(unsigned int address);
Darin Petkove7cb7f82011-06-03 13:21:51 -0700152
Darin Petkov92c43902011-06-09 20:46:06 -0700153 // Called when the dhcpcd client process exits.
154 static void ChildWatchCallback(GPid pid, gint status, gpointer data);
155
Darin Petkov98dd6a02011-06-10 15:12:57 -0700156 // Cleans up remaining state from a running client, if any, including freeing
157 // its GPid, exit watch callback, and state files.
Darin Petkov92c43902011-06-09 20:46:06 -0700158 void CleanupClientState();
159
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700160 // Initialize a callback that will invoke ProcessDHCPTimeout if we
161 // do not get a lease in a reasonable amount of time.
162 void StartDHCPTimeout();
163 // Cancel callback created by StartDHCPTimeout. One-liner included
164 // for symmetry.
165 void StopDHCPTimeout();
166 // Called if we do not get a DHCP lease in a reasonable amount of time.
167 // Informs upper layers of the failure.
168 void ProcessDHCPTimeout();
169
Darin Petkov3fe17662013-02-04 14:19:08 +0100170 void KillClient();
171
Darin Petkovab565bb2011-10-06 02:55:51 -0700172 // Store cached copies of singletons for speed/ease of testing.
173 ProxyFactory *proxy_factory_;
174
Darin Petkovd1b715b2011-06-02 21:21:22 -0700175 DHCPProvider *provider_;
176
Paul Stewartd32f4842012-01-11 16:08:13 -0800177 // Hostname to be used in the request. This will be passed to the DHCP
178 // server in the request.
179 std::string request_hostname_;
180
Paul Stewartd408fdf2012-05-07 17:15:57 -0700181 // DHCP lease file suffix, used to differentiate the lease of one interface
182 // or network from another.
183 std::string lease_file_suffix_;
184
185 // Specifies whether to supply an argument to the DHCP client to validate
186 // the acquired IP address using an ARP request to the gateway IP address.
187 bool arp_gateway_;
188
Darin Petkovd1b715b2011-06-02 21:21:22 -0700189 // The PID of the spawned DHCP client. May be 0 if no client has been spawned
190 // yet or the client has died.
Darin Petkov92c43902011-06-09 20:46:06 -0700191 int pid_;
192
193 // Child exit watch callback source tag.
194 unsigned int child_watch_tag_;
Darin Petkovd1b715b2011-06-02 21:21:22 -0700195
Paul Stewart217c61d2013-06-13 15:12:02 -0700196 // Whether a lease has been acquired from the DHCP server or gateway ARP.
197 bool is_lease_active_;
198
Darin Petkovd1b715b2011-06-02 21:21:22 -0700199 // The proxy for communicating with the DHCP client.
200 scoped_ptr<DHCPProxyInterface> proxy_;
201
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700202 // Called if we fail to get a DHCP lease in a timely manner.
203 base::CancelableClosure lease_acquisition_timeout_callback_;
204
205 // Time to wait for a DHCP lease. Represented as field so that it
206 // can be overriden in tests.
207 unsigned int lease_acquisition_timeout_seconds_;
208
Darin Petkov92c43902011-06-09 20:46:06 -0700209 // Root file path, used for testing.
Albert Chaulk0e1cdea2013-02-27 15:32:55 -0800210 base::FilePath root_;
Darin Petkov92c43902011-06-09 20:46:06 -0700211
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700212 base::WeakPtrFactory<DHCPConfig> weak_ptr_factory_;
Darin Petkova7b89492011-07-27 12:48:17 -0700213 EventDispatcher *dispatcher_;
Darin Petkov3258a812011-06-23 11:28:45 -0700214 GLib *glib_;
Darin Petkovf7897bc2011-06-08 17:13:36 -0700215
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700216 Minijail *minijail_;
217
Darin Petkov50308cd2011-06-01 18:25:07 -0700218 DISALLOW_COPY_AND_ASSIGN(DHCPConfig);
219};
220
221} // namespace shill
222
223#endif // SHILL_DHCP_CONFIG_