ares-test-init.cc (25569B)
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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: 543 explicit MakeUnreadable(const std::string& filename) 544 : filename_(filename) { 545 chmod(filename_.c_str(), 0000); 546 } 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