blob: 4e3904584f333c0bdfd27b636ad8490be12233e7 [file] [log] [blame]
Peter Qiuc0beca52015-09-03 11:25:46 -07001//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Paul Stewartc2350ee2011-10-19 12:28:40 -070016
17#include "shill/dns_client.h"
18
19#include <arpa/inet.h>
20#include <netdb.h>
21#include <netinet/in.h>
22#include <sys/socket.h>
23
24#include <map>
Alex Vakulenkoa41ab512014-07-23 14:24:23 -070025#include <memory>
Paul Stewartc2350ee2011-10-19 12:28:40 -070026#include <set>
27#include <string>
Paul Stewartc2350ee2011-10-19 12:28:40 -070028#include <vector>
29
Eric Shienbrood3e20a232012-02-16 11:35:56 -050030#include <base/bind.h>
31#include <base/bind_helpers.h>
32#include <base/stl_util.h>
Ben Chana0ddf462014-02-06 11:32:42 -080033#include <base/strings/string_number_conversions.h>
Paul Stewartc2350ee2011-10-19 12:28:40 -070034
Christopher Wileyb691efd2012-08-09 13:51:51 -070035#include "shill/logging.h"
Peter Qiu8d6b5972014-10-28 15:33:34 -070036#include "shill/net/shill_time.h"
Darin Petkov89593a92012-02-21 10:59:48 +010037#include "shill/shill_ares.h"
Paul Stewartc2350ee2011-10-19 12:28:40 -070038
Eric Shienbrood3e20a232012-02-16 11:35:56 -050039using base::Bind;
40using base::Unretained;
Paul Stewartc2350ee2011-10-19 12:28:40 -070041using std::map;
42using std::set;
43using std::string;
44using std::vector;
45
46namespace shill {
47
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -070048namespace Logging {
49static auto kModuleLogScope = ScopeLogger::kDNS;
Paul Stewarta794cd62015-06-16 13:13:10 -070050static string ObjectID(DNSClient* d) { return d->interface_name(); }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -070051}
52
Paul Stewartc2350ee2011-10-19 12:28:40 -070053const char DNSClient::kErrorNoData[] = "The query response contains no answers";
54const char DNSClient::kErrorFormErr[] = "The server says the query is bad";
55const char DNSClient::kErrorServerFail[] = "The server says it had a failure";
56const char DNSClient::kErrorNotFound[] = "The queried-for domain was not found";
57const char DNSClient::kErrorNotImp[] = "The server doesn't implement operation";
58const char DNSClient::kErrorRefused[] = "The server replied, refused the query";
59const char DNSClient::kErrorBadQuery[] = "Locally we could not format a query";
60const char DNSClient::kErrorNetRefused[] = "The network connection was refused";
61const char DNSClient::kErrorTimedOut[] = "The network connection was timed out";
62const char DNSClient::kErrorUnknown[] = "DNS Resolver unknown internal error";
63
Peter Qiuf3a8f902014-08-20 10:05:42 -070064const int DNSClient::kDefaultDNSPort = 53;
65
Paul Stewartc2350ee2011-10-19 12:28:40 -070066// Private to the implementation of resolver so callers don't include ares.h
67struct DNSClientState {
Ben Chancc225ef2014-09-30 13:26:51 -070068 DNSClientState() : channel(nullptr), start_time{} {}
Darin Petkove636c692012-05-31 10:22:17 +020069
Paul Stewartc2350ee2011-10-19 12:28:40 -070070 ares_channel channel;
Ben Chane2ee5e02014-09-19 19:29:42 -070071 map<ares_socket_t, std::shared_ptr<IOHandler>> read_handlers;
72 map<ares_socket_t, std::shared_ptr<IOHandler>> write_handlers;
Darin Petkove636c692012-05-31 10:22:17 +020073 struct timeval start_time;
Paul Stewartc2350ee2011-10-19 12:28:40 -070074};
75
76DNSClient::DNSClient(IPAddress::Family family,
Paul Stewarta794cd62015-06-16 13:13:10 -070077 const string& interface_name,
78 const vector<string>& dns_servers,
Paul Stewartc2350ee2011-10-19 12:28:40 -070079 int timeout_ms,
Paul Stewarta794cd62015-06-16 13:13:10 -070080 EventDispatcher* dispatcher,
81 const ClientCallback& callback)
Paul Stewartc2350ee2011-10-19 12:28:40 -070082 : address_(IPAddress(family)),
83 interface_name_(interface_name),
84 dns_servers_(dns_servers),
85 dispatcher_(dispatcher),
86 callback_(callback),
87 timeout_ms_(timeout_ms),
88 running_(false),
Eric Shienbrood3e20a232012-02-16 11:35:56 -050089 weak_ptr_factory_(this),
Paul Stewartc2350ee2011-10-19 12:28:40 -070090 ares_(Ares::GetInstance()),
91 time_(Time::GetInstance()) {}
92
93DNSClient::~DNSClient() {
94 Stop();
95}
96
Paul Stewarta794cd62015-06-16 13:13:10 -070097bool DNSClient::Start(const string& hostname, Error* error) {
Paul Stewartc2350ee2011-10-19 12:28:40 -070098 if (running_) {
Paul Stewart34f424e2015-01-16 15:30:20 -080099 Error::PopulateAndLog(FROM_HERE, error, Error::kInProgress,
Paul Stewartbdb02e62012-02-22 16:24:33 -0800100 "Only one DNS request is allowed at a time");
Paul Stewartc2350ee2011-10-19 12:28:40 -0700101 return false;
102 }
103
104 if (!resolver_state_.get()) {
105 struct ares_options options;
106 memset(&options, 0, sizeof(options));
Peter Qiuf3a8f902014-08-20 10:05:42 -0700107 options.timeout = timeout_ms_;
Paul Stewartc2350ee2011-10-19 12:28:40 -0700108
Peter Qiuf3a8f902014-08-20 10:05:42 -0700109 if (dns_servers_.empty()) {
Paul Stewart34f424e2015-01-16 15:30:20 -0800110 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
Paul Stewartbdb02e62012-02-22 16:24:33 -0800111 "No valid DNS server addresses");
Paul Stewartc2350ee2011-10-19 12:28:40 -0700112 return false;
113 }
114
Paul Stewartc2350ee2011-10-19 12:28:40 -0700115 resolver_state_.reset(new DNSClientState);
116 int status = ares_->InitOptions(&resolver_state_->channel,
117 &options,
Peter Qiuf3a8f902014-08-20 10:05:42 -0700118 ARES_OPT_TIMEOUTMS);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700119 if (status != ARES_SUCCESS) {
Paul Stewart34f424e2015-01-16 15:30:20 -0800120 Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
Paul Stewartbdb02e62012-02-22 16:24:33 -0800121 "ARES initialization returns error code: " +
122 base::IntToString(status));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700123 resolver_state_.reset();
124 return false;
125 }
126
Peter Qiuf3a8f902014-08-20 10:05:42 -0700127 // Format DNS server addresses string as "host:port[,host:port...]" to be
128 // used in call to ares_set_servers_csv for setting DNS server addresses.
129 // There is a bug in ares library when parsing IPv6 addresses, where it
130 // always assumes the port number are specified when address contains ":".
131 // So when IPv6 address are given without port number as "xx:xx:xx::yy",the
132 // parser would parse the address as "xx:xx:xx:" and port number as "yy".
133 // To work around this bug, port number are added to each address.
134 //
135 // Alternatively, we can use ares_set_servers instead, where we would
136 // explicitly construct a link list of ares_addr_node.
137 string server_addresses;
138 bool first = true;
Paul Stewarta794cd62015-06-16 13:13:10 -0700139 for (const auto& ip : dns_servers_) {
Peter Qiuf3a8f902014-08-20 10:05:42 -0700140 if (!first) {
141 server_addresses += ",";
142 } else {
143 first = false;
144 }
145 server_addresses += (ip + ":" + base::IntToString(kDefaultDNSPort));
146 }
147 status = ares_->SetServersCsv(resolver_state_->channel,
148 server_addresses.c_str());
149 if (status != ARES_SUCCESS) {
Paul Stewart34f424e2015-01-16 15:30:20 -0800150 Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
Peter Qiuf3a8f902014-08-20 10:05:42 -0700151 "ARES set DNS servers error code: " +
152 base::IntToString(status));
153 resolver_state_.reset();
154 return false;
155 }
156
Paul Stewartc2350ee2011-10-19 12:28:40 -0700157 ares_->SetLocalDev(resolver_state_->channel, interface_name_.c_str());
158 }
159
160 running_ = true;
Darin Petkove636c692012-05-31 10:22:17 +0200161 time_->GetTimeMonotonic(&resolver_state_->start_time);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700162 ares_->GetHostByName(resolver_state_->channel, hostname.c_str(),
163 address_.family(), ReceiveDNSReplyCB, this);
164
165 if (!RefreshHandles()) {
166 LOG(ERROR) << "Impossibly short timeout.";
Paul Stewartbdb02e62012-02-22 16:24:33 -0800167 error->CopyFrom(error_);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700168 Stop();
169 return false;
170 }
171
172 return true;
173}
174
175void DNSClient::Stop() {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700176 SLOG(this, 3) << "In " << __func__;
Paul Stewartc2350ee2011-10-19 12:28:40 -0700177 if (!resolver_state_.get()) {
178 return;
179 }
180
181 running_ = false;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500182 weak_ptr_factory_.InvalidateWeakPtrs();
Paul Stewartbdb02e62012-02-22 16:24:33 -0800183 error_.Reset();
184 address_.SetAddressToDefault();
Paul Stewartc2350ee2011-10-19 12:28:40 -0700185 ares_->Destroy(resolver_state_->channel);
186 resolver_state_.reset();
187}
188
Prathmesh Prabhu3e452f82013-04-10 16:31:44 -0700189bool DNSClient::IsActive() const {
190 return running_;
191}
192
Paul Stewartbdb02e62012-02-22 16:24:33 -0800193// We delay our call to completion so that we exit all IOHandlers, and
194// can clean up all of our local state before calling the callback, or
195// during the process of the execution of the callee (which is free to
196// call our destructor safely).
197void DNSClient::HandleCompletion() {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700198 SLOG(this, 3) << "In " << __func__;
Paul Stewartbdb02e62012-02-22 16:24:33 -0800199 Error error;
200 error.CopyFrom(error_);
201 IPAddress address(address_);
202 if (!error.IsSuccess()) {
203 // If the DNS request did not succeed, do not trust it for future
204 // attempts.
205 Stop();
206 } else {
207 // Prepare our state for the next request without destroying the
208 // current ARES state.
209 error_.Reset();
210 address_.SetAddressToDefault();
211 }
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500212 callback_.Run(error, address);
Paul Stewartbdb02e62012-02-22 16:24:33 -0800213}
214
Paul Stewartc2350ee2011-10-19 12:28:40 -0700215void DNSClient::HandleDNSRead(int fd) {
216 ares_->ProcessFd(resolver_state_->channel, fd, ARES_SOCKET_BAD);
217 RefreshHandles();
218}
219
220void DNSClient::HandleDNSWrite(int fd) {
221 ares_->ProcessFd(resolver_state_->channel, ARES_SOCKET_BAD, fd);
222 RefreshHandles();
223}
224
225void DNSClient::HandleTimeout() {
226 ares_->ProcessFd(resolver_state_->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
Paul Stewartbdb02e62012-02-22 16:24:33 -0800227 RefreshHandles();
Paul Stewartc2350ee2011-10-19 12:28:40 -0700228}
229
Paul Stewarta794cd62015-06-16 13:13:10 -0700230void DNSClient::ReceiveDNSReply(int status, struct hostent* hostent) {
Paul Stewartc2350ee2011-10-19 12:28:40 -0700231 if (!running_) {
232 // We can be called during ARES shutdown -- ignore these events.
233 return;
234 }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700235 SLOG(this, 3) << "In " << __func__;
Paul Stewartc2350ee2011-10-19 12:28:40 -0700236 running_ = false;
Paul Stewartf582b502012-04-04 21:39:22 -0700237 timeout_closure_.Cancel();
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500238 dispatcher_->PostTask(Bind(&DNSClient::HandleCompletion,
239 weak_ptr_factory_.GetWeakPtr()));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700240
241 if (status == ARES_SUCCESS &&
Ben Chancc225ef2014-09-30 13:26:51 -0700242 hostent != nullptr &&
Paul Stewartc2350ee2011-10-19 12:28:40 -0700243 hostent->h_addrtype == address_.family() &&
Eric Shienbroodc74cf9c2012-03-02 15:00:35 -0500244 static_cast<size_t>(hostent->h_length) ==
245 IPAddress::GetAddressLength(address_.family()) &&
Ben Chancc225ef2014-09-30 13:26:51 -0700246 hostent->h_addr_list != nullptr &&
247 hostent->h_addr_list[0] != nullptr) {
Paul Stewartc2350ee2011-10-19 12:28:40 -0700248 address_ = IPAddress(address_.family(),
Paul Stewarta794cd62015-06-16 13:13:10 -0700249 ByteString(reinterpret_cast<unsigned char*>(
Paul Stewartc2350ee2011-10-19 12:28:40 -0700250 hostent->h_addr_list[0]), hostent->h_length));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700251 } else {
252 switch (status) {
253 case ARES_ENODATA:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800254 error_.Populate(Error::kOperationFailed, kErrorNoData);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700255 break;
256 case ARES_EFORMERR:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800257 error_.Populate(Error::kOperationFailed, kErrorFormErr);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700258 break;
259 case ARES_ESERVFAIL:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800260 error_.Populate(Error::kOperationFailed, kErrorServerFail);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700261 break;
262 case ARES_ENOTFOUND:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800263 error_.Populate(Error::kOperationFailed, kErrorNotFound);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700264 break;
265 case ARES_ENOTIMP:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800266 error_.Populate(Error::kOperationFailed, kErrorNotImp);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700267 break;
268 case ARES_EREFUSED:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800269 error_.Populate(Error::kOperationFailed, kErrorRefused);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700270 break;
271 case ARES_EBADQUERY:
272 case ARES_EBADNAME:
273 case ARES_EBADFAMILY:
274 case ARES_EBADRESP:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800275 error_.Populate(Error::kOperationFailed, kErrorBadQuery);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700276 break;
277 case ARES_ECONNREFUSED:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800278 error_.Populate(Error::kOperationFailed, kErrorNetRefused);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700279 break;
280 case ARES_ETIMEOUT:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800281 error_.Populate(Error::kOperationTimeout, kErrorTimedOut);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700282 break;
283 default:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800284 error_.Populate(Error::kOperationFailed, kErrorUnknown);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700285 if (status == ARES_SUCCESS) {
286 LOG(ERROR) << "ARES returned success but hostent was invalid!";
287 } else {
288 LOG(ERROR) << "ARES returned unhandled error status " << status;
289 }
290 break;
291 }
Paul Stewartc2350ee2011-10-19 12:28:40 -0700292 }
293}
294
Paul Stewarta794cd62015-06-16 13:13:10 -0700295void DNSClient::ReceiveDNSReplyCB(void* arg, int status,
Paul Stewartc2350ee2011-10-19 12:28:40 -0700296 int /*timeouts*/,
Paul Stewarta794cd62015-06-16 13:13:10 -0700297 struct hostent* hostent) {
298 DNSClient* res = static_cast<DNSClient*>(arg);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700299 res->ReceiveDNSReply(status, hostent);
300}
301
302bool DNSClient::RefreshHandles() {
Ben Chane2ee5e02014-09-19 19:29:42 -0700303 map<ares_socket_t, std::shared_ptr<IOHandler>> old_read =
Paul Stewartc2350ee2011-10-19 12:28:40 -0700304 resolver_state_->read_handlers;
Ben Chane2ee5e02014-09-19 19:29:42 -0700305 map<ares_socket_t, std::shared_ptr<IOHandler>> old_write =
Paul Stewartc2350ee2011-10-19 12:28:40 -0700306 resolver_state_->write_handlers;
307
308 resolver_state_->read_handlers.clear();
309 resolver_state_->write_handlers.clear();
310
311 ares_socket_t sockets[ARES_GETSOCK_MAXNUM];
312 int action_bits = ares_->GetSock(resolver_state_->channel, sockets,
Paul Stewartbdb02e62012-02-22 16:24:33 -0800313 ARES_GETSOCK_MAXNUM);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700314
Paul Stewartf582b502012-04-04 21:39:22 -0700315 base::Callback<void(int)> read_callback(
316 Bind(&DNSClient::HandleDNSRead, weak_ptr_factory_.GetWeakPtr()));
317 base::Callback<void(int)> write_callback(
318 Bind(&DNSClient::HandleDNSWrite, weak_ptr_factory_.GetWeakPtr()));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700319 for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
320 if (ARES_GETSOCK_READABLE(action_bits, i)) {
321 if (ContainsKey(old_read, sockets[i])) {
322 resolver_state_->read_handlers[sockets[i]] = old_read[sockets[i]];
323 } else {
324 resolver_state_->read_handlers[sockets[i]] =
Alex Vakulenko8a532292014-06-16 17:18:44 -0700325 std::shared_ptr<IOHandler> (
Paul Stewartc2350ee2011-10-19 12:28:40 -0700326 dispatcher_->CreateReadyHandler(sockets[i],
327 IOHandler::kModeInput,
Paul Stewartf582b502012-04-04 21:39:22 -0700328 read_callback));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700329 }
330 }
331 if (ARES_GETSOCK_WRITABLE(action_bits, i)) {
332 if (ContainsKey(old_write, sockets[i])) {
333 resolver_state_->write_handlers[sockets[i]] = old_write[sockets[i]];
334 } else {
335 resolver_state_->write_handlers[sockets[i]] =
Alex Vakulenko8a532292014-06-16 17:18:44 -0700336 std::shared_ptr<IOHandler> (
Paul Stewartc2350ee2011-10-19 12:28:40 -0700337 dispatcher_->CreateReadyHandler(sockets[i],
338 IOHandler::kModeOutput,
Paul Stewartf582b502012-04-04 21:39:22 -0700339 write_callback));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700340 }
341 }
342 }
343
344 if (!running_) {
Paul Stewartbdb02e62012-02-22 16:24:33 -0800345 // We are here just to clean up socket handles, and the ARES state was
346 // cleaned up during the last call to ares_->ProcessFd().
Paul Stewartc2350ee2011-10-19 12:28:40 -0700347 return false;
348 }
349
350 // Schedule timer event for the earlier of our timeout or one requested by
351 // the resolver library.
352 struct timeval now, elapsed_time, timeout_tv;
Paul Stewarte6927402012-01-23 16:11:30 -0800353 time_->GetTimeMonotonic(&now);
Darin Petkove636c692012-05-31 10:22:17 +0200354 timersub(&now, &resolver_state_->start_time, &elapsed_time);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700355 timeout_tv.tv_sec = timeout_ms_ / 1000;
356 timeout_tv.tv_usec = (timeout_ms_ % 1000) * 1000;
Paul Stewartf582b502012-04-04 21:39:22 -0700357 timeout_closure_.Cancel();
Paul Stewartbdb02e62012-02-22 16:24:33 -0800358
Paul Stewartc2350ee2011-10-19 12:28:40 -0700359 if (timercmp(&elapsed_time, &timeout_tv, >=)) {
360 // There are 3 cases of interest:
Paul Stewartbdb02e62012-02-22 16:24:33 -0800361 // - If we got here from Start(), when we return, Stop() will be
362 // called, so our cleanup task will not run, so we will not have the
363 // side-effect of both invoking the callback and returning False
364 // in Start().
365 // - If we got here from the tail of an IO event, we can't call
366 // Stop() since that will blow away the IOHandler we are running
367 // in. We will perform the cleanup in the posted task below.
368 // - If we got here from a timeout handler, we will perform cleanup
369 // in the posted task.
Paul Stewartc2350ee2011-10-19 12:28:40 -0700370 running_ = false;
Paul Stewartbdb02e62012-02-22 16:24:33 -0800371 error_.Populate(Error::kOperationTimeout, kErrorTimedOut);
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500372 dispatcher_->PostTask(Bind(&DNSClient::HandleCompletion,
373 weak_ptr_factory_.GetWeakPtr()));
Paul Stewartc2350ee2011-10-19 12:28:40 -0700374 return false;
375 } else {
376 struct timeval max, ret_tv;
377 timersub(&timeout_tv, &elapsed_time, &max);
Paul Stewarta794cd62015-06-16 13:13:10 -0700378 struct timeval* tv = ares_->Timeout(resolver_state_->channel,
Paul Stewartc2350ee2011-10-19 12:28:40 -0700379 &max, &ret_tv);
Paul Stewartf582b502012-04-04 21:39:22 -0700380 timeout_closure_.Reset(
381 Bind(&DNSClient::HandleTimeout, weak_ptr_factory_.GetWeakPtr()));
382 dispatcher_->PostDelayedTask(timeout_closure_.callback(),
383 tv->tv_sec * 1000 + tv->tv_usec / 1000);
Paul Stewartc2350ee2011-10-19 12:28:40 -0700384 }
385
386 return true;
387}
388
389} // namespace shill