1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/dns/mock_host_resolver.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h"
16 #include "base/threading/platform_thread.h"
17 #include "net/base/ip_endpoint.h"
18 #include "net/base/net_errors.h"
19 #include "net/base/net_util.h"
20 #include "net/base/test_completion_callback.h"
21 #include "net/dns/host_cache.h"
22
23 #if defined(OS_WIN)
24 #include "net/base/winsock_init.h"
25 #endif
26
27 namespace net {
28
29 namespace {
30
31 // Cache size for the MockCachingHostResolver.
32 const unsigned kMaxCacheEntries = 100;
33 // TTL for the successful resolutions. Failures are not cached.
34 const unsigned kCacheEntryTTLSeconds = 60;
35
36 } // namespace
37
ParseAddressList(const std::string & host_list,const std::string & canonical_name,AddressList * addrlist)38 int ParseAddressList(const std::string& host_list,
39 const std::string& canonical_name,
40 AddressList* addrlist) {
41 *addrlist = AddressList();
42 std::vector<std::string> addresses;
43 base::SplitString(host_list, ',', &addresses);
44 addrlist->set_canonical_name(canonical_name);
45 for (size_t index = 0; index < addresses.size(); ++index) {
46 IPAddressNumber ip_number;
47 if (!ParseIPLiteralToNumber(addresses[index], &ip_number)) {
48 LOG(WARNING) << "Not a supported IP literal: " << addresses[index];
49 return ERR_UNEXPECTED;
50 }
51 addrlist->push_back(IPEndPoint(ip_number, -1));
52 }
53 return OK;
54 }
55
56 struct MockHostResolverBase::Request {
Requestnet::MockHostResolverBase::Request57 Request(const RequestInfo& req_info,
58 AddressList* addr,
59 const CompletionCallback& cb)
60 : info(req_info), addresses(addr), callback(cb) {}
61 RequestInfo info;
62 AddressList* addresses;
63 CompletionCallback callback;
64 };
65
~MockHostResolverBase()66 MockHostResolverBase::~MockHostResolverBase() {
67 STLDeleteValues(&requests_);
68 }
69
Resolve(const RequestInfo & info,RequestPriority priority,AddressList * addresses,const CompletionCallback & callback,RequestHandle * handle,const BoundNetLog & net_log)70 int MockHostResolverBase::Resolve(const RequestInfo& info,
71 RequestPriority priority,
72 AddressList* addresses,
73 const CompletionCallback& callback,
74 RequestHandle* handle,
75 const BoundNetLog& net_log) {
76 DCHECK(CalledOnValidThread());
77 last_request_priority_ = priority;
78 num_resolve_++;
79 size_t id = next_request_id_++;
80 int rv = ResolveFromIPLiteralOrCache(info, addresses);
81 if (rv != ERR_DNS_CACHE_MISS) {
82 return rv;
83 }
84 if (synchronous_mode_) {
85 return ResolveProc(id, info, addresses);
86 }
87 // Store the request for asynchronous resolution
88 Request* req = new Request(info, addresses, callback);
89 requests_[id] = req;
90 if (handle)
91 *handle = reinterpret_cast<RequestHandle>(id);
92
93 if (!ondemand_mode_) {
94 base::MessageLoop::current()->PostTask(
95 FROM_HERE,
96 base::Bind(&MockHostResolverBase::ResolveNow, AsWeakPtr(), id));
97 }
98
99 return ERR_IO_PENDING;
100 }
101
ResolveFromCache(const RequestInfo & info,AddressList * addresses,const BoundNetLog & net_log)102 int MockHostResolverBase::ResolveFromCache(const RequestInfo& info,
103 AddressList* addresses,
104 const BoundNetLog& net_log) {
105 num_resolve_from_cache_++;
106 DCHECK(CalledOnValidThread());
107 next_request_id_++;
108 int rv = ResolveFromIPLiteralOrCache(info, addresses);
109 return rv;
110 }
111
CancelRequest(RequestHandle handle)112 void MockHostResolverBase::CancelRequest(RequestHandle handle) {
113 DCHECK(CalledOnValidThread());
114 size_t id = reinterpret_cast<size_t>(handle);
115 RequestMap::iterator it = requests_.find(id);
116 if (it != requests_.end()) {
117 scoped_ptr<Request> req(it->second);
118 requests_.erase(it);
119 } else {
120 NOTREACHED() << "CancelRequest must NOT be called after request is "
121 "complete or canceled.";
122 }
123 }
124
GetHostCache()125 HostCache* MockHostResolverBase::GetHostCache() {
126 return cache_.get();
127 }
128
ResolveAllPending()129 void MockHostResolverBase::ResolveAllPending() {
130 DCHECK(CalledOnValidThread());
131 DCHECK(ondemand_mode_);
132 for (RequestMap::iterator i = requests_.begin(); i != requests_.end(); ++i) {
133 base::MessageLoop::current()->PostTask(
134 FROM_HERE,
135 base::Bind(&MockHostResolverBase::ResolveNow, AsWeakPtr(), i->first));
136 }
137 }
138
139 // start id from 1 to distinguish from NULL RequestHandle
MockHostResolverBase(bool use_caching)140 MockHostResolverBase::MockHostResolverBase(bool use_caching)
141 : last_request_priority_(DEFAULT_PRIORITY),
142 synchronous_mode_(false),
143 ondemand_mode_(false),
144 next_request_id_(1),
145 num_resolve_(0),
146 num_resolve_from_cache_(0) {
147 rules_ = CreateCatchAllHostResolverProc();
148
149 if (use_caching) {
150 cache_.reset(new HostCache(kMaxCacheEntries));
151 }
152 }
153
ResolveFromIPLiteralOrCache(const RequestInfo & info,AddressList * addresses)154 int MockHostResolverBase::ResolveFromIPLiteralOrCache(const RequestInfo& info,
155 AddressList* addresses) {
156 IPAddressNumber ip;
157 if (ParseIPLiteralToNumber(info.hostname(), &ip)) {
158 // This matches the behavior HostResolverImpl.
159 if (info.address_family() != ADDRESS_FAMILY_UNSPECIFIED &&
160 info.address_family() != GetAddressFamily(ip)) {
161 return ERR_NAME_NOT_RESOLVED;
162 }
163
164 *addresses = AddressList::CreateFromIPAddress(ip, info.port());
165 if (info.host_resolver_flags() & HOST_RESOLVER_CANONNAME)
166 addresses->SetDefaultCanonicalName();
167 return OK;
168 }
169 int rv = ERR_DNS_CACHE_MISS;
170 if (cache_.get() && info.allow_cached_response()) {
171 HostCache::Key key(info.hostname(),
172 info.address_family(),
173 info.host_resolver_flags());
174 const HostCache::Entry* entry = cache_->Lookup(key, base::TimeTicks::Now());
175 if (entry) {
176 rv = entry->error;
177 if (rv == OK)
178 *addresses = AddressList::CopyWithPort(entry->addrlist, info.port());
179 }
180 }
181 return rv;
182 }
183
ResolveProc(size_t id,const RequestInfo & info,AddressList * addresses)184 int MockHostResolverBase::ResolveProc(size_t id,
185 const RequestInfo& info,
186 AddressList* addresses) {
187 AddressList addr;
188 int rv = rules_->Resolve(info.hostname(),
189 info.address_family(),
190 info.host_resolver_flags(),
191 &addr,
192 NULL);
193 if (cache_.get()) {
194 HostCache::Key key(info.hostname(),
195 info.address_family(),
196 info.host_resolver_flags());
197 // Storing a failure with TTL 0 so that it overwrites previous value.
198 base::TimeDelta ttl;
199 if (rv == OK)
200 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds);
201 cache_->Set(key, HostCache::Entry(rv, addr), base::TimeTicks::Now(), ttl);
202 }
203 if (rv == OK)
204 *addresses = AddressList::CopyWithPort(addr, info.port());
205 return rv;
206 }
207
ResolveNow(size_t id)208 void MockHostResolverBase::ResolveNow(size_t id) {
209 RequestMap::iterator it = requests_.find(id);
210 if (it == requests_.end())
211 return; // was canceled
212
213 scoped_ptr<Request> req(it->second);
214 requests_.erase(it);
215 int rv = ResolveProc(id, req->info, req->addresses);
216 if (!req->callback.is_null())
217 req->callback.Run(rv);
218 }
219
220 //-----------------------------------------------------------------------------
221
222 struct RuleBasedHostResolverProc::Rule {
223 enum ResolverType {
224 kResolverTypeFail,
225 kResolverTypeSystem,
226 kResolverTypeIPLiteral,
227 };
228
229 ResolverType resolver_type;
230 std::string host_pattern;
231 AddressFamily address_family;
232 HostResolverFlags host_resolver_flags;
233 std::string replacement;
234 std::string canonical_name;
235 int latency_ms; // In milliseconds.
236
Rulenet::RuleBasedHostResolverProc::Rule237 Rule(ResolverType resolver_type,
238 const std::string& host_pattern,
239 AddressFamily address_family,
240 HostResolverFlags host_resolver_flags,
241 const std::string& replacement,
242 const std::string& canonical_name,
243 int latency_ms)
244 : resolver_type(resolver_type),
245 host_pattern(host_pattern),
246 address_family(address_family),
247 host_resolver_flags(host_resolver_flags),
248 replacement(replacement),
249 canonical_name(canonical_name),
250 latency_ms(latency_ms) {}
251 };
252
RuleBasedHostResolverProc(HostResolverProc * previous)253 RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous)
254 : HostResolverProc(previous) {
255 }
256
AddRule(const std::string & host_pattern,const std::string & replacement)257 void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern,
258 const std::string& replacement) {
259 AddRuleForAddressFamily(host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
260 replacement);
261 }
262
AddRuleForAddressFamily(const std::string & host_pattern,AddressFamily address_family,const std::string & replacement)263 void RuleBasedHostResolverProc::AddRuleForAddressFamily(
264 const std::string& host_pattern,
265 AddressFamily address_family,
266 const std::string& replacement) {
267 DCHECK(!replacement.empty());
268 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
269 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
270 Rule rule(Rule::kResolverTypeSystem,
271 host_pattern,
272 address_family,
273 flags,
274 replacement,
275 std::string(),
276 0);
277 rules_.push_back(rule);
278 }
279
AddIPLiteralRule(const std::string & host_pattern,const std::string & ip_literal,const std::string & canonical_name)280 void RuleBasedHostResolverProc::AddIPLiteralRule(
281 const std::string& host_pattern,
282 const std::string& ip_literal,
283 const std::string& canonical_name) {
284 // Literals are always resolved to themselves by HostResolverImpl,
285 // consequently we do not support remapping them.
286 IPAddressNumber ip_number;
287 DCHECK(!ParseIPLiteralToNumber(host_pattern, &ip_number));
288 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
289 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
290 if (!canonical_name.empty())
291 flags |= HOST_RESOLVER_CANONNAME;
292 Rule rule(Rule::kResolverTypeIPLiteral, host_pattern,
293 ADDRESS_FAMILY_UNSPECIFIED, flags, ip_literal, canonical_name,
294 0);
295 rules_.push_back(rule);
296 }
297
AddRuleWithLatency(const std::string & host_pattern,const std::string & replacement,int latency_ms)298 void RuleBasedHostResolverProc::AddRuleWithLatency(
299 const std::string& host_pattern,
300 const std::string& replacement,
301 int latency_ms) {
302 DCHECK(!replacement.empty());
303 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
304 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
305 Rule rule(Rule::kResolverTypeSystem,
306 host_pattern,
307 ADDRESS_FAMILY_UNSPECIFIED,
308 flags,
309 replacement,
310 std::string(),
311 latency_ms);
312 rules_.push_back(rule);
313 }
314
AllowDirectLookup(const std::string & host_pattern)315 void RuleBasedHostResolverProc::AllowDirectLookup(
316 const std::string& host_pattern) {
317 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
318 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
319 Rule rule(Rule::kResolverTypeSystem,
320 host_pattern,
321 ADDRESS_FAMILY_UNSPECIFIED,
322 flags,
323 std::string(),
324 std::string(),
325 0);
326 rules_.push_back(rule);
327 }
328
AddSimulatedFailure(const std::string & host_pattern)329 void RuleBasedHostResolverProc::AddSimulatedFailure(
330 const std::string& host_pattern) {
331 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
332 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
333 Rule rule(Rule::kResolverTypeFail,
334 host_pattern,
335 ADDRESS_FAMILY_UNSPECIFIED,
336 flags,
337 std::string(),
338 std::string(),
339 0);
340 rules_.push_back(rule);
341 }
342
ClearRules()343 void RuleBasedHostResolverProc::ClearRules() {
344 rules_.clear();
345 }
346
Resolve(const std::string & host,AddressFamily address_family,HostResolverFlags host_resolver_flags,AddressList * addrlist,int * os_error)347 int RuleBasedHostResolverProc::Resolve(const std::string& host,
348 AddressFamily address_family,
349 HostResolverFlags host_resolver_flags,
350 AddressList* addrlist,
351 int* os_error) {
352 RuleList::iterator r;
353 for (r = rules_.begin(); r != rules_.end(); ++r) {
354 bool matches_address_family =
355 r->address_family == ADDRESS_FAMILY_UNSPECIFIED ||
356 r->address_family == address_family;
357 // Ignore HOST_RESOLVER_SYSTEM_ONLY, since it should have no impact on
358 // whether a rule matches.
359 HostResolverFlags flags = host_resolver_flags & ~HOST_RESOLVER_SYSTEM_ONLY;
360 // Flags match if all of the bitflags in host_resolver_flags are enabled
361 // in the rule's host_resolver_flags. However, the rule may have additional
362 // flags specified, in which case the flags should still be considered a
363 // match.
364 bool matches_flags = (r->host_resolver_flags & flags) == flags;
365 if (matches_flags && matches_address_family &&
366 MatchPattern(host, r->host_pattern)) {
367 if (r->latency_ms != 0) {
368 base::PlatformThread::Sleep(
369 base::TimeDelta::FromMilliseconds(r->latency_ms));
370 }
371
372 // Remap to a new host.
373 const std::string& effective_host =
374 r->replacement.empty() ? host : r->replacement;
375
376 // Apply the resolving function to the remapped hostname.
377 switch (r->resolver_type) {
378 case Rule::kResolverTypeFail:
379 return ERR_NAME_NOT_RESOLVED;
380 case Rule::kResolverTypeSystem:
381 #if defined(OS_WIN)
382 net::EnsureWinsockInit();
383 #endif
384 return SystemHostResolverCall(effective_host,
385 address_family,
386 host_resolver_flags,
387 addrlist, os_error);
388 case Rule::kResolverTypeIPLiteral:
389 return ParseAddressList(effective_host,
390 r->canonical_name,
391 addrlist);
392 default:
393 NOTREACHED();
394 return ERR_UNEXPECTED;
395 }
396 }
397 }
398 return ResolveUsingPrevious(host, address_family,
399 host_resolver_flags, addrlist, os_error);
400 }
401
~RuleBasedHostResolverProc()402 RuleBasedHostResolverProc::~RuleBasedHostResolverProc() {
403 }
404
CreateCatchAllHostResolverProc()405 RuleBasedHostResolverProc* CreateCatchAllHostResolverProc() {
406 RuleBasedHostResolverProc* catchall = new RuleBasedHostResolverProc(NULL);
407 catchall->AddIPLiteralRule("*", "127.0.0.1", "localhost");
408
409 // Next add a rules-based layer the use controls.
410 return new RuleBasedHostResolverProc(catchall);
411 }
412
413 //-----------------------------------------------------------------------------
414
Resolve(const RequestInfo & info,RequestPriority priority,AddressList * addresses,const CompletionCallback & callback,RequestHandle * out_req,const BoundNetLog & net_log)415 int HangingHostResolver::Resolve(const RequestInfo& info,
416 RequestPriority priority,
417 AddressList* addresses,
418 const CompletionCallback& callback,
419 RequestHandle* out_req,
420 const BoundNetLog& net_log) {
421 return ERR_IO_PENDING;
422 }
423
ResolveFromCache(const RequestInfo & info,AddressList * addresses,const BoundNetLog & net_log)424 int HangingHostResolver::ResolveFromCache(const RequestInfo& info,
425 AddressList* addresses,
426 const BoundNetLog& net_log) {
427 return ERR_DNS_CACHE_MISS;
428 }
429
430 //-----------------------------------------------------------------------------
431
ScopedDefaultHostResolverProc()432 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc() {}
433
ScopedDefaultHostResolverProc(HostResolverProc * proc)434 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc(
435 HostResolverProc* proc) {
436 Init(proc);
437 }
438
~ScopedDefaultHostResolverProc()439 ScopedDefaultHostResolverProc::~ScopedDefaultHostResolverProc() {
440 HostResolverProc* old_proc =
441 HostResolverProc::SetDefault(previous_proc_.get());
442 // The lifetimes of multiple instances must be nested.
443 CHECK_EQ(old_proc, current_proc_.get());
444 }
445
Init(HostResolverProc * proc)446 void ScopedDefaultHostResolverProc::Init(HostResolverProc* proc) {
447 current_proc_ = proc;
448 previous_proc_ = HostResolverProc::SetDefault(current_proc_.get());
449 current_proc_->SetLastProc(previous_proc_.get());
450 }
451
452 } // namespace net
453