blob: fdd71f90d9ed435c8e3d4ebdba3b62faca3ed9b5 [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[];
108
Thieu Le94eed562012-02-21 15:57:29 -0800109 static const int kDHCPCDExitPollMilliseconds;
110 static const int kDHCPCDExitWaitMilliseconds;
Darin Petkovd1b715b2011-06-02 21:21:22 -0700111 static const char kDHCPCDPath[];
Darin Petkov92c43902011-06-09 20:46:06 -0700112 static const char kDHCPCDPathFormatPID[];
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700113 static const int kDHCPTimeoutSeconds;
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700114 static const char kDHCPCDUser[];
Darin Petkovd1b715b2011-06-02 21:21:22 -0700115
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700116 static const char kReasonBound[];
Paul Stewarta02ee492012-05-16 10:04:53 -0700117 static const char kReasonGatewayArp[];
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700118 static const char kReasonFail[];
119 static const char kReasonRebind[];
120 static const char kReasonReboot[];
121 static const char kReasonRenew[];
122
Chris Masone0756f232011-07-21 17:24:00 -0700123 static const char kType[];
124
Darin Petkovd1b715b2011-06-02 21:21:22 -0700125 // Starts dhcpcd, returns true on success and false otherwise.
126 bool Start();
127
Darin Petkov92c43902011-06-09 20:46:06 -0700128 // Stops dhcpcd if running.
mukesh agrawal1835e772013-01-15 18:35:03 -0800129 void Stop(const char *reason);
Darin Petkov92c43902011-06-09 20:46:06 -0700130
Darin Petkov98dd6a02011-06-10 15:12:57 -0700131 // Stops dhcpcd if already running and then starts it. Returns true on success
132 // and false otherwise.
133 bool Restart();
134
Paul Stewart65bcd082012-11-16 09:37:14 -0800135 // Parses |classless_routes| into |properties|. Sets the default gateway
136 // if one is supplied and |properties| does not already contain one. It
137 // also sets the "routes" parameter of the IPConfig properties for all
138 // routes not converted into the default gateway. Returns true on
139 // success, and false otherwise.
140 static bool ParseClasslessStaticRoutes(const std::string &classless_routes,
141 IPConfig::Properties *properties);
142
Darin Petkove7cb7f82011-06-03 13:21:51 -0700143 // Parses |configuration| into |properties|. Returns true on success, and
144 // false otherwise.
mukesh agrawal28fd88e2013-05-02 14:06:10 -0700145 static bool ParseConfiguration(const Configuration &configuration,
146 IPConfig::Properties *properties);
Darin Petkove7cb7f82011-06-03 13:21:51 -0700147
148 // Returns the string representation of the IP address |address|, or an
149 // empty string on failure.
mukesh agrawal28fd88e2013-05-02 14:06:10 -0700150 static std::string GetIPv4AddressString(unsigned int address);
Darin Petkove7cb7f82011-06-03 13:21:51 -0700151
Darin Petkov92c43902011-06-09 20:46:06 -0700152 // Called when the dhcpcd client process exits.
153 static void ChildWatchCallback(GPid pid, gint status, gpointer data);
154
Darin Petkov98dd6a02011-06-10 15:12:57 -0700155 // Cleans up remaining state from a running client, if any, including freeing
156 // its GPid, exit watch callback, and state files.
Darin Petkov92c43902011-06-09 20:46:06 -0700157 void CleanupClientState();
158
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700159 // Initialize a callback that will invoke ProcessDHCPTimeout if we
160 // do not get a lease in a reasonable amount of time.
161 void StartDHCPTimeout();
162 // Cancel callback created by StartDHCPTimeout. One-liner included
163 // for symmetry.
164 void StopDHCPTimeout();
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 ProcessDHCPTimeout();
168
Darin Petkov3fe17662013-02-04 14:19:08 +0100169 void KillClient();
170
Darin Petkovab565bb2011-10-06 02:55:51 -0700171 // Store cached copies of singletons for speed/ease of testing.
172 ProxyFactory *proxy_factory_;
173
Darin Petkovd1b715b2011-06-02 21:21:22 -0700174 DHCPProvider *provider_;
175
Paul Stewartd32f4842012-01-11 16:08:13 -0800176 // Hostname to be used in the request. This will be passed to the DHCP
177 // server in the request.
178 std::string request_hostname_;
179
Paul Stewartd408fdf2012-05-07 17:15:57 -0700180 // DHCP lease file suffix, used to differentiate the lease of one interface
181 // or network from another.
182 std::string lease_file_suffix_;
183
184 // Specifies whether to supply an argument to the DHCP client to validate
185 // the acquired IP address using an ARP request to the gateway IP address.
186 bool arp_gateway_;
187
Darin Petkovd1b715b2011-06-02 21:21:22 -0700188 // The PID of the spawned DHCP client. May be 0 if no client has been spawned
189 // yet or the client has died.
Darin Petkov92c43902011-06-09 20:46:06 -0700190 int pid_;
191
192 // Child exit watch callback source tag.
193 unsigned int child_watch_tag_;
Darin Petkovd1b715b2011-06-02 21:21:22 -0700194
Paul Stewart217c61d2013-06-13 15:12:02 -0700195 // Whether a lease has been acquired from the DHCP server or gateway ARP.
196 bool is_lease_active_;
197
Darin Petkovd1b715b2011-06-02 21:21:22 -0700198 // The proxy for communicating with the DHCP client.
199 scoped_ptr<DHCPProxyInterface> proxy_;
200
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700201 // Called if we fail to get a DHCP lease in a timely manner.
202 base::CancelableClosure lease_acquisition_timeout_callback_;
203
204 // Time to wait for a DHCP lease. Represented as field so that it
205 // can be overriden in tests.
206 unsigned int lease_acquisition_timeout_seconds_;
207
Darin Petkov92c43902011-06-09 20:46:06 -0700208 // Root file path, used for testing.
Albert Chaulk0e1cdea2013-02-27 15:32:55 -0800209 base::FilePath root_;
Darin Petkov92c43902011-06-09 20:46:06 -0700210
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700211 base::WeakPtrFactory<DHCPConfig> weak_ptr_factory_;
Darin Petkova7b89492011-07-27 12:48:17 -0700212 EventDispatcher *dispatcher_;
Darin Petkov3258a812011-06-23 11:28:45 -0700213 GLib *glib_;
Darin Petkovf7897bc2011-06-08 17:13:36 -0700214
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700215 Minijail *minijail_;
216
Darin Petkov50308cd2011-06-01 18:25:07 -0700217 DISALLOW_COPY_AND_ASSIGN(DHCPConfig);
218};
219
220} // namespace shill
221
222#endif // SHILL_DHCP_CONFIG_