• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* MIT License
2  *
3  * Copyright (c) The c-ares project and its contributors
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  * SPDX-License-Identifier: MIT
25  */
26 #include "ares-test.h"
27 
28 extern "C" {
29   #include "ares_private.h"
30 }
31 
32 // library initialization is only needed for windows builds
33 #ifdef WIN32
34 #define EXPECTED_NONINIT ARES_ENOTINITIALIZED
35 #else
36 #define EXPECTED_NONINIT ARES_SUCCESS
37 #endif
38 
39 namespace ares {
40 namespace test {
41 
TEST(LibraryInit,Basic)42 TEST(LibraryInit, Basic) {
43   EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized());
44   EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL));
45   EXPECT_EQ(ARES_SUCCESS, ares_library_initialized());
46   ares_library_cleanup();
47   EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized());
48 }
49 
TEST(LibraryInit,UnexpectedCleanup)50 TEST(LibraryInit, UnexpectedCleanup) {
51   EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized());
52   ares_library_cleanup();
53   EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized());
54 }
55 
TEST(LibraryInit,Nested)56 TEST(LibraryInit, Nested) {
57   EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized());
58   EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL));
59   EXPECT_EQ(ARES_SUCCESS, ares_library_initialized());
60   EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL));
61   EXPECT_EQ(ARES_SUCCESS, ares_library_initialized());
62   ares_library_cleanup();
63   EXPECT_EQ(ARES_SUCCESS, ares_library_initialized());
64   ares_library_cleanup();
65   EXPECT_EQ(EXPECTED_NONINIT, ares_library_initialized());
66 }
67 
TEST(LibraryInit,BasicChannelInit)68 TEST(LibraryInit, BasicChannelInit) {
69   EXPECT_EQ(ARES_SUCCESS, ares_library_init(ARES_LIB_INIT_ALL));
70   ares_channel_t *channel = nullptr;
71   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
72   EXPECT_NE(nullptr, channel);
73   ares_destroy(channel);
74   ares_library_cleanup();
75 }
76 
TEST_F(LibraryTest,OptionsChannelInit)77 TEST_F(LibraryTest, OptionsChannelInit) {
78   struct ares_options opts;
79   int optmask = 0;
80   memset(&opts, 0, sizeof(opts));
81   opts.flags = ARES_FLAG_USEVC | ARES_FLAG_PRIMARY;
82   optmask |= ARES_OPT_FLAGS;
83   opts.timeout = 2000;
84   optmask |= ARES_OPT_TIMEOUTMS;
85   opts.tries = 2;
86   optmask |= ARES_OPT_TRIES;
87   opts.ndots = 4;
88   optmask |= ARES_OPT_NDOTS;
89   opts.udp_port = 54;
90   optmask |= ARES_OPT_MAXTIMEOUTMS;
91   opts.maxtimeout = 10000;
92   optmask |= ARES_OPT_UDP_PORT;
93   opts.tcp_port = 54;
94   optmask |= ARES_OPT_TCP_PORT;
95   opts.socket_send_buffer_size = 514;
96   optmask |= ARES_OPT_SOCK_SNDBUF;
97   opts.socket_receive_buffer_size = 514;
98   optmask |= ARES_OPT_SOCK_RCVBUF;
99   opts.ednspsz = 1280;
100   optmask |= ARES_OPT_EDNSPSZ;
101   opts.nservers = 2;
102   opts.servers = (struct in_addr *)malloc((size_t)opts.nservers * sizeof(struct in_addr));
103   opts.servers[0].s_addr = htonl(0x01020304);
104   opts.servers[1].s_addr = htonl(0x02030405);
105   optmask |= ARES_OPT_SERVERS;
106   opts.ndomains = 2;
107   opts.domains = (char **)malloc((size_t)opts.ndomains * sizeof(char *));
108   opts.domains[0] = strdup("example.com");
109   opts.domains[1] = strdup("example2.com");
110   optmask |= ARES_OPT_DOMAINS;
111   opts.lookups = strdup("b");
112   optmask |= ARES_OPT_LOOKUPS;
113   optmask |= ARES_OPT_ROTATE;
114   opts.resolvconf_path = strdup("/etc/resolv.conf");
115   optmask |= ARES_OPT_RESOLVCONF;
116   opts.hosts_path = strdup("/etc/hosts");
117   optmask |= ARES_OPT_HOSTS_FILE;
118 
119   ares_channel_t *channel = nullptr;
120   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask));
121   EXPECT_NE(nullptr, channel);
122 
123   ares_channel_t *channel2 = nullptr;
124   EXPECT_EQ(ARES_SUCCESS, ares_dup(&channel2, channel));
125   EXPECT_NE(nullptr, channel2);
126 
127   struct ares_options opts2;
128   int optmask2 = 0;
129   memset(&opts2, 0, sizeof(opts2));
130   EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel2, &opts2, &optmask2));
131 
132   // Note that not all opts-settable fields are saved (e.g.
133   // ednspsz, socket_{send,receive}_buffer_size).
134   EXPECT_EQ(opts.flags, opts2.flags);
135   EXPECT_EQ(opts.timeout, opts2.timeout);
136   EXPECT_EQ(opts.tries, opts2.tries);
137   EXPECT_EQ(opts.ndots, opts2.ndots);
138   EXPECT_EQ(opts.maxtimeout, opts2.maxtimeout);
139   EXPECT_EQ(opts.udp_port, opts2.udp_port);
140   EXPECT_EQ(opts.tcp_port, opts2.tcp_port);
141   EXPECT_EQ(1, opts2.nservers);  // Truncated by ARES_FLAG_PRIMARY
142   EXPECT_EQ(opts.servers[0].s_addr, opts2.servers[0].s_addr);
143   EXPECT_EQ(opts.ndomains, opts2.ndomains);
144   EXPECT_EQ(std::string(opts.domains[0]), std::string(opts2.domains[0]));
145   EXPECT_EQ(std::string(opts.domains[1]), std::string(opts2.domains[1]));
146   EXPECT_EQ(std::string(opts.lookups), std::string(opts2.lookups));
147   EXPECT_EQ(std::string(opts.resolvconf_path), std::string(opts2.resolvconf_path));
148   EXPECT_EQ(std::string(opts.hosts_path), std::string(opts2.hosts_path));
149 
150   ares_destroy_options(&opts);
151   ares_destroy_options(&opts2);
152   ares_destroy(channel);
153   ares_destroy(channel2);
154 }
155 
TEST_F(LibraryTest,ChannelAllocFail)156 TEST_F(LibraryTest, ChannelAllocFail) {
157   ares_channel_t *channel;
158   for (int ii = 1; ii <= 25; ii++) {
159     ClearFails();
160     SetAllocFail(ii);
161     channel = nullptr;
162     int rc = ares_init(&channel);
163     // The number of allocations depends on local environment, so don't expect ENOMEM.
164     if (rc == ARES_ENOMEM) {
165       EXPECT_EQ(nullptr, channel);
166     } else {
167       ares_destroy(channel);
168     }
169   }
170 }
171 
TEST_F(LibraryTest,OptionsChannelAllocFail)172 TEST_F(LibraryTest, OptionsChannelAllocFail) {
173   struct ares_options opts;
174   int optmask = 0;
175   memset(&opts, 0, sizeof(opts));
176   opts.flags = ARES_FLAG_USEVC;
177   optmask |= ARES_OPT_FLAGS;
178   opts.timeout = 2;
179   optmask |= ARES_OPT_TIMEOUT;
180   opts.tries = 2;
181   optmask |= ARES_OPT_TRIES;
182   opts.ndots = 4;
183   optmask |= ARES_OPT_NDOTS;
184   opts.udp_port = 54;
185   optmask |= ARES_OPT_UDP_PORT;
186   opts.tcp_port = 54;
187   optmask |= ARES_OPT_TCP_PORT;
188   opts.socket_send_buffer_size = 514;
189   optmask |= ARES_OPT_SOCK_SNDBUF;
190   opts.socket_receive_buffer_size = 514;
191   optmask |= ARES_OPT_SOCK_RCVBUF;
192   opts.ednspsz = 1280;
193   optmask |= ARES_OPT_EDNSPSZ;
194   opts.nservers = 2;
195   opts.servers = (struct in_addr *)malloc((size_t)opts.nservers * sizeof(struct in_addr));
196   opts.servers[0].s_addr = htonl(0x01020304);
197   opts.servers[1].s_addr = htonl(0x02030405);
198   optmask |= ARES_OPT_SERVERS;
199   opts.ndomains = 2;
200   opts.domains = (char **)malloc((size_t)opts.ndomains * sizeof(char *));
201   opts.domains[0] = strdup("example.com");
202   opts.domains[1] = strdup("example2.com");
203   optmask |= ARES_OPT_DOMAINS;
204   opts.lookups = strdup("b");
205   optmask |= ARES_OPT_LOOKUPS;
206   optmask |= ARES_OPT_ROTATE;
207   opts.resolvconf_path = strdup("/etc/resolv.conf");
208   optmask |= ARES_OPT_RESOLVCONF;
209   opts.hosts_path = strdup("/etc/hosts");
210   optmask |= ARES_OPT_HOSTS_FILE;
211 
212   ares_channel_t *channel = nullptr;
213   for (int ii = 1; ii <= 8; ii++) {
214     ClearFails();
215     SetAllocFail(ii);
216     int rc = ares_init_options(&channel, &opts, optmask);
217     if (rc == ARES_ENOMEM) {
218       EXPECT_EQ(nullptr, channel);
219     } else {
220       EXPECT_EQ(ARES_SUCCESS, rc);
221       ares_destroy(channel);
222       channel = nullptr;
223     }
224   }
225   ClearFails();
226 
227   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask));
228   EXPECT_NE(nullptr, channel);
229 
230   // Add some servers and a sortlist for flavour.
231   EXPECT_EQ(ARES_SUCCESS,
232             ares_set_servers_csv(channel, "1.2.3.4,0102:0304:0506:0708:0910:1112:1314:1516,2.3.4.5"));
233   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel, "1.2.3.4 2.3.4.5"));
234 
235   ares_channel_t *channel2 = nullptr;
236   for (int ii = 1; ii <= 18; ii++) {
237     ClearFails();
238     SetAllocFail(ii);
239     EXPECT_EQ(ARES_ENOMEM, ares_dup(&channel2, channel)) << ii;
240     EXPECT_EQ(nullptr, channel2) << ii;
241   }
242 
243   struct ares_options opts2;
244   int optmask2 = 0;
245   for (int ii = 1; ii <= 6; ii++) {
246     memset(&opts2, 0, sizeof(opts2));
247     ClearFails();
248     SetAllocFail(ii);
249     EXPECT_EQ(ARES_ENOMEM, ares_save_options(channel, &opts2, &optmask2)) << ii;
250     // May still have allocations even after ARES_ENOMEM return code.
251     ares_destroy_options(&opts2);
252   }
253   ares_destroy_options(&opts);
254   ares_destroy(channel);
255 }
256 
TEST_F(LibraryTest,FailChannelInit)257 TEST_F(LibraryTest, FailChannelInit) {
258   EXPECT_EQ(ARES_SUCCESS,
259             ares_library_init_mem(ARES_LIB_INIT_ALL,
260                                   &LibraryTest::amalloc,
261                                   &LibraryTest::afree,
262                                   &LibraryTest::arealloc));
263   SetAllocFail(1);
264   ares_channel_t *channel = nullptr;
265   EXPECT_EQ(ARES_ENOMEM, ares_init(&channel));
266   EXPECT_EQ(nullptr, channel);
267   ares_library_cleanup();
268 }
269 
270 #ifndef WIN32
TEST_F(LibraryTest,EnvInit)271 TEST_F(LibraryTest, EnvInit) {
272   ares_channel_t *channel = nullptr;
273   EnvValue v1("LOCALDOMAIN", "this.is.local");
274   EnvValue v2("RES_OPTIONS", "options debug ndots:3 retry:3 rotate retrans:2");
275   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
276   ares_destroy(channel);
277 }
278 
TEST_F(LibraryTest,EnvInitModernOptions)279 TEST_F(LibraryTest, EnvInitModernOptions) {
280   ares_channel_t *channel = nullptr;
281   EnvValue v1("LOCALDOMAIN", "this.is.local");
282   EnvValue v2("RES_OPTIONS", "options debug retrans:2 ndots:3 attempts:4 timeout:5 rotate");
283   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
284 
285   channel->optmask |= ARES_OPT_TRIES;
286   channel->optmask |= ARES_OPT_TIMEOUTMS;
287 
288   struct ares_options opts;
289   memset(&opts, 0, sizeof(opts));
290   int optmask = 0;
291   EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel, &opts, &optmask));
292   EXPECT_EQ(5000, opts.timeout);
293   EXPECT_EQ(4, opts.tries);
294 
295   ares_destroy(channel);
296 }
297 
TEST_F(LibraryTest,EnvInitAllocFail)298 TEST_F(LibraryTest, EnvInitAllocFail) {
299   ares_channel_t *channel;
300   EnvValue v1("LOCALDOMAIN", "this.is.local");
301   EnvValue v2("RES_OPTIONS", "options debug ndots:3 retry:3 rotate retrans:2");
302   for (int ii = 1; ii <= 10; ii++) {
303     ClearFails();
304     SetAllocFail(ii);
305     channel = nullptr;
306     int rc = ares_init(&channel);
307     if (rc == ARES_SUCCESS) {
308       ares_destroy(channel);
309     } else {
310       EXPECT_EQ(ARES_ENOMEM, rc);
311     }
312   }
313 }
314 #endif
315 
TEST_F(DefaultChannelTest,SetAddresses)316 TEST_F(DefaultChannelTest, SetAddresses) {
317   ares_set_local_ip4(channel_, 0x01020304);
318   byte addr6[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
319                     0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};
320   ares_set_local_ip6(channel_, addr6);
321   ares_set_local_dev(channel_, "dummy");
322 }
323 
TEST_F(DefaultChannelTest,SetSortlistFailures)324 TEST_F(DefaultChannelTest, SetSortlistFailures) {
325   EXPECT_EQ(ARES_ENODATA, ares_set_sortlist(nullptr, "1.2.3.4"));
326   EXPECT_EQ(ARES_EBADSTR, ares_set_sortlist(channel_, "111.111.111.111*/16"));
327   EXPECT_EQ(ARES_EBADSTR, ares_set_sortlist(channel_, "111.111.111.111/255.255.255.240*"));
328   EXPECT_EQ(ARES_EBADSTR, ares_set_sortlist(channel_, "1 0123456789012345"));
329   EXPECT_EQ(ARES_EBADSTR, ares_set_sortlist(channel_, "1 /01234567890123456789012345678901"));
330   EXPECT_EQ(ARES_EBADSTR, ares_set_sortlist(channel_, "xyzzy ; lwk"));
331   EXPECT_EQ(ARES_EBADSTR, ares_set_sortlist(channel_, "xyzzy ; 0x123"));
332 }
333 
TEST_F(DefaultChannelTest,SetSortlistVariants)334 TEST_F(DefaultChannelTest, SetSortlistVariants) {
335   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "1.2.3.4"));
336   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "1.2.3.4 ; 2.3.4.5"));
337   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "1.2.3.4/26;1234::5678/126;4.5.6.7;5678::1234"));
338   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, " 1.2.3.4/26 1234::5678/126   4.5.6.7 5678::1234  "));
339   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "129.1.1.1"));
340   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "192.1.1.1"));
341   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "224.1.1.1"));
342   EXPECT_EQ(ARES_SUCCESS, ares_set_sortlist(channel_, "225.1.1.1"));
343 }
344 
TEST_F(DefaultChannelTest,SetSortlistAllocFail)345 TEST_F(DefaultChannelTest, SetSortlistAllocFail) {
346   for (int ii = 1; ii <= 3; ii++) {
347     ClearFails();
348     SetAllocFail(ii);
349     EXPECT_EQ(ARES_ENOMEM, ares_set_sortlist(channel_, "12.13.0.0/16 1234::5678/40 1.2.3.4")) << ii;
350   }
351 }
352 
353 #ifdef USE_WINSOCK
TEST(Init,NoLibraryInit)354 TEST(Init, NoLibraryInit) {
355   ares_channel_t *channel = nullptr;
356   EXPECT_EQ(ARES_ENOTINITIALIZED, ares_init(&channel));
357 }
358 #endif
359 
360 #ifdef HAVE_CONTAINER
361 // These tests rely on the ability of non-root users to create a chroot
362 // using Linux namespaces.
363 
364 
365 // The library uses a variety of information sources to initialize a channel,
366 // in particular to determine:
367 //  - search: the search domains to use
368 //  - servers: the name servers to use
369 //  - lookup: whether to check files or DNS or both (e.g. "fb")
370 //  - options: various resolver options
371 //  - sortlist: the order of preference for IP addresses
372 //
373 // The first source from the following list is used:
374 //  - init_by_options(): explicitly specified values in struct ares_options
375 //  - init_by_environment(): values from the environment:
376 //     - LOCALDOMAIN -> search (single value)
377 //     - RES_OPTIONS -> options
378 //  - init_by_resolv_conf(): values from various config files:
379 //     - /etc/resolv.conf -> search, lookup, servers, sortlist, options
380 //     - /etc/nsswitch.conf -> lookup
381 //     - /etc/host.conf -> lookup
382 //     - /etc/svc.conf -> lookup
383 //  - init_by_defaults(): fallback values:
384 //     - gethostname(3) -> domain
385 //     - "fb" -> lookup
386 
387 NameContentList filelist = {
388   {"/etc/resolv.conf", "nameserver 1.2.3.4\n"
389                        "sortlist 1.2.3.4/16 2.3.4.5\n"
390                        "search first.com second.com\n"},
391   {"/etc/hosts", "3.4.5.6 ahostname.com\n"},
392   {"/etc/nsswitch.conf", "hosts: files\n"}};
393 CONTAINED_TEST_F(LibraryTest, ContainerChannelInit,
394                  "myhostname", "mydomainname.org", filelist) {
395   ares_channel_t *channel = nullptr;
396   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
397   std::string actual = GetNameServers(channel);
398   std::string expected = "1.2.3.4:53";
399   EXPECT_EQ(expected, actual);
400   EXPECT_EQ(2, channel->ndomains);
401   EXPECT_EQ(std::string("first.com"), std::string(channel->domains[0]));
402   EXPECT_EQ(std::string("second.com"), std::string(channel->domains[1]));
403 
404   HostResult result;
405   ares_gethostbyname(channel, "ahostname.com", AF_INET, HostCallback, &result);
406   ProcessWork(channel, NoExtraFDs, nullptr);
407   EXPECT_TRUE(result.done_);
408   std::stringstream ss;
409   ss << result.host_;
410 
411   EXPECT_EQ("{'ahostname.com' aliases=[] addrs=[3.4.5.6]}", ss.str());
412 
413   ares_destroy(channel);
414   return HasFailure();
415 }
416 
417 CONTAINED_TEST_F(LibraryTest, ContainerSortlistOptionInit,
418                  "myhostname", "mydomainname.org", filelist) {
419   ares_channel_t *channel = nullptr;
420   struct ares_options opts;
421   memset(&opts, 0, sizeof(opts));
422   int optmask = 0;
423   optmask |= ARES_OPT_SORTLIST;
424   opts.nsort = 0;
425   // Explicitly specifying an empty sortlist in the options should override the
426   // environment.
427   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask));
428   EXPECT_EQ(0, channel->nsort);
429   EXPECT_EQ(nullptr, channel->sortlist);
430   EXPECT_EQ(ARES_OPT_SORTLIST, (channel->optmask & ARES_OPT_SORTLIST));
431 
432   ares_destroy(channel);
433   return HasFailure();
434 }
435 
436 NameContentList fullresolv = {
437   {"/etc/resolv.conf", " nameserver   1.2.3.4 \n"
438                        "search   first.com second.com\n"
439                        "lookup bind\n"
440                        "options debug ndots:5\n"
441                        "sortlist 1.2.3.4/16 2.3.4.5\n"}};
442 CONTAINED_TEST_F(LibraryTest, ContainerFullResolvInit,
443                  "myhostname", "mydomainname.org", fullresolv) {
444   ares_channel_t *channel = nullptr;
445   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
446 
447   EXPECT_EQ(std::string("b"), std::string(channel->lookups));
448   EXPECT_EQ(5, channel->ndots);
449 
450   ares_destroy(channel);
451   return HasFailure();
452 }
453 
454 // Allow path for resolv.conf to be configurable
455 NameContentList myresolvconf = {
456   {"/tmp/myresolv.cnf", " nameserver   1.2.3.4 \n"
457                        "search   first.com second.com\n"
458                        "lookup bind\n"
459                        "options debug ndots:5\n"
460                        "sortlist 1.2.3.4/16 2.3.4.5\n"}};
461 CONTAINED_TEST_F(LibraryTest, ContainerMyResolvConfInit,
462                  "myhostname", "mydomain.org", myresolvconf) {
463   char filename[] = "/tmp/myresolv.cnf";
464   ares_channel_t *channel = nullptr;
465   struct ares_options options;
466   memset(&options, 0, sizeof(options));
467   options.resolvconf_path = strdup(filename);
468   int optmask = ARES_OPT_RESOLVCONF;
469   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &options, optmask));
470 
471   optmask = 0;
472   free(options.resolvconf_path);
473   options.resolvconf_path = NULL;
474 
475   EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel, &options, &optmask));
476   EXPECT_EQ(ARES_OPT_RESOLVCONF, (optmask & ARES_OPT_RESOLVCONF));
477   EXPECT_EQ(std::string(filename), std::string(options.resolvconf_path));
478 
479   ares_destroy_options(&options);
480   ares_destroy(channel);
481   return HasFailure();
482 }
483 
484 // Allow hosts path to be configurable
485 NameContentList myhosts = {
486   {"/tmp/hosts", "10.0.12.26     foobar\n"
487                  "2001:A0:C::1A  foobar\n"}};
488 CONTAINED_TEST_F(LibraryTest, ContainerMyHostsInit,
489                  "myhostname", "mydomain.org", myhosts) {
490   char filename[] = "/tmp/hosts";
491   ares_channel_t *channel = nullptr;
492   struct ares_options options;
493 
494   options.hosts_path = strdup(filename);
495   int optmask = ARES_OPT_HOSTS_FILE;
496   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &options, optmask));
497   memset(&options, 0, sizeof(options));
498   optmask = 0;
499   free(options.hosts_path);
500   options.hosts_path = NULL;
501 
502   EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel, &options, &optmask));
503   EXPECT_EQ(ARES_OPT_HOSTS_FILE, (optmask & ARES_OPT_HOSTS_FILE));
504   EXPECT_EQ(std::string(filename), std::string(options.hosts_path));
505 
506   ares_destroy_options(&options);
507   ares_destroy(channel);
508   return HasFailure();
509 }
510 
511 NameContentList svcconf = {
512   {"/etc/resolv.conf", "nameserver 1.2.3.4\n"
513                        "search first.com second.com\n"},
514   {"/etc/svc.conf", "hosts= bind\n"}};
515 CONTAINED_TEST_F(LibraryTest, ContainerSvcConfInit,
516                  "myhostname", "mydomainname.org", svcconf) {
517   ares_channel_t *channel = nullptr;
518   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
519 
520   EXPECT_EQ(std::string("b"), std::string(channel->lookups));
521 
522   ares_destroy(channel);
523   return HasFailure();
524 }
525 
526 NameContentList malformedresolvconflookup = {
527   {"/etc/resolv.conf", "nameserver 1.2.3.4\n"
528                        "lookup garbage\n"}};  // malformed line
529 CONTAINED_TEST_F(LibraryTest, ContainerMalformedResolvConfLookup,
530                  "myhostname", "mydomainname.org", malformedresolvconflookup) {
531   ares_channel_t *channel = nullptr;
532   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
533 
534   EXPECT_EQ(std::string("fb"), std::string(channel->lookups));
535 
536   ares_destroy(channel);
537   return HasFailure();
538 }
539 
540 // Failures when expected config filenames are inaccessible.
541 class MakeUnreadable {
542  public:
MakeUnreadable(const std::string & filename)543   explicit MakeUnreadable(const std::string& filename)
544     : filename_(filename) {
545     chmod(filename_.c_str(), 0000);
546   }
~MakeUnreadable()547   ~MakeUnreadable() { chmod(filename_.c_str(), 0644); }
548  private:
549   std::string filename_;
550 };
551 
552 CONTAINED_TEST_F(LibraryTest, ContainerResolvConfNotReadable,
553                  "myhostname", "mydomainname.org", filelist) {
554   ares_channel_t *channel = nullptr;
555   MakeUnreadable hide("/etc/resolv.conf");
556   // Unavailable /etc/resolv.conf falls back to defaults
557   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
558   return HasFailure();
559 }
560 CONTAINED_TEST_F(LibraryTest, ContainerNsswitchConfNotReadable,
561                  "myhostname", "mydomainname.org", filelist) {
562   ares_channel_t *channel = nullptr;
563   // Unavailable /etc/nsswitch.conf falls back to defaults.
564   MakeUnreadable hide("/etc/nsswitch.conf");
565   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
566 
567   EXPECT_EQ(std::string("fb"), std::string(channel->lookups));
568 
569   ares_destroy(channel);
570   return HasFailure();
571 }
572 
573 CONTAINED_TEST_F(LibraryTest, ContainerSvcConfNotReadable,
574                  "myhostname", "mydomainname.org", svcconf) {
575   ares_channel_t *channel = nullptr;
576   // Unavailable /etc/svc.conf falls back to defaults.
577   MakeUnreadable hide("/etc/svc.conf");
578   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
579   ares_destroy(channel);
580   return HasFailure();
581 }
582 
583 NameContentList rotateenv = {
584   {"/etc/resolv.conf", "nameserver 1.2.3.4\n"
585                        "search first.com second.com\n"
586                        "options rotate\n"}};
587 CONTAINED_TEST_F(LibraryTest, ContainerRotateInit,
588                  "myhostname", "mydomainname.org", rotateenv) {
589   ares_channel_t *channel = nullptr;
590   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
591 
592   EXPECT_EQ(ARES_TRUE, channel->rotate);
593 
594   ares_destroy(channel);
595   return HasFailure();
596 }
597 
598 CONTAINED_TEST_F(LibraryTest, ContainerRotateOverride,
599                  "myhostname", "mydomainname.org", rotateenv) {
600   ares_channel_t *channel = nullptr;
601   struct ares_options opts;
602   memset(&opts, 0, sizeof(opts));
603   int optmask = ARES_OPT_NOROTATE;
604   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask));
605   optmask = 0;
606   ares_save_options(channel, &opts, &optmask);
607   EXPECT_EQ(ARES_OPT_NOROTATE, (optmask & ARES_OPT_NOROTATE));
608   ares_destroy_options(&opts);
609 
610   ares_destroy(channel);
611   return HasFailure();
612 }
613 
614 // Test that blacklisted IPv6 resolves are ignored.  They're filtered from any
615 // source, so resolv.conf is as good as any.
616 NameContentList blacklistedIpv6 = {
617   {"/etc/resolv.conf", " nameserver 254.192.1.1\n" // 0xfe.0xc0.0x01.0x01
618                        " nameserver fec0::dead\n"  // Blacklisted
619                        " nameserver ffc0::c001\n"  // Not blacklisted
620                        " domain first.com\n"},
621   {"/etc/nsswitch.conf", "hosts: files\n"}};
622 CONTAINED_TEST_F(LibraryTest, ContainerBlacklistedIpv6,
623                  "myhostname", "mydomainname.org", blacklistedIpv6) {
624   ares_channel_t *channel = nullptr;
625   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
626   std::string actual = GetNameServers(channel);
627   std::string expected = "254.192.1.1:53,"
628                          "[ffc0::c001]:53";
629   EXPECT_EQ(expected, actual);
630 
631   EXPECT_EQ(1, channel->ndomains);
632   EXPECT_EQ(std::string("first.com"), std::string(channel->domains[0]));
633 
634   ares_destroy(channel);
635   return HasFailure();
636 }
637 
638 NameContentList multiresolv = {
639   {"/etc/resolv.conf", " nameserver 1::2 ;  ;;\n"
640                        " domain first.com\n"},
641   {"/etc/nsswitch.conf", "hosts: files\n"}};
642 CONTAINED_TEST_F(LibraryTest, ContainerMultiResolvInit,
643                  "myhostname", "mydomainname.org", multiresolv) {
644   ares_channel_t *channel = nullptr;
645   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
646   std::string actual = GetNameServers(channel);
647   std::string expected = "[1::2]:53";
648   EXPECT_EQ(expected, actual);
649 
650   EXPECT_EQ(1, channel->ndomains);
651   EXPECT_EQ(std::string("first.com"), std::string(channel->domains[0]));
652 
653   ares_destroy(channel);
654   return HasFailure();
655 }
656 
657 NameContentList systemdresolv = {
658   {"/etc/resolv.conf", "nameserver 1.2.3.4\n"
659                        "domain first.com\n"},
660   {"/etc/nsswitch.conf", "hosts: junk resolve files\n"}};
661 CONTAINED_TEST_F(LibraryTest, ContainerSystemdResolvInit,
662                  "myhostname", "mydomainname.org", systemdresolv) {
663   ares_channel_t *channel = nullptr;
664   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
665 
666   EXPECT_EQ(std::string("bf"), std::string(channel->lookups));
667 
668   ares_destroy(channel);
669   return HasFailure();
670 }
671 
672 NameContentList empty = {};  // no files
673 CONTAINED_TEST_F(LibraryTest, ContainerEmptyInit,
674                  "host.domain.org", "domain.org", empty) {
675   ares_channel_t *channel = nullptr;
676   EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
677   std::string actual = GetNameServers(channel);
678   std::string expected = "127.0.0.1:53";
679   EXPECT_EQ(expected, actual);
680 
681   EXPECT_EQ(1, channel->ndomains);
682   EXPECT_EQ(std::string("domain.org"), std::string(channel->domains[0]));
683   EXPECT_EQ(std::string("fb"), std::string(channel->lookups));
684 
685   ares_destroy(channel);
686   return HasFailure();
687 }
688 
689 // Test that init fails if the flag to not use a default local named server is
690 // enabled and no other nameservers are available.
691 CONTAINED_TEST_F(LibraryTest, ContainerNoDfltSvrEmptyInit,
692                  "myhostname", "mydomainname.org", empty) {
693   ares_channel_t *channel = nullptr;
694   struct ares_options opts;
695   memset(&opts, 0, sizeof(opts));
696   int optmask = ARES_OPT_FLAGS;
697   opts.flags = ARES_FLAG_NO_DFLT_SVR;
698   EXPECT_EQ(ARES_ENOSERVER, ares_init_options(&channel, &opts, optmask));
699 
700   EXPECT_EQ(nullptr, channel);
701   return HasFailure();
702 }
703 // Test that init succeeds if the flag to not use a default local named server
704 // is enabled but other nameservers are available.
705 CONTAINED_TEST_F(LibraryTest, ContainerNoDfltSvrFullInit,
706                  "myhostname", "mydomainname.org", filelist) {
707   ares_channel_t *channel = nullptr;
708   struct ares_options opts;
709   memset(&opts, 0, sizeof(opts));
710   int optmask = ARES_OPT_FLAGS;
711   opts.flags = ARES_FLAG_NO_DFLT_SVR;
712   EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel, &opts, optmask));
713 
714   std::string actual = GetNameServers(channel);
715   std::string expected = "1.2.3.4:53";
716   EXPECT_EQ(expected, actual);
717 
718   ares_destroy(channel);
719   return HasFailure();
720 }
721 
722 #endif
723 
724 }  // namespace test
725 }  // namespace ares
726