blob: 05cbdb569c17c76b953f140a61381b1dae2473ac [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#include "shill/dhcp_config.h"
6
Darin Petkove7cb7f82011-06-03 13:21:51 -07007#include <arpa/inet.h>
Thieu Le94eed562012-02-21 15:57:29 -08008#include <sys/wait.h>
Darin Petkove7cb7f82011-06-03 13:21:51 -07009
Darin Petkov92c43902011-06-09 20:46:06 -070010#include <base/file_util.h>
Darin Petkov92c43902011-06-09 20:46:06 -070011#include <base/stringprintf.h>
Chris Masone43b48a12011-07-01 13:37:07 -070012#include <chromeos/dbus/service_constants.h>
Darin Petkovd1b715b2011-06-02 21:21:22 -070013
14#include "shill/dhcpcd_proxy.h"
15#include "shill/dhcp_provider.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070016#include "shill/event_dispatcher.h"
Darin Petkov3258a812011-06-23 11:28:45 -070017#include "shill/glib.h"
Paul Stewart1d18e8c2011-07-15 11:00:31 -070018#include "shill/ip_address.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070019#include "shill/logging.h"
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -070020#include "shill/minijail.h"
Darin Petkovaceede32011-07-18 15:32:38 -070021#include "shill/proxy_factory.h"
Darin Petkov50308cd2011-06-01 18:25:07 -070022
Darin Petkove7cb7f82011-06-03 13:21:51 -070023using std::string;
24using std::vector;
25
Darin Petkov50308cd2011-06-01 18:25:07 -070026namespace shill {
27
Chris Masone0756f232011-07-21 17:24:00 -070028// static
Darin Petkove7cb7f82011-06-03 13:21:51 -070029const char DHCPConfig::kConfigurationKeyBroadcastAddress[] = "BroadcastAddress";
30const char DHCPConfig::kConfigurationKeyDNS[] = "DomainNameServers";
31const char DHCPConfig::kConfigurationKeyDomainName[] = "DomainName";
32const char DHCPConfig::kConfigurationKeyDomainSearch[] = "DomainSearch";
33const char DHCPConfig::kConfigurationKeyIPAddress[] = "IPAddress";
34const char DHCPConfig::kConfigurationKeyMTU[] = "InterfaceMTU";
35const char DHCPConfig::kConfigurationKeyRouters[] = "Routers";
36const char DHCPConfig::kConfigurationKeySubnetCIDR[] = "SubnetCIDR";
Thieu Le94eed562012-02-21 15:57:29 -080037const int DHCPConfig::kDHCPCDExitPollMilliseconds = 50;
38const int DHCPConfig::kDHCPCDExitWaitMilliseconds = 3000;
Darin Petkovd1b715b2011-06-02 21:21:22 -070039const char DHCPConfig::kDHCPCDPath[] = "/sbin/dhcpcd";
Paul Stewartd408fdf2012-05-07 17:15:57 -070040const char DHCPConfig::kDHCPCDPathFormatLease[] =
41 "var/lib/dhcpcd/dhcpcd-%s.lease";
Jorge Lucangeli Obes2f3169d2012-04-25 11:38:25 -070042const char DHCPConfig::kDHCPCDPathFormatPID[] =
43 "var/run/dhcpcd/dhcpcd-%s.pid";
mukesh agrawalcc0fded2012-05-09 13:40:58 -070044const int DHCPConfig::kDHCPTimeoutSeconds = 30;
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -070045const char DHCPConfig::kDHCPCDUser[] = "dhcp";
Darin Petkov14c29ec2012-03-02 11:34:19 +010046const int DHCPConfig::kMinMTU = 576;
Darin Petkovf9b0ca82011-06-20 12:10:23 -070047const char DHCPConfig::kReasonBound[] = "BOUND";
48const char DHCPConfig::kReasonFail[] = "FAIL";
Paul Stewarta02ee492012-05-16 10:04:53 -070049const char DHCPConfig::kReasonGatewayArp[] = "GATEWAY-ARP";
Darin Petkovf9b0ca82011-06-20 12:10:23 -070050const char DHCPConfig::kReasonRebind[] = "REBIND";
51const char DHCPConfig::kReasonReboot[] = "REBOOT";
52const char DHCPConfig::kReasonRenew[] = "RENEW";
Chris Masone0756f232011-07-21 17:24:00 -070053// static
54const char DHCPConfig::kType[] = "dhcp";
Darin Petkovf9b0ca82011-06-20 12:10:23 -070055
Darin Petkove7cb7f82011-06-03 13:21:51 -070056
Chris Masone19e30402011-07-19 15:48:47 -070057DHCPConfig::DHCPConfig(ControlInterface *control_interface,
Darin Petkova7b89492011-07-27 12:48:17 -070058 EventDispatcher *dispatcher,
Chris Masone19e30402011-07-19 15:48:47 -070059 DHCPProvider *provider,
Darin Petkovf65e9282011-06-21 14:29:56 -070060 const string &device_name,
Paul Stewartd32f4842012-01-11 16:08:13 -080061 const string &request_hostname,
Paul Stewartd408fdf2012-05-07 17:15:57 -070062 const string &lease_file_suffix,
63 bool arp_gateway,
Darin Petkov3258a812011-06-23 11:28:45 -070064 GLib *glib)
Chris Masone0756f232011-07-21 17:24:00 -070065 : IPConfig(control_interface, device_name, kType),
Darin Petkovab565bb2011-10-06 02:55:51 -070066 proxy_factory_(ProxyFactory::GetInstance()),
Darin Petkovd1b715b2011-06-02 21:21:22 -070067 provider_(provider),
Paul Stewartd32f4842012-01-11 16:08:13 -080068 request_hostname_(request_hostname),
Paul Stewartd408fdf2012-05-07 17:15:57 -070069 lease_file_suffix_(lease_file_suffix),
70 arp_gateway_(arp_gateway),
Darin Petkovf7897bc2011-06-08 17:13:36 -070071 pid_(0),
Darin Petkov92c43902011-06-09 20:46:06 -070072 child_watch_tag_(0),
mukesh agrawalcc0fded2012-05-09 13:40:58 -070073 lease_acquisition_timeout_seconds_(kDHCPTimeoutSeconds),
Darin Petkov92c43902011-06-09 20:46:06 -070074 root_("/"),
mukesh agrawalcc0fded2012-05-09 13:40:58 -070075 weak_ptr_factory_(this),
Darin Petkova7b89492011-07-27 12:48:17 -070076 dispatcher_(dispatcher),
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -070077 glib_(glib),
78 minijail_(Minijail::GetInstance()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -070079 SLOG(DHCP, 2) << __func__ << ": " << device_name;
Paul Stewartd408fdf2012-05-07 17:15:57 -070080 if (lease_file_suffix_.empty()) {
81 lease_file_suffix_ = device_name;
82 }
Darin Petkov50308cd2011-06-01 18:25:07 -070083}
84
85DHCPConfig::~DHCPConfig() {
Ben Chanfad4a0b2012-04-18 15:49:59 -070086 SLOG(DHCP, 2) << __func__ << ": " << device_name();
Darin Petkov92c43902011-06-09 20:46:06 -070087
88 // Don't leave behind dhcpcd running.
89 Stop();
90
Darin Petkov98dd6a02011-06-10 15:12:57 -070091 // Make sure we don't get any callbacks to the destroyed instance.
Darin Petkov92c43902011-06-09 20:46:06 -070092 CleanupClientState();
Darin Petkovd1b715b2011-06-02 21:21:22 -070093}
94
Darin Petkov92c43902011-06-09 20:46:06 -070095bool DHCPConfig::RequestIP() {
Ben Chanfad4a0b2012-04-18 15:49:59 -070096 SLOG(DHCP, 2) << __func__ << ": " << device_name();
Darin Petkovd1b715b2011-06-02 21:21:22 -070097 if (!pid_) {
98 return Start();
99 }
100 if (!proxy_.get()) {
Darin Petkov98dd6a02011-06-10 15:12:57 -0700101 LOG(ERROR) << "Unable to request IP before acquiring destination.";
102 return Restart();
Darin Petkovd1b715b2011-06-02 21:21:22 -0700103 }
Darin Petkov92c43902011-06-09 20:46:06 -0700104 return RenewIP();
Darin Petkovd1b715b2011-06-02 21:21:22 -0700105}
106
Darin Petkov92c43902011-06-09 20:46:06 -0700107bool DHCPConfig::RenewIP() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700108 SLOG(DHCP, 2) << __func__ << ": " << device_name();
Darin Petkov98dd6a02011-06-10 15:12:57 -0700109 if (!pid_) {
110 return false;
111 }
Paul Stewartc02344a2012-08-17 16:57:37 -0700112 if (!proxy_.get()) {
113 LOG(ERROR) << "Unable to renew IP before acquiring destination.";
114 return false;
115 }
Darin Petkovaceede32011-07-18 15:32:38 -0700116 proxy_->Rebind(device_name());
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700117 StartDHCPTimeout();
Darin Petkovd1b715b2011-06-02 21:21:22 -0700118 return true;
119}
120
Darin Petkov92c43902011-06-09 20:46:06 -0700121bool DHCPConfig::ReleaseIP() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700122 SLOG(DHCP, 2) << __func__ << ": " << device_name();
Darin Petkov98dd6a02011-06-10 15:12:57 -0700123 if (!pid_) {
124 return true;
125 }
Paul Stewarta02ee492012-05-16 10:04:53 -0700126 // If we are using gateway unicast ARP to speed up re-connect, don't
127 // give up our leases when we disconnect.
128 if (!arp_gateway_ && proxy_.get()) {
Darin Petkova7b89492011-07-27 12:48:17 -0700129 proxy_->Release(device_name());
Darin Petkov98dd6a02011-06-10 15:12:57 -0700130 }
Darin Petkov98dd6a02011-06-10 15:12:57 -0700131 Stop();
132 return true;
Darin Petkov92c43902011-06-09 20:46:06 -0700133}
134
Darin Petkova7b89492011-07-27 12:48:17 -0700135void DHCPConfig::InitProxy(const string &service) {
Darin Petkova7b89492011-07-27 12:48:17 -0700136 if (!proxy_.get()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700137 SLOG(DHCP, 2) << "Init DHCP Proxy: " << device_name() << " at " << service;
Darin Petkovab565bb2011-10-06 02:55:51 -0700138 proxy_.reset(proxy_factory_->CreateDHCPProxy(service));
Darin Petkovd1b715b2011-06-02 21:21:22 -0700139 }
140}
141
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700142void DHCPConfig::ProcessEventSignal(const string &reason,
Darin Petkove7cb7f82011-06-03 13:21:51 -0700143 const Configuration &configuration) {
144 LOG(INFO) << "Event reason: " << reason;
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700145 if (reason == kReasonFail) {
146 LOG(ERROR) << "Received failure event from DHCP client.";
147 UpdateProperties(IPConfig::Properties(), false);
Darin Petkove7cb7f82011-06-03 13:21:51 -0700148 return;
149 }
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700150 if (reason != kReasonBound &&
151 reason != kReasonRebind &&
152 reason != kReasonReboot &&
Paul Stewarta02ee492012-05-16 10:04:53 -0700153 reason != kReasonRenew &&
154 reason != kReasonGatewayArp) {
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700155 LOG(WARNING) << "Event ignored.";
156 return;
157 }
158 IPConfig::Properties properties;
159 CHECK(ParseConfiguration(configuration, &properties));
Paul Stewarta02ee492012-05-16 10:04:53 -0700160 if (reason == kReasonGatewayArp) {
161 // This is a non-authoritative confirmation that we or on the same
162 // network as the one we received a lease on previously. The DHCP
163 // client is still running, so we should not cancel the timeout
164 // until that completes. In the meantime, however, we can tentatively
165 // configure our network in anticipation of successful completion.
166 IPConfig::UpdateProperties(properties, true);
167 } else {
168 UpdateProperties(properties, true);
169 }
Darin Petkove7cb7f82011-06-03 13:21:51 -0700170}
171
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700172void DHCPConfig::UpdateProperties(const Properties &properties, bool success) {
173 StopDHCPTimeout();
174 IPConfig::UpdateProperties(properties, success);
175}
176
Darin Petkovd1b715b2011-06-02 21:21:22 -0700177bool DHCPConfig::Start() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700178 SLOG(DHCP, 2) << __func__ << ": " << device_name();
Darin Petkovd1b715b2011-06-02 21:21:22 -0700179
Paul Stewartd32f4842012-01-11 16:08:13 -0800180 vector<char *> args;
181 args.push_back(const_cast<char *>(kDHCPCDPath));
Paul Stewartd408fdf2012-05-07 17:15:57 -0700182 args.push_back(const_cast<char *>("-B")); // Run in foreground.
mukesh agrawal7eb02892012-05-29 11:22:37 -0700183 args.push_back(const_cast<char *>("-q")); // Only warnings+errors to stderr.
Paul Stewartd32f4842012-01-11 16:08:13 -0800184 if (!request_hostname_.empty()) {
Paul Stewartd408fdf2012-05-07 17:15:57 -0700185 args.push_back(const_cast<char *>("-h")); // Request hostname from server.
Paul Stewartd32f4842012-01-11 16:08:13 -0800186 args.push_back(const_cast<char *>(request_hostname_.c_str()));
187 }
Paul Stewartd408fdf2012-05-07 17:15:57 -0700188 if (arp_gateway_) {
189 args.push_back(const_cast<char *>("-R")); // ARP for default gateway.
Paul Stewarta02ee492012-05-16 10:04:53 -0700190 args.push_back(const_cast<char *>("-U")); // Enable unicast ARP on renew.
Paul Stewartd408fdf2012-05-07 17:15:57 -0700191 }
192 string interface_arg(device_name());
193 if (lease_file_suffix_ != device_name()) {
194 interface_arg = base::StringPrintf("%s=%s", device_name().c_str(),
195 lease_file_suffix_.c_str());
196 }
197 args.push_back(const_cast<char *>(interface_arg.c_str()));
Paul Stewartd32f4842012-01-11 16:08:13 -0800198 args.push_back(NULL);
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700199
200 struct minijail *jail = minijail_->New();
201 minijail_->DropRoot(jail, kDHCPCDUser);
202 minijail_->UseCapabilities(jail,
203 CAP_TO_MASK(CAP_NET_BIND_SERVICE) |
204 CAP_TO_MASK(CAP_NET_BROADCAST) |
205 CAP_TO_MASK(CAP_NET_ADMIN) |
206 CAP_TO_MASK(CAP_NET_RAW));
Darin Petkovd1b715b2011-06-02 21:21:22 -0700207
Darin Petkov98dd6a02011-06-10 15:12:57 -0700208 CHECK(!pid_);
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700209 if (!minijail_->RunAndDestroy(jail, args, &pid_)) {
210 LOG(ERROR) << "Unable to spawn " << kDHCPCDPath << " in a jail.";
Darin Petkovd1b715b2011-06-02 21:21:22 -0700211 return false;
212 }
Darin Petkovd1b715b2011-06-02 21:21:22 -0700213 LOG(INFO) << "Spawned " << kDHCPCDPath << " with pid: " << pid_;
Darin Petkovf7897bc2011-06-08 17:13:36 -0700214 provider_->BindPID(pid_, this);
Darin Petkov98dd6a02011-06-10 15:12:57 -0700215 CHECK(!child_watch_tag_);
216 child_watch_tag_ = glib_->ChildWatchAdd(pid_, ChildWatchCallback, this);
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700217 StartDHCPTimeout();
Darin Petkovd1b715b2011-06-02 21:21:22 -0700218 return true;
Darin Petkov50308cd2011-06-01 18:25:07 -0700219}
220
Darin Petkov92c43902011-06-09 20:46:06 -0700221void DHCPConfig::Stop() {
222 if (pid_) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700223 SLOG(DHCP, 2) << "Terminating " << pid_;
Thieu Le94eed562012-02-21 15:57:29 -0800224 if (kill(pid_, SIGTERM) < 0) {
225 PLOG(ERROR);
226 return;
227 }
228 pid_t ret;
229 int num_iterations =
230 kDHCPCDExitWaitMilliseconds / kDHCPCDExitPollMilliseconds;
231 for (int count = 0; count < num_iterations; ++count) {
232 ret = waitpid(pid_, NULL, WNOHANG);
233 if (ret == pid_ || ret == -1)
234 break;
235 usleep(kDHCPCDExitPollMilliseconds * 1000);
236 if (count == num_iterations / 2) // Make one last attempt to kill dhcpcd.
237 kill(pid_, SIGKILL);
238 }
239 if (ret != pid_)
240 PLOG(ERROR);
Darin Petkov92c43902011-06-09 20:46:06 -0700241 }
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700242 StopDHCPTimeout();
Darin Petkov92c43902011-06-09 20:46:06 -0700243}
244
Darin Petkov98dd6a02011-06-10 15:12:57 -0700245bool DHCPConfig::Restart() {
246 // Check to ensure that this instance doesn't get destroyed in the middle of
247 // this call. If stopping a running client while there's only one reference to
248 // this instance, we will end up destroying it when the PID is unbound from
249 // the Provider. Since the Provider doesn't invoke Restart, this would mean
250 // that Restart was erroneously executed through a bare reference.
251 CHECK(!pid_ || !HasOneRef());
252 Stop();
253 if (pid_) {
254 provider_->UnbindPID(pid_);
255 }
256 CleanupClientState();
257 return Start();
258}
259
Darin Petkove7cb7f82011-06-03 13:21:51 -0700260string DHCPConfig::GetIPv4AddressString(unsigned int address) {
261 char str[INET_ADDRSTRLEN];
262 if (inet_ntop(AF_INET, &address, str, arraysize(str))) {
263 return str;
264 }
265 LOG(ERROR) << "Unable to convert IPv4 address to string: " << address;
266 return "";
267}
268
269bool DHCPConfig::ParseConfiguration(const Configuration& configuration,
270 IPConfig::Properties *properties) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700271 SLOG(DHCP, 2) << __func__;
Chris Masone43b48a12011-07-01 13:37:07 -0700272 properties->method = flimflam::kTypeDHCP;
Paul Stewart7355ce12011-09-02 10:47:01 -0700273 properties->address_family = IPAddress::kFamilyIPv4;
Darin Petkove7cb7f82011-06-03 13:21:51 -0700274 for (Configuration::const_iterator it = configuration.begin();
275 it != configuration.end(); ++it) {
276 const string &key = it->first;
277 const DBus::Variant &value = it->second;
Ben Chanfad4a0b2012-04-18 15:49:59 -0700278 SLOG(DHCP, 2) << "Processing key: " << key;
Darin Petkove7cb7f82011-06-03 13:21:51 -0700279 if (key == kConfigurationKeyIPAddress) {
280 properties->address = GetIPv4AddressString(value.reader().get_uint32());
281 if (properties->address.empty()) {
282 return false;
283 }
284 } else if (key == kConfigurationKeySubnetCIDR) {
Paul Stewart48100b02012-03-19 07:53:52 -0700285 properties->subnet_prefix = value.reader().get_byte();
Darin Petkove7cb7f82011-06-03 13:21:51 -0700286 } else if (key == kConfigurationKeyBroadcastAddress) {
287 properties->broadcast_address =
288 GetIPv4AddressString(value.reader().get_uint32());
289 if (properties->broadcast_address.empty()) {
290 return false;
291 }
292 } else if (key == kConfigurationKeyRouters) {
Darin Petkovf7897bc2011-06-08 17:13:36 -0700293 vector<unsigned int> routers = value.operator vector<unsigned int>();
Darin Petkove7cb7f82011-06-03 13:21:51 -0700294 if (routers.empty()) {
295 LOG(ERROR) << "No routers provided.";
296 return false;
297 }
298 properties->gateway = GetIPv4AddressString(routers[0]);
299 if (properties->gateway.empty()) {
300 return false;
301 }
302 } else if (key == kConfigurationKeyDNS) {
Darin Petkovf7897bc2011-06-08 17:13:36 -0700303 vector<unsigned int> servers = value.operator vector<unsigned int>();
Darin Petkove7cb7f82011-06-03 13:21:51 -0700304 for (vector<unsigned int>::const_iterator it = servers.begin();
305 it != servers.end(); ++it) {
306 string server = GetIPv4AddressString(*it);
307 if (server.empty()) {
308 return false;
309 }
310 properties->dns_servers.push_back(server);
311 }
312 } else if (key == kConfigurationKeyDomainName) {
313 properties->domain_name = value.reader().get_string();
314 } else if (key == kConfigurationKeyDomainSearch) {
Darin Petkovf7897bc2011-06-08 17:13:36 -0700315 properties->domain_search = value.operator vector<string>();
Darin Petkove7cb7f82011-06-03 13:21:51 -0700316 } else if (key == kConfigurationKeyMTU) {
317 int mtu = value.reader().get_uint16();
Darin Petkov14c29ec2012-03-02 11:34:19 +0100318 if (mtu >= kMinMTU) {
Darin Petkove7cb7f82011-06-03 13:21:51 -0700319 properties->mtu = mtu;
320 }
321 } else {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700322 SLOG(DHCP, 2) << "Key ignored.";
Darin Petkove7cb7f82011-06-03 13:21:51 -0700323 }
324 }
325 return true;
326}
327
Darin Petkov92c43902011-06-09 20:46:06 -0700328void DHCPConfig::ChildWatchCallback(GPid pid, gint status, gpointer data) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700329 SLOG(DHCP, 2) << "pid " << pid << " exit status " << status;
Darin Petkov92c43902011-06-09 20:46:06 -0700330 DHCPConfig *config = reinterpret_cast<DHCPConfig *>(data);
331 config->child_watch_tag_ = 0;
Darin Petkov92c43902011-06-09 20:46:06 -0700332 CHECK_EQ(pid, config->pid_);
Darin Petkov92c43902011-06-09 20:46:06 -0700333 config->CleanupClientState();
334
335 // |config| instance may be destroyed after this call.
336 config->provider_->UnbindPID(pid);
337}
338
339void DHCPConfig::CleanupClientState() {
Darin Petkov98dd6a02011-06-10 15:12:57 -0700340 if (child_watch_tag_) {
341 glib_->SourceRemove(child_watch_tag_);
342 child_watch_tag_ = 0;
343 }
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700344 pid_ = 0;
Darin Petkovf9b0ca82011-06-20 12:10:23 -0700345 proxy_.reset();
Paul Stewartd408fdf2012-05-07 17:15:57 -0700346 if (lease_file_suffix_ == device_name()) {
347 // If the lease file suffix was left as default, clean it up at exit.
348 file_util::Delete(root_.Append(
349 base::StringPrintf(kDHCPCDPathFormatLease,
350 device_name().c_str())), false);
351 }
352 file_util::Delete(root_.Append(
353 base::StringPrintf(kDHCPCDPathFormatPID, device_name().c_str())), false);
Darin Petkov92c43902011-06-09 20:46:06 -0700354}
355
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700356void DHCPConfig::StartDHCPTimeout() {
357 lease_acquisition_timeout_callback_.Reset(
358 Bind(&DHCPConfig::ProcessDHCPTimeout, weak_ptr_factory_.GetWeakPtr()));
359 dispatcher_->PostDelayedTask(
360 lease_acquisition_timeout_callback_.callback(),
361 lease_acquisition_timeout_seconds_ * 1000);
362}
363
364void DHCPConfig::StopDHCPTimeout() {
365 lease_acquisition_timeout_callback_.Cancel();
366}
367
368void DHCPConfig::ProcessDHCPTimeout() {
369 LOG(ERROR) << "Timed out waiting for DHCP lease on " << device_name() << " "
370 << "(after " << lease_acquisition_timeout_seconds_ << " seconds).";
371 UpdateProperties(IPConfig::Properties(), false);
372}
373
Darin Petkov50308cd2011-06-01 18:25:07 -0700374} // namespace shill