blob: 70c87e130cc9d23538a5268017cc67ad28fd3095 [file] [log] [blame]
Paul Stewarte6927402012-01-23 16:11:30 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewartc2350ee2011-10-19 12:28:40 -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/dns_client.h"
6
7#include <arpa/inet.h>
8#include <netdb.h>
9#include <netinet/in.h>
10#include <sys/socket.h>
11
12#include <map>
Alex Vakulenkoa41ab512014-07-23 14:24:23 -070013#include <memory>
Paul Stewartc2350ee2011-10-19 12:28:40 -070014#include <set>
15#include <string>
Paul Stewartc2350ee2011-10-19 12:28:40 -070016#include <vector>
17
Eric Shienbrood3e20a232012-02-16 11:35:56 -050018#include <base/bind.h>
19#include <base/bind_helpers.h>
20#include <base/stl_util.h>
Ben Chana0ddf462014-02-06 11:32:42 -080021#include <base/strings/string_number_conversions.h>
Paul Stewartc2350ee2011-10-19 12:28:40 -070022
Christopher Wileyb691efd2012-08-09 13:51:51 -070023#include "shill/logging.h"
Darin Petkov89593a92012-02-21 10:59:48 +010024#include "shill/shill_ares.h"
25#include "shill/shill_time.h"
Paul Stewartc2350ee2011-10-19 12:28:40 -070026
Eric Shienbrood3e20a232012-02-16 11:35:56 -050027using base::Bind;
28using base::Unretained;
Paul Stewartc2350ee2011-10-19 12:28:40 -070029using std::map;
30using std::set;
31using std::string;
32using std::vector;
33
34namespace shill {
35
Paul Stewartc2350ee2011-10-19 12:28:40 -070036const char DNSClient::kErrorNoData[] = "The query response contains no answers";
37const char DNSClient::kErrorFormErr[] = "The server says the query is bad";
38const char DNSClient::kErrorServerFail[] = "The server says it had a failure";
39const char DNSClient::kErrorNotFound[] = "The queried-for domain was not found";
40const char DNSClient::kErrorNotImp[] = "The server doesn't implement operation";
41const char DNSClient::kErrorRefused[] = "The server replied, refused the query";
42const char DNSClient::kErrorBadQuery[] = "Locally we could not format a query";
43const char DNSClient::kErrorNetRefused[] = "The network connection was refused";
44const char DNSClient::kErrorTimedOut[] = "The network connection was timed out";
45const char DNSClient::kErrorUnknown[] = "DNS Resolver unknown internal error";
46
Peter Qiuf3a8f902014-08-20 10:05:42 -070047const int DNSClient::kDefaultDNSPort = 53;
48
Paul Stewartc2350ee2011-10-19 12:28:40 -070049// Private to the implementation of resolver so callers don't include ares.h
50struct DNSClientState {
Ben Chancc225ef2014-09-30 13:26:51 -070051 DNSClientState() : channel(nullptr), start_time{} {}
Darin Petkove636c692012-05-31 10:22:17 +020052
Paul Stewartc2350ee2011-10-19 12:28:40 -070053 ares_channel channel;
Ben Chane2ee5e02014-09-19 19:29:42 -070054 map<ares_socket_t, std::shared_ptr<IOHandler>> read_handlers;
55 map<ares_socket_t, std::shared_ptr<IOHandler>> write_handlers;
Darin Petkove636c692012-05-31 10:22:17 +020056 struct timeval start_time;
Paul Stewartc2350ee2011-10-19 12:28:40 -070057};
58
59DNSClient::DNSClient(IPAddress::Family family,
60 const string &interface_name,
61 const vector<string> &dns_servers,
62 int timeout_ms,
63 EventDispatcher *dispatcher,
Eric Shienbrood3e20a232012-02-16 11:35:56 -050064 const ClientCallback &callback)
Paul Stewartc2350ee2011-10-19 12:28:40 -070065 : address_(IPAddress(family)),
66 interface_name_(interface_name),
67 dns_servers_(dns_servers),
68 dispatcher_(dispatcher),
69 callback_(callback),
70 timeout_ms_(timeout_ms),
71 running_(false),
Eric Shienbrood3e20a232012-02-16 11:35:56 -050072 weak_ptr_factory_(this),
Paul Stewartc2350ee2011-10-19 12:28:40 -070073 ares_(Ares::GetInstance()),
74 time_(Time::GetInstance()) {}
75
76DNSClient::~DNSClient() {
77 Stop();
78}
79
Paul Stewartbdb02e62012-02-22 16:24:33 -080080bool DNSClient::Start(const string &hostname, Error *error) {
Paul Stewartc2350ee2011-10-19 12:28:40 -070081 if (running_) {
Paul Stewartbdb02e62012-02-22 16:24:33 -080082 Error::PopulateAndLog(error, Error::kInProgress,
83 "Only one DNS request is allowed at a time");
Paul Stewartc2350ee2011-10-19 12:28:40 -070084 return false;
85 }
86
87 if (!resolver_state_.get()) {
88 struct ares_options options;
89 memset(&options, 0, sizeof(options));
Peter Qiuf3a8f902014-08-20 10:05:42 -070090 options.timeout = timeout_ms_;
Paul Stewartc2350ee2011-10-19 12:28:40 -070091
Peter Qiuf3a8f902014-08-20 10:05:42 -070092 if (dns_servers_.empty()) {
Paul Stewartbdb02e62012-02-22 16:24:33 -080093 Error::PopulateAndLog(error, Error::kInvalidArguments,
94 "No valid DNS server addresses");
Paul Stewartc2350ee2011-10-19 12:28:40 -070095 return false;
96 }
97
Paul Stewartc2350ee2011-10-19 12:28:40 -070098 resolver_state_.reset(new DNSClientState);
99 int status = ares_->InitOptions(&resolver_state_->channel,
100 &options,
Peter Qiuf3a8f902014-08-20 10:05:42 -0700101 ARES_OPT_TIMEOUTMS);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700102 if (status != ARES_SUCCESS) {
Paul Stewartbdb02e62012-02-22 16:24:33 -0800103 Error::PopulateAndLog(error, Error::kOperationFailed,
104 "ARES initialization returns error code: " +
105 base::IntToString(status));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700106 resolver_state_.reset();
107 return false;
108 }
109
Peter Qiuf3a8f902014-08-20 10:05:42 -0700110 // Format DNS server addresses string as "host:port[,host:port...]" to be
111 // used in call to ares_set_servers_csv for setting DNS server addresses.
112 // There is a bug in ares library when parsing IPv6 addresses, where it
113 // always assumes the port number are specified when address contains ":".
114 // So when IPv6 address are given without port number as "xx:xx:xx::yy",the
115 // parser would parse the address as "xx:xx:xx:" and port number as "yy".
116 // To work around this bug, port number are added to each address.
117 //
118 // Alternatively, we can use ares_set_servers instead, where we would
119 // explicitly construct a link list of ares_addr_node.
120 string server_addresses;
121 bool first = true;
122 for (const auto &ip : dns_servers_) {
123 if (!first) {
124 server_addresses += ",";
125 } else {
126 first = false;
127 }
128 server_addresses += (ip + ":" + base::IntToString(kDefaultDNSPort));
129 }
130 status = ares_->SetServersCsv(resolver_state_->channel,
131 server_addresses.c_str());
132 if (status != ARES_SUCCESS) {
133 Error::PopulateAndLog(error, Error::kOperationFailed,
134 "ARES set DNS servers error code: " +
135 base::IntToString(status));
136 resolver_state_.reset();
137 return false;
138 }
139
Paul Stewartc2350ee2011-10-19 12:28:40 -0700140 ares_->SetLocalDev(resolver_state_->channel, interface_name_.c_str());
141 }
142
143 running_ = true;
Darin Petkove636c692012-05-31 10:22:17 +0200144 time_->GetTimeMonotonic(&resolver_state_->start_time);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700145 ares_->GetHostByName(resolver_state_->channel, hostname.c_str(),
146 address_.family(), ReceiveDNSReplyCB, this);
147
148 if (!RefreshHandles()) {
149 LOG(ERROR) << "Impossibly short timeout.";
Paul Stewartbdb02e62012-02-22 16:24:33 -0800150 error->CopyFrom(error_);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700151 Stop();
152 return false;
153 }
154
155 return true;
156}
157
158void DNSClient::Stop() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700159 SLOG(DNS, 3) << "In " << __func__;
Paul Stewartc2350ee2011-10-19 12:28:40 -0700160 if (!resolver_state_.get()) {
161 return;
162 }
163
164 running_ = false;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500165 weak_ptr_factory_.InvalidateWeakPtrs();
Paul Stewartbdb02e62012-02-22 16:24:33 -0800166 error_.Reset();
167 address_.SetAddressToDefault();
Paul Stewartc2350ee2011-10-19 12:28:40 -0700168 ares_->Destroy(resolver_state_->channel);
169 resolver_state_.reset();
170}
171
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700172bool DNSClient::IsActive() const {
173 return running_;
174}
175
Paul Stewartbdb02e62012-02-22 16:24:33 -0800176// We delay our call to completion so that we exit all IOHandlers, and
177// can clean up all of our local state before calling the callback, or
178// during the process of the execution of the callee (which is free to
179// call our destructor safely).
180void DNSClient::HandleCompletion() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700181 SLOG(DNS, 3) << "In " << __func__;
Paul Stewartbdb02e62012-02-22 16:24:33 -0800182 Error error;
183 error.CopyFrom(error_);
184 IPAddress address(address_);
185 if (!error.IsSuccess()) {
186 // If the DNS request did not succeed, do not trust it for future
187 // attempts.
188 Stop();
189 } else {
190 // Prepare our state for the next request without destroying the
191 // current ARES state.
192 error_.Reset();
193 address_.SetAddressToDefault();
194 }
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500195 callback_.Run(error, address);
Paul Stewartbdb02e62012-02-22 16:24:33 -0800196}
197
Paul Stewartc2350ee2011-10-19 12:28:40 -0700198void DNSClient::HandleDNSRead(int fd) {
199 ares_->ProcessFd(resolver_state_->channel, fd, ARES_SOCKET_BAD);
200 RefreshHandles();
201}
202
203void DNSClient::HandleDNSWrite(int fd) {
204 ares_->ProcessFd(resolver_state_->channel, ARES_SOCKET_BAD, fd);
205 RefreshHandles();
206}
207
208void DNSClient::HandleTimeout() {
209 ares_->ProcessFd(resolver_state_->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
Paul Stewartbdb02e62012-02-22 16:24:33 -0800210 RefreshHandles();
Paul Stewartc2350ee2011-10-19 12:28:40 -0700211}
212
213void DNSClient::ReceiveDNSReply(int status, struct hostent *hostent) {
214 if (!running_) {
215 // We can be called during ARES shutdown -- ignore these events.
216 return;
217 }
Ben Chanfad4a0b2012-04-18 15:49:59 -0700218 SLOG(DNS, 3) << "In " << __func__;
Paul Stewartc2350ee2011-10-19 12:28:40 -0700219 running_ = false;
Paul Stewartf582b502012-04-04 21:39:22 -0700220 timeout_closure_.Cancel();
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500221 dispatcher_->PostTask(Bind(&DNSClient::HandleCompletion,
222 weak_ptr_factory_.GetWeakPtr()));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700223
224 if (status == ARES_SUCCESS &&
Ben Chancc225ef2014-09-30 13:26:51 -0700225 hostent != nullptr &&
Paul Stewartc2350ee2011-10-19 12:28:40 -0700226 hostent->h_addrtype == address_.family() &&
Eric Shienbroodc74cf9c2012-03-02 15:00:35 -0500227 static_cast<size_t>(hostent->h_length) ==
228 IPAddress::GetAddressLength(address_.family()) &&
Ben Chancc225ef2014-09-30 13:26:51 -0700229 hostent->h_addr_list != nullptr &&
230 hostent->h_addr_list[0] != nullptr) {
Paul Stewartc2350ee2011-10-19 12:28:40 -0700231 address_ = IPAddress(address_.family(),
232 ByteString(reinterpret_cast<unsigned char *>(
233 hostent->h_addr_list[0]), hostent->h_length));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700234 } else {
235 switch (status) {
236 case ARES_ENODATA:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800237 error_.Populate(Error::kOperationFailed, kErrorNoData);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700238 break;
239 case ARES_EFORMERR:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800240 error_.Populate(Error::kOperationFailed, kErrorFormErr);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700241 break;
242 case ARES_ESERVFAIL:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800243 error_.Populate(Error::kOperationFailed, kErrorServerFail);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700244 break;
245 case ARES_ENOTFOUND:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800246 error_.Populate(Error::kOperationFailed, kErrorNotFound);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700247 break;
248 case ARES_ENOTIMP:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800249 error_.Populate(Error::kOperationFailed, kErrorNotImp);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700250 break;
251 case ARES_EREFUSED:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800252 error_.Populate(Error::kOperationFailed, kErrorRefused);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700253 break;
254 case ARES_EBADQUERY:
255 case ARES_EBADNAME:
256 case ARES_EBADFAMILY:
257 case ARES_EBADRESP:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800258 error_.Populate(Error::kOperationFailed, kErrorBadQuery);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700259 break;
260 case ARES_ECONNREFUSED:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800261 error_.Populate(Error::kOperationFailed, kErrorNetRefused);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700262 break;
263 case ARES_ETIMEOUT:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800264 error_.Populate(Error::kOperationTimeout, kErrorTimedOut);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700265 break;
266 default:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800267 error_.Populate(Error::kOperationFailed, kErrorUnknown);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700268 if (status == ARES_SUCCESS) {
269 LOG(ERROR) << "ARES returned success but hostent was invalid!";
270 } else {
271 LOG(ERROR) << "ARES returned unhandled error status " << status;
272 }
273 break;
274 }
Paul Stewartc2350ee2011-10-19 12:28:40 -0700275 }
276}
277
278void DNSClient::ReceiveDNSReplyCB(void *arg, int status,
279 int /*timeouts*/,
280 struct hostent *hostent) {
281 DNSClient *res = static_cast<DNSClient *>(arg);
282 res->ReceiveDNSReply(status, hostent);
283}
284
285bool DNSClient::RefreshHandles() {
Ben Chane2ee5e02014-09-19 19:29:42 -0700286 map<ares_socket_t, std::shared_ptr<IOHandler>> old_read =
Paul Stewartc2350ee2011-10-19 12:28:40 -0700287 resolver_state_->read_handlers;
Ben Chane2ee5e02014-09-19 19:29:42 -0700288 map<ares_socket_t, std::shared_ptr<IOHandler>> old_write =
Paul Stewartc2350ee2011-10-19 12:28:40 -0700289 resolver_state_->write_handlers;
290
291 resolver_state_->read_handlers.clear();
292 resolver_state_->write_handlers.clear();
293
294 ares_socket_t sockets[ARES_GETSOCK_MAXNUM];
295 int action_bits = ares_->GetSock(resolver_state_->channel, sockets,
Paul Stewartbdb02e62012-02-22 16:24:33 -0800296 ARES_GETSOCK_MAXNUM);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700297
Paul Stewartf582b502012-04-04 21:39:22 -0700298 base::Callback<void(int)> read_callback(
299 Bind(&DNSClient::HandleDNSRead, weak_ptr_factory_.GetWeakPtr()));
300 base::Callback<void(int)> write_callback(
301 Bind(&DNSClient::HandleDNSWrite, weak_ptr_factory_.GetWeakPtr()));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700302 for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
303 if (ARES_GETSOCK_READABLE(action_bits, i)) {
304 if (ContainsKey(old_read, sockets[i])) {
305 resolver_state_->read_handlers[sockets[i]] = old_read[sockets[i]];
306 } else {
307 resolver_state_->read_handlers[sockets[i]] =
Alex Vakulenko8a532292014-06-16 17:18:44 -0700308 std::shared_ptr<IOHandler> (
Paul Stewartc2350ee2011-10-19 12:28:40 -0700309 dispatcher_->CreateReadyHandler(sockets[i],
310 IOHandler::kModeInput,
Paul Stewartf582b502012-04-04 21:39:22 -0700311 read_callback));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700312 }
313 }
314 if (ARES_GETSOCK_WRITABLE(action_bits, i)) {
315 if (ContainsKey(old_write, sockets[i])) {
316 resolver_state_->write_handlers[sockets[i]] = old_write[sockets[i]];
317 } else {
318 resolver_state_->write_handlers[sockets[i]] =
Alex Vakulenko8a532292014-06-16 17:18:44 -0700319 std::shared_ptr<IOHandler> (
Paul Stewartc2350ee2011-10-19 12:28:40 -0700320 dispatcher_->CreateReadyHandler(sockets[i],
321 IOHandler::kModeOutput,
Paul Stewartf582b502012-04-04 21:39:22 -0700322 write_callback));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700323 }
324 }
325 }
326
327 if (!running_) {
Paul Stewartbdb02e62012-02-22 16:24:33 -0800328 // We are here just to clean up socket handles, and the ARES state was
329 // cleaned up during the last call to ares_->ProcessFd().
Paul Stewartc2350ee2011-10-19 12:28:40 -0700330 return false;
331 }
332
333 // Schedule timer event for the earlier of our timeout or one requested by
334 // the resolver library.
335 struct timeval now, elapsed_time, timeout_tv;
Paul Stewarte6927402012-01-23 16:11:30 -0800336 time_->GetTimeMonotonic(&now);
Darin Petkove636c692012-05-31 10:22:17 +0200337 timersub(&now, &resolver_state_->start_time, &elapsed_time);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700338 timeout_tv.tv_sec = timeout_ms_ / 1000;
339 timeout_tv.tv_usec = (timeout_ms_ % 1000) * 1000;
Paul Stewartf582b502012-04-04 21:39:22 -0700340 timeout_closure_.Cancel();
Paul Stewartbdb02e62012-02-22 16:24:33 -0800341
Paul Stewartc2350ee2011-10-19 12:28:40 -0700342 if (timercmp(&elapsed_time, &timeout_tv, >=)) {
343 // There are 3 cases of interest:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800344 // - If we got here from Start(), when we return, Stop() will be
345 // called, so our cleanup task will not run, so we will not have the
346 // side-effect of both invoking the callback and returning False
347 // in Start().
348 // - If we got here from the tail of an IO event, we can't call
349 // Stop() since that will blow away the IOHandler we are running
350 // in. We will perform the cleanup in the posted task below.
351 // - If we got here from a timeout handler, we will perform cleanup
352 // in the posted task.
Paul Stewartc2350ee2011-10-19 12:28:40 -0700353 running_ = false;
Paul Stewartbdb02e62012-02-22 16:24:33 -0800354 error_.Populate(Error::kOperationTimeout, kErrorTimedOut);
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500355 dispatcher_->PostTask(Bind(&DNSClient::HandleCompletion,
356 weak_ptr_factory_.GetWeakPtr()));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700357 return false;
358 } else {
359 struct timeval max, ret_tv;
360 timersub(&timeout_tv, &elapsed_time, &max);
361 struct timeval *tv = ares_->Timeout(resolver_state_->channel,
362 &max, &ret_tv);
Paul Stewartf582b502012-04-04 21:39:22 -0700363 timeout_closure_.Reset(
364 Bind(&DNSClient::HandleTimeout, weak_ptr_factory_.GetWeakPtr()));
365 dispatcher_->PostDelayedTask(timeout_closure_.callback(),
366 tv->tv_sec * 1000 + tv->tv_usec / 1000);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700367 }
368
369 return true;
370}
371
372} // namespace shill