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