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