1 /*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include "src/core/lib/iomgr/resolve_address.h"
20 #include <grpc/grpc.h>
21 #include <grpc/support/alloc.h>
22 #include <grpc/support/log.h>
23 #include <grpc/support/sync.h>
24 #include <grpc/support/time.h>
25
26 #include <address_sorting/address_sorting.h>
27
28 #include <string.h>
29
30 #include "src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h"
31 #include "src/core/lib/gpr/string.h"
32 #include "src/core/lib/iomgr/executor.h"
33 #include "src/core/lib/iomgr/iomgr.h"
34 #include "test/core/util/cmdline.h"
35 #include "test/core/util/test_config.h"
36
test_deadline(void)37 static gpr_timespec test_deadline(void) {
38 return grpc_timeout_seconds_to_deadline(100);
39 }
40
41 typedef struct args_struct {
42 gpr_event ev;
43 grpc_resolved_addresses* addrs;
44 gpr_atm done_atm;
45 gpr_mu* mu;
46 grpc_pollset* pollset;
47 grpc_pollset_set* pollset_set;
48 } args_struct;
49
do_nothing(void *,grpc_error *)50 static void do_nothing(void* /*arg*/, grpc_error* /*error*/) {}
51
args_init(args_struct * args)52 void args_init(args_struct* args) {
53 gpr_event_init(&args->ev);
54 args->pollset = static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
55 grpc_pollset_init(args->pollset, &args->mu);
56 args->pollset_set = grpc_pollset_set_create();
57 grpc_pollset_set_add_pollset(args->pollset_set, args->pollset);
58 args->addrs = nullptr;
59 gpr_atm_rel_store(&args->done_atm, 0);
60 }
61
args_finish(args_struct * args)62 void args_finish(args_struct* args) {
63 GPR_ASSERT(gpr_event_wait(&args->ev, test_deadline()));
64 grpc_resolved_addresses_destroy(args->addrs);
65 grpc_pollset_set_del_pollset(args->pollset_set, args->pollset);
66 grpc_pollset_set_destroy(args->pollset_set);
67 grpc_closure do_nothing_cb;
68 GRPC_CLOSURE_INIT(&do_nothing_cb, do_nothing, nullptr,
69 grpc_schedule_on_exec_ctx);
70 gpr_mu_lock(args->mu);
71 grpc_pollset_shutdown(args->pollset, &do_nothing_cb);
72 gpr_mu_unlock(args->mu);
73 // exec_ctx needs to be flushed before calling grpc_pollset_destroy()
74 grpc_core::ExecCtx::Get()->Flush();
75 grpc_pollset_destroy(args->pollset);
76 gpr_free(args->pollset);
77 }
78
n_sec_deadline(int seconds)79 static grpc_millis n_sec_deadline(int seconds) {
80 return grpc_timespec_to_millis_round_up(
81 grpc_timeout_seconds_to_deadline(seconds));
82 }
83
poll_pollset_until_request_done(args_struct * args)84 static void poll_pollset_until_request_done(args_struct* args) {
85 grpc_core::ExecCtx exec_ctx;
86 // Try to give enough time for c-ares to run through its retries
87 // a few times if needed.
88 grpc_millis deadline = n_sec_deadline(90);
89 while (true) {
90 bool done = gpr_atm_acq_load(&args->done_atm) != 0;
91 if (done) {
92 break;
93 }
94 grpc_millis time_left = deadline - grpc_core::ExecCtx::Get()->Now();
95 gpr_log(GPR_DEBUG, "done=%d, time_left=%" PRId64, done, time_left);
96 GPR_ASSERT(time_left >= 0);
97 grpc_pollset_worker* worker = nullptr;
98 gpr_mu_lock(args->mu);
99 GRPC_LOG_IF_ERROR("pollset_work", grpc_pollset_work(args->pollset, &worker,
100 n_sec_deadline(1)));
101 gpr_mu_unlock(args->mu);
102 grpc_core::ExecCtx::Get()->Flush();
103 }
104 gpr_event_set(&args->ev, (void*)1);
105 }
106
must_succeed(void * argsp,grpc_error * err)107 static void must_succeed(void* argsp, grpc_error* err) {
108 args_struct* args = static_cast<args_struct*>(argsp);
109 GPR_ASSERT(err == GRPC_ERROR_NONE);
110 GPR_ASSERT(args->addrs != nullptr);
111 GPR_ASSERT(args->addrs->naddrs > 0);
112 gpr_atm_rel_store(&args->done_atm, 1);
113 gpr_mu_lock(args->mu);
114 GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, nullptr));
115 gpr_mu_unlock(args->mu);
116 }
117
must_fail(void * argsp,grpc_error * err)118 static void must_fail(void* argsp, grpc_error* err) {
119 args_struct* args = static_cast<args_struct*>(argsp);
120 GPR_ASSERT(err != GRPC_ERROR_NONE);
121 gpr_atm_rel_store(&args->done_atm, 1);
122 gpr_mu_lock(args->mu);
123 GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, nullptr));
124 gpr_mu_unlock(args->mu);
125 }
126
127 // This test assumes the environment has an ipv6 loopback
must_succeed_with_ipv6_first(void * argsp,grpc_error * err)128 static void must_succeed_with_ipv6_first(void* argsp, grpc_error* err) {
129 args_struct* args = static_cast<args_struct*>(argsp);
130 GPR_ASSERT(err == GRPC_ERROR_NONE);
131 GPR_ASSERT(args->addrs != nullptr);
132 GPR_ASSERT(args->addrs->naddrs > 0);
133 const struct sockaddr* first_address =
134 reinterpret_cast<const struct sockaddr*>(args->addrs->addrs[0].addr);
135 GPR_ASSERT(first_address->sa_family == AF_INET6);
136 gpr_atm_rel_store(&args->done_atm, 1);
137 gpr_mu_lock(args->mu);
138 GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, nullptr));
139 gpr_mu_unlock(args->mu);
140 }
141
must_succeed_with_ipv4_first(void * argsp,grpc_error * err)142 static void must_succeed_with_ipv4_first(void* argsp, grpc_error* err) {
143 args_struct* args = static_cast<args_struct*>(argsp);
144 GPR_ASSERT(err == GRPC_ERROR_NONE);
145 GPR_ASSERT(args->addrs != nullptr);
146 GPR_ASSERT(args->addrs->naddrs > 0);
147 const struct sockaddr* first_address =
148 reinterpret_cast<const struct sockaddr*>(args->addrs->addrs[0].addr);
149 GPR_ASSERT(first_address->sa_family == AF_INET);
150 gpr_atm_rel_store(&args->done_atm, 1);
151 gpr_mu_lock(args->mu);
152 GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, nullptr));
153 gpr_mu_unlock(args->mu);
154 }
155
test_localhost(void)156 static void test_localhost(void) {
157 grpc_core::ExecCtx exec_ctx;
158 args_struct args;
159 args_init(&args);
160 grpc_resolve_address(
161 "localhost:1", nullptr, args.pollset_set,
162 GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx),
163 &args.addrs);
164 grpc_core::ExecCtx::Get()->Flush();
165 poll_pollset_until_request_done(&args);
166 args_finish(&args);
167 }
168
test_default_port(void)169 static void test_default_port(void) {
170 grpc_core::ExecCtx exec_ctx;
171 args_struct args;
172 args_init(&args);
173 grpc_resolve_address(
174 "localhost", "1", args.pollset_set,
175 GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx),
176 &args.addrs);
177 grpc_core::ExecCtx::Get()->Flush();
178 poll_pollset_until_request_done(&args);
179 args_finish(&args);
180 }
181
test_localhost_result_has_ipv6_first(void)182 static void test_localhost_result_has_ipv6_first(void) {
183 grpc_core::ExecCtx exec_ctx;
184 args_struct args;
185 args_init(&args);
186 grpc_resolve_address("localhost:1", nullptr, args.pollset_set,
187 GRPC_CLOSURE_CREATE(must_succeed_with_ipv6_first, &args,
188 grpc_schedule_on_exec_ctx),
189 &args.addrs);
190 grpc_core::ExecCtx::Get()->Flush();
191 poll_pollset_until_request_done(&args);
192 args_finish(&args);
193 }
194
test_localhost_result_has_ipv4_first_when_ipv6_isnt_available(void)195 static void test_localhost_result_has_ipv4_first_when_ipv6_isnt_available(
196 void) {
197 grpc_core::ExecCtx exec_ctx;
198 args_struct args;
199 args_init(&args);
200 grpc_resolve_address("localhost:1", nullptr, args.pollset_set,
201 GRPC_CLOSURE_CREATE(must_succeed_with_ipv4_first, &args,
202 grpc_schedule_on_exec_ctx),
203 &args.addrs);
204 grpc_core::ExecCtx::Get()->Flush();
205 poll_pollset_until_request_done(&args);
206 args_finish(&args);
207 }
208
test_non_numeric_default_port(void)209 static void test_non_numeric_default_port(void) {
210 grpc_core::ExecCtx exec_ctx;
211 args_struct args;
212 args_init(&args);
213 grpc_resolve_address(
214 "localhost", "https", args.pollset_set,
215 GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx),
216 &args.addrs);
217 grpc_core::ExecCtx::Get()->Flush();
218 poll_pollset_until_request_done(&args);
219 args_finish(&args);
220 }
221
test_missing_default_port(void)222 static void test_missing_default_port(void) {
223 grpc_core::ExecCtx exec_ctx;
224 args_struct args;
225 args_init(&args);
226 grpc_resolve_address(
227 "localhost", nullptr, args.pollset_set,
228 GRPC_CLOSURE_CREATE(must_fail, &args, grpc_schedule_on_exec_ctx),
229 &args.addrs);
230 grpc_core::ExecCtx::Get()->Flush();
231 poll_pollset_until_request_done(&args);
232 args_finish(&args);
233 }
234
test_ipv6_with_port(void)235 static void test_ipv6_with_port(void) {
236 grpc_core::ExecCtx exec_ctx;
237 args_struct args;
238 args_init(&args);
239 grpc_resolve_address(
240 "[2001:db8::1]:1", nullptr, args.pollset_set,
241 GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx),
242 &args.addrs);
243 grpc_core::ExecCtx::Get()->Flush();
244 poll_pollset_until_request_done(&args);
245 args_finish(&args);
246 }
247
test_ipv6_without_port(void)248 static void test_ipv6_without_port(void) {
249 const char* const kCases[] = {
250 "2001:db8::1",
251 "2001:db8::1.2.3.4",
252 "[2001:db8::1]",
253 };
254 unsigned i;
255 for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) {
256 grpc_core::ExecCtx exec_ctx;
257 args_struct args;
258 args_init(&args);
259 grpc_resolve_address(
260 kCases[i], "80", args.pollset_set,
261 GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx),
262 &args.addrs);
263 grpc_core::ExecCtx::Get()->Flush();
264 poll_pollset_until_request_done(&args);
265 args_finish(&args);
266 }
267 }
268
test_invalid_ip_addresses(void)269 static void test_invalid_ip_addresses(void) {
270 const char* const kCases[] = {
271 "293.283.1238.3:1",
272 "[2001:db8::11111]:1",
273 };
274 unsigned i;
275 for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) {
276 grpc_core::ExecCtx exec_ctx;
277 args_struct args;
278 args_init(&args);
279 grpc_resolve_address(
280 kCases[i], nullptr, args.pollset_set,
281 GRPC_CLOSURE_CREATE(must_fail, &args, grpc_schedule_on_exec_ctx),
282 &args.addrs);
283 grpc_core::ExecCtx::Get()->Flush();
284 poll_pollset_until_request_done(&args);
285 args_finish(&args);
286 }
287 }
288
test_unparseable_hostports(void)289 static void test_unparseable_hostports(void) {
290 const char* const kCases[] = {
291 "[", "[::1", "[::1]bad", "[1.2.3.4]", "[localhost]", "[localhost]:1",
292 };
293 unsigned i;
294 for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) {
295 grpc_core::ExecCtx exec_ctx;
296 args_struct args;
297 args_init(&args);
298 grpc_resolve_address(
299 kCases[i], "1", args.pollset_set,
300 GRPC_CLOSURE_CREATE(must_fail, &args, grpc_schedule_on_exec_ctx),
301 &args.addrs);
302 grpc_core::ExecCtx::Get()->Flush();
303 poll_pollset_until_request_done(&args);
304 args_finish(&args);
305 }
306 }
307
308 typedef struct mock_ipv6_disabled_source_addr_factory {
309 address_sorting_source_addr_factory base;
310 } mock_ipv6_disabled_source_addr_factory;
311
mock_ipv6_disabled_source_addr_factory_get_source_addr(address_sorting_source_addr_factory *,const address_sorting_address * dest_addr,address_sorting_address * source_addr)312 static bool mock_ipv6_disabled_source_addr_factory_get_source_addr(
313 address_sorting_source_addr_factory* /*factory*/,
314 const address_sorting_address* dest_addr,
315 address_sorting_address* source_addr) {
316 // Mock lack of IPv6. For IPv4, set the source addr to be the same
317 // as the destination; tests won't actually connect on the result anyways.
318 if (address_sorting_abstract_get_family(dest_addr) ==
319 ADDRESS_SORTING_AF_INET6) {
320 return false;
321 }
322 memcpy(source_addr->addr, &dest_addr->addr, dest_addr->len);
323 source_addr->len = dest_addr->len;
324 return true;
325 }
326
mock_ipv6_disabled_source_addr_factory_destroy(address_sorting_source_addr_factory * factory)327 void mock_ipv6_disabled_source_addr_factory_destroy(
328 address_sorting_source_addr_factory* factory) {
329 mock_ipv6_disabled_source_addr_factory* f =
330 reinterpret_cast<mock_ipv6_disabled_source_addr_factory*>(factory);
331 gpr_free(f);
332 }
333
334 const address_sorting_source_addr_factory_vtable
335 kMockIpv6DisabledSourceAddrFactoryVtable = {
336 mock_ipv6_disabled_source_addr_factory_get_source_addr,
337 mock_ipv6_disabled_source_addr_factory_destroy,
338 };
339
main(int argc,char ** argv)340 int main(int argc, char** argv) {
341 // First set the resolver type based off of --resolver
342 const char* resolver_type = nullptr;
343 gpr_cmdline* cl = gpr_cmdline_create("resolve address test");
344 gpr_cmdline_add_string(cl, "resolver", "Resolver type (ares or native)",
345 &resolver_type);
346 // In case that there are more than one argument on the command line,
347 // --resolver will always be the first one, so only parse the first argument
348 // (other arguments may be unknown to cl)
349 gpr_cmdline_parse(cl, argc > 2 ? 2 : argc, argv);
350 grpc_core::UniquePtr<char> resolver =
351 GPR_GLOBAL_CONFIG_GET(grpc_dns_resolver);
352 if (strlen(resolver.get()) != 0) {
353 gpr_log(GPR_INFO, "Warning: overriding resolver setting of %s",
354 resolver.get());
355 }
356 if (resolver_type != nullptr && gpr_stricmp(resolver_type, "native") == 0) {
357 GPR_GLOBAL_CONFIG_SET(grpc_dns_resolver, "native");
358 } else if (resolver_type != nullptr &&
359 gpr_stricmp(resolver_type, "ares") == 0) {
360 #ifndef GRPC_UV
361 GPR_GLOBAL_CONFIG_SET(grpc_dns_resolver, "ares");
362 #endif
363 } else {
364 gpr_log(GPR_ERROR, "--resolver_type was not set to ares or native");
365 abort();
366 }
367 // Run the test.
368 grpc::testing::TestEnvironment env(argc, argv);
369 grpc_init();
370 {
371 grpc_core::ExecCtx exec_ctx;
372 test_localhost();
373 test_default_port();
374 test_non_numeric_default_port();
375 test_missing_default_port();
376 test_ipv6_with_port();
377 test_ipv6_without_port();
378 test_invalid_ip_addresses();
379 test_unparseable_hostports();
380 if (gpr_stricmp(resolver_type, "ares") == 0) {
381 // This behavior expectation is specific to c-ares.
382 test_localhost_result_has_ipv6_first();
383 }
384 grpc_core::Executor::ShutdownAll();
385 }
386 gpr_cmdline_destroy(cl);
387 grpc_shutdown();
388 // The following test uses
389 // "address_sorting_override_source_addr_factory_for_testing", which works
390 // on a per-grpc-init basis, and so it's simplest to run this next test
391 // within a standalone grpc_init/grpc_shutdown pair.
392 if (gpr_stricmp(resolver_type, "ares") == 0) {
393 // Run a test case in which c-ares's address sorter
394 // thinks that IPv4 is available and IPv6 isn't.
395 grpc_init();
396 mock_ipv6_disabled_source_addr_factory* factory =
397 static_cast<mock_ipv6_disabled_source_addr_factory*>(
398 gpr_malloc(sizeof(mock_ipv6_disabled_source_addr_factory)));
399 factory->base.vtable = &kMockIpv6DisabledSourceAddrFactoryVtable;
400 address_sorting_override_source_addr_factory_for_testing(&factory->base);
401 test_localhost_result_has_ipv4_first_when_ipv6_isnt_available();
402 grpc_shutdown();
403 }
404 return 0;
405 }
406