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