1 // Copyright (c) 2011 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/base/mock_host_resolver.h"
6
7 #include "base/memory/ref_counted.h"
8 #include "base/string_split.h"
9 #include "base/string_util.h"
10 #include "base/threading/platform_thread.h"
11 #include "net/base/net_errors.h"
12 #include "net/base/net_util.h"
13 #include "net/base/sys_addrinfo.h"
14
15 namespace net {
16
17 namespace {
18
do_strdup(const char * src)19 char* do_strdup(const char* src) {
20 #if defined(OS_WIN)
21 return _strdup(src);
22 #else
23 return strdup(src);
24 #endif
25 }
26
27 // Fills |*addrlist| with a socket address for |host_list| which should be a
28 // comma-separated list of IPv4 or IPv6 literal(s) without enclosing brackets.
29 // If |canonical_name| is non-empty it is used as the DNS canonical name for
30 // the host. Returns OK on success, ERR_UNEXPECTED otherwise.
CreateIPAddressList(const std::string & host_list,const std::string & canonical_name,AddressList * addrlist)31 int CreateIPAddressList(const std::string& host_list,
32 const std::string& canonical_name,
33 AddressList* addrlist) {
34 *addrlist = AddressList();
35 std::vector<std::string> addresses;
36 base::SplitString(host_list, ',', &addresses);
37 for (size_t index = 0; index < addresses.size(); ++index) {
38 IPAddressNumber ip_number;
39 if (!ParseIPLiteralToNumber(addresses[index], &ip_number)) {
40 LOG(WARNING) << "Not a supported IP literal: " << addresses[index];
41 return ERR_UNEXPECTED;
42 }
43
44 AddressList result(ip_number, -1, false);
45 struct addrinfo* ai = const_cast<struct addrinfo*>(result.head());
46 if (index == 0)
47 ai->ai_canonname = do_strdup(canonical_name.c_str());
48 if (!addrlist->head())
49 addrlist->Copy(result.head(), false);
50 else
51 addrlist->Append(result.head());
52 }
53 return OK;
54 }
55
56 } // namespace
57
~MockHostResolverBase()58 MockHostResolverBase::~MockHostResolverBase() {}
59
Reset(HostResolverProc * interceptor)60 void MockHostResolverBase::Reset(HostResolverProc* interceptor) {
61 synchronous_mode_ = false;
62
63 // At the root of the chain, map everything to localhost.
64 scoped_refptr<RuleBasedHostResolverProc> catchall(
65 new RuleBasedHostResolverProc(NULL));
66 catchall->AddRule("*", "127.0.0.1");
67
68 // Next add a rules-based layer the use controls.
69 rules_ = new RuleBasedHostResolverProc(catchall);
70
71 HostResolverProc* proc = rules_;
72
73 // Lastly add the provided interceptor to the front of the chain.
74 if (interceptor) {
75 interceptor->SetPreviousProc(proc);
76 proc = interceptor;
77 }
78
79 HostCache* cache = NULL;
80
81 if (use_caching_) {
82 cache = new HostCache(
83 100, // max entries.
84 base::TimeDelta::FromMinutes(1),
85 base::TimeDelta::FromSeconds(0));
86 }
87
88 impl_.reset(new HostResolverImpl(proc, cache, 50u, NULL));
89 }
90
Resolve(const RequestInfo & info,AddressList * addresses,CompletionCallback * callback,RequestHandle * out_req,const BoundNetLog & net_log)91 int MockHostResolverBase::Resolve(const RequestInfo& info,
92 AddressList* addresses,
93 CompletionCallback* callback,
94 RequestHandle* out_req,
95 const BoundNetLog& net_log) {
96 if (synchronous_mode_) {
97 callback = NULL;
98 out_req = NULL;
99 }
100 return impl_->Resolve(info, addresses, callback, out_req, net_log);
101 }
102
CancelRequest(RequestHandle req)103 void MockHostResolverBase::CancelRequest(RequestHandle req) {
104 impl_->CancelRequest(req);
105 }
106
AddObserver(Observer * observer)107 void MockHostResolverBase::AddObserver(Observer* observer) {
108 impl_->AddObserver(observer);
109 }
110
RemoveObserver(Observer * observer)111 void MockHostResolverBase::RemoveObserver(Observer* observer) {
112 impl_->RemoveObserver(observer);
113 }
114
MockHostResolverBase(bool use_caching)115 MockHostResolverBase::MockHostResolverBase(bool use_caching)
116 : use_caching_(use_caching) {
117 Reset(NULL);
118 }
119
120 //-----------------------------------------------------------------------------
121
122 struct RuleBasedHostResolverProc::Rule {
123 enum ResolverType {
124 kResolverTypeFail,
125 kResolverTypeSystem,
126 kResolverTypeIPLiteral,
127 };
128
129 ResolverType resolver_type;
130 std::string host_pattern;
131 AddressFamily address_family;
132 HostResolverFlags host_resolver_flags;
133 std::string replacement;
134 std::string canonical_name;
135 int latency_ms; // In milliseconds.
136
Rulenet::RuleBasedHostResolverProc::Rule137 Rule(ResolverType resolver_type,
138 const std::string& host_pattern,
139 AddressFamily address_family,
140 HostResolverFlags host_resolver_flags,
141 const std::string& replacement,
142 const std::string& canonical_name,
143 int latency_ms)
144 : resolver_type(resolver_type),
145 host_pattern(host_pattern),
146 address_family(address_family),
147 host_resolver_flags(host_resolver_flags),
148 replacement(replacement),
149 canonical_name(canonical_name),
150 latency_ms(latency_ms) {}
151 };
152
RuleBasedHostResolverProc(HostResolverProc * previous)153 RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous)
154 : HostResolverProc(previous) {
155 }
156
AddRule(const std::string & host_pattern,const std::string & replacement)157 void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern,
158 const std::string& replacement) {
159 AddRuleForAddressFamily(host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
160 replacement);
161 }
162
AddRuleForAddressFamily(const std::string & host_pattern,AddressFamily address_family,const std::string & replacement)163 void RuleBasedHostResolverProc::AddRuleForAddressFamily(
164 const std::string& host_pattern,
165 AddressFamily address_family,
166 const std::string& replacement) {
167 DCHECK(!replacement.empty());
168 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
169 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
170 Rule rule(Rule::kResolverTypeSystem, host_pattern, address_family, flags,
171 replacement, "", 0);
172 rules_.push_back(rule);
173 }
174
AddIPLiteralRule(const std::string & host_pattern,const std::string & ip_literal,const std::string & canonical_name)175 void RuleBasedHostResolverProc::AddIPLiteralRule(
176 const std::string& host_pattern,
177 const std::string& ip_literal,
178 const std::string& canonical_name) {
179 // Literals are always resolved to themselves by HostResolverImpl,
180 // consequently we do not support remapping them.
181 IPAddressNumber ip_number;
182 DCHECK(!ParseIPLiteralToNumber(host_pattern, &ip_number));
183 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
184 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
185 if (!canonical_name.empty())
186 flags |= HOST_RESOLVER_CANONNAME;
187 Rule rule(Rule::kResolverTypeIPLiteral, host_pattern,
188 ADDRESS_FAMILY_UNSPECIFIED, flags, ip_literal, canonical_name,
189 0);
190 rules_.push_back(rule);
191 }
192
AddRuleWithLatency(const std::string & host_pattern,const std::string & replacement,int latency_ms)193 void RuleBasedHostResolverProc::AddRuleWithLatency(
194 const std::string& host_pattern,
195 const std::string& replacement,
196 int latency_ms) {
197 DCHECK(!replacement.empty());
198 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
199 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
200 Rule rule(Rule::kResolverTypeSystem, host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
201 flags, replacement, "", latency_ms);
202 rules_.push_back(rule);
203 }
204
AllowDirectLookup(const std::string & host_pattern)205 void RuleBasedHostResolverProc::AllowDirectLookup(
206 const std::string& host_pattern) {
207 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
208 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
209 Rule rule(Rule::kResolverTypeSystem, host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
210 flags, "", "", 0);
211 rules_.push_back(rule);
212 }
213
AddSimulatedFailure(const std::string & host_pattern)214 void RuleBasedHostResolverProc::AddSimulatedFailure(
215 const std::string& host_pattern) {
216 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
217 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
218 Rule rule(Rule::kResolverTypeFail, host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
219 flags, "", "", 0);
220 rules_.push_back(rule);
221 }
222
Resolve(const std::string & host,AddressFamily address_family,HostResolverFlags host_resolver_flags,AddressList * addrlist,int * os_error)223 int RuleBasedHostResolverProc::Resolve(const std::string& host,
224 AddressFamily address_family,
225 HostResolverFlags host_resolver_flags,
226 AddressList* addrlist,
227 int* os_error) {
228 RuleList::iterator r;
229 for (r = rules_.begin(); r != rules_.end(); ++r) {
230 bool matches_address_family =
231 r->address_family == ADDRESS_FAMILY_UNSPECIFIED ||
232 r->address_family == address_family;
233 // Flags match if all of the bitflags in host_resolver_flags are enabled
234 // in the rule's host_resolver_flags. However, the rule may have additional
235 // flags specified, in which case the flags should still be considered a
236 // match.
237 bool matches_flags = (r->host_resolver_flags & host_resolver_flags) ==
238 host_resolver_flags;
239 if (matches_flags && matches_address_family &&
240 MatchPattern(host, r->host_pattern)) {
241 if (r->latency_ms != 0)
242 base::PlatformThread::Sleep(r->latency_ms);
243
244 // Remap to a new host.
245 const std::string& effective_host =
246 r->replacement.empty() ? host : r->replacement;
247
248 // Apply the resolving function to the remapped hostname.
249 switch (r->resolver_type) {
250 case Rule::kResolverTypeFail:
251 return ERR_NAME_NOT_RESOLVED;
252 case Rule::kResolverTypeSystem:
253 return SystemHostResolverProc(effective_host,
254 address_family,
255 host_resolver_flags,
256 addrlist, os_error);
257 case Rule::kResolverTypeIPLiteral:
258 return CreateIPAddressList(effective_host,
259 r->canonical_name,
260 addrlist);
261 default:
262 NOTREACHED();
263 return ERR_UNEXPECTED;
264 }
265 }
266 }
267 return ResolveUsingPrevious(host, address_family,
268 host_resolver_flags, addrlist, os_error);
269 }
270
~RuleBasedHostResolverProc()271 RuleBasedHostResolverProc::~RuleBasedHostResolverProc() {
272 }
273
274 //-----------------------------------------------------------------------------
275
WaitingHostResolverProc(HostResolverProc * previous)276 WaitingHostResolverProc::WaitingHostResolverProc(HostResolverProc* previous)
277 : HostResolverProc(previous), event_(false, false) {}
278
Signal()279 void WaitingHostResolverProc::Signal() {
280 event_.Signal();
281 }
282
Resolve(const std::string & host,AddressFamily address_family,HostResolverFlags host_resolver_flags,AddressList * addrlist,int * os_error)283 int WaitingHostResolverProc::Resolve(const std::string& host,
284 AddressFamily address_family,
285 HostResolverFlags host_resolver_flags,
286 AddressList* addrlist,
287 int* os_error) {
288 event_.Wait();
289 return ResolveUsingPrevious(host, address_family, host_resolver_flags,
290 addrlist, os_error);
291 }
292
~WaitingHostResolverProc()293 WaitingHostResolverProc::~WaitingHostResolverProc() {}
294
295 //-----------------------------------------------------------------------------
296
ScopedDefaultHostResolverProc()297 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc() {}
298
ScopedDefaultHostResolverProc(HostResolverProc * proc)299 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc(
300 HostResolverProc* proc) {
301 Init(proc);
302 }
303
~ScopedDefaultHostResolverProc()304 ScopedDefaultHostResolverProc::~ScopedDefaultHostResolverProc() {
305 HostResolverProc* old_proc = HostResolverProc::SetDefault(previous_proc_);
306 // The lifetimes of multiple instances must be nested.
307 CHECK_EQ(old_proc, current_proc_);
308 }
309
Init(HostResolverProc * proc)310 void ScopedDefaultHostResolverProc::Init(HostResolverProc* proc) {
311 current_proc_ = proc;
312 previous_proc_ = HostResolverProc::SetDefault(current_proc_);
313 current_proc_->SetLastProc(previous_proc_);
314 }
315
316 } // namespace net
317