11cb0ef41Sopenharmony_ci/* MIT License
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Copyright (c) 1998 Massachusetts Institute of Technology
41cb0ef41Sopenharmony_ci * Copyright (c) 2007 Daniel Stenberg
51cb0ef41Sopenharmony_ci *
61cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
71cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
81cb0ef41Sopenharmony_ci * in the Software without restriction, including without limitation the rights
91cb0ef41Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
101cb0ef41Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
111cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
121cb0ef41Sopenharmony_ci *
131cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice (including the next
141cb0ef41Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
151cb0ef41Sopenharmony_ci * Software.
161cb0ef41Sopenharmony_ci *
171cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
181cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
191cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
201cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
211cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
221cb0ef41Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
231cb0ef41Sopenharmony_ci * SOFTWARE.
241cb0ef41Sopenharmony_ci *
251cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT
261cb0ef41Sopenharmony_ci */
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci#include "ares_setup.h"
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci#ifdef HAVE_SYS_PARAM_H
311cb0ef41Sopenharmony_ci#  include <sys/param.h>
321cb0ef41Sopenharmony_ci#endif
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci#ifdef HAVE_NETINET_IN_H
351cb0ef41Sopenharmony_ci#  include <netinet/in.h>
361cb0ef41Sopenharmony_ci#endif
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci#ifdef HAVE_NETDB_H
391cb0ef41Sopenharmony_ci#  include <netdb.h>
401cb0ef41Sopenharmony_ci#endif
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci#ifdef HAVE_ARPA_INET_H
431cb0ef41Sopenharmony_ci#  include <arpa/inet.h>
441cb0ef41Sopenharmony_ci#endif
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci#include "ares_nameser.h"
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci#if defined(ANDROID) || defined(__ANDROID__)
491cb0ef41Sopenharmony_ci#  include <sys/system_properties.h>
501cb0ef41Sopenharmony_ci#  include "ares_android.h"
511cb0ef41Sopenharmony_ci/* From the Bionic sources */
521cb0ef41Sopenharmony_ci#  define DNS_PROP_NAME_PREFIX "net.dns"
531cb0ef41Sopenharmony_ci#  define MAX_DNS_PROPERTIES   8
541cb0ef41Sopenharmony_ci#endif
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci#if defined(CARES_USE_LIBRESOLV)
571cb0ef41Sopenharmony_ci#  include <resolv.h>
581cb0ef41Sopenharmony_ci#endif
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci#if defined(USE_WINSOCK) && defined(HAVE_IPHLPAPI_H)
611cb0ef41Sopenharmony_ci#  include <iphlpapi.h>
621cb0ef41Sopenharmony_ci#endif
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci#include "ares.h"
651cb0ef41Sopenharmony_ci#include "ares_inet_net_pton.h"
661cb0ef41Sopenharmony_ci#include "ares_platform.h"
671cb0ef41Sopenharmony_ci#include "ares_private.h"
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci#ifdef WATT32
701cb0ef41Sopenharmony_ci#  undef WIN32 /* Redefined in MingW/MSVC headers */
711cb0ef41Sopenharmony_ci#endif
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ciint ares_init(ares_channel_t **channelptr)
751cb0ef41Sopenharmony_ci{
761cb0ef41Sopenharmony_ci  return ares_init_options(channelptr, NULL, 0);
771cb0ef41Sopenharmony_ci}
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_cistatic int ares_query_timeout_cmp_cb(const void *arg1, const void *arg2)
801cb0ef41Sopenharmony_ci{
811cb0ef41Sopenharmony_ci  const struct query *q1 = arg1;
821cb0ef41Sopenharmony_ci  const struct query *q2 = arg2;
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci  if (q1->timeout.tv_sec > q2->timeout.tv_sec) {
851cb0ef41Sopenharmony_ci    return 1;
861cb0ef41Sopenharmony_ci  }
871cb0ef41Sopenharmony_ci  if (q1->timeout.tv_sec < q2->timeout.tv_sec) {
881cb0ef41Sopenharmony_ci    return -1;
891cb0ef41Sopenharmony_ci  }
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  if (q1->timeout.tv_usec > q2->timeout.tv_usec) {
921cb0ef41Sopenharmony_ci    return 1;
931cb0ef41Sopenharmony_ci  }
941cb0ef41Sopenharmony_ci  if (q1->timeout.tv_usec < q2->timeout.tv_usec) {
951cb0ef41Sopenharmony_ci    return -1;
961cb0ef41Sopenharmony_ci  }
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  return 0;
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_cistatic int server_sort_cb(const void *data1, const void *data2)
1021cb0ef41Sopenharmony_ci{
1031cb0ef41Sopenharmony_ci  const struct server_state *s1 = data1;
1041cb0ef41Sopenharmony_ci  const struct server_state *s2 = data2;
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  if (s1->consec_failures < s2->consec_failures) {
1071cb0ef41Sopenharmony_ci    return -1;
1081cb0ef41Sopenharmony_ci  }
1091cb0ef41Sopenharmony_ci  if (s1->consec_failures > s2->consec_failures) {
1101cb0ef41Sopenharmony_ci    return 1;
1111cb0ef41Sopenharmony_ci  }
1121cb0ef41Sopenharmony_ci  if (s1->idx < s2->idx) {
1131cb0ef41Sopenharmony_ci    return -1;
1141cb0ef41Sopenharmony_ci  }
1151cb0ef41Sopenharmony_ci  if (s1->idx > s2->idx) {
1161cb0ef41Sopenharmony_ci    return 1;
1171cb0ef41Sopenharmony_ci  }
1181cb0ef41Sopenharmony_ci  return 0;
1191cb0ef41Sopenharmony_ci}
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_cistatic void server_destroy_cb(void *data)
1221cb0ef41Sopenharmony_ci{
1231cb0ef41Sopenharmony_ci  if (data == NULL) {
1241cb0ef41Sopenharmony_ci    return;
1251cb0ef41Sopenharmony_ci  }
1261cb0ef41Sopenharmony_ci  ares__destroy_server(data);
1271cb0ef41Sopenharmony_ci}
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_cistatic ares_status_t init_by_defaults(ares_channel_t *channel)
1301cb0ef41Sopenharmony_ci{
1311cb0ef41Sopenharmony_ci  char         *hostname = NULL;
1321cb0ef41Sopenharmony_ci  ares_status_t rc       = ARES_SUCCESS;
1331cb0ef41Sopenharmony_ci#ifdef HAVE_GETHOSTNAME
1341cb0ef41Sopenharmony_ci  const char *dot;
1351cb0ef41Sopenharmony_ci#endif
1361cb0ef41Sopenharmony_ci  struct ares_addr addr;
1371cb0ef41Sopenharmony_ci  ares__llist_t   *sconfig = NULL;
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci  /* Enable EDNS by default */
1401cb0ef41Sopenharmony_ci  if (!(channel->optmask & ARES_OPT_FLAGS)) {
1411cb0ef41Sopenharmony_ci    channel->flags = ARES_FLAG_EDNS;
1421cb0ef41Sopenharmony_ci  }
1431cb0ef41Sopenharmony_ci  if (channel->ednspsz == 0) {
1441cb0ef41Sopenharmony_ci    channel->ednspsz = EDNSPACKETSZ;
1451cb0ef41Sopenharmony_ci  }
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci  if (channel->timeout == 0) {
1481cb0ef41Sopenharmony_ci    channel->timeout = DEFAULT_TIMEOUT;
1491cb0ef41Sopenharmony_ci  }
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  if (channel->tries == 0) {
1521cb0ef41Sopenharmony_ci    channel->tries = DEFAULT_TRIES;
1531cb0ef41Sopenharmony_ci  }
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  if (channel->ndots == 0) {
1561cb0ef41Sopenharmony_ci    channel->ndots = 1;
1571cb0ef41Sopenharmony_ci  }
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  if (ares__slist_len(channel->servers) == 0) {
1601cb0ef41Sopenharmony_ci    /* Add a default local named server to the channel unless configured not
1611cb0ef41Sopenharmony_ci     * to (in which case return an error).
1621cb0ef41Sopenharmony_ci     */
1631cb0ef41Sopenharmony_ci    if (channel->flags & ARES_FLAG_NO_DFLT_SVR) {
1641cb0ef41Sopenharmony_ci      rc = ARES_ENOSERVER;
1651cb0ef41Sopenharmony_ci      goto error;
1661cb0ef41Sopenharmony_ci    }
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci    addr.family            = AF_INET;
1691cb0ef41Sopenharmony_ci    addr.addr.addr4.s_addr = htonl(INADDR_LOOPBACK);
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci    rc = ares__sconfig_append(&sconfig, &addr, 0, 0, NULL);
1721cb0ef41Sopenharmony_ci    if (rc != ARES_SUCCESS) {
1731cb0ef41Sopenharmony_ci      goto error;
1741cb0ef41Sopenharmony_ci    }
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci    rc = ares__servers_update(channel, sconfig, ARES_FALSE);
1771cb0ef41Sopenharmony_ci    ares__llist_destroy(sconfig);
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci    if (rc != ARES_SUCCESS) {
1801cb0ef41Sopenharmony_ci      goto error;
1811cb0ef41Sopenharmony_ci    }
1821cb0ef41Sopenharmony_ci  }
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci#if defined(USE_WINSOCK)
1851cb0ef41Sopenharmony_ci#  define toolong(x) (x == -1) && (SOCKERRNO == WSAEFAULT)
1861cb0ef41Sopenharmony_ci#elif defined(ENAMETOOLONG)
1871cb0ef41Sopenharmony_ci#  define toolong(x) \
1881cb0ef41Sopenharmony_ci    (x == -1) && ((SOCKERRNO == ENAMETOOLONG) || (SOCKERRNO == EINVAL))
1891cb0ef41Sopenharmony_ci#else
1901cb0ef41Sopenharmony_ci#  define toolong(x) (x == -1) && (SOCKERRNO == EINVAL)
1911cb0ef41Sopenharmony_ci#endif
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci  if (channel->ndomains == 0) {
1941cb0ef41Sopenharmony_ci    /* Derive a default domain search list from the kernel hostname,
1951cb0ef41Sopenharmony_ci     * or set it to empty if the hostname isn't helpful.
1961cb0ef41Sopenharmony_ci     */
1971cb0ef41Sopenharmony_ci#ifndef HAVE_GETHOSTNAME
1981cb0ef41Sopenharmony_ci    channel->ndomains = 0; /* default to none */
1991cb0ef41Sopenharmony_ci#else
2001cb0ef41Sopenharmony_ci    GETHOSTNAME_TYPE_ARG2 lenv = 64;
2011cb0ef41Sopenharmony_ci    size_t                len  = 64;
2021cb0ef41Sopenharmony_ci    int                   res;
2031cb0ef41Sopenharmony_ci    channel->ndomains = 0; /* default to none */
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci    hostname = ares_malloc(len);
2061cb0ef41Sopenharmony_ci    if (!hostname) {
2071cb0ef41Sopenharmony_ci      rc = ARES_ENOMEM;
2081cb0ef41Sopenharmony_ci      goto error;
2091cb0ef41Sopenharmony_ci    }
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci    do {
2121cb0ef41Sopenharmony_ci      res = gethostname(hostname, lenv);
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci      if (toolong(res)) {
2151cb0ef41Sopenharmony_ci        char *p;
2161cb0ef41Sopenharmony_ci        len  *= 2;
2171cb0ef41Sopenharmony_ci        lenv *= 2;
2181cb0ef41Sopenharmony_ci        p     = ares_realloc(hostname, len);
2191cb0ef41Sopenharmony_ci        if (!p) {
2201cb0ef41Sopenharmony_ci          rc = ARES_ENOMEM;
2211cb0ef41Sopenharmony_ci          goto error;
2221cb0ef41Sopenharmony_ci        }
2231cb0ef41Sopenharmony_ci        hostname = p;
2241cb0ef41Sopenharmony_ci        continue;
2251cb0ef41Sopenharmony_ci      } else if (res) {
2261cb0ef41Sopenharmony_ci        /* Lets not treat a gethostname failure as critical, since we
2271cb0ef41Sopenharmony_ci         * are ok if gethostname doesn't even exist */
2281cb0ef41Sopenharmony_ci        *hostname = '\0';
2291cb0ef41Sopenharmony_ci        break;
2301cb0ef41Sopenharmony_ci      }
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci    } while (res != 0);
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci    dot = strchr(hostname, '.');
2351cb0ef41Sopenharmony_ci    if (dot) {
2361cb0ef41Sopenharmony_ci      /* a dot was found */
2371cb0ef41Sopenharmony_ci      channel->domains = ares_malloc(sizeof(char *));
2381cb0ef41Sopenharmony_ci      if (!channel->domains) {
2391cb0ef41Sopenharmony_ci        rc = ARES_ENOMEM;
2401cb0ef41Sopenharmony_ci        goto error;
2411cb0ef41Sopenharmony_ci      }
2421cb0ef41Sopenharmony_ci      channel->domains[0] = ares_strdup(dot + 1);
2431cb0ef41Sopenharmony_ci      if (!channel->domains[0]) {
2441cb0ef41Sopenharmony_ci        rc = ARES_ENOMEM;
2451cb0ef41Sopenharmony_ci        goto error;
2461cb0ef41Sopenharmony_ci      }
2471cb0ef41Sopenharmony_ci      channel->ndomains = 1;
2481cb0ef41Sopenharmony_ci    }
2491cb0ef41Sopenharmony_ci#endif
2501cb0ef41Sopenharmony_ci  }
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_ci  if (channel->nsort == 0) {
2531cb0ef41Sopenharmony_ci    channel->sortlist = NULL;
2541cb0ef41Sopenharmony_ci  }
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci  if (!channel->lookups) {
2571cb0ef41Sopenharmony_ci    channel->lookups = ares_strdup("fb");
2581cb0ef41Sopenharmony_ci    if (!channel->lookups) {
2591cb0ef41Sopenharmony_ci      rc = ARES_ENOMEM;
2601cb0ef41Sopenharmony_ci    }
2611cb0ef41Sopenharmony_ci  }
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_cierror:
2641cb0ef41Sopenharmony_ci  if (rc) {
2651cb0ef41Sopenharmony_ci    if (channel->domains && channel->domains[0]) {
2661cb0ef41Sopenharmony_ci      ares_free(channel->domains[0]);
2671cb0ef41Sopenharmony_ci    }
2681cb0ef41Sopenharmony_ci    if (channel->domains) {
2691cb0ef41Sopenharmony_ci      ares_free(channel->domains);
2701cb0ef41Sopenharmony_ci      channel->domains = NULL;
2711cb0ef41Sopenharmony_ci    }
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_ci    if (channel->lookups) {
2741cb0ef41Sopenharmony_ci      ares_free(channel->lookups);
2751cb0ef41Sopenharmony_ci      channel->lookups = NULL;
2761cb0ef41Sopenharmony_ci    }
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ci    if (channel->resolvconf_path) {
2791cb0ef41Sopenharmony_ci      ares_free(channel->resolvconf_path);
2801cb0ef41Sopenharmony_ci      channel->resolvconf_path = NULL;
2811cb0ef41Sopenharmony_ci    }
2821cb0ef41Sopenharmony_ci
2831cb0ef41Sopenharmony_ci    if (channel->hosts_path) {
2841cb0ef41Sopenharmony_ci      ares_free(channel->hosts_path);
2851cb0ef41Sopenharmony_ci      channel->hosts_path = NULL;
2861cb0ef41Sopenharmony_ci    }
2871cb0ef41Sopenharmony_ci  }
2881cb0ef41Sopenharmony_ci
2891cb0ef41Sopenharmony_ci  if (hostname) {
2901cb0ef41Sopenharmony_ci    ares_free(hostname);
2911cb0ef41Sopenharmony_ci  }
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ci  return rc;
2941cb0ef41Sopenharmony_ci}
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ciint ares_init_options(ares_channel_t           **channelptr,
2971cb0ef41Sopenharmony_ci                      const struct ares_options *options, int optmask)
2981cb0ef41Sopenharmony_ci{
2991cb0ef41Sopenharmony_ci  ares_channel_t *channel;
3001cb0ef41Sopenharmony_ci  ares_status_t   status = ARES_SUCCESS;
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci  if (ares_library_initialized() != ARES_SUCCESS) {
3031cb0ef41Sopenharmony_ci    return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */
3041cb0ef41Sopenharmony_ci  }
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_ci  channel = ares_malloc_zero(sizeof(*channel));
3071cb0ef41Sopenharmony_ci  if (!channel) {
3081cb0ef41Sopenharmony_ci    *channelptr = NULL;
3091cb0ef41Sopenharmony_ci    return ARES_ENOMEM;
3101cb0ef41Sopenharmony_ci  }
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ci  status = ares__channel_threading_init(channel);
3131cb0ef41Sopenharmony_ci  if (status != ARES_SUCCESS) {
3141cb0ef41Sopenharmony_ci    goto done;
3151cb0ef41Sopenharmony_ci  }
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci  /* Generate random key */
3181cb0ef41Sopenharmony_ci  channel->rand_state = ares__init_rand_state();
3191cb0ef41Sopenharmony_ci  if (channel->rand_state == NULL) {
3201cb0ef41Sopenharmony_ci    status = ARES_ENOMEM;
3211cb0ef41Sopenharmony_ci    DEBUGF(fprintf(stderr, "Error: init_id_key failed: %s\n",
3221cb0ef41Sopenharmony_ci                   ares_strerror(status)));
3231cb0ef41Sopenharmony_ci    goto done;
3241cb0ef41Sopenharmony_ci  }
3251cb0ef41Sopenharmony_ci
3261cb0ef41Sopenharmony_ci  /* Initialize Server List */
3271cb0ef41Sopenharmony_ci  channel->servers =
3281cb0ef41Sopenharmony_ci    ares__slist_create(channel->rand_state, server_sort_cb, server_destroy_cb);
3291cb0ef41Sopenharmony_ci  if (channel->servers == NULL) {
3301cb0ef41Sopenharmony_ci    status = ARES_ENOMEM;
3311cb0ef41Sopenharmony_ci    goto done;
3321cb0ef41Sopenharmony_ci  }
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci  /* Initialize our lists of queries */
3351cb0ef41Sopenharmony_ci  channel->all_queries = ares__llist_create(NULL);
3361cb0ef41Sopenharmony_ci  if (channel->all_queries == NULL) {
3371cb0ef41Sopenharmony_ci    status = ARES_ENOMEM;
3381cb0ef41Sopenharmony_ci    goto done;
3391cb0ef41Sopenharmony_ci  }
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  channel->queries_by_qid = ares__htable_szvp_create(NULL);
3421cb0ef41Sopenharmony_ci  if (channel->queries_by_qid == NULL) {
3431cb0ef41Sopenharmony_ci    status = ARES_ENOMEM;
3441cb0ef41Sopenharmony_ci    goto done;
3451cb0ef41Sopenharmony_ci  }
3461cb0ef41Sopenharmony_ci
3471cb0ef41Sopenharmony_ci  channel->queries_by_timeout =
3481cb0ef41Sopenharmony_ci    ares__slist_create(channel->rand_state, ares_query_timeout_cmp_cb, NULL);
3491cb0ef41Sopenharmony_ci  if (channel->queries_by_timeout == NULL) {
3501cb0ef41Sopenharmony_ci    status = ARES_ENOMEM;
3511cb0ef41Sopenharmony_ci    goto done;
3521cb0ef41Sopenharmony_ci  }
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci  channel->connnode_by_socket = ares__htable_asvp_create(NULL);
3551cb0ef41Sopenharmony_ci  if (channel->connnode_by_socket == NULL) {
3561cb0ef41Sopenharmony_ci    status = ARES_ENOMEM;
3571cb0ef41Sopenharmony_ci    goto done;
3581cb0ef41Sopenharmony_ci  }
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci  /* Initialize configuration by each of the four sources, from highest
3611cb0ef41Sopenharmony_ci   * precedence to lowest.
3621cb0ef41Sopenharmony_ci   */
3631cb0ef41Sopenharmony_ci
3641cb0ef41Sopenharmony_ci  status = ares__init_by_options(channel, options, optmask);
3651cb0ef41Sopenharmony_ci  if (status != ARES_SUCCESS) {
3661cb0ef41Sopenharmony_ci    DEBUGF(fprintf(stderr, "Error: init_by_options failed: %s\n",
3671cb0ef41Sopenharmony_ci                   ares_strerror(status)));
3681cb0ef41Sopenharmony_ci    /* If we fail to apply user-specified options, fail the whole init process
3691cb0ef41Sopenharmony_ci     */
3701cb0ef41Sopenharmony_ci    goto done;
3711cb0ef41Sopenharmony_ci  }
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci  if (channel->qcache_max_ttl > 0) {
3741cb0ef41Sopenharmony_ci    status = ares__qcache_create(channel->rand_state, channel->qcache_max_ttl,
3751cb0ef41Sopenharmony_ci                                 &channel->qcache);
3761cb0ef41Sopenharmony_ci    if (status != ARES_SUCCESS) {
3771cb0ef41Sopenharmony_ci      goto done;
3781cb0ef41Sopenharmony_ci    }
3791cb0ef41Sopenharmony_ci  }
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_ci  if (status == ARES_SUCCESS) {
3821cb0ef41Sopenharmony_ci    status = ares__init_by_sysconfig(channel);
3831cb0ef41Sopenharmony_ci    if (status != ARES_SUCCESS) {
3841cb0ef41Sopenharmony_ci      DEBUGF(fprintf(stderr, "Error: init_by_sysconfig failed: %s\n",
3851cb0ef41Sopenharmony_ci                     ares_strerror(status)));
3861cb0ef41Sopenharmony_ci    }
3871cb0ef41Sopenharmony_ci  }
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_ci  /*
3901cb0ef41Sopenharmony_ci   * No matter what failed or succeeded, seed defaults to provide
3911cb0ef41Sopenharmony_ci   * useful behavior for things that we missed.
3921cb0ef41Sopenharmony_ci   */
3931cb0ef41Sopenharmony_ci  status = init_by_defaults(channel);
3941cb0ef41Sopenharmony_ci  if (status != ARES_SUCCESS) {
3951cb0ef41Sopenharmony_ci    DEBUGF(fprintf(stderr, "Error: init_by_defaults failed: %s\n",
3961cb0ef41Sopenharmony_ci                   ares_strerror(status)));
3971cb0ef41Sopenharmony_ci    goto done;
3981cb0ef41Sopenharmony_ci  }
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ci  /* Initialize the event thread */
4011cb0ef41Sopenharmony_ci  if (channel->optmask & ARES_OPT_EVENT_THREAD) {
4021cb0ef41Sopenharmony_ci    status = ares_event_thread_init(channel);
4031cb0ef41Sopenharmony_ci    if (status != ARES_SUCCESS) {
4041cb0ef41Sopenharmony_ci      goto done;
4051cb0ef41Sopenharmony_ci    }
4061cb0ef41Sopenharmony_ci  }
4071cb0ef41Sopenharmony_ci
4081cb0ef41Sopenharmony_cidone:
4091cb0ef41Sopenharmony_ci  if (status != ARES_SUCCESS) {
4101cb0ef41Sopenharmony_ci    ares_destroy(channel);
4111cb0ef41Sopenharmony_ci    return (int)status;
4121cb0ef41Sopenharmony_ci  }
4131cb0ef41Sopenharmony_ci
4141cb0ef41Sopenharmony_ci  *channelptr = channel;
4151cb0ef41Sopenharmony_ci  return ARES_SUCCESS;
4161cb0ef41Sopenharmony_ci}
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ciares_status_t ares_reinit(ares_channel_t *channel)
4191cb0ef41Sopenharmony_ci{
4201cb0ef41Sopenharmony_ci  ares_status_t status;
4211cb0ef41Sopenharmony_ci
4221cb0ef41Sopenharmony_ci  if (channel == NULL) {
4231cb0ef41Sopenharmony_ci    return ARES_EFORMERR;
4241cb0ef41Sopenharmony_ci  }
4251cb0ef41Sopenharmony_ci
4261cb0ef41Sopenharmony_ci  ares__channel_lock(channel);
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci  status = ares__init_by_sysconfig(channel);
4291cb0ef41Sopenharmony_ci  if (status != ARES_SUCCESS) {
4301cb0ef41Sopenharmony_ci    DEBUGF(fprintf(stderr, "Error: init_by_sysconfig failed: %s\n",
4311cb0ef41Sopenharmony_ci                   ares_strerror(status)));
4321cb0ef41Sopenharmony_ci  }
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_ci  /* Flush cached queries on reinit */
4351cb0ef41Sopenharmony_ci  if (channel->qcache) {
4361cb0ef41Sopenharmony_ci    ares__qcache_flush(channel->qcache);
4371cb0ef41Sopenharmony_ci  }
4381cb0ef41Sopenharmony_ci
4391cb0ef41Sopenharmony_ci  ares__channel_unlock(channel);
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ci  return status;
4421cb0ef41Sopenharmony_ci}
4431cb0ef41Sopenharmony_ci
4441cb0ef41Sopenharmony_ci/* ares_dup() duplicates a channel handle with all its options and returns a
4451cb0ef41Sopenharmony_ci   new channel handle */
4461cb0ef41Sopenharmony_ciint ares_dup(ares_channel_t **dest, ares_channel_t *src)
4471cb0ef41Sopenharmony_ci{
4481cb0ef41Sopenharmony_ci  struct ares_options opts;
4491cb0ef41Sopenharmony_ci  ares_status_t       rc;
4501cb0ef41Sopenharmony_ci  int                 optmask;
4511cb0ef41Sopenharmony_ci
4521cb0ef41Sopenharmony_ci  if (dest == NULL || src == NULL) {
4531cb0ef41Sopenharmony_ci    return ARES_EFORMERR;
4541cb0ef41Sopenharmony_ci  }
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  *dest = NULL; /* in case of failure return NULL explicitly */
4571cb0ef41Sopenharmony_ci
4581cb0ef41Sopenharmony_ci  ares__channel_lock(src);
4591cb0ef41Sopenharmony_ci  /* First get the options supported by the old ares_save_options() function,
4601cb0ef41Sopenharmony_ci     which is most of them */
4611cb0ef41Sopenharmony_ci  rc = (ares_status_t)ares_save_options(src, &opts, &optmask);
4621cb0ef41Sopenharmony_ci  if (rc != ARES_SUCCESS) {
4631cb0ef41Sopenharmony_ci    ares_destroy_options(&opts);
4641cb0ef41Sopenharmony_ci    goto done;
4651cb0ef41Sopenharmony_ci  }
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ci  /* Then create the new channel with those options */
4681cb0ef41Sopenharmony_ci  rc = (ares_status_t)ares_init_options(dest, &opts, optmask);
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_ci  /* destroy the options copy to not leak any memory */
4711cb0ef41Sopenharmony_ci  ares_destroy_options(&opts);
4721cb0ef41Sopenharmony_ci
4731cb0ef41Sopenharmony_ci  if (rc != ARES_SUCCESS) {
4741cb0ef41Sopenharmony_ci    goto done;
4751cb0ef41Sopenharmony_ci  }
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_ci  /* Now clone the options that ares_save_options() doesn't support, but are
4781cb0ef41Sopenharmony_ci   * user-provided */
4791cb0ef41Sopenharmony_ci  (*dest)->sock_create_cb      = src->sock_create_cb;
4801cb0ef41Sopenharmony_ci  (*dest)->sock_create_cb_data = src->sock_create_cb_data;
4811cb0ef41Sopenharmony_ci  (*dest)->sock_config_cb      = src->sock_config_cb;
4821cb0ef41Sopenharmony_ci  (*dest)->sock_config_cb_data = src->sock_config_cb_data;
4831cb0ef41Sopenharmony_ci  (*dest)->sock_funcs          = src->sock_funcs;
4841cb0ef41Sopenharmony_ci  (*dest)->sock_func_cb_data   = src->sock_func_cb_data;
4851cb0ef41Sopenharmony_ci
4861cb0ef41Sopenharmony_ci  ares_strcpy((*dest)->local_dev_name, src->local_dev_name,
4871cb0ef41Sopenharmony_ci              sizeof((*dest)->local_dev_name));
4881cb0ef41Sopenharmony_ci  (*dest)->local_ip4 = src->local_ip4;
4891cb0ef41Sopenharmony_ci  memcpy((*dest)->local_ip6, src->local_ip6, sizeof(src->local_ip6));
4901cb0ef41Sopenharmony_ci
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci  /* Servers are a bit unique as ares_init_options() only allows ipv4 servers
4931cb0ef41Sopenharmony_ci   * and not a port per server, but there are other user specified ways, that
4941cb0ef41Sopenharmony_ci   * too will toggle the optmask ARES_OPT_SERVERS to let us know.  If that's
4951cb0ef41Sopenharmony_ci   * the case, pull them in.
4961cb0ef41Sopenharmony_ci   *
4971cb0ef41Sopenharmony_ci   * We don't want to clone system-configuration servers though.
4981cb0ef41Sopenharmony_ci   *
4991cb0ef41Sopenharmony_ci   * We must use the "csv" format to get things like link-local address support
5001cb0ef41Sopenharmony_ci   */
5011cb0ef41Sopenharmony_ci
5021cb0ef41Sopenharmony_ci  if (optmask & ARES_OPT_SERVERS) {
5031cb0ef41Sopenharmony_ci    char *csv = ares_get_servers_csv(src);
5041cb0ef41Sopenharmony_ci    if (csv == NULL) {
5051cb0ef41Sopenharmony_ci      ares_destroy(*dest);
5061cb0ef41Sopenharmony_ci      *dest = NULL;
5071cb0ef41Sopenharmony_ci      rc    = ARES_ENOMEM;
5081cb0ef41Sopenharmony_ci      goto done;
5091cb0ef41Sopenharmony_ci    }
5101cb0ef41Sopenharmony_ci
5111cb0ef41Sopenharmony_ci    rc = (ares_status_t)ares_set_servers_ports_csv(*dest, csv);
5121cb0ef41Sopenharmony_ci    ares_free_string(csv);
5131cb0ef41Sopenharmony_ci    if (rc != ARES_SUCCESS) {
5141cb0ef41Sopenharmony_ci      ares_destroy(*dest);
5151cb0ef41Sopenharmony_ci      *dest = NULL;
5161cb0ef41Sopenharmony_ci      goto done;
5171cb0ef41Sopenharmony_ci    }
5181cb0ef41Sopenharmony_ci  }
5191cb0ef41Sopenharmony_ci
5201cb0ef41Sopenharmony_ci  rc = ARES_SUCCESS;
5211cb0ef41Sopenharmony_cidone:
5221cb0ef41Sopenharmony_ci  ares__channel_unlock(src);
5231cb0ef41Sopenharmony_ci  return (int)rc; /* everything went fine */
5241cb0ef41Sopenharmony_ci}
5251cb0ef41Sopenharmony_ci
5261cb0ef41Sopenharmony_civoid ares_set_local_ip4(ares_channel_t *channel, unsigned int local_ip)
5271cb0ef41Sopenharmony_ci{
5281cb0ef41Sopenharmony_ci  if (channel == NULL) {
5291cb0ef41Sopenharmony_ci    return;
5301cb0ef41Sopenharmony_ci  }
5311cb0ef41Sopenharmony_ci  ares__channel_lock(channel);
5321cb0ef41Sopenharmony_ci  channel->local_ip4 = local_ip;
5331cb0ef41Sopenharmony_ci  ares__channel_unlock(channel);
5341cb0ef41Sopenharmony_ci}
5351cb0ef41Sopenharmony_ci
5361cb0ef41Sopenharmony_ci/* local_ip6 should be 16 bytes in length */
5371cb0ef41Sopenharmony_civoid ares_set_local_ip6(ares_channel_t *channel, const unsigned char *local_ip6)
5381cb0ef41Sopenharmony_ci{
5391cb0ef41Sopenharmony_ci  if (channel == NULL) {
5401cb0ef41Sopenharmony_ci    return;
5411cb0ef41Sopenharmony_ci  }
5421cb0ef41Sopenharmony_ci  ares__channel_lock(channel);
5431cb0ef41Sopenharmony_ci  memcpy(&channel->local_ip6, local_ip6, sizeof(channel->local_ip6));
5441cb0ef41Sopenharmony_ci  ares__channel_unlock(channel);
5451cb0ef41Sopenharmony_ci}
5461cb0ef41Sopenharmony_ci
5471cb0ef41Sopenharmony_ci/* local_dev_name should be null terminated. */
5481cb0ef41Sopenharmony_civoid ares_set_local_dev(ares_channel_t *channel, const char *local_dev_name)
5491cb0ef41Sopenharmony_ci{
5501cb0ef41Sopenharmony_ci  if (channel == NULL) {
5511cb0ef41Sopenharmony_ci    return;
5521cb0ef41Sopenharmony_ci  }
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci  ares__channel_lock(channel);
5551cb0ef41Sopenharmony_ci  ares_strcpy(channel->local_dev_name, local_dev_name,
5561cb0ef41Sopenharmony_ci              sizeof(channel->local_dev_name));
5571cb0ef41Sopenharmony_ci  channel->local_dev_name[sizeof(channel->local_dev_name) - 1] = 0;
5581cb0ef41Sopenharmony_ci  ares__channel_unlock(channel);
5591cb0ef41Sopenharmony_ci}
5601cb0ef41Sopenharmony_ci
5611cb0ef41Sopenharmony_ciint ares_set_sortlist(ares_channel_t *channel, const char *sortstr)
5621cb0ef41Sopenharmony_ci{
5631cb0ef41Sopenharmony_ci  size_t           nsort    = 0;
5641cb0ef41Sopenharmony_ci  struct apattern *sortlist = NULL;
5651cb0ef41Sopenharmony_ci  ares_status_t    status;
5661cb0ef41Sopenharmony_ci
5671cb0ef41Sopenharmony_ci  if (!channel) {
5681cb0ef41Sopenharmony_ci    return ARES_ENODATA;
5691cb0ef41Sopenharmony_ci  }
5701cb0ef41Sopenharmony_ci  ares__channel_lock(channel);
5711cb0ef41Sopenharmony_ci
5721cb0ef41Sopenharmony_ci  status = ares__parse_sortlist(&sortlist, &nsort, sortstr);
5731cb0ef41Sopenharmony_ci  if (status == ARES_SUCCESS && sortlist) {
5741cb0ef41Sopenharmony_ci    if (channel->sortlist) {
5751cb0ef41Sopenharmony_ci      ares_free(channel->sortlist);
5761cb0ef41Sopenharmony_ci    }
5771cb0ef41Sopenharmony_ci    channel->sortlist = sortlist;
5781cb0ef41Sopenharmony_ci    channel->nsort    = nsort;
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_ci    /* Save sortlist as if it was passed in as an option */
5811cb0ef41Sopenharmony_ci    channel->optmask |= ARES_OPT_SORTLIST;
5821cb0ef41Sopenharmony_ci  }
5831cb0ef41Sopenharmony_ci  ares__channel_unlock(channel);
5841cb0ef41Sopenharmony_ci  return (int)status;
5851cb0ef41Sopenharmony_ci}
586