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