diff options
author | neksard <neksard@yandex-team.ru> | 2022-02-10 16:45:23 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:23 +0300 |
commit | 8f7cf138264e0caa318144bf8a2c950e0b0a8593 (patch) | |
tree | 83bf5c8c8047c42d8475e6095df90ccdc3d1b57f /contrib/libs/c-ares/ares_init.c | |
parent | d3a398281c6fd1d3672036cb2d63f842d2cb28c5 (diff) | |
download | ydb-8f7cf138264e0caa318144bf8a2c950e0b0a8593.tar.gz |
Restoring authorship annotation for <neksard@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/c-ares/ares_init.c')
-rw-r--r-- | contrib/libs/c-ares/ares_init.c | 3506 |
1 files changed, 1753 insertions, 1753 deletions
diff --git a/contrib/libs/c-ares/ares_init.c b/contrib/libs/c-ares/ares_init.c index e06265c6a2..9ea3ec16c6 100644 --- a/contrib/libs/c-ares/ares_init.c +++ b/contrib/libs/c-ares/ares_init.c @@ -1,440 +1,440 @@ - -/* Copyright 1998 by the Massachusetts Institute of Technology. - * Copyright (C) 2007-2013 by Daniel Stenberg - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without - * fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting - * documentation, and that the name of M.I.T. not be used in - * advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" - * without express or implied warranty. - */ - -#include "ares_setup.h" - -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif - -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif - -#ifdef HAVE_NETDB_H -#include <netdb.h> -#endif - -#ifdef HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif - -#ifdef HAVE_ARPA_NAMESER_H -# include <arpa/nameser.h> -#else -# include "nameser.h" -#endif -#ifdef HAVE_ARPA_NAMESER_COMPAT_H -# include <arpa/nameser_compat.h> -#endif - -#if defined(ANDROID) || defined(__ANDROID__) -#include <sys/system_properties.h> + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2007-2013 by Daniel Stenberg + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif + +#ifdef HAVE_ARPA_NAMESER_H +# include <arpa/nameser.h> +#else +# include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +# include <arpa/nameser_compat.h> +#endif + +#if defined(ANDROID) || defined(__ANDROID__) +#include <sys/system_properties.h> #include "ares_android.h" -/* From the Bionic sources */ -#define DNS_PROP_NAME_PREFIX "net.dns" -#define MAX_DNS_PROPERTIES 8 -#endif - +/* From the Bionic sources */ +#define DNS_PROP_NAME_PREFIX "net.dns" +#define MAX_DNS_PROPERTIES 8 +#endif + #if defined(CARES_USE_LIBRESOLV) #include <resolv.h> #endif -#include "ares.h" -#include "ares_inet_net_pton.h" -#include "ares_library_init.h" -#include "ares_nowarn.h" -#include "ares_platform.h" -#include "ares_private.h" - -#ifdef WATT32 -#undef WIN32 /* Redefined in MingW/MSVC headers */ -#endif - -static int init_by_options(ares_channel channel, - const struct ares_options *options, - int optmask); -static int init_by_environment(ares_channel channel); -static int init_by_resolv_conf(ares_channel channel); -static int init_by_defaults(ares_channel channel); - -#ifndef WATT32 -static int config_nameserver(struct server_state **servers, int *nservers, - char *str); -#endif -static int set_search(ares_channel channel, const char *str); -static int set_options(ares_channel channel, const char *str); -static const char *try_option(const char *p, const char *q, const char *opt); -static int init_id_key(rc4_key* key,int key_data_len); - +#include "ares.h" +#include "ares_inet_net_pton.h" +#include "ares_library_init.h" +#include "ares_nowarn.h" +#include "ares_platform.h" +#include "ares_private.h" + +#ifdef WATT32 +#undef WIN32 /* Redefined in MingW/MSVC headers */ +#endif + +static int init_by_options(ares_channel channel, + const struct ares_options *options, + int optmask); +static int init_by_environment(ares_channel channel); +static int init_by_resolv_conf(ares_channel channel); +static int init_by_defaults(ares_channel channel); + +#ifndef WATT32 +static int config_nameserver(struct server_state **servers, int *nservers, + char *str); +#endif +static int set_search(ares_channel channel, const char *str); +static int set_options(ares_channel channel, const char *str); +static const char *try_option(const char *p, const char *q, const char *opt); +static int init_id_key(rc4_key* key,int key_data_len); + static int config_sortlist(struct apattern **sortlist, int *nsort, const char *str); -static int sortlist_alloc(struct apattern **sortlist, int *nsort, - struct apattern *pat); +static int sortlist_alloc(struct apattern **sortlist, int *nsort, + struct apattern *pat); static int ip_addr(const char *s, ares_ssize_t len, struct in_addr *addr); -static void natural_mask(struct apattern *pat); +static void natural_mask(struct apattern *pat); #if !defined(WIN32) && !defined(WATT32) && \ !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV) -static int config_domain(ares_channel channel, char *str); -static int config_lookup(ares_channel channel, const char *str, +static int config_domain(ares_channel channel, char *str); +static int config_lookup(ares_channel channel, const char *str, const char *bindch, const char *altbindch, const char *filech); -static char *try_config(char *s, const char *opt, char scc); -#endif - -#define ARES_CONFIG_CHECK(x) (x->lookups && x->nsort > -1 && \ - x->nservers > -1 && \ - x->ndomains > -1 && \ - x->ndots > -1 && x->timeout > -1 && \ - x->tries > -1) - -int ares_init(ares_channel *channelptr) -{ - return ares_init_options(channelptr, NULL, 0); -} - -int ares_init_options(ares_channel *channelptr, struct ares_options *options, - int optmask) -{ - ares_channel channel; - int i; - int status = ARES_SUCCESS; - struct timeval now; - -#ifdef CURLDEBUG - const char *env = getenv("CARES_MEMDEBUG"); - - if (env) - curl_memdebug(env); - env = getenv("CARES_MEMLIMIT"); - if (env) { - char *endptr; - long num = strtol(env, &endptr, 10); - if((endptr != env) && (endptr == env + strlen(env)) && (num > 0)) - curl_memlimit(num); - } -#endif - - if (ares_library_initialized() != ARES_SUCCESS) +static char *try_config(char *s, const char *opt, char scc); +#endif + +#define ARES_CONFIG_CHECK(x) (x->lookups && x->nsort > -1 && \ + x->nservers > -1 && \ + x->ndomains > -1 && \ + x->ndots > -1 && x->timeout > -1 && \ + x->tries > -1) + +int ares_init(ares_channel *channelptr) +{ + return ares_init_options(channelptr, NULL, 0); +} + +int ares_init_options(ares_channel *channelptr, struct ares_options *options, + int optmask) +{ + ares_channel channel; + int i; + int status = ARES_SUCCESS; + struct timeval now; + +#ifdef CURLDEBUG + const char *env = getenv("CARES_MEMDEBUG"); + + if (env) + curl_memdebug(env); + env = getenv("CARES_MEMLIMIT"); + if (env) { + char *endptr; + long num = strtol(env, &endptr, 10); + if((endptr != env) && (endptr == env + strlen(env)) && (num > 0)) + curl_memlimit(num); + } +#endif + + if (ares_library_initialized() != ARES_SUCCESS) return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */ - + channel = ares_malloc(sizeof(struct ares_channeldata)); - if (!channel) { - *channelptr = NULL; - return ARES_ENOMEM; - } - - now = ares__tvnow(); - - /* Set everything to distinguished values so we know they haven't - * been set yet. - */ - channel->flags = -1; - channel->timeout = -1; + if (!channel) { + *channelptr = NULL; + return ARES_ENOMEM; + } + + now = ares__tvnow(); + + /* Set everything to distinguished values so we know they haven't + * been set yet. + */ + channel->flags = -1; + channel->timeout = -1; channel->maxtimeout = -1; channel->jitter = -1; channel->jitter_rand_state = -1; - channel->tries = -1; - channel->ndots = -1; - channel->rotate = -1; - channel->udp_port = -1; - channel->tcp_port = -1; - channel->ednspsz = -1; - channel->socket_send_buffer_size = -1; - channel->socket_receive_buffer_size = -1; - channel->nservers = -1; - channel->ndomains = -1; - channel->nsort = -1; - channel->tcp_connection_generation = 0; - channel->lookups = NULL; - channel->domains = NULL; - channel->sortlist = NULL; - channel->servers = NULL; - channel->sock_state_cb = NULL; - channel->sock_state_cb_data = NULL; - channel->sock_create_cb = NULL; - channel->sock_create_cb_data = NULL; + channel->tries = -1; + channel->ndots = -1; + channel->rotate = -1; + channel->udp_port = -1; + channel->tcp_port = -1; + channel->ednspsz = -1; + channel->socket_send_buffer_size = -1; + channel->socket_receive_buffer_size = -1; + channel->nservers = -1; + channel->ndomains = -1; + channel->nsort = -1; + channel->tcp_connection_generation = 0; + channel->lookups = NULL; + channel->domains = NULL; + channel->sortlist = NULL; + channel->servers = NULL; + channel->sock_state_cb = NULL; + channel->sock_state_cb_data = NULL; + channel->sock_create_cb = NULL; + channel->sock_create_cb_data = NULL; channel->sock_config_cb = NULL; channel->sock_config_cb_data = NULL; channel->sock_funcs = NULL; channel->sock_func_cb_data = NULL; channel->resolvconf_path = NULL; - - channel->last_server = 0; - channel->last_timeout_processed = (time_t)now.tv_sec; - - memset(&channel->local_dev_name, 0, sizeof(channel->local_dev_name)); - channel->local_ip4 = 0; - memset(&channel->local_ip6, 0, sizeof(channel->local_ip6)); - - /* Initialize our lists of queries */ - ares__init_list_head(&(channel->all_queries)); - for (i = 0; i < ARES_QID_TABLE_SIZE; i++) - { - ares__init_list_head(&(channel->queries_by_qid[i])); - } - for (i = 0; i < ARES_TIMEOUT_TABLE_SIZE; i++) - { - ares__init_list_head(&(channel->queries_by_timeout[i])); - } - - /* Initialize configuration by each of the four sources, from highest - * precedence to lowest. - */ - + + channel->last_server = 0; + channel->last_timeout_processed = (time_t)now.tv_sec; + + memset(&channel->local_dev_name, 0, sizeof(channel->local_dev_name)); + channel->local_ip4 = 0; + memset(&channel->local_ip6, 0, sizeof(channel->local_ip6)); + + /* Initialize our lists of queries */ + ares__init_list_head(&(channel->all_queries)); + for (i = 0; i < ARES_QID_TABLE_SIZE; i++) + { + ares__init_list_head(&(channel->queries_by_qid[i])); + } + for (i = 0; i < ARES_TIMEOUT_TABLE_SIZE; i++) + { + ares__init_list_head(&(channel->queries_by_timeout[i])); + } + + /* Initialize configuration by each of the four sources, from highest + * precedence to lowest. + */ + status = init_by_options(channel, options, optmask); if (status != ARES_SUCCESS) { DEBUGF(fprintf(stderr, "Error: init_by_options failed: %s\n", ares_strerror(status))); /* If we fail to apply user-specified options, fail the whole init process */ goto done; - } + } status = init_by_environment(channel); if (status != ARES_SUCCESS) DEBUGF(fprintf(stderr, "Error: init_by_environment failed: %s\n", ares_strerror(status))); - if (status == ARES_SUCCESS) { - status = init_by_resolv_conf(channel); - if (status != ARES_SUCCESS) - DEBUGF(fprintf(stderr, "Error: init_by_resolv_conf failed: %s\n", - ares_strerror(status))); - } - - /* - * No matter what failed or succeeded, seed defaults to provide - * useful behavior for things that we missed. - */ - status = init_by_defaults(channel); - if (status != ARES_SUCCESS) - DEBUGF(fprintf(stderr, "Error: init_by_defaults failed: %s\n", - ares_strerror(status))); - - /* Generate random key */ - - if (status == ARES_SUCCESS) { - status = init_id_key(&channel->id_key, ARES_ID_KEY_LEN); - if (status == ARES_SUCCESS) - channel->next_id = ares__generate_new_id(&channel->id_key); - else - DEBUGF(fprintf(stderr, "Error: init_id_key failed: %s\n", - ares_strerror(status))); - } - + if (status == ARES_SUCCESS) { + status = init_by_resolv_conf(channel); + if (status != ARES_SUCCESS) + DEBUGF(fprintf(stderr, "Error: init_by_resolv_conf failed: %s\n", + ares_strerror(status))); + } + + /* + * No matter what failed or succeeded, seed defaults to provide + * useful behavior for things that we missed. + */ + status = init_by_defaults(channel); + if (status != ARES_SUCCESS) + DEBUGF(fprintf(stderr, "Error: init_by_defaults failed: %s\n", + ares_strerror(status))); + + /* Generate random key */ + + if (status == ARES_SUCCESS) { + status = init_id_key(&channel->id_key, ARES_ID_KEY_LEN); + if (status == ARES_SUCCESS) + channel->next_id = ares__generate_new_id(&channel->id_key); + else + DEBUGF(fprintf(stderr, "Error: init_id_key failed: %s\n", + ares_strerror(status))); + } + done: - if (status != ARES_SUCCESS) - { - /* Something failed; clean up memory we may have allocated. */ - if (channel->servers) + if (status != ARES_SUCCESS) + { + /* Something failed; clean up memory we may have allocated. */ + if (channel->servers) ares_free(channel->servers); if (channel->ndomains != -1) ares_strsplit_free(channel->domains, channel->ndomains); - if (channel->sortlist) + if (channel->sortlist) ares_free(channel->sortlist); - if(channel->lookups) + if(channel->lookups) ares_free(channel->lookups); if(channel->resolvconf_path) ares_free(channel->resolvconf_path); ares_free(channel); - return status; - } - - /* Trim to one server if ARES_FLAG_PRIMARY is set. */ - if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1) - channel->nservers = 1; - - ares__init_servers_state(channel); - - *channelptr = channel; - return ARES_SUCCESS; -} - -/* ares_dup() duplicates a channel handle with all its options and returns a - new channel handle */ -int ares_dup(ares_channel *dest, ares_channel src) -{ - struct ares_options opts; + return status; + } + + /* Trim to one server if ARES_FLAG_PRIMARY is set. */ + if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1) + channel->nservers = 1; + + ares__init_servers_state(channel); + + *channelptr = channel; + return ARES_SUCCESS; +} + +/* ares_dup() duplicates a channel handle with all its options and returns a + new channel handle */ +int ares_dup(ares_channel *dest, ares_channel src) +{ + struct ares_options opts; struct ares_addr_port_node *servers; int non_v4_default_port = 0; - int i, rc; - int optmask; - - *dest = NULL; /* in case of failure return NULL explicitly */ - - /* First get the options supported by the old ares_save_options() function, - which is most of them */ - rc = ares_save_options(src, &opts, &optmask); - if(rc) + int i, rc; + int optmask; + + *dest = NULL; /* in case of failure return NULL explicitly */ + + /* First get the options supported by the old ares_save_options() function, + which is most of them */ + rc = ares_save_options(src, &opts, &optmask); + if(rc) { ares_destroy_options(&opts); - return rc; + return rc; } - - /* Then create the new channel with those options */ - rc = ares_init_options(dest, &opts, optmask); - - /* destroy the options copy to not leak any memory */ - ares_destroy_options(&opts); - - if(rc) - return rc; - - /* Now clone the options that ares_save_options() doesn't support. */ - (*dest)->sock_create_cb = src->sock_create_cb; - (*dest)->sock_create_cb_data = src->sock_create_cb_data; + + /* Then create the new channel with those options */ + rc = ares_init_options(dest, &opts, optmask); + + /* destroy the options copy to not leak any memory */ + ares_destroy_options(&opts); + + if(rc) + return rc; + + /* Now clone the options that ares_save_options() doesn't support. */ + (*dest)->sock_create_cb = src->sock_create_cb; + (*dest)->sock_create_cb_data = src->sock_create_cb_data; (*dest)->sock_config_cb = src->sock_config_cb; (*dest)->sock_config_cb_data = src->sock_config_cb_data; (*dest)->sock_funcs = src->sock_funcs; (*dest)->sock_func_cb_data = src->sock_func_cb_data; - - strncpy((*dest)->local_dev_name, src->local_dev_name, + + strncpy((*dest)->local_dev_name, src->local_dev_name, sizeof((*dest)->local_dev_name)); - (*dest)->local_ip4 = src->local_ip4; - memcpy((*dest)->local_ip6, src->local_ip6, sizeof(src->local_ip6)); - + (*dest)->local_ip4 = src->local_ip4; + memcpy((*dest)->local_ip6, src->local_ip6, sizeof(src->local_ip6)); + /* Full name server cloning required if there is a non-IPv4, or non-default port, nameserver */ - for (i = 0; i < src->nservers; i++) - { + for (i = 0; i < src->nservers; i++) + { if ((src->servers[i].addr.family != AF_INET) || (src->servers[i].addr.udp_port != 0) || (src->servers[i].addr.tcp_port != 0)) { non_v4_default_port++; - break; - } - } + break; + } + } if (non_v4_default_port) { rc = ares_get_servers_ports(src, &servers); if (rc != ARES_SUCCESS) { ares_destroy(*dest); *dest = NULL; - return rc; + return rc; } rc = ares_set_servers_ports(*dest, servers); - ares_free_data(servers); + ares_free_data(servers); if (rc != ARES_SUCCESS) { ares_destroy(*dest); *dest = NULL; - return rc; + return rc; } - } - - return ARES_SUCCESS; /* everything went fine */ -} - -/* Save options from initialized channel */ -int ares_save_options(ares_channel channel, struct ares_options *options, - int *optmask) -{ - int i, j; - int ipv4_nservers = 0; - - /* Zero everything out */ - memset(options, 0, sizeof(struct ares_options)); - - if (!ARES_CONFIG_CHECK(channel)) - return ARES_ENODATA; - - /* Traditionally the optmask wasn't saved in the channel struct so it was - recreated here. ROTATE is the first option that has no struct field of - its own in the public config struct */ - (*optmask) = (ARES_OPT_FLAGS|ARES_OPT_TRIES|ARES_OPT_NDOTS| - ARES_OPT_UDP_PORT|ARES_OPT_TCP_PORT|ARES_OPT_SOCK_STATE_CB| - ARES_OPT_SERVERS|ARES_OPT_DOMAINS|ARES_OPT_LOOKUPS| + } + + return ARES_SUCCESS; /* everything went fine */ +} + +/* Save options from initialized channel */ +int ares_save_options(ares_channel channel, struct ares_options *options, + int *optmask) +{ + int i, j; + int ipv4_nservers = 0; + + /* Zero everything out */ + memset(options, 0, sizeof(struct ares_options)); + + if (!ARES_CONFIG_CHECK(channel)) + return ARES_ENODATA; + + /* Traditionally the optmask wasn't saved in the channel struct so it was + recreated here. ROTATE is the first option that has no struct field of + its own in the public config struct */ + (*optmask) = (ARES_OPT_FLAGS|ARES_OPT_TRIES|ARES_OPT_NDOTS| + ARES_OPT_UDP_PORT|ARES_OPT_TCP_PORT|ARES_OPT_SOCK_STATE_CB| + ARES_OPT_SERVERS|ARES_OPT_DOMAINS|ARES_OPT_LOOKUPS| ARES_OPT_SORTLIST|ARES_OPT_TIMEOUTMS|ARES_OPT_MAXTIMEOUTMS| ARES_OPT_JITTER); (*optmask) |= (channel->rotate ? ARES_OPT_ROTATE : ARES_OPT_NOROTATE); - + if (channel->resolvconf_path) (*optmask) |= ARES_OPT_RESOLVCONF; - /* Copy easy stuff */ - options->flags = channel->flags; - - /* We return full millisecond resolution but that's only because we don't - set the ARES_OPT_TIMEOUT anymore, only the new ARES_OPT_TIMEOUTMS */ - options->timeout = channel->timeout; + /* Copy easy stuff */ + options->flags = channel->flags; + + /* We return full millisecond resolution but that's only because we don't + set the ARES_OPT_TIMEOUT anymore, only the new ARES_OPT_TIMEOUTMS */ + options->timeout = channel->timeout; options->maxtimeout = channel->maxtimeout; options->jitter = channel->jitter; options->jitter_rand_seed = channel->jitter_rand_state; - options->tries = channel->tries; - options->ndots = channel->ndots; - options->udp_port = ntohs(aresx_sitous(channel->udp_port)); - options->tcp_port = ntohs(aresx_sitous(channel->tcp_port)); - options->sock_state_cb = channel->sock_state_cb; - options->sock_state_cb_data = channel->sock_state_cb_data; - + options->tries = channel->tries; + options->ndots = channel->ndots; + options->udp_port = ntohs(aresx_sitous(channel->udp_port)); + options->tcp_port = ntohs(aresx_sitous(channel->tcp_port)); + options->sock_state_cb = channel->sock_state_cb; + options->sock_state_cb_data = channel->sock_state_cb_data; + /* Copy IPv4 servers that use the default port */ - if (channel->nservers) { - for (i = 0; i < channel->nservers; i++) - { + if (channel->nservers) { + for (i = 0; i < channel->nservers; i++) + { if ((channel->servers[i].addr.family == AF_INET) && (channel->servers[i].addr.udp_port == 0) && (channel->servers[i].addr.tcp_port == 0)) - ipv4_nservers++; - } - if (ipv4_nservers) { + ipv4_nservers++; + } + if (ipv4_nservers) { options->servers = ares_malloc(ipv4_nservers * sizeof(struct in_addr)); - if (!options->servers) - return ARES_ENOMEM; - for (i = j = 0; i < channel->nservers; i++) - { + if (!options->servers) + return ARES_ENOMEM; + for (i = j = 0; i < channel->nservers; i++) + { if ((channel->servers[i].addr.family == AF_INET) && (channel->servers[i].addr.udp_port == 0) && (channel->servers[i].addr.tcp_port == 0)) - memcpy(&options->servers[j++], - &channel->servers[i].addr.addrV4, - sizeof(channel->servers[i].addr.addrV4)); - } - } - } - options->nservers = ipv4_nservers; - - /* copy domains */ - if (channel->ndomains) { + memcpy(&options->servers[j++], + &channel->servers[i].addr.addrV4, + sizeof(channel->servers[i].addr.addrV4)); + } + } + } + options->nservers = ipv4_nservers; + + /* copy domains */ + if (channel->ndomains) { options->domains = ares_malloc(channel->ndomains * sizeof(char *)); - if (!options->domains) - return ARES_ENOMEM; - - for (i = 0; i < channel->ndomains; i++) - { - options->ndomains = i; + if (!options->domains) + return ARES_ENOMEM; + + for (i = 0; i < channel->ndomains; i++) + { + options->ndomains = i; options->domains[i] = ares_strdup(channel->domains[i]); - if (!options->domains[i]) - return ARES_ENOMEM; - } - } - options->ndomains = channel->ndomains; - - /* copy lookups */ - if (channel->lookups) { + if (!options->domains[i]) + return ARES_ENOMEM; + } + } + options->ndomains = channel->ndomains; + + /* copy lookups */ + if (channel->lookups) { options->lookups = ares_strdup(channel->lookups); - if (!options->lookups && channel->lookups) - return ARES_ENOMEM; - } - - /* copy sortlist */ - if (channel->nsort) { + if (!options->lookups && channel->lookups) + return ARES_ENOMEM; + } + + /* copy sortlist */ + if (channel->nsort) { options->sortlist = ares_malloc(channel->nsort * sizeof(struct apattern)); - if (!options->sortlist) - return ARES_ENOMEM; - for (i = 0; i < channel->nsort; i++) - options->sortlist[i] = channel->sortlist[i]; - } - options->nsort = channel->nsort; - + if (!options->sortlist) + return ARES_ENOMEM; + for (i = 0; i < channel->nsort; i++) + options->sortlist[i] = channel->sortlist[i]; + } + options->nsort = channel->nsort; + /* copy path for resolv.conf file */ if (channel->resolvconf_path) { options->resolvconf_path = ares_strdup(channel->resolvconf_path); @@ -442,22 +442,22 @@ int ares_save_options(ares_channel channel, struct ares_options *options, return ARES_ENOMEM; } - return ARES_SUCCESS; -} - -static int init_by_options(ares_channel channel, - const struct ares_options *options, - int optmask) -{ - int i; - - /* Easy stuff. */ - if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1) - channel->flags = options->flags; - if ((optmask & ARES_OPT_TIMEOUTMS) && channel->timeout == -1) - channel->timeout = options->timeout; - else if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1) - channel->timeout = options->timeout * 1000; + return ARES_SUCCESS; +} + +static int init_by_options(ares_channel channel, + const struct ares_options *options, + int optmask) +{ + int i; + + /* Easy stuff. */ + if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1) + channel->flags = options->flags; + if ((optmask & ARES_OPT_TIMEOUTMS) && channel->timeout == -1) + channel->timeout = options->timeout; + else if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1) + channel->timeout = options->timeout * 1000; if ((optmask & ARES_OPT_MAXTIMEOUTMS) && channel->maxtimeout == -1) channel->maxtimeout = options->maxtimeout; if ((optmask & ARES_OPT_JITTER) && channel->jitter == -1) @@ -465,87 +465,87 @@ static int init_by_options(ares_channel channel, channel->jitter = options->jitter; channel->jitter_rand_state = options->jitter_rand_seed; } - if ((optmask & ARES_OPT_TRIES) && channel->tries == -1) - channel->tries = options->tries; - if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1) - channel->ndots = options->ndots; - if ((optmask & ARES_OPT_ROTATE) && channel->rotate == -1) - channel->rotate = 1; + if ((optmask & ARES_OPT_TRIES) && channel->tries == -1) + channel->tries = options->tries; + if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1) + channel->ndots = options->ndots; + if ((optmask & ARES_OPT_ROTATE) && channel->rotate == -1) + channel->rotate = 1; if ((optmask & ARES_OPT_NOROTATE) && channel->rotate == -1) channel->rotate = 0; - if ((optmask & ARES_OPT_UDP_PORT) && channel->udp_port == -1) - channel->udp_port = htons(options->udp_port); - if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1) - channel->tcp_port = htons(options->tcp_port); - if ((optmask & ARES_OPT_SOCK_STATE_CB) && channel->sock_state_cb == NULL) - { - channel->sock_state_cb = options->sock_state_cb; - channel->sock_state_cb_data = options->sock_state_cb_data; - } - if ((optmask & ARES_OPT_SOCK_SNDBUF) - && channel->socket_send_buffer_size == -1) - channel->socket_send_buffer_size = options->socket_send_buffer_size; - if ((optmask & ARES_OPT_SOCK_RCVBUF) - && channel->socket_receive_buffer_size == -1) - channel->socket_receive_buffer_size = options->socket_receive_buffer_size; - - if ((optmask & ARES_OPT_EDNSPSZ) && channel->ednspsz == -1) - channel->ednspsz = options->ednspsz; - - /* Copy the IPv4 servers, if given. */ - if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1) - { - /* Avoid zero size allocations at any cost */ - if (options->nservers > 0) - { - channel->servers = + if ((optmask & ARES_OPT_UDP_PORT) && channel->udp_port == -1) + channel->udp_port = htons(options->udp_port); + if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1) + channel->tcp_port = htons(options->tcp_port); + if ((optmask & ARES_OPT_SOCK_STATE_CB) && channel->sock_state_cb == NULL) + { + channel->sock_state_cb = options->sock_state_cb; + channel->sock_state_cb_data = options->sock_state_cb_data; + } + if ((optmask & ARES_OPT_SOCK_SNDBUF) + && channel->socket_send_buffer_size == -1) + channel->socket_send_buffer_size = options->socket_send_buffer_size; + if ((optmask & ARES_OPT_SOCK_RCVBUF) + && channel->socket_receive_buffer_size == -1) + channel->socket_receive_buffer_size = options->socket_receive_buffer_size; + + if ((optmask & ARES_OPT_EDNSPSZ) && channel->ednspsz == -1) + channel->ednspsz = options->ednspsz; + + /* Copy the IPv4 servers, if given. */ + if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1) + { + /* Avoid zero size allocations at any cost */ + if (options->nservers > 0) + { + channel->servers = ares_malloc(options->nservers * sizeof(struct server_state)); - if (!channel->servers) - return ARES_ENOMEM; - for (i = 0; i < options->nservers; i++) - { - channel->servers[i].addr.family = AF_INET; + if (!channel->servers) + return ARES_ENOMEM; + for (i = 0; i < options->nservers; i++) + { + channel->servers[i].addr.family = AF_INET; channel->servers[i].addr.udp_port = 0; channel->servers[i].addr.tcp_port = 0; - memcpy(&channel->servers[i].addr.addrV4, - &options->servers[i], - sizeof(channel->servers[i].addr.addrV4)); - } - } - channel->nservers = options->nservers; - } - - /* Copy the domains, if given. Keep channel->ndomains consistent so - * we can clean up in case of error. - */ - if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1) - { - /* Avoid zero size allocations at any cost */ - if (options->ndomains > 0) - { + memcpy(&channel->servers[i].addr.addrV4, + &options->servers[i], + sizeof(channel->servers[i].addr.addrV4)); + } + } + channel->nservers = options->nservers; + } + + /* Copy the domains, if given. Keep channel->ndomains consistent so + * we can clean up in case of error. + */ + if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1) + { + /* Avoid zero size allocations at any cost */ + if (options->ndomains > 0) + { channel->domains = ares_malloc(options->ndomains * sizeof(char *)); - if (!channel->domains) - return ARES_ENOMEM; - for (i = 0; i < options->ndomains; i++) - { - channel->ndomains = i; + if (!channel->domains) + return ARES_ENOMEM; + for (i = 0; i < options->ndomains; i++) + { + channel->ndomains = i; channel->domains[i] = ares_strdup(options->domains[i]); - if (!channel->domains[i]) - return ARES_ENOMEM; - } - } - channel->ndomains = options->ndomains; - } - - /* Set lookups, if given. */ - if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups) - { + if (!channel->domains[i]) + return ARES_ENOMEM; + } + } + channel->ndomains = options->ndomains; + } + + /* Set lookups, if given. */ + if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups) + { channel->lookups = ares_strdup(options->lookups); - if (!channel->lookups) - return ARES_ENOMEM; - } - - /* copy sortlist */ + if (!channel->lookups) + return ARES_ENOMEM; + } + + /* copy sortlist */ if ((optmask & ARES_OPT_SORTLIST) && (channel->nsort == -1)) { if (options->nsort > 0) { channel->sortlist = ares_malloc(options->nsort * sizeof(struct apattern)); @@ -554,9 +554,9 @@ static int init_by_options(ares_channel channel, for (i = 0; i < options->nsort; i++) channel->sortlist[i] = options->sortlist[i]; } - channel->nsort = options->nsort; - } - + channel->nsort = options->nsort; + } + /* Set path for resolv.conf file, if given. */ if ((optmask & ARES_OPT_RESOLVCONF) && !channel->resolvconf_path) { @@ -565,305 +565,305 @@ static int init_by_options(ares_channel channel, return ARES_ENOMEM; } - channel->optmask = optmask; - - return ARES_SUCCESS; -} - -static int init_by_environment(ares_channel channel) -{ - const char *localdomain, *res_options; - int status; - - localdomain = getenv("LOCALDOMAIN"); - if (localdomain && channel->ndomains == -1) - { - status = set_search(channel, localdomain); - if (status != ARES_SUCCESS) - return status; - } - - res_options = getenv("RES_OPTIONS"); - if (res_options) - { - status = set_options(channel, res_options); - if (status != ARES_SUCCESS) + channel->optmask = optmask; + + return ARES_SUCCESS; +} + +static int init_by_environment(ares_channel channel) +{ + const char *localdomain, *res_options; + int status; + + localdomain = getenv("LOCALDOMAIN"); + if (localdomain && channel->ndomains == -1) + { + status = set_search(channel, localdomain); + if (status != ARES_SUCCESS) + return status; + } + + res_options = getenv("RES_OPTIONS"); + if (res_options) + { + status = set_options(channel, res_options); + if (status != ARES_SUCCESS) return status; /* LCOV_EXCL_LINE: set_options() never fails */ - } - - return ARES_SUCCESS; -} - -#ifdef WIN32 -/* - * get_REG_SZ() - * - * Given a 'hKey' handle to an open registry key and a 'leafKeyName' pointer - * to the name of the registry leaf key to be queried, fetch it's string - * value and return a pointer in *outptr to a newly allocated memory area - * holding it as a null-terminated string. - * - * Returns 0 and nullifies *outptr upon inability to return a string value. - * - * Returns 1 and sets *outptr when returning a dynamically allocated string. - * - * Supported on Windows NT 3.5 and newer. - */ -static int get_REG_SZ(HKEY hKey, const char *leafKeyName, char **outptr) -{ - DWORD size = 0; - int res; - - *outptr = NULL; - - /* Find out size of string stored in registry */ + } + + return ARES_SUCCESS; +} + +#ifdef WIN32 +/* + * get_REG_SZ() + * + * Given a 'hKey' handle to an open registry key and a 'leafKeyName' pointer + * to the name of the registry leaf key to be queried, fetch it's string + * value and return a pointer in *outptr to a newly allocated memory area + * holding it as a null-terminated string. + * + * Returns 0 and nullifies *outptr upon inability to return a string value. + * + * Returns 1 and sets *outptr when returning a dynamically allocated string. + * + * Supported on Windows NT 3.5 and newer. + */ +static int get_REG_SZ(HKEY hKey, const char *leafKeyName, char **outptr) +{ + DWORD size = 0; + int res; + + *outptr = NULL; + + /* Find out size of string stored in registry */ res = RegQueryValueExA(hKey, leafKeyName, 0, NULL, NULL, &size); - if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size) - return 0; - - /* Allocate buffer of indicated size plus one given that string - might have been stored without null termination */ + if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size) + return 0; + + /* Allocate buffer of indicated size plus one given that string + might have been stored without null termination */ *outptr = ares_malloc(size+1); - if (!*outptr) - return 0; - - /* Get the value for real */ + if (!*outptr) + return 0; + + /* Get the value for real */ res = RegQueryValueExA(hKey, leafKeyName, 0, NULL, - (unsigned char *)*outptr, &size); - if ((res != ERROR_SUCCESS) || (size == 1)) - { + (unsigned char *)*outptr, &size); + if ((res != ERROR_SUCCESS) || (size == 1)) + { ares_free(*outptr); - *outptr = NULL; - return 0; - } - - /* Null terminate buffer allways */ - *(*outptr + size) = '\0'; - - return 1; -} - -/* - * get_REG_SZ_9X() - * - * Functionally identical to get_REG_SZ() - * - * Supported on Windows 95, 98 and ME. - */ -static int get_REG_SZ_9X(HKEY hKey, const char *leafKeyName, char **outptr) -{ - DWORD dataType = 0; - DWORD size = 0; - int res; - - *outptr = NULL; - - /* Find out size of string stored in registry */ + *outptr = NULL; + return 0; + } + + /* Null terminate buffer allways */ + *(*outptr + size) = '\0'; + + return 1; +} + +/* + * get_REG_SZ_9X() + * + * Functionally identical to get_REG_SZ() + * + * Supported on Windows 95, 98 and ME. + */ +static int get_REG_SZ_9X(HKEY hKey, const char *leafKeyName, char **outptr) +{ + DWORD dataType = 0; + DWORD size = 0; + int res; + + *outptr = NULL; + + /* Find out size of string stored in registry */ res = RegQueryValueExA(hKey, leafKeyName, 0, &dataType, NULL, &size); - if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size) - return 0; - - /* Allocate buffer of indicated size plus one given that string - might have been stored without null termination */ + if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size) + return 0; + + /* Allocate buffer of indicated size plus one given that string + might have been stored without null termination */ *outptr = ares_malloc(size+1); - if (!*outptr) - return 0; - - /* Get the value for real */ + if (!*outptr) + return 0; + + /* Get the value for real */ res = RegQueryValueExA(hKey, leafKeyName, 0, &dataType, - (unsigned char *)*outptr, &size); - if ((res != ERROR_SUCCESS) || (size == 1)) - { + (unsigned char *)*outptr, &size); + if ((res != ERROR_SUCCESS) || (size == 1)) + { ares_free(*outptr); - *outptr = NULL; - return 0; - } - - /* Null terminate buffer allways */ - *(*outptr + size) = '\0'; - - return 1; -} - -/* - * get_enum_REG_SZ() - * - * Given a 'hKeyParent' handle to an open registry key and a 'leafKeyName' - * pointer to the name of the registry leaf key to be queried, parent key - * is enumerated searching in child keys for given leaf key name and its - * associated string value. When located, this returns a pointer in *outptr - * to a newly allocated memory area holding it as a null-terminated string. - * - * Returns 0 and nullifies *outptr upon inability to return a string value. - * - * Returns 1 and sets *outptr when returning a dynamically allocated string. - * - * Supported on Windows NT 3.5 and newer. - */ -static int get_enum_REG_SZ(HKEY hKeyParent, const char *leafKeyName, - char **outptr) -{ - char enumKeyName[256]; - DWORD enumKeyNameBuffSize; - DWORD enumKeyIdx = 0; - HKEY hKeyEnum; - int gotString; - int res; - - *outptr = NULL; - - for(;;) - { - enumKeyNameBuffSize = sizeof(enumKeyName); + *outptr = NULL; + return 0; + } + + /* Null terminate buffer allways */ + *(*outptr + size) = '\0'; + + return 1; +} + +/* + * get_enum_REG_SZ() + * + * Given a 'hKeyParent' handle to an open registry key and a 'leafKeyName' + * pointer to the name of the registry leaf key to be queried, parent key + * is enumerated searching in child keys for given leaf key name and its + * associated string value. When located, this returns a pointer in *outptr + * to a newly allocated memory area holding it as a null-terminated string. + * + * Returns 0 and nullifies *outptr upon inability to return a string value. + * + * Returns 1 and sets *outptr when returning a dynamically allocated string. + * + * Supported on Windows NT 3.5 and newer. + */ +static int get_enum_REG_SZ(HKEY hKeyParent, const char *leafKeyName, + char **outptr) +{ + char enumKeyName[256]; + DWORD enumKeyNameBuffSize; + DWORD enumKeyIdx = 0; + HKEY hKeyEnum; + int gotString; + int res; + + *outptr = NULL; + + for(;;) + { + enumKeyNameBuffSize = sizeof(enumKeyName); res = RegEnumKeyExA(hKeyParent, enumKeyIdx++, enumKeyName, - &enumKeyNameBuffSize, 0, NULL, NULL, NULL); - if (res != ERROR_SUCCESS) - break; + &enumKeyNameBuffSize, 0, NULL, NULL, NULL); + if (res != ERROR_SUCCESS) + break; res = RegOpenKeyExA(hKeyParent, enumKeyName, 0, KEY_QUERY_VALUE, - &hKeyEnum); - if (res != ERROR_SUCCESS) - continue; - gotString = get_REG_SZ(hKeyEnum, leafKeyName, outptr); - RegCloseKey(hKeyEnum); - if (gotString) - break; - } - - if (!*outptr) - return 0; - - return 1; -} - -/* - * get_DNS_Registry_9X() - * - * Functionally identical to get_DNS_Registry() - * - * Implementation supports Windows 95, 98 and ME. - */ -static int get_DNS_Registry_9X(char **outptr) -{ - HKEY hKey_VxD_MStcp; - int gotString; - int res; - - *outptr = NULL; - + &hKeyEnum); + if (res != ERROR_SUCCESS) + continue; + gotString = get_REG_SZ(hKeyEnum, leafKeyName, outptr); + RegCloseKey(hKeyEnum); + if (gotString) + break; + } + + if (!*outptr) + return 0; + + return 1; +} + +/* + * get_DNS_Registry_9X() + * + * Functionally identical to get_DNS_Registry() + * + * Implementation supports Windows 95, 98 and ME. + */ +static int get_DNS_Registry_9X(char **outptr) +{ + HKEY hKey_VxD_MStcp; + int gotString; + int res; + + *outptr = NULL; + res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_9X, 0, KEY_READ, - &hKey_VxD_MStcp); - if (res != ERROR_SUCCESS) - return 0; - - gotString = get_REG_SZ_9X(hKey_VxD_MStcp, NAMESERVER, outptr); - RegCloseKey(hKey_VxD_MStcp); - - if (!gotString || !*outptr) - return 0; - - return 1; -} - -/* - * get_DNS_Registry_NT() - * - * Functionally identical to get_DNS_Registry() - * - * Refs: Microsoft Knowledge Base articles KB120642 and KB314053. - * - * Implementation supports Windows NT 3.5 and newer. - */ -static int get_DNS_Registry_NT(char **outptr) -{ - HKEY hKey_Interfaces = NULL; - HKEY hKey_Tcpip_Parameters; - int gotString; - int res; - - *outptr = NULL; - + &hKey_VxD_MStcp); + if (res != ERROR_SUCCESS) + return 0; + + gotString = get_REG_SZ_9X(hKey_VxD_MStcp, NAMESERVER, outptr); + RegCloseKey(hKey_VxD_MStcp); + + if (!gotString || !*outptr) + return 0; + + return 1; +} + +/* + * get_DNS_Registry_NT() + * + * Functionally identical to get_DNS_Registry() + * + * Refs: Microsoft Knowledge Base articles KB120642 and KB314053. + * + * Implementation supports Windows NT 3.5 and newer. + */ +static int get_DNS_Registry_NT(char **outptr) +{ + HKEY hKey_Interfaces = NULL; + HKEY hKey_Tcpip_Parameters; + int gotString; + int res; + + *outptr = NULL; + res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ, - &hKey_Tcpip_Parameters); - if (res != ERROR_SUCCESS) - return 0; - - /* - ** Global DNS settings override adapter specific parameters when both - ** are set. Additionally static DNS settings override DHCP-configured - ** parameters when both are set. - */ - - /* Global DNS static parameters */ - gotString = get_REG_SZ(hKey_Tcpip_Parameters, NAMESERVER, outptr); - if (gotString) - goto done; - - /* Global DNS DHCP-configured parameters */ - gotString = get_REG_SZ(hKey_Tcpip_Parameters, DHCPNAMESERVER, outptr); - if (gotString) - goto done; - - /* Try adapter specific parameters */ + &hKey_Tcpip_Parameters); + if (res != ERROR_SUCCESS) + return 0; + + /* + ** Global DNS settings override adapter specific parameters when both + ** are set. Additionally static DNS settings override DHCP-configured + ** parameters when both are set. + */ + + /* Global DNS static parameters */ + gotString = get_REG_SZ(hKey_Tcpip_Parameters, NAMESERVER, outptr); + if (gotString) + goto done; + + /* Global DNS DHCP-configured parameters */ + gotString = get_REG_SZ(hKey_Tcpip_Parameters, DHCPNAMESERVER, outptr); + if (gotString) + goto done; + + /* Try adapter specific parameters */ res = RegOpenKeyExA(hKey_Tcpip_Parameters, "Interfaces", 0, - KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, - &hKey_Interfaces); - if (res != ERROR_SUCCESS) - { - hKey_Interfaces = NULL; - goto done; - } - - /* Adapter specific DNS static parameters */ - gotString = get_enum_REG_SZ(hKey_Interfaces, NAMESERVER, outptr); - if (gotString) - goto done; - - /* Adapter specific DNS DHCP-configured parameters */ - gotString = get_enum_REG_SZ(hKey_Interfaces, DHCPNAMESERVER, outptr); - -done: - if (hKey_Interfaces) - RegCloseKey(hKey_Interfaces); - - RegCloseKey(hKey_Tcpip_Parameters); - - if (!gotString || !*outptr) - return 0; - - return 1; -} - -/* - * get_DNS_Registry() - * - * Locates DNS info in the registry. When located, this returns a pointer - * in *outptr to a newly allocated memory area holding a null-terminated - * string with a space or comma seperated list of DNS IP addresses. - * - * Returns 0 and nullifies *outptr upon inability to return DNSes string. - * - * Returns 1 and sets *outptr when returning a dynamically allocated string. - */ -static int get_DNS_Registry(char **outptr) -{ - win_platform platform; - int gotString = 0; - - *outptr = NULL; - - platform = ares__getplatform(); - - if (platform == WIN_NT) - gotString = get_DNS_Registry_NT(outptr); - else if (platform == WIN_9X) - gotString = get_DNS_Registry_9X(outptr); - - if (!gotString) - return 0; - - return 1; -} - + KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, + &hKey_Interfaces); + if (res != ERROR_SUCCESS) + { + hKey_Interfaces = NULL; + goto done; + } + + /* Adapter specific DNS static parameters */ + gotString = get_enum_REG_SZ(hKey_Interfaces, NAMESERVER, outptr); + if (gotString) + goto done; + + /* Adapter specific DNS DHCP-configured parameters */ + gotString = get_enum_REG_SZ(hKey_Interfaces, DHCPNAMESERVER, outptr); + +done: + if (hKey_Interfaces) + RegCloseKey(hKey_Interfaces); + + RegCloseKey(hKey_Tcpip_Parameters); + + if (!gotString || !*outptr) + return 0; + + return 1; +} + +/* + * get_DNS_Registry() + * + * Locates DNS info in the registry. When located, this returns a pointer + * in *outptr to a newly allocated memory area holding a null-terminated + * string with a space or comma seperated list of DNS IP addresses. + * + * Returns 0 and nullifies *outptr upon inability to return DNSes string. + * + * Returns 1 and sets *outptr when returning a dynamically allocated string. + */ +static int get_DNS_Registry(char **outptr) +{ + win_platform platform; + int gotString = 0; + + *outptr = NULL; + + platform = ares__getplatform(); + + if (platform == WIN_NT) + gotString = get_DNS_Registry_NT(outptr); + else if (platform == WIN_9X) + gotString = get_DNS_Registry_9X(outptr); + + if (!gotString) + return 0; + + return 1; +} + static void commanjoin(char** dst, const char* const src, const size_t len) { char *newbuf; @@ -882,100 +882,100 @@ static void commanjoin(char** dst, const char* const src, const size_t len) strncat(*dst, src, len); } -/* - * commajoin() - * - * RTF code. - */ -static void commajoin(char **dst, const char *src) -{ +/* + * commajoin() + * + * RTF code. + */ +static void commajoin(char **dst, const char *src) +{ commanjoin(dst, src, strlen(src)); -} - -/* - * get_DNS_NetworkParams() - * - * Locates DNS info using GetNetworkParams() function from the Internet - * Protocol Helper (IP Helper) API. When located, this returns a pointer - * in *outptr to a newly allocated memory area holding a null-terminated - * string with a space or comma seperated list of DNS IP addresses. - * - * Returns 0 and nullifies *outptr upon inability to return DNSes string. - * - * Returns 1 and sets *outptr when returning a dynamically allocated string. - * - * Implementation supports Windows 98 and newer. - * - * Note: Ancient PSDK required in order to build a W98 target. - */ -static int get_DNS_NetworkParams(char **outptr) -{ - FIXED_INFO *fi, *newfi; - struct ares_addr namesrvr; - char *txtaddr; - IP_ADDR_STRING *ipAddr; - int res; - DWORD size = sizeof (*fi); - - *outptr = NULL; - - /* Verify run-time availability of GetNetworkParams() */ - if (ares_fpGetNetworkParams == ZERO_NULL) - return 0; - +} + +/* + * get_DNS_NetworkParams() + * + * Locates DNS info using GetNetworkParams() function from the Internet + * Protocol Helper (IP Helper) API. When located, this returns a pointer + * in *outptr to a newly allocated memory area holding a null-terminated + * string with a space or comma seperated list of DNS IP addresses. + * + * Returns 0 and nullifies *outptr upon inability to return DNSes string. + * + * Returns 1 and sets *outptr when returning a dynamically allocated string. + * + * Implementation supports Windows 98 and newer. + * + * Note: Ancient PSDK required in order to build a W98 target. + */ +static int get_DNS_NetworkParams(char **outptr) +{ + FIXED_INFO *fi, *newfi; + struct ares_addr namesrvr; + char *txtaddr; + IP_ADDR_STRING *ipAddr; + int res; + DWORD size = sizeof (*fi); + + *outptr = NULL; + + /* Verify run-time availability of GetNetworkParams() */ + if (ares_fpGetNetworkParams == ZERO_NULL) + return 0; + fi = ares_malloc(size); - if (!fi) - return 0; - - res = (*ares_fpGetNetworkParams) (fi, &size); - if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS)) - goto done; - + if (!fi) + return 0; + + res = (*ares_fpGetNetworkParams) (fi, &size); + if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS)) + goto done; + newfi = ares_realloc(fi, size); - if (!newfi) - goto done; - - fi = newfi; - res = (*ares_fpGetNetworkParams) (fi, &size); - if (res != ERROR_SUCCESS) - goto done; - - for (ipAddr = &fi->DnsServerList; ipAddr; ipAddr = ipAddr->Next) - { - txtaddr = &ipAddr->IpAddress.String[0]; - - /* Validate converting textual address to binary format. */ - if (ares_inet_pton(AF_INET, txtaddr, &namesrvr.addrV4) == 1) - { - if ((namesrvr.addrV4.S_un.S_addr == INADDR_ANY) || - (namesrvr.addrV4.S_un.S_addr == INADDR_NONE)) - continue; - } - else if (ares_inet_pton(AF_INET6, txtaddr, &namesrvr.addrV6) == 1) - { - if (memcmp(&namesrvr.addrV6, &ares_in6addr_any, - sizeof(namesrvr.addrV6)) == 0) - continue; - } - else - continue; - - commajoin(outptr, txtaddr); - - if (!*outptr) - break; - } - -done: - if (fi) + if (!newfi) + goto done; + + fi = newfi; + res = (*ares_fpGetNetworkParams) (fi, &size); + if (res != ERROR_SUCCESS) + goto done; + + for (ipAddr = &fi->DnsServerList; ipAddr; ipAddr = ipAddr->Next) + { + txtaddr = &ipAddr->IpAddress.String[0]; + + /* Validate converting textual address to binary format. */ + if (ares_inet_pton(AF_INET, txtaddr, &namesrvr.addrV4) == 1) + { + if ((namesrvr.addrV4.S_un.S_addr == INADDR_ANY) || + (namesrvr.addrV4.S_un.S_addr == INADDR_NONE)) + continue; + } + else if (ares_inet_pton(AF_INET6, txtaddr, &namesrvr.addrV6) == 1) + { + if (memcmp(&namesrvr.addrV6, &ares_in6addr_any, + sizeof(namesrvr.addrV6)) == 0) + continue; + } + else + continue; + + commajoin(outptr, txtaddr); + + if (!*outptr) + break; + } + +done: + if (fi) ares_free(fi); - - if (!*outptr) - return 0; - - return 1; -} - + + if (!*outptr) + return 0; + + return 1; +} + static BOOL ares_IsWindowsVistaOrGreater(void) { OSVERSIONINFO vinfo; @@ -1101,32 +1101,32 @@ static ULONG getBestRouteMetric(IF_LUID * const luid, /* Can't be const :( */ return row.Metric + interfaceMetric; } -/* - * get_DNS_AdaptersAddresses() - * - * Locates DNS info using GetAdaptersAddresses() function from the Internet - * Protocol Helper (IP Helper) API. When located, this returns a pointer - * in *outptr to a newly allocated memory area holding a null-terminated - * string with a space or comma seperated list of DNS IP addresses. - * - * Returns 0 and nullifies *outptr upon inability to return DNSes string. - * - * Returns 1 and sets *outptr when returning a dynamically allocated string. - * - * Implementation supports Windows XP and newer. - */ -#define IPAA_INITIAL_BUF_SZ 15 * 1024 -#define IPAA_MAX_TRIES 3 -static int get_DNS_AdaptersAddresses(char **outptr) -{ - IP_ADAPTER_DNS_SERVER_ADDRESS *ipaDNSAddr; - IP_ADAPTER_ADDRESSES *ipaa, *newipaa, *ipaaEntry; - ULONG ReqBufsz = IPAA_INITIAL_BUF_SZ; - ULONG Bufsz = IPAA_INITIAL_BUF_SZ; - ULONG AddrFlags = 0; - int trying = IPAA_MAX_TRIES; - int res; - +/* + * get_DNS_AdaptersAddresses() + * + * Locates DNS info using GetAdaptersAddresses() function from the Internet + * Protocol Helper (IP Helper) API. When located, this returns a pointer + * in *outptr to a newly allocated memory area holding a null-terminated + * string with a space or comma seperated list of DNS IP addresses. + * + * Returns 0 and nullifies *outptr upon inability to return DNSes string. + * + * Returns 1 and sets *outptr when returning a dynamically allocated string. + * + * Implementation supports Windows XP and newer. + */ +#define IPAA_INITIAL_BUF_SZ 15 * 1024 +#define IPAA_MAX_TRIES 3 +static int get_DNS_AdaptersAddresses(char **outptr) +{ + IP_ADAPTER_DNS_SERVER_ADDRESS *ipaDNSAddr; + IP_ADAPTER_ADDRESSES *ipaa, *newipaa, *ipaaEntry; + ULONG ReqBufsz = IPAA_INITIAL_BUF_SZ; + ULONG Bufsz = IPAA_INITIAL_BUF_SZ; + ULONG AddrFlags = 0; + int trying = IPAA_MAX_TRIES; + int res; + /* The capacity of addresses, in elements. */ size_t addressesSize; /* The number of elements in addresses. */ @@ -1134,22 +1134,22 @@ static int get_DNS_AdaptersAddresses(char **outptr) /* The addresses we will sort. */ Address *addresses; - union { - struct sockaddr *sa; - struct sockaddr_in *sa4; - struct sockaddr_in6 *sa6; - } namesrvr; - - *outptr = NULL; - - /* Verify run-time availability of GetAdaptersAddresses() */ - if (ares_fpGetAdaptersAddresses == ZERO_NULL) - return 0; - + union { + struct sockaddr *sa; + struct sockaddr_in *sa4; + struct sockaddr_in6 *sa6; + } namesrvr; + + *outptr = NULL; + + /* Verify run-time availability of GetAdaptersAddresses() */ + if (ares_fpGetAdaptersAddresses == ZERO_NULL) + return 0; + ipaa = ares_malloc(Bufsz); - if (!ipaa) - return 0; - + if (!ipaa) + return 0; + /* Start with enough room for a few DNS server addresses and we'll grow it * as we encounter more. */ @@ -1161,32 +1161,32 @@ static int get_DNS_AdaptersAddresses(char **outptr) return 0; } - /* Usually this call suceeds with initial buffer size */ - res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL, - ipaa, &ReqBufsz); - if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS)) - goto done; - - while ((res == ERROR_BUFFER_OVERFLOW) && (--trying)) - { - if (Bufsz < ReqBufsz) - { + /* Usually this call suceeds with initial buffer size */ + res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL, + ipaa, &ReqBufsz); + if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS)) + goto done; + + while ((res == ERROR_BUFFER_OVERFLOW) && (--trying)) + { + if (Bufsz < ReqBufsz) + { newipaa = ares_realloc(ipaa, ReqBufsz); - if (!newipaa) - goto done; - Bufsz = ReqBufsz; - ipaa = newipaa; - } - res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL, - ipaa, &ReqBufsz); - if (res == ERROR_SUCCESS) - break; - } - if (res != ERROR_SUCCESS) - goto done; - - for (ipaaEntry = ipaa; ipaaEntry; ipaaEntry = ipaaEntry->Next) - { + if (!newipaa) + goto done; + Bufsz = ReqBufsz; + ipaa = newipaa; + } + res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL, + ipaa, &ReqBufsz); + if (res == ERROR_SUCCESS) + break; + } + if (res != ERROR_SUCCESS) + goto done; + + for (ipaaEntry = ipaa; ipaaEntry; ipaaEntry = ipaaEntry->Next) + { if(ipaaEntry->OperStatus != IfOperStatusUp) continue; @@ -1196,17 +1196,17 @@ static int get_DNS_AdaptersAddresses(char **outptr) * compute the resulting total metric, just as Windows routing will do. * Then, sort all the addresses found by the metric. */ - for (ipaDNSAddr = ipaaEntry->FirstDnsServerAddress; - ipaDNSAddr; - ipaDNSAddr = ipaDNSAddr->Next) - { - namesrvr.sa = ipaDNSAddr->Address.lpSockaddr; - - if (namesrvr.sa->sa_family == AF_INET) - { - if ((namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_ANY) || - (namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_NONE)) - continue; + for (ipaDNSAddr = ipaaEntry->FirstDnsServerAddress; + ipaDNSAddr; + ipaDNSAddr = ipaDNSAddr->Next) + { + namesrvr.sa = ipaDNSAddr->Address.lpSockaddr; + + if (namesrvr.sa->sa_family == AF_INET) + { + if ((namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_ANY) || + (namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_NONE)) + continue; /* Allocate room for another address, if necessary, else skip. */ if(addressesIndex == addressesSize) { @@ -1237,18 +1237,18 @@ static int get_DNS_AdaptersAddresses(char **outptr) /* Record insertion index to make qsort stable */ addresses[addressesIndex].orig_idx = addressesIndex; - if (! ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr, + if (! ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr, addresses[addressesIndex].text, sizeof(addresses[0].text))) { - continue; + continue; } ++addressesIndex; - } - else if (namesrvr.sa->sa_family == AF_INET6) - { - if (memcmp(&namesrvr.sa6->sin6_addr, &ares_in6addr_any, - sizeof(namesrvr.sa6->sin6_addr)) == 0) - continue; + } + else if (namesrvr.sa->sa_family == AF_INET6) + { + if (memcmp(&namesrvr.sa6->sin6_addr, &ares_in6addr_any, + sizeof(namesrvr.sa6->sin6_addr)) == 0) + continue; /* Allocate room for another address, if necessary, else skip. */ if(addressesIndex == addressesSize) { @@ -1279,24 +1279,24 @@ static int get_DNS_AdaptersAddresses(char **outptr) /* Record insertion index to make qsort stable */ addresses[addressesIndex].orig_idx = addressesIndex; - if (! ares_inet_ntop(AF_INET6, &namesrvr.sa6->sin6_addr, + if (! ares_inet_ntop(AF_INET6, &namesrvr.sa6->sin6_addr, addresses[addressesIndex].text, sizeof(addresses[0].text))) { - continue; + continue; } ++addressesIndex; - } + } else { /* Skip non-IPv4/IPv6 addresses completely. */ - continue; + continue; } } } - + /* Sort all of the textual addresses by their metric (and original index if * metrics are equal). */ qsort(addresses, addressesIndex, sizeof(*addresses), compareAddresses); - + /* Join them all into a single string, removing duplicates. */ { size_t i; @@ -1313,50 +1313,50 @@ static int get_DNS_AdaptersAddresses(char **outptr) /* Add that to outptr (if we can). */ commajoin(outptr, addresses[i].text); } - } - } - -done: + } + } + +done: ares_free(addresses); - if (ipaa) + if (ipaa) ares_free(ipaa); - + if (!*outptr) { - return 0; + return 0; } - - return 1; -} - -/* - * get_DNS_Windows() - * - * Locates DNS info from Windows employing most suitable methods available at - * run-time no matter which Windows version it is. When located, this returns - * a pointer in *outptr to a newly allocated memory area holding a string with - * a space or comma seperated list of DNS IP addresses, null-terminated. - * - * Returns 0 and nullifies *outptr upon inability to return DNSes string. - * - * Returns 1 and sets *outptr when returning a dynamically allocated string. - * - * Implementation supports Windows 95 and newer. - */ -static int get_DNS_Windows(char **outptr) -{ + + return 1; +} + +/* + * get_DNS_Windows() + * + * Locates DNS info from Windows employing most suitable methods available at + * run-time no matter which Windows version it is. When located, this returns + * a pointer in *outptr to a newly allocated memory area holding a string with + * a space or comma seperated list of DNS IP addresses, null-terminated. + * + * Returns 0 and nullifies *outptr upon inability to return DNSes string. + * + * Returns 1 and sets *outptr when returning a dynamically allocated string. + * + * Implementation supports Windows 95 and newer. + */ +static int get_DNS_Windows(char **outptr) +{ /* Try using IP helper API GetAdaptersAddresses(). IPv4 + IPv6, also sorts * DNS servers by interface route metrics to try to use the best DNS server. */ - if (get_DNS_AdaptersAddresses(outptr)) - return 1; - + if (get_DNS_AdaptersAddresses(outptr)) + return 1; + /* Try using IP helper API GetNetworkParams(). IPv4 only. */ - if (get_DNS_NetworkParams(outptr)) - return 1; - - /* Fall-back to registry information */ - return get_DNS_Registry(outptr); -} + if (get_DNS_NetworkParams(outptr)) + return 1; + + /* Fall-back to registry information */ + return get_DNS_Registry(outptr); +} /* * get_SuffixList_Windows() @@ -1465,102 +1465,102 @@ static int get_SuffixList_Windows(char **outptr) return *outptr != NULL; } -#endif - -static int init_by_resolv_conf(ares_channel channel) -{ +#endif + +static int init_by_resolv_conf(ares_channel channel) +{ #if !defined(ANDROID) && !defined(__ANDROID__) && !defined(WATT32) && \ !defined(CARES_USE_LIBRESOLV) - char *line = NULL; -#endif - int status = -1, nservers = 0, nsort = 0; - struct server_state *servers = NULL; - struct apattern *sortlist = NULL; - -#ifdef WIN32 - - if (channel->nservers > -1) /* don't override ARES_OPT_SERVER */ - return ARES_SUCCESS; - - if (get_DNS_Windows(&line)) - { - status = config_nameserver(&servers, &nservers, line); + char *line = NULL; +#endif + int status = -1, nservers = 0, nsort = 0; + struct server_state *servers = NULL; + struct apattern *sortlist = NULL; + +#ifdef WIN32 + + if (channel->nservers > -1) /* don't override ARES_OPT_SERVER */ + return ARES_SUCCESS; + + if (get_DNS_Windows(&line)) + { + status = config_nameserver(&servers, &nservers, line); ares_free(line); - } - + } + if (channel->ndomains == -1 && get_SuffixList_Windows(&line)) { status = set_search(channel, line); ares_free(line); } - if (status == ARES_SUCCESS) - status = ARES_EOF; - else - /* Catch the case when all the above checks fail (which happens when there - is no network card or the cable is unplugged) */ - status = ARES_EFILE; - -#elif defined(__riscos__) - - /* Under RISC OS, name servers are listed in the - system variable Inet$Resolvers, space separated. */ - - line = getenv("Inet$Resolvers"); - status = ARES_EOF; - if (line) { + if (status == ARES_SUCCESS) + status = ARES_EOF; + else + /* Catch the case when all the above checks fail (which happens when there + is no network card or the cable is unplugged) */ + status = ARES_EFILE; + +#elif defined(__riscos__) + + /* Under RISC OS, name servers are listed in the + system variable Inet$Resolvers, space separated. */ + + line = getenv("Inet$Resolvers"); + status = ARES_EOF; + if (line) { char *resolvers = ares_strdup(line), *pos, *space; - - if (!resolvers) - return ARES_ENOMEM; - - pos = resolvers; - do { - space = strchr(pos, ' '); - if (space) - *space = '\0'; - status = config_nameserver(&servers, &nservers, pos); - if (status != ARES_SUCCESS) - break; - pos = space + 1; - } while (space); - - if (status == ARES_SUCCESS) - status = ARES_EOF; - + + if (!resolvers) + return ARES_ENOMEM; + + pos = resolvers; + do { + space = strchr(pos, ' '); + if (space) + *space = '\0'; + status = config_nameserver(&servers, &nservers, pos); + if (status != ARES_SUCCESS) + break; + pos = space + 1; + } while (space); + + if (status == ARES_SUCCESS) + status = ARES_EOF; + ares_free(resolvers); - } - -#elif defined(WATT32) - int i; - - sock_init(); - for (i = 0; def_nameservers[i]; i++) - ; - if (i == 0) - return ARES_SUCCESS; /* use localhost DNS server */ - - nservers = i; + } + +#elif defined(WATT32) + int i; + + sock_init(); + for (i = 0; def_nameservers[i]; i++) + ; + if (i == 0) + return ARES_SUCCESS; /* use localhost DNS server */ + + nservers = i; servers = ares_malloc(sizeof(struct server_state)); - if (!servers) - return ARES_ENOMEM; + if (!servers) + return ARES_ENOMEM; memset(servers, 0, sizeof(struct server_state)); - - for (i = 0; def_nameservers[i]; i++) - { - servers[i].addr.addrV4.s_addr = htonl(def_nameservers[i]); - servers[i].addr.family = AF_INET; + + for (i = 0; def_nameservers[i]; i++) + { + servers[i].addr.addrV4.s_addr = htonl(def_nameservers[i]); + servers[i].addr.family = AF_INET; servers[i].addr.udp_port = 0; servers[i].addr.tcp_port = 0; - } - status = ARES_EOF; - -#elif defined(ANDROID) || defined(__ANDROID__) - unsigned int i; + } + status = ARES_EOF; + +#elif defined(ANDROID) || defined(__ANDROID__) + unsigned int i; char **dns_servers; char *domains; size_t num_servers; - + /* Use the Android connectivity manager to get a list * of DNS servers. As of Android 8 (Oreo) net.dns# * system properties are no longer available. Google claims this @@ -1575,8 +1575,8 @@ static int init_by_resolv_conf(ares_channel channel) status = config_nameserver(&servers, &nservers, dns_servers[i]); if (status != ARES_SUCCESS) break; - status = ARES_EOF; - } + status = ARES_EOF; + } for (i = 0; i < num_servers; i++) { ares_free(dns_servers[i]); @@ -1620,7 +1620,7 @@ static int init_by_resolv_conf(ares_channel channel) memset(&res, 0, sizeof(res)); int result = res_ninit(&res); if (result == 0 && (res.options & RES_INIT)) { - status = ARES_EOF; + status = ARES_EOF; if (channel->nservers == -1) { union res_sockaddr_union addr[MAXNS]; @@ -1671,20 +1671,20 @@ static int init_by_resolv_conf(ares_channel channel) channel->timeout = res.retrans * 1000; res_ndestroy(&res); - } -#else - { - char *p; - FILE *fp; - size_t linesize; - int error; + } +#else + { + char *p; + FILE *fp; + size_t linesize; + int error; int update_domains; const char *resolvconf_path; - - /* Don't read resolv.conf and friends if we don't have to */ - if (ARES_CONFIG_CHECK(channel)) - return ARES_SUCCESS; - + + /* Don't read resolv.conf and friends if we don't have to */ + if (ARES_CONFIG_CHECK(channel)) + return ARES_SUCCESS; + /* Only update search domains if they're not already specified */ update_domains = (channel->ndomains == -1); @@ -1696,381 +1696,381 @@ static int init_by_resolv_conf(ares_channel channel) } fp = fopen(resolvconf_path, "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) - { + if (fp) { + while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) + { if ((p = try_config(line, "domain", ';')) && update_domains) - status = config_domain(channel, p); - else if ((p = try_config(line, "lookup", ';')) && !channel->lookups) + status = config_domain(channel, p); + else if ((p = try_config(line, "lookup", ';')) && !channel->lookups) status = config_lookup(channel, p, "bind", NULL, "file"); else if ((p = try_config(line, "search", ';')) && update_domains) - status = set_search(channel, p); - else if ((p = try_config(line, "nameserver", ';')) && + status = set_search(channel, p); + else if ((p = try_config(line, "nameserver", ';')) && channel->nservers == -1) - status = config_nameserver(&servers, &nservers, p); - else if ((p = try_config(line, "sortlist", ';')) && + status = config_nameserver(&servers, &nservers, p); + else if ((p = try_config(line, "sortlist", ';')) && channel->nsort == -1) - status = config_sortlist(&sortlist, &nsort, p); - else if ((p = try_config(line, "options", ';'))) - status = set_options(channel, p); - else - status = ARES_SUCCESS; - if (status != ARES_SUCCESS) - break; - } - fclose(fp); - } - else { - error = ERRNO; - switch(error) { - case ENOENT: - case ESRCH: - status = ARES_EOF; - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", + status = config_sortlist(&sortlist, &nsort, p); + else if ((p = try_config(line, "options", ';'))) + status = set_options(channel, p); + else + status = ARES_SUCCESS; + if (status != ARES_SUCCESS) + break; + } + fclose(fp); + } + else { + error = ERRNO; + switch(error) { + case ENOENT: + case ESRCH: + status = ARES_EOF; + break; + default: + DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF)); - status = ARES_EFILE; - } - } - - if ((status == ARES_EOF) && (!channel->lookups)) { - /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */ - fp = fopen("/etc/nsswitch.conf", "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == - ARES_SUCCESS) - { - if ((p = try_config(line, "hosts:", '\0')) && !channel->lookups) + DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF)); + status = ARES_EFILE; + } + } + + if ((status == ARES_EOF) && (!channel->lookups)) { + /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */ + fp = fopen("/etc/nsswitch.conf", "r"); + if (fp) { + while ((status = ares__read_line(fp, &line, &linesize)) == + ARES_SUCCESS) + { + if ((p = try_config(line, "hosts:", '\0')) && !channel->lookups) (void)config_lookup(channel, p, "dns", "resolve", "files"); - } - fclose(fp); - } - else { - error = ERRNO; - switch(error) { - case ENOENT: - case ESRCH: - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", - error, strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", - "/etc/nsswitch.conf")); - } + } + fclose(fp); + } + else { + error = ERRNO; + switch(error) { + case ENOENT: + case ESRCH: + break; + default: + DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", + error, strerror(error))); + DEBUGF(fprintf(stderr, "Error opening file: %s\n", + "/etc/nsswitch.conf")); + } /* ignore error, maybe we will get luck in next if clause */ status = ARES_EOF; - } - } - - if ((status == ARES_EOF) && (!channel->lookups)) { - /* Linux / GNU libc 2.x and possibly others have host.conf */ - fp = fopen("/etc/host.conf", "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == - ARES_SUCCESS) - { - if ((p = try_config(line, "order", '\0')) && !channel->lookups) - /* ignore errors */ + } + } + + if ((status == ARES_EOF) && (!channel->lookups)) { + /* Linux / GNU libc 2.x and possibly others have host.conf */ + fp = fopen("/etc/host.conf", "r"); + if (fp) { + while ((status = ares__read_line(fp, &line, &linesize)) == + ARES_SUCCESS) + { + if ((p = try_config(line, "order", '\0')) && !channel->lookups) + /* ignore errors */ (void)config_lookup(channel, p, "bind", NULL, "hosts"); - } - fclose(fp); - } - else { - error = ERRNO; - switch(error) { - case ENOENT: - case ESRCH: - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", - error, strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", - "/etc/host.conf")); - } + } + fclose(fp); + } + else { + error = ERRNO; + switch(error) { + case ENOENT: + case ESRCH: + break; + default: + DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", + error, strerror(error))); + DEBUGF(fprintf(stderr, "Error opening file: %s\n", + "/etc/host.conf")); + } /* ignore error, maybe we will get luck in next if clause */ status = ARES_EOF; - } - } - - if ((status == ARES_EOF) && (!channel->lookups)) { - /* Tru64 uses /etc/svc.conf */ - fp = fopen("/etc/svc.conf", "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == - ARES_SUCCESS) - { - if ((p = try_config(line, "hosts=", '\0')) && !channel->lookups) - /* ignore errors */ + } + } + + if ((status == ARES_EOF) && (!channel->lookups)) { + /* Tru64 uses /etc/svc.conf */ + fp = fopen("/etc/svc.conf", "r"); + if (fp) { + while ((status = ares__read_line(fp, &line, &linesize)) == + ARES_SUCCESS) + { + if ((p = try_config(line, "hosts=", '\0')) && !channel->lookups) + /* ignore errors */ (void)config_lookup(channel, p, "bind", NULL, "local"); - } - fclose(fp); - } - else { - error = ERRNO; - switch(error) { - case ENOENT: - case ESRCH: - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", - error, strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf")); - } + } + fclose(fp); + } + else { + error = ERRNO; + switch(error) { + case ENOENT: + case ESRCH: + break; + default: + DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", + error, strerror(error))); + DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf")); + } /* ignore error, default value will be chosen for `channel->lookups` */ status = ARES_EOF; - } - } - - if(line) + } + } + + if(line) ares_free(line); - } - -#endif - - /* Handle errors. */ - if (status != ARES_EOF) - { - if (servers != NULL) + } + +#endif + + /* Handle errors. */ + if (status != ARES_EOF) + { + if (servers != NULL) ares_free(servers); - if (sortlist != NULL) + if (sortlist != NULL) ares_free(sortlist); - return status; - } - - /* If we got any name server entries, fill them in. */ - if (servers) - { - channel->servers = servers; - channel->nservers = nservers; - } - - /* If we got any sortlist entries, fill them in. */ - if (sortlist) - { - channel->sortlist = sortlist; - channel->nsort = nsort; - } - - return ARES_SUCCESS; -} - -static int init_by_defaults(ares_channel channel) -{ - char *hostname = NULL; - int rc = ARES_SUCCESS; -#ifdef HAVE_GETHOSTNAME - char *dot; -#endif - - if (channel->flags == -1) - channel->flags = 0; - if (channel->timeout == -1) - channel->timeout = DEFAULT_TIMEOUT; - if (channel->tries == -1) - channel->tries = DEFAULT_TRIES; - if (channel->ndots == -1) - channel->ndots = 1; - if (channel->rotate == -1) - channel->rotate = 0; - if (channel->udp_port == -1) - channel->udp_port = htons(NAMESERVER_PORT); - if (channel->tcp_port == -1) - channel->tcp_port = htons(NAMESERVER_PORT); - - if (channel->ednspsz == -1) - channel->ednspsz = EDNSPACKETSZ; - - if (channel->nservers == -1) { - /* If nobody specified servers, try a local named. */ + return status; + } + + /* If we got any name server entries, fill them in. */ + if (servers) + { + channel->servers = servers; + channel->nservers = nservers; + } + + /* If we got any sortlist entries, fill them in. */ + if (sortlist) + { + channel->sortlist = sortlist; + channel->nsort = nsort; + } + + return ARES_SUCCESS; +} + +static int init_by_defaults(ares_channel channel) +{ + char *hostname = NULL; + int rc = ARES_SUCCESS; +#ifdef HAVE_GETHOSTNAME + char *dot; +#endif + + if (channel->flags == -1) + channel->flags = 0; + if (channel->timeout == -1) + channel->timeout = DEFAULT_TIMEOUT; + if (channel->tries == -1) + channel->tries = DEFAULT_TRIES; + if (channel->ndots == -1) + channel->ndots = 1; + if (channel->rotate == -1) + channel->rotate = 0; + if (channel->udp_port == -1) + channel->udp_port = htons(NAMESERVER_PORT); + if (channel->tcp_port == -1) + channel->tcp_port = htons(NAMESERVER_PORT); + + if (channel->ednspsz == -1) + channel->ednspsz = EDNSPACKETSZ; + + if (channel->nservers == -1) { + /* If nobody specified servers, try a local named. */ channel->servers = ares_malloc(sizeof(struct server_state)); - if (!channel->servers) { - rc = ARES_ENOMEM; - goto error; - } - channel->servers[0].addr.family = AF_INET; - channel->servers[0].addr.addrV4.s_addr = htonl(INADDR_LOOPBACK); + if (!channel->servers) { + rc = ARES_ENOMEM; + goto error; + } + channel->servers[0].addr.family = AF_INET; + channel->servers[0].addr.addrV4.s_addr = htonl(INADDR_LOOPBACK); channel->servers[0].addr.udp_port = 0; channel->servers[0].addr.tcp_port = 0; - channel->nservers = 1; - } - -#if defined(USE_WINSOCK) -#define toolong(x) (x == -1) && (SOCKERRNO == WSAEFAULT) -#elif defined(ENAMETOOLONG) -#define toolong(x) (x == -1) && ((SOCKERRNO == ENAMETOOLONG) || \ - (SOCKERRNO == EINVAL)) -#else -#define toolong(x) (x == -1) && (SOCKERRNO == EINVAL) -#endif - - if (channel->ndomains == -1) { - /* Derive a default domain search list from the kernel hostname, - * or set it to empty if the hostname isn't helpful. - */ -#ifndef HAVE_GETHOSTNAME - channel->ndomains = 0; /* default to none */ -#else - GETHOSTNAME_TYPE_ARG2 lenv = 64; - size_t len = 64; - int res; - channel->ndomains = 0; /* default to none */ - + channel->nservers = 1; + } + +#if defined(USE_WINSOCK) +#define toolong(x) (x == -1) && (SOCKERRNO == WSAEFAULT) +#elif defined(ENAMETOOLONG) +#define toolong(x) (x == -1) && ((SOCKERRNO == ENAMETOOLONG) || \ + (SOCKERRNO == EINVAL)) +#else +#define toolong(x) (x == -1) && (SOCKERRNO == EINVAL) +#endif + + if (channel->ndomains == -1) { + /* Derive a default domain search list from the kernel hostname, + * or set it to empty if the hostname isn't helpful. + */ +#ifndef HAVE_GETHOSTNAME + channel->ndomains = 0; /* default to none */ +#else + GETHOSTNAME_TYPE_ARG2 lenv = 64; + size_t len = 64; + int res; + channel->ndomains = 0; /* default to none */ + hostname = ares_malloc(len); - if(!hostname) { - rc = ARES_ENOMEM; - goto error; - } - - do { - res = gethostname(hostname, lenv); - - if(toolong(res)) { - char *p; - len *= 2; - lenv *= 2; + if(!hostname) { + rc = ARES_ENOMEM; + goto error; + } + + do { + res = gethostname(hostname, lenv); + + if(toolong(res)) { + char *p; + len *= 2; + lenv *= 2; p = ares_realloc(hostname, len); - if(!p) { - rc = ARES_ENOMEM; - goto error; - } - hostname = p; - continue; - } - else if(res) { + if(!p) { + rc = ARES_ENOMEM; + goto error; + } + hostname = p; + continue; + } + else if(res) { /* Lets not treat a gethostname failure as critical, since we * are ok if gethostname doesn't even exist */ *hostname = '\0'; break; - } - + } + } while (res != 0); - - dot = strchr(hostname, '.'); - if (dot) { - /* a dot was found */ + + dot = strchr(hostname, '.'); + if (dot) { + /* a dot was found */ channel->domains = ares_malloc(sizeof(char *)); - if (!channel->domains) { - rc = ARES_ENOMEM; - goto error; - } + if (!channel->domains) { + rc = ARES_ENOMEM; + goto error; + } channel->domains[0] = ares_strdup(dot + 1); - if (!channel->domains[0]) { - rc = ARES_ENOMEM; - goto error; - } - channel->ndomains = 1; - } -#endif - } - - if (channel->nsort == -1) { - channel->sortlist = NULL; - channel->nsort = 0; - } - - if (!channel->lookups) { + if (!channel->domains[0]) { + rc = ARES_ENOMEM; + goto error; + } + channel->ndomains = 1; + } +#endif + } + + if (channel->nsort == -1) { + channel->sortlist = NULL; + channel->nsort = 0; + } + + if (!channel->lookups) { channel->lookups = ares_strdup("fb"); - if (!channel->lookups) - rc = ARES_ENOMEM; - } - - error: - if(rc) { - if(channel->servers) { + if (!channel->lookups) + rc = ARES_ENOMEM; + } + + error: + if(rc) { + if(channel->servers) { ares_free(channel->servers); - channel->servers = NULL; - } - - if(channel->domains && channel->domains[0]) + channel->servers = NULL; + } + + if(channel->domains && channel->domains[0]) ares_free(channel->domains[0]); - if(channel->domains) { + if(channel->domains) { ares_free(channel->domains); - channel->domains = NULL; - } - - if(channel->lookups) { + channel->domains = NULL; + } + + if(channel->lookups) { ares_free(channel->lookups); - channel->lookups = NULL; - } + channel->lookups = NULL; + } if(channel->resolvconf_path) { ares_free(channel->resolvconf_path); channel->resolvconf_path = NULL; } - } - - if(hostname) + } + + if(hostname) ares_free(hostname); - - return rc; -} - -#if !defined(WIN32) && !defined(WATT32) && \ + + return rc; +} + +#if !defined(WIN32) && !defined(WATT32) && \ !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV) -static int config_domain(ares_channel channel, char *str) -{ - char *q; - - /* Set a single search domain. */ - q = str; - while (*q && !ISSPACE(*q)) - q++; - *q = '\0'; - return set_search(channel, str); -} - -#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \ - defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__) - /* workaround icc 9.1 optimizer issue */ -# define vqualifier volatile -#else -# define vqualifier -#endif - -static int config_lookup(ares_channel channel, const char *str, +static int config_domain(ares_channel channel, char *str) +{ + char *q; + + /* Set a single search domain. */ + q = str; + while (*q && !ISSPACE(*q)) + q++; + *q = '\0'; + return set_search(channel, str); +} + +#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \ + defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__) + /* workaround icc 9.1 optimizer issue */ +# define vqualifier volatile +#else +# define vqualifier +#endif + +static int config_lookup(ares_channel channel, const char *str, const char *bindch, const char *altbindch, const char *filech) -{ - char lookups[3], *l; - const char *vqualifier p; +{ + char lookups[3], *l; + const char *vqualifier p; int found; - + if (altbindch == NULL) altbindch = bindch; - /* Set the lookup order. Only the first letter of each work - * is relevant, and it has to be "b" for DNS or "f" for the - * host file. Ignore everything else. - */ - l = lookups; - p = str; + /* Set the lookup order. Only the first letter of each work + * is relevant, and it has to be "b" for DNS or "f" for the + * host file. Ignore everything else. + */ + l = lookups; + p = str; found = 0; - while (*p) - { + while (*p) + { if ((*p == *bindch || *p == *altbindch || *p == *filech) && l < lookups + 2) { if (*p == *bindch || *p == *altbindch) *l++ = 'b'; - else *l++ = 'f'; + else *l++ = 'f'; found = 1; - } - while (*p && !ISSPACE(*p) && (*p != ',')) - p++; - while (*p && (ISSPACE(*p) || (*p == ','))) - p++; - } + } + while (*p && !ISSPACE(*p) && (*p != ',')) + p++; + while (*p && (ISSPACE(*p) || (*p == ','))) + p++; + } if (!found) return ARES_ENOTINITIALIZED; - *l = '\0'; + *l = '\0'; channel->lookups = ares_strdup(lookups); - return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM; -} + return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM; +} #endif /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ & !CARES_USE_LIBRESOLV */ - -#ifndef WATT32 + +#ifndef WATT32 /* Validate that the ip address matches the subnet (network base and network * mask) specified. Addresses are specified in standard Network Byte Order as * 16 bytes, and the netmask is 0 to 128 (bits). @@ -2141,340 +2141,340 @@ static int ares_ipv6_server_blacklisted(const unsigned char ipaddr[16]) * * Returns an error code on failure, else ARES_SUCCESS. */ -static int config_nameserver(struct server_state **servers, int *nservers, - char *str) -{ - struct ares_addr host; - struct server_state *newserv; - char *p, *txtaddr; - /* On Windows, there may be more than one nameserver specified in the same - * registry key, so we parse input as a space or comma seperated list. - */ - for (p = str; p;) - { - /* Skip whitespace and commas. */ - while (*p && (ISSPACE(*p) || (*p == ','))) - p++; - if (!*p) - /* No more input, done. */ - break; - - /* Pointer to start of IPv4 or IPv6 address part. */ - txtaddr = p; - - /* Advance past this address. */ - while (*p && !ISSPACE(*p) && (*p != ',')) - p++; - if (*p) - /* Null terminate this address. */ - *p++ = '\0'; - else - /* Reached end of input, done when this address is processed. */ - p = NULL; - - /* Convert textual address to binary format. */ - if (ares_inet_pton(AF_INET, txtaddr, &host.addrV4) == 1) - host.family = AF_INET; +static int config_nameserver(struct server_state **servers, int *nservers, + char *str) +{ + struct ares_addr host; + struct server_state *newserv; + char *p, *txtaddr; + /* On Windows, there may be more than one nameserver specified in the same + * registry key, so we parse input as a space or comma seperated list. + */ + for (p = str; p;) + { + /* Skip whitespace and commas. */ + while (*p && (ISSPACE(*p) || (*p == ','))) + p++; + if (!*p) + /* No more input, done. */ + break; + + /* Pointer to start of IPv4 or IPv6 address part. */ + txtaddr = p; + + /* Advance past this address. */ + while (*p && !ISSPACE(*p) && (*p != ',')) + p++; + if (*p) + /* Null terminate this address. */ + *p++ = '\0'; + else + /* Reached end of input, done when this address is processed. */ + p = NULL; + + /* Convert textual address to binary format. */ + if (ares_inet_pton(AF_INET, txtaddr, &host.addrV4) == 1) + host.family = AF_INET; else if (ares_inet_pton(AF_INET6, txtaddr, &host.addrV6) == 1 /* Silently skip blacklisted IPv6 servers. */ && !ares_ipv6_server_blacklisted( (const unsigned char *)&host.addrV6)) - host.family = AF_INET6; - else - continue; - - /* Resize servers state array. */ + host.family = AF_INET6; + else + continue; + + /* Resize servers state array. */ newserv = ares_realloc(*servers, (*nservers + 1) * sizeof(struct server_state)); - if (!newserv) - return ARES_ENOMEM; - - /* Store address data. */ - newserv[*nservers].addr.family = host.family; + if (!newserv) + return ARES_ENOMEM; + + /* Store address data. */ + newserv[*nservers].addr.family = host.family; newserv[*nservers].addr.udp_port = 0; newserv[*nservers].addr.tcp_port = 0; - if (host.family == AF_INET) - memcpy(&newserv[*nservers].addr.addrV4, &host.addrV4, - sizeof(host.addrV4)); - else - memcpy(&newserv[*nservers].addr.addrV6, &host.addrV6, - sizeof(host.addrV6)); - - /* Update arguments. */ - *servers = newserv; - *nservers += 1; - } - - return ARES_SUCCESS; -} + if (host.family == AF_INET) + memcpy(&newserv[*nservers].addr.addrV4, &host.addrV4, + sizeof(host.addrV4)); + else + memcpy(&newserv[*nservers].addr.addrV6, &host.addrV6, + sizeof(host.addrV6)); + + /* Update arguments. */ + *servers = newserv; + *nservers += 1; + } + + return ARES_SUCCESS; +} #endif /* !WATT32 */ - -static int config_sortlist(struct apattern **sortlist, int *nsort, - const char *str) -{ - struct apattern pat; - const char *q; - - /* Add sortlist entries. */ - while (*str && *str != ';') - { - int bits; - char ipbuf[16], ipbufpfx[32]; - /* Find just the IP */ - q = str; - while (*q && *q != '/' && *q != ';' && !ISSPACE(*q)) - q++; - memcpy(ipbuf, str, q-str); - ipbuf[q-str] = '\0'; - /* Find the prefix */ - if (*q == '/') - { - const char *str2 = q+1; - while (*q && *q != ';' && !ISSPACE(*q)) - q++; - memcpy(ipbufpfx, str, q-str); - ipbufpfx[q-str] = '\0'; - str = str2; - } - else - ipbufpfx[0] = '\0'; - /* Lets see if it is CIDR */ - /* First we'll try IPv6 */ - if ((bits = ares_inet_net_pton(AF_INET6, ipbufpfx[0] ? ipbufpfx : ipbuf, - &pat.addrV6, - sizeof(pat.addrV6))) > 0) - { - pat.type = PATTERN_CIDR; - pat.mask.bits = (unsigned short)bits; - pat.family = AF_INET6; + +static int config_sortlist(struct apattern **sortlist, int *nsort, + const char *str) +{ + struct apattern pat; + const char *q; + + /* Add sortlist entries. */ + while (*str && *str != ';') + { + int bits; + char ipbuf[16], ipbufpfx[32]; + /* Find just the IP */ + q = str; + while (*q && *q != '/' && *q != ';' && !ISSPACE(*q)) + q++; + memcpy(ipbuf, str, q-str); + ipbuf[q-str] = '\0'; + /* Find the prefix */ + if (*q == '/') + { + const char *str2 = q+1; + while (*q && *q != ';' && !ISSPACE(*q)) + q++; + memcpy(ipbufpfx, str, q-str); + ipbufpfx[q-str] = '\0'; + str = str2; + } + else + ipbufpfx[0] = '\0'; + /* Lets see if it is CIDR */ + /* First we'll try IPv6 */ + if ((bits = ares_inet_net_pton(AF_INET6, ipbufpfx[0] ? ipbufpfx : ipbuf, + &pat.addrV6, + sizeof(pat.addrV6))) > 0) + { + pat.type = PATTERN_CIDR; + pat.mask.bits = (unsigned short)bits; + pat.family = AF_INET6; if (!sortlist_alloc(sortlist, nsort, &pat)) { ares_free(*sortlist); *sortlist = NULL; - return ARES_ENOMEM; + return ARES_ENOMEM; } - } - else if (ipbufpfx[0] && - (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addrV4, - sizeof(pat.addrV4))) > 0) - { - pat.type = PATTERN_CIDR; - pat.mask.bits = (unsigned short)bits; - pat.family = AF_INET; + } + else if (ipbufpfx[0] && + (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addrV4, + sizeof(pat.addrV4))) > 0) + { + pat.type = PATTERN_CIDR; + pat.mask.bits = (unsigned short)bits; + pat.family = AF_INET; if (!sortlist_alloc(sortlist, nsort, &pat)) { ares_free(*sortlist); *sortlist = NULL; - return ARES_ENOMEM; + return ARES_ENOMEM; } - } - /* See if it is just a regular IP */ - else if (ip_addr(ipbuf, q-str, &pat.addrV4) == 0) - { - if (ipbufpfx[0]) - { - memcpy(ipbuf, str, q-str); - ipbuf[q-str] = '\0'; - if (ip_addr(ipbuf, q-str, &pat.mask.addr4) != 0) - natural_mask(&pat); - } - else - natural_mask(&pat); - pat.family = AF_INET; - pat.type = PATTERN_MASK; + } + /* See if it is just a regular IP */ + else if (ip_addr(ipbuf, q-str, &pat.addrV4) == 0) + { + if (ipbufpfx[0]) + { + memcpy(ipbuf, str, q-str); + ipbuf[q-str] = '\0'; + if (ip_addr(ipbuf, q-str, &pat.mask.addr4) != 0) + natural_mask(&pat); + } + else + natural_mask(&pat); + pat.family = AF_INET; + pat.type = PATTERN_MASK; if (!sortlist_alloc(sortlist, nsort, &pat)) { ares_free(*sortlist); *sortlist = NULL; - return ARES_ENOMEM; + return ARES_ENOMEM; } - } - else - { - while (*q && *q != ';' && !ISSPACE(*q)) - q++; - } - str = q; - while (ISSPACE(*str)) - str++; - } - - return ARES_SUCCESS; -} - -static int set_search(ares_channel channel, const char *str) -{ + } + else + { + while (*q && *q != ';' && !ISSPACE(*q)) + q++; + } + str = q; + while (ISSPACE(*str)) + str++; + } + + return ARES_SUCCESS; +} + +static int set_search(ares_channel channel, const char *str) +{ size_t cnt; - - if(channel->ndomains != -1) { + + if(channel->ndomains != -1) { /* LCOV_EXCL_START: all callers check ndomains == -1 */ - /* if we already have some domains present, free them first */ + /* if we already have some domains present, free them first */ ares_strsplit_free(channel->domains, channel->ndomains); - channel->domains = NULL; - channel->ndomains = -1; + channel->domains = NULL; + channel->ndomains = -1; } /* LCOV_EXCL_STOP */ - + channel->domains = ares_strsplit(str, ", ", 1, &cnt); channel->ndomains = (int)cnt; if (channel->domains == NULL || channel->ndomains == 0) { channel->domains = NULL; channel->ndomains = -1; } - - return ARES_SUCCESS; -} - -static int set_options(ares_channel channel, const char *str) -{ - const char *p, *q, *val; - - p = str; - while (*p) - { - q = p; - while (*q && !ISSPACE(*q)) - q++; - val = try_option(p, q, "ndots:"); - if (val && channel->ndots == -1) - channel->ndots = aresx_sltosi(strtol(val, NULL, 10)); - val = try_option(p, q, "retrans:"); - if (val && channel->timeout == -1) - channel->timeout = aresx_sltosi(strtol(val, NULL, 10)); + + return ARES_SUCCESS; +} + +static int set_options(ares_channel channel, const char *str) +{ + const char *p, *q, *val; + + p = str; + while (*p) + { + q = p; + while (*q && !ISSPACE(*q)) + q++; + val = try_option(p, q, "ndots:"); + if (val && channel->ndots == -1) + channel->ndots = aresx_sltosi(strtol(val, NULL, 10)); + val = try_option(p, q, "retrans:"); + if (val && channel->timeout == -1) + channel->timeout = aresx_sltosi(strtol(val, NULL, 10)); val = try_option(p, q, "timeout:"); if (val && channel->timeout == -1) channel->timeout = aresx_sltosi(strtol(val, NULL, 10)) * 1000; val = try_option(p, q, "maxtimeout:"); if (val && channel->maxtimeout == -1) channel->maxtimeout = aresx_sltosi(strtol(val, NULL, 10)) * 1000; - val = try_option(p, q, "retry:"); - if (val && channel->tries == -1) - channel->tries = aresx_sltosi(strtol(val, NULL, 10)); + val = try_option(p, q, "retry:"); + if (val && channel->tries == -1) + channel->tries = aresx_sltosi(strtol(val, NULL, 10)); val = try_option(p, q, "attempts:"); if (val && channel->tries == -1) channel->tries = aresx_sltosi(strtol(val, NULL, 10)); - val = try_option(p, q, "rotate"); - if (val && channel->rotate == -1) - channel->rotate = 1; + val = try_option(p, q, "rotate"); + if (val && channel->rotate == -1) + channel->rotate = 1; val = try_option(p, q, "jitter:"); if (val && channel->jitter == -1) channel->jitter = aresx_sltosi(strtol(val, NULL, 10)); - p = q; - while (ISSPACE(*p)) - p++; - } - - return ARES_SUCCESS; -} - -static const char *try_option(const char *p, const char *q, const char *opt) -{ - size_t len = strlen(opt); - return ((size_t)(q - p) >= len && !strncmp(p, opt, len)) ? &p[len] : NULL; -} - -#if !defined(WIN32) && !defined(WATT32) && \ + p = q; + while (ISSPACE(*p)) + p++; + } + + return ARES_SUCCESS; +} + +static const char *try_option(const char *p, const char *q, const char *opt) +{ + size_t len = strlen(opt); + return ((size_t)(q - p) >= len && !strncmp(p, opt, len)) ? &p[len] : NULL; +} + +#if !defined(WIN32) && !defined(WATT32) && \ !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV) -static char *try_config(char *s, const char *opt, char scc) -{ - size_t len; - char *p; - char *q; - - if (!s || !opt) - /* no line or no option */ +static char *try_config(char *s, const char *opt, char scc) +{ + size_t len; + char *p; + char *q; + + if (!s || !opt) + /* no line or no option */ return NULL; /* LCOV_EXCL_LINE */ - - /* Hash '#' character is always used as primary comment char, additionally - a not-NUL secondary comment char will be considered when specified. */ - - /* trim line comment */ - p = s; - if(scc) - while (*p && (*p != '#') && (*p != scc)) - p++; - else - while (*p && (*p != '#')) - p++; - *p = '\0'; - - /* trim trailing whitespace */ - q = p - 1; - while ((q >= s) && ISSPACE(*q)) - q--; - *++q = '\0'; - - /* skip leading whitespace */ - p = s; - while (*p && ISSPACE(*p)) - p++; - - if (!*p) - /* empty line */ - return NULL; - - if ((len = strlen(opt)) == 0) - /* empty option */ + + /* Hash '#' character is always used as primary comment char, additionally + a not-NUL secondary comment char will be considered when specified. */ + + /* trim line comment */ + p = s; + if(scc) + while (*p && (*p != '#') && (*p != scc)) + p++; + else + while (*p && (*p != '#')) + p++; + *p = '\0'; + + /* trim trailing whitespace */ + q = p - 1; + while ((q >= s) && ISSPACE(*q)) + q--; + *++q = '\0'; + + /* skip leading whitespace */ + p = s; + while (*p && ISSPACE(*p)) + p++; + + if (!*p) + /* empty line */ + return NULL; + + if ((len = strlen(opt)) == 0) + /* empty option */ return NULL; /* LCOV_EXCL_LINE */ - - if (strncmp(p, opt, len) != 0) - /* line and option do not match */ - return NULL; - - /* skip over given option name */ - p += len; - - if (!*p) - /* no option value */ + + if (strncmp(p, opt, len) != 0) + /* line and option do not match */ + return NULL; + + /* skip over given option name */ + p += len; + + if (!*p) + /* no option value */ return NULL; /* LCOV_EXCL_LINE */ - - if ((opt[len-1] != ':') && (opt[len-1] != '=') && !ISSPACE(*p)) - /* whitespace between option name and value is mandatory - for given option names which do not end with ':' or '=' */ - return NULL; - - /* skip over whitespace */ - while (*p && ISSPACE(*p)) - p++; - - if (!*p) - /* no option value */ - return NULL; - - /* return pointer to option value */ - return p; -} + + if ((opt[len-1] != ':') && (opt[len-1] != '=') && !ISSPACE(*p)) + /* whitespace between option name and value is mandatory + for given option names which do not end with ':' or '=' */ + return NULL; + + /* skip over whitespace */ + while (*p && ISSPACE(*p)) + p++; + + if (!*p) + /* no option value */ + return NULL; + + /* return pointer to option value */ + return p; +} #endif /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ */ - + static int ip_addr(const char *ipbuf, ares_ssize_t len, struct in_addr *addr) -{ - - /* Four octets and three periods yields at most 15 characters. */ - if (len > 15) - return -1; - +{ + + /* Four octets and three periods yields at most 15 characters. */ + if (len > 15) + return -1; + if (ares_inet_pton(AF_INET, ipbuf, addr) < 1) - return -1; - - return 0; -} - -static void natural_mask(struct apattern *pat) -{ - struct in_addr addr; - - /* Store a host-byte-order copy of pat in a struct in_addr. Icky, - * but portable. - */ - addr.s_addr = ntohl(pat->addrV4.s_addr); - - /* This is out of date in the CIDR world, but some people might - * still rely on it. - */ - if (IN_CLASSA(addr.s_addr)) - pat->mask.addr4.s_addr = htonl(IN_CLASSA_NET); - else if (IN_CLASSB(addr.s_addr)) - pat->mask.addr4.s_addr = htonl(IN_CLASSB_NET); - else - pat->mask.addr4.s_addr = htonl(IN_CLASSC_NET); -} - + return -1; + + return 0; +} + +static void natural_mask(struct apattern *pat) +{ + struct in_addr addr; + + /* Store a host-byte-order copy of pat in a struct in_addr. Icky, + * but portable. + */ + addr.s_addr = ntohl(pat->addrV4.s_addr); + + /* This is out of date in the CIDR world, but some people might + * still rely on it. + */ + if (IN_CLASSA(addr.s_addr)) + pat->mask.addr4.s_addr = htonl(IN_CLASSA_NET); + else if (IN_CLASSB(addr.s_addr)) + pat->mask.addr4.s_addr = htonl(IN_CLASSB_NET); + else + pat->mask.addr4.s_addr = htonl(IN_CLASSC_NET); +} + static int sortlist_alloc(struct apattern **sortlist, int *nsort, struct apattern *pat) { @@ -2488,105 +2488,105 @@ static int sortlist_alloc(struct apattern **sortlist, int *nsort, return 1; } -/* initialize an rc4 key. If possible a cryptographically secure random key - is generated using a suitable function (for example win32's RtlGenRandom as - described in - http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx - otherwise the code defaults to cross-platform albeit less secure mechanism - using rand -*/ -static void randomize_key(unsigned char* key,int key_data_len) -{ - int randomized = 0; - int counter=0; -#ifdef WIN32 - BOOLEAN res; - if (ares_fpSystemFunction036) - { - res = (*ares_fpSystemFunction036) (key, key_data_len); - if (res) - randomized = 1; - } -#else /* !WIN32 */ -#ifdef RANDOM_FILE - FILE *f = fopen(RANDOM_FILE, "rb"); - if(f) { - counter = aresx_uztosi(fread(key, 1, key_data_len, f)); - fclose(f); - } -#endif -#endif /* WIN32 */ - - if (!randomized) { - for (;counter<key_data_len;counter++) +/* initialize an rc4 key. If possible a cryptographically secure random key + is generated using a suitable function (for example win32's RtlGenRandom as + described in + http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx + otherwise the code defaults to cross-platform albeit less secure mechanism + using rand +*/ +static void randomize_key(unsigned char* key,int key_data_len) +{ + int randomized = 0; + int counter=0; +#ifdef WIN32 + BOOLEAN res; + if (ares_fpSystemFunction036) + { + res = (*ares_fpSystemFunction036) (key, key_data_len); + if (res) + randomized = 1; + } +#else /* !WIN32 */ +#ifdef RANDOM_FILE + FILE *f = fopen(RANDOM_FILE, "rb"); + if(f) { + counter = aresx_uztosi(fread(key, 1, key_data_len, f)); + fclose(f); + } +#endif +#endif /* WIN32 */ + + if (!randomized) { + for (;counter<key_data_len;counter++) key[counter]=(unsigned char)(rand() % 256); /* LCOV_EXCL_LINE */ - } -} - -static int init_id_key(rc4_key* key,int key_data_len) -{ - unsigned char index1; - unsigned char index2; - unsigned char* state; - short counter; - unsigned char *key_data_ptr = 0; - + } +} + +static int init_id_key(rc4_key* key,int key_data_len) +{ + unsigned char index1; + unsigned char index2; + unsigned char* state; + short counter; + unsigned char *key_data_ptr = 0; + key_data_ptr = ares_malloc(key_data_len); - if (!key_data_ptr) - return ARES_ENOMEM; + if (!key_data_ptr) + return ARES_ENOMEM; memset(key_data_ptr, 0, key_data_len); - - state = &key->state[0]; - for(counter = 0; counter < 256; counter++) - /* unnecessary AND but it keeps some compilers happier */ - state[counter] = (unsigned char)(counter & 0xff); - randomize_key(key->state,key_data_len); - key->x = 0; - key->y = 0; - index1 = 0; - index2 = 0; - for(counter = 0; counter < 256; counter++) - { - index2 = (unsigned char)((key_data_ptr[index1] + state[counter] + - index2) % 256); - ARES_SWAP_BYTE(&state[counter], &state[index2]); - - index1 = (unsigned char)((index1 + 1) % key_data_len); - } + + state = &key->state[0]; + for(counter = 0; counter < 256; counter++) + /* unnecessary AND but it keeps some compilers happier */ + state[counter] = (unsigned char)(counter & 0xff); + randomize_key(key->state,key_data_len); + key->x = 0; + key->y = 0; + index1 = 0; + index2 = 0; + for(counter = 0; counter < 256; counter++) + { + index2 = (unsigned char)((key_data_ptr[index1] + state[counter] + + index2) % 256); + ARES_SWAP_BYTE(&state[counter], &state[index2]); + + index1 = (unsigned char)((index1 + 1) % key_data_len); + } ares_free(key_data_ptr); - return ARES_SUCCESS; -} - -void ares_set_local_ip4(ares_channel channel, unsigned int local_ip) -{ - channel->local_ip4 = local_ip; -} - -/* local_ip6 should be 16 bytes in length */ -void ares_set_local_ip6(ares_channel channel, - const unsigned char* local_ip6) -{ - memcpy(&channel->local_ip6, local_ip6, sizeof(channel->local_ip6)); -} - -/* local_dev_name should be null terminated. */ -void ares_set_local_dev(ares_channel channel, - const char* local_dev_name) -{ - strncpy(channel->local_dev_name, local_dev_name, - sizeof(channel->local_dev_name)); - channel->local_dev_name[sizeof(channel->local_dev_name) - 1] = 0; -} - - -void ares_set_socket_callback(ares_channel channel, - ares_sock_create_callback cb, - void *data) -{ - channel->sock_create_cb = cb; - channel->sock_create_cb_data = data; -} - + return ARES_SUCCESS; +} + +void ares_set_local_ip4(ares_channel channel, unsigned int local_ip) +{ + channel->local_ip4 = local_ip; +} + +/* local_ip6 should be 16 bytes in length */ +void ares_set_local_ip6(ares_channel channel, + const unsigned char* local_ip6) +{ + memcpy(&channel->local_ip6, local_ip6, sizeof(channel->local_ip6)); +} + +/* local_dev_name should be null terminated. */ +void ares_set_local_dev(ares_channel channel, + const char* local_dev_name) +{ + strncpy(channel->local_dev_name, local_dev_name, + sizeof(channel->local_dev_name)); + channel->local_dev_name[sizeof(channel->local_dev_name) - 1] = 0; +} + + +void ares_set_socket_callback(ares_channel channel, + ares_sock_create_callback cb, + void *data) +{ + channel->sock_create_cb = cb; + channel->sock_create_cb_data = data; +} + void ares_set_socket_configure_callback(ares_channel channel, ares_sock_config_callback cb, void *data) @@ -2622,25 +2622,25 @@ int ares_set_sortlist(ares_channel channel, const char *sortstr) return status; } -void ares__init_servers_state(ares_channel channel) -{ - struct server_state *server; - int i; - - for (i = 0; i < channel->nservers; i++) - { - server = &channel->servers[i]; - server->udp_socket = ARES_SOCKET_BAD; - server->tcp_socket = ARES_SOCKET_BAD; - server->tcp_connection_generation = ++channel->tcp_connection_generation; - server->tcp_lenbuf_pos = 0; - server->tcp_buffer_pos = 0; - server->tcp_buffer = NULL; - server->tcp_length = 0; - server->qhead = NULL; - server->qtail = NULL; - ares__init_list_head(&server->queries_to_server); - server->channel = channel; - server->is_broken = 0; - } -} +void ares__init_servers_state(ares_channel channel) +{ + struct server_state *server; + int i; + + for (i = 0; i < channel->nservers; i++) + { + server = &channel->servers[i]; + server->udp_socket = ARES_SOCKET_BAD; + server->tcp_socket = ARES_SOCKET_BAD; + server->tcp_connection_generation = ++channel->tcp_connection_generation; + server->tcp_lenbuf_pos = 0; + server->tcp_buffer_pos = 0; + server->tcp_buffer = NULL; + server->tcp_length = 0; + server->qhead = NULL; + server->qtail = NULL; + ares__init_list_head(&server->queries_to_server); + server->channel = channel; + server->is_broken = 0; + } +} |