1/* MIT License 2 * 3 * Copyright (c) 1998 Massachusetts Institute of Technology 4 * Copyright (c) 2007 Daniel Stenberg 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * SPDX-License-Identifier: MIT 26 */ 27 28#include "ares_setup.h" 29 30#ifdef HAVE_SYS_PARAM_H 31# include <sys/param.h> 32#endif 33 34#ifdef HAVE_NETINET_IN_H 35# include <netinet/in.h> 36#endif 37 38#ifdef HAVE_NETDB_H 39# include <netdb.h> 40#endif 41 42#ifdef HAVE_ARPA_INET_H 43# include <arpa/inet.h> 44#endif 45 46#include "ares_nameser.h" 47 48#if defined(ANDROID) || defined(__ANDROID__) 49# include <sys/system_properties.h> 50# include "ares_android.h" 51/* From the Bionic sources */ 52# define DNS_PROP_NAME_PREFIX "net.dns" 53# define MAX_DNS_PROPERTIES 8 54#endif 55 56#if defined(CARES_USE_LIBRESOLV) 57# include <resolv.h> 58#endif 59 60#if defined(USE_WINSOCK) && defined(HAVE_IPHLPAPI_H) 61# include <iphlpapi.h> 62#endif 63 64#include "ares.h" 65#include "ares_inet_net_pton.h" 66#include "ares_platform.h" 67#include "ares_private.h" 68 69#ifdef WATT32 70# undef WIN32 /* Redefined in MingW/MSVC headers */ 71#endif 72 73 74int ares_init(ares_channel_t **channelptr) 75{ 76 return ares_init_options(channelptr, NULL, 0); 77} 78 79static int ares_query_timeout_cmp_cb(const void *arg1, const void *arg2) 80{ 81 const struct query *q1 = arg1; 82 const struct query *q2 = arg2; 83 84 if (q1->timeout.tv_sec > q2->timeout.tv_sec) { 85 return 1; 86 } 87 if (q1->timeout.tv_sec < q2->timeout.tv_sec) { 88 return -1; 89 } 90 91 if (q1->timeout.tv_usec > q2->timeout.tv_usec) { 92 return 1; 93 } 94 if (q1->timeout.tv_usec < q2->timeout.tv_usec) { 95 return -1; 96 } 97 98 return 0; 99} 100 101static int server_sort_cb(const void *data1, const void *data2) 102{ 103 const struct server_state *s1 = data1; 104 const struct server_state *s2 = data2; 105 106 if (s1->consec_failures < s2->consec_failures) { 107 return -1; 108 } 109 if (s1->consec_failures > s2->consec_failures) { 110 return 1; 111 } 112 if (s1->idx < s2->idx) { 113 return -1; 114 } 115 if (s1->idx > s2->idx) { 116 return 1; 117 } 118 return 0; 119} 120 121static void server_destroy_cb(void *data) 122{ 123 if (data == NULL) { 124 return; 125 } 126 ares__destroy_server(data); 127} 128 129static ares_status_t init_by_defaults(ares_channel_t *channel) 130{ 131 char *hostname = NULL; 132 ares_status_t rc = ARES_SUCCESS; 133#ifdef HAVE_GETHOSTNAME 134 const char *dot; 135#endif 136 struct ares_addr addr; 137 ares__llist_t *sconfig = NULL; 138 139 /* Enable EDNS by default */ 140 if (!(channel->optmask & ARES_OPT_FLAGS)) { 141 channel->flags = ARES_FLAG_EDNS; 142 } 143 if (channel->ednspsz == 0) { 144 channel->ednspsz = EDNSPACKETSZ; 145 } 146 147 if (channel->timeout == 0) { 148 channel->timeout = DEFAULT_TIMEOUT; 149 } 150 151 if (channel->tries == 0) { 152 channel->tries = DEFAULT_TRIES; 153 } 154 155 if (channel->ndots == 0) { 156 channel->ndots = 1; 157 } 158 159 if (ares__slist_len(channel->servers) == 0) { 160 /* Add a default local named server to the channel unless configured not 161 * to (in which case return an error). 162 */ 163 if (channel->flags & ARES_FLAG_NO_DFLT_SVR) { 164 rc = ARES_ENOSERVER; 165 goto error; 166 } 167 168 addr.family = AF_INET; 169 addr.addr.addr4.s_addr = htonl(INADDR_LOOPBACK); 170 171 rc = ares__sconfig_append(&sconfig, &addr, 0, 0, NULL); 172 if (rc != ARES_SUCCESS) { 173 goto error; 174 } 175 176 rc = ares__servers_update(channel, sconfig, ARES_FALSE); 177 ares__llist_destroy(sconfig); 178 179 if (rc != ARES_SUCCESS) { 180 goto error; 181 } 182 } 183 184#if defined(USE_WINSOCK) 185# define toolong(x) (x == -1) && (SOCKERRNO == WSAEFAULT) 186#elif defined(ENAMETOOLONG) 187# define toolong(x) \ 188 (x == -1) && ((SOCKERRNO == ENAMETOOLONG) || (SOCKERRNO == EINVAL)) 189#else 190# define toolong(x) (x == -1) && (SOCKERRNO == EINVAL) 191#endif 192 193 if (channel->ndomains == 0) { 194 /* Derive a default domain search list from the kernel hostname, 195 * or set it to empty if the hostname isn't helpful. 196 */ 197#ifndef HAVE_GETHOSTNAME 198 channel->ndomains = 0; /* default to none */ 199#else 200 GETHOSTNAME_TYPE_ARG2 lenv = 64; 201 size_t len = 64; 202 int res; 203 channel->ndomains = 0; /* default to none */ 204 205 hostname = ares_malloc(len); 206 if (!hostname) { 207 rc = ARES_ENOMEM; 208 goto error; 209 } 210 211 do { 212 res = gethostname(hostname, lenv); 213 214 if (toolong(res)) { 215 char *p; 216 len *= 2; 217 lenv *= 2; 218 p = ares_realloc(hostname, len); 219 if (!p) { 220 rc = ARES_ENOMEM; 221 goto error; 222 } 223 hostname = p; 224 continue; 225 } else if (res) { 226 /* Lets not treat a gethostname failure as critical, since we 227 * are ok if gethostname doesn't even exist */ 228 *hostname = '\0'; 229 break; 230 } 231 232 } while (res != 0); 233 234 dot = strchr(hostname, '.'); 235 if (dot) { 236 /* a dot was found */ 237 channel->domains = ares_malloc(sizeof(char *)); 238 if (!channel->domains) { 239 rc = ARES_ENOMEM; 240 goto error; 241 } 242 channel->domains[0] = ares_strdup(dot + 1); 243 if (!channel->domains[0]) { 244 rc = ARES_ENOMEM; 245 goto error; 246 } 247 channel->ndomains = 1; 248 } 249#endif 250 } 251 252 if (channel->nsort == 0) { 253 channel->sortlist = NULL; 254 } 255 256 if (!channel->lookups) { 257 channel->lookups = ares_strdup("fb"); 258 if (!channel->lookups) { 259 rc = ARES_ENOMEM; 260 } 261 } 262 263error: 264 if (rc) { 265 if (channel->domains && channel->domains[0]) { 266 ares_free(channel->domains[0]); 267 } 268 if (channel->domains) { 269 ares_free(channel->domains); 270 channel->domains = NULL; 271 } 272 273 if (channel->lookups) { 274 ares_free(channel->lookups); 275 channel->lookups = NULL; 276 } 277 278 if (channel->resolvconf_path) { 279 ares_free(channel->resolvconf_path); 280 channel->resolvconf_path = NULL; 281 } 282 283 if (channel->hosts_path) { 284 ares_free(channel->hosts_path); 285 channel->hosts_path = NULL; 286 } 287 } 288 289 if (hostname) { 290 ares_free(hostname); 291 } 292 293 return rc; 294} 295 296int ares_init_options(ares_channel_t **channelptr, 297 const struct ares_options *options, int optmask) 298{ 299 ares_channel_t *channel; 300 ares_status_t status = ARES_SUCCESS; 301 302 if (ares_library_initialized() != ARES_SUCCESS) { 303 return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */ 304 } 305 306 channel = ares_malloc_zero(sizeof(*channel)); 307 if (!channel) { 308 *channelptr = NULL; 309 return ARES_ENOMEM; 310 } 311 312 status = ares__channel_threading_init(channel); 313 if (status != ARES_SUCCESS) { 314 goto done; 315 } 316 317 /* Generate random key */ 318 channel->rand_state = ares__init_rand_state(); 319 if (channel->rand_state == NULL) { 320 status = ARES_ENOMEM; 321 DEBUGF(fprintf(stderr, "Error: init_id_key failed: %s\n", 322 ares_strerror(status))); 323 goto done; 324 } 325 326 /* Initialize Server List */ 327 channel->servers = 328 ares__slist_create(channel->rand_state, server_sort_cb, server_destroy_cb); 329 if (channel->servers == NULL) { 330 status = ARES_ENOMEM; 331 goto done; 332 } 333 334 /* Initialize our lists of queries */ 335 channel->all_queries = ares__llist_create(NULL); 336 if (channel->all_queries == NULL) { 337 status = ARES_ENOMEM; 338 goto done; 339 } 340 341 channel->queries_by_qid = ares__htable_szvp_create(NULL); 342 if (channel->queries_by_qid == NULL) { 343 status = ARES_ENOMEM; 344 goto done; 345 } 346 347 channel->queries_by_timeout = 348 ares__slist_create(channel->rand_state, ares_query_timeout_cmp_cb, NULL); 349 if (channel->queries_by_timeout == NULL) { 350 status = ARES_ENOMEM; 351 goto done; 352 } 353 354 channel->connnode_by_socket = ares__htable_asvp_create(NULL); 355 if (channel->connnode_by_socket == NULL) { 356 status = ARES_ENOMEM; 357 goto done; 358 } 359 360 /* Initialize configuration by each of the four sources, from highest 361 * precedence to lowest. 362 */ 363 364 status = ares__init_by_options(channel, options, optmask); 365 if (status != ARES_SUCCESS) { 366 DEBUGF(fprintf(stderr, "Error: init_by_options failed: %s\n", 367 ares_strerror(status))); 368 /* If we fail to apply user-specified options, fail the whole init process 369 */ 370 goto done; 371 } 372 373 if (channel->qcache_max_ttl > 0) { 374 status = ares__qcache_create(channel->rand_state, channel->qcache_max_ttl, 375 &channel->qcache); 376 if (status != ARES_SUCCESS) { 377 goto done; 378 } 379 } 380 381 if (status == ARES_SUCCESS) { 382 status = ares__init_by_sysconfig(channel); 383 if (status != ARES_SUCCESS) { 384 DEBUGF(fprintf(stderr, "Error: init_by_sysconfig failed: %s\n", 385 ares_strerror(status))); 386 } 387 } 388 389 /* 390 * No matter what failed or succeeded, seed defaults to provide 391 * useful behavior for things that we missed. 392 */ 393 status = init_by_defaults(channel); 394 if (status != ARES_SUCCESS) { 395 DEBUGF(fprintf(stderr, "Error: init_by_defaults failed: %s\n", 396 ares_strerror(status))); 397 goto done; 398 } 399 400 /* Initialize the event thread */ 401 if (channel->optmask & ARES_OPT_EVENT_THREAD) { 402 status = ares_event_thread_init(channel); 403 if (status != ARES_SUCCESS) { 404 goto done; 405 } 406 } 407 408done: 409 if (status != ARES_SUCCESS) { 410 ares_destroy(channel); 411 return (int)status; 412 } 413 414 *channelptr = channel; 415 return ARES_SUCCESS; 416} 417 418ares_status_t ares_reinit(ares_channel_t *channel) 419{ 420 ares_status_t status; 421 422 if (channel == NULL) { 423 return ARES_EFORMERR; 424 } 425 426 ares__channel_lock(channel); 427 428 status = ares__init_by_sysconfig(channel); 429 if (status != ARES_SUCCESS) { 430 DEBUGF(fprintf(stderr, "Error: init_by_sysconfig failed: %s\n", 431 ares_strerror(status))); 432 } 433 434 /* Flush cached queries on reinit */ 435 if (channel->qcache) { 436 ares__qcache_flush(channel->qcache); 437 } 438 439 ares__channel_unlock(channel); 440 441 return status; 442} 443 444/* ares_dup() duplicates a channel handle with all its options and returns a 445 new channel handle */ 446int ares_dup(ares_channel_t **dest, ares_channel_t *src) 447{ 448 struct ares_options opts; 449 ares_status_t rc; 450 int optmask; 451 452 if (dest == NULL || src == NULL) { 453 return ARES_EFORMERR; 454 } 455 456 *dest = NULL; /* in case of failure return NULL explicitly */ 457 458 ares__channel_lock(src); 459 /* First get the options supported by the old ares_save_options() function, 460 which is most of them */ 461 rc = (ares_status_t)ares_save_options(src, &opts, &optmask); 462 if (rc != ARES_SUCCESS) { 463 ares_destroy_options(&opts); 464 goto done; 465 } 466 467 /* Then create the new channel with those options */ 468 rc = (ares_status_t)ares_init_options(dest, &opts, optmask); 469 470 /* destroy the options copy to not leak any memory */ 471 ares_destroy_options(&opts); 472 473 if (rc != ARES_SUCCESS) { 474 goto done; 475 } 476 477 /* Now clone the options that ares_save_options() doesn't support, but are 478 * user-provided */ 479 (*dest)->sock_create_cb = src->sock_create_cb; 480 (*dest)->sock_create_cb_data = src->sock_create_cb_data; 481 (*dest)->sock_config_cb = src->sock_config_cb; 482 (*dest)->sock_config_cb_data = src->sock_config_cb_data; 483 (*dest)->sock_funcs = src->sock_funcs; 484 (*dest)->sock_func_cb_data = src->sock_func_cb_data; 485 486 ares_strcpy((*dest)->local_dev_name, src->local_dev_name, 487 sizeof((*dest)->local_dev_name)); 488 (*dest)->local_ip4 = src->local_ip4; 489 memcpy((*dest)->local_ip6, src->local_ip6, sizeof(src->local_ip6)); 490 491 492 /* Servers are a bit unique as ares_init_options() only allows ipv4 servers 493 * and not a port per server, but there are other user specified ways, that 494 * too will toggle the optmask ARES_OPT_SERVERS to let us know. If that's 495 * the case, pull them in. 496 * 497 * We don't want to clone system-configuration servers though. 498 * 499 * We must use the "csv" format to get things like link-local address support 500 */ 501 502 if (optmask & ARES_OPT_SERVERS) { 503 char *csv = ares_get_servers_csv(src); 504 if (csv == NULL) { 505 ares_destroy(*dest); 506 *dest = NULL; 507 rc = ARES_ENOMEM; 508 goto done; 509 } 510 511 rc = (ares_status_t)ares_set_servers_ports_csv(*dest, csv); 512 ares_free_string(csv); 513 if (rc != ARES_SUCCESS) { 514 ares_destroy(*dest); 515 *dest = NULL; 516 goto done; 517 } 518 } 519 520 rc = ARES_SUCCESS; 521done: 522 ares__channel_unlock(src); 523 return (int)rc; /* everything went fine */ 524} 525 526void ares_set_local_ip4(ares_channel_t *channel, unsigned int local_ip) 527{ 528 if (channel == NULL) { 529 return; 530 } 531 ares__channel_lock(channel); 532 channel->local_ip4 = local_ip; 533 ares__channel_unlock(channel); 534} 535 536/* local_ip6 should be 16 bytes in length */ 537void ares_set_local_ip6(ares_channel_t *channel, const unsigned char *local_ip6) 538{ 539 if (channel == NULL) { 540 return; 541 } 542 ares__channel_lock(channel); 543 memcpy(&channel->local_ip6, local_ip6, sizeof(channel->local_ip6)); 544 ares__channel_unlock(channel); 545} 546 547/* local_dev_name should be null terminated. */ 548void ares_set_local_dev(ares_channel_t *channel, const char *local_dev_name) 549{ 550 if (channel == NULL) { 551 return; 552 } 553 554 ares__channel_lock(channel); 555 ares_strcpy(channel->local_dev_name, local_dev_name, 556 sizeof(channel->local_dev_name)); 557 channel->local_dev_name[sizeof(channel->local_dev_name) - 1] = 0; 558 ares__channel_unlock(channel); 559} 560 561int ares_set_sortlist(ares_channel_t *channel, const char *sortstr) 562{ 563 size_t nsort = 0; 564 struct apattern *sortlist = NULL; 565 ares_status_t status; 566 567 if (!channel) { 568 return ARES_ENODATA; 569 } 570 ares__channel_lock(channel); 571 572 status = ares__parse_sortlist(&sortlist, &nsort, sortstr); 573 if (status == ARES_SUCCESS && sortlist) { 574 if (channel->sortlist) { 575 ares_free(channel->sortlist); 576 } 577 channel->sortlist = sortlist; 578 channel->nsort = nsort; 579 580 /* Save sortlist as if it was passed in as an option */ 581 channel->optmask |= ARES_OPT_SORTLIST; 582 } 583 ares__channel_unlock(channel); 584 return (int)status; 585} 586