diff options
author | snermolaev <snermolaev@yandex-team.ru> | 2022-02-10 16:45:53 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:53 +0300 |
commit | 2015790ac9fcc04caab83fccc23ab2460310a797 (patch) | |
tree | e644e9bc3f6f688561a871793b59bf8a637e0f72 /contrib/libs/c-ares/ares_init.c | |
parent | c768a99151e47c3a4bb7b92c514d256abd301c4d (diff) | |
download | ydb-2015790ac9fcc04caab83fccc23ab2460310a797.tar.gz |
Restoring authorship annotation for <snermolaev@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 | 1342 |
1 files changed, 671 insertions, 671 deletions
diff --git a/contrib/libs/c-ares/ares_init.c b/contrib/libs/c-ares/ares_init.c index e06265c6a2..fad0c52b36 100644 --- a/contrib/libs/c-ares/ares_init.c +++ b/contrib/libs/c-ares/ares_init.c @@ -44,16 +44,16 @@ #if defined(ANDROID) || defined(__ANDROID__) #include <sys/system_properties.h> -#include "ares_android.h" +#include "ares_android.h" /* 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 - +#if defined(CARES_USE_LIBRESOLV) +#include <resolv.h> +#endif + #include "ares.h" #include "ares_inet_net_pton.h" #include "ares_library_init.h" @@ -81,18 +81,18 @@ 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 config_sortlist(struct apattern **sortlist, int *nsort, + const char *str); 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 int ip_addr(const char *s, ares_ssize_t len, struct in_addr *addr); static void natural_mask(struct apattern *pat); -#if !defined(WIN32) && !defined(WATT32) && \ - !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV) +#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, - const char *bindch, const char *altbindch, - const char *filech); + const char *bindch, const char *altbindch, + const char *filech); static char *try_config(char *s, const char *opt, char scc); #endif @@ -130,9 +130,9 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options, #endif if (ares_library_initialized() != ARES_SUCCESS) - return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */ + return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */ - channel = ares_malloc(sizeof(struct ares_channeldata)); + channel = ares_malloc(sizeof(struct ares_channeldata)); if (!channel) { *channelptr = NULL; return ARES_ENOMEM; @@ -168,10 +168,10 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options, 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->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; @@ -196,17 +196,17 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options, * 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_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))); + 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) @@ -234,21 +234,21 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options, ares_strerror(status))); } -done: +done: if (status != ARES_SUCCESS) { /* Something failed; clean up memory we may have allocated. */ if (channel->servers) - ares_free(channel->servers); + ares_free(channel->servers); if (channel->ndomains != -1) ares_strsplit_free(channel->domains, channel->ndomains); if (channel->sortlist) - ares_free(channel->sortlist); + ares_free(channel->sortlist); if(channel->lookups) - ares_free(channel->lookups); + ares_free(channel->lookups); if(channel->resolvconf_path) ares_free(channel->resolvconf_path); - ares_free(channel); + ares_free(channel); return status; } @@ -267,8 +267,8 @@ done: 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; + struct ares_addr_port_node *servers; + int non_v4_default_port = 0; int i, rc; int optmask; @@ -278,10 +278,10 @@ int ares_dup(ares_channel *dest, ares_channel src) which is most of them */ rc = ares_save_options(src, &opts, &optmask); if(rc) - { - ares_destroy_options(&opts); + { + ares_destroy_options(&opts); return rc; - } + } /* Then create the new channel with those options */ rc = ares_init_options(dest, &opts, optmask); @@ -295,40 +295,40 @@ int ares_dup(ares_channel *dest, ares_channel src) /* 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; + (*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, sizeof((*dest)->local_dev_name)); (*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 */ + /* Full name server cloning required if there is a non-IPv4, or non-default port, nameserver */ 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++; + 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; } } - if (non_v4_default_port) { - rc = ares_get_servers_ports(src, &servers); - if (rc != ARES_SUCCESS) { - ares_destroy(*dest); - *dest = NULL; + if (non_v4_default_port) { + rc = ares_get_servers_ports(src, &servers); + if (rc != ARES_SUCCESS) { + ares_destroy(*dest); + *dest = NULL; return rc; - } - rc = ares_set_servers_ports(*dest, servers); + } + rc = ares_set_servers_ports(*dest, servers); ares_free_data(servers); - if (rc != ARES_SUCCESS) { - ares_destroy(*dest); - *dest = NULL; + if (rc != ARES_SUCCESS) { + ares_destroy(*dest); + *dest = NULL; return rc; - } + } } return ARES_SUCCESS; /* everything went fine */ @@ -355,7 +355,7 @@ int ares_save_options(ares_channel channel, struct ares_options *options, 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); + (*optmask) |= (channel->rotate ? ARES_OPT_ROTATE : ARES_OPT_NOROTATE); if (channel->resolvconf_path) (*optmask) |= ARES_OPT_RESOLVCONF; @@ -376,24 +376,24 @@ int ares_save_options(ares_channel channel, struct ares_options *options, 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 */ + /* Copy IPv4 servers that use the default port */ 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)) + 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) { - options->servers = ares_malloc(ipv4_nservers * sizeof(struct in_addr)); + 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 ((channel->servers[i].addr.family == AF_INET) && - (channel->servers[i].addr.udp_port == 0) && - (channel->servers[i].addr.tcp_port == 0)) + 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)); @@ -404,14 +404,14 @@ int ares_save_options(ares_channel channel, struct ares_options *options, /* copy domains */ if (channel->ndomains) { - options->domains = ares_malloc(channel->ndomains * sizeof(char *)); + options->domains = ares_malloc(channel->ndomains * sizeof(char *)); if (!options->domains) return ARES_ENOMEM; for (i = 0; i < channel->ndomains; i++) { options->ndomains = i; - options->domains[i] = ares_strdup(channel->domains[i]); + options->domains[i] = ares_strdup(channel->domains[i]); if (!options->domains[i]) return ARES_ENOMEM; } @@ -420,14 +420,14 @@ int ares_save_options(ares_channel channel, struct ares_options *options, /* copy lookups */ if (channel->lookups) { - options->lookups = ares_strdup(channel->lookups); + options->lookups = ares_strdup(channel->lookups); if (!options->lookups && channel->lookups) return ARES_ENOMEM; } /* copy sortlist */ if (channel->nsort) { - options->sortlist = ares_malloc(channel->nsort * sizeof(struct apattern)); + options->sortlist = ares_malloc(channel->nsort * sizeof(struct apattern)); if (!options->sortlist) return ARES_ENOMEM; for (i = 0; i < channel->nsort; i++) @@ -471,8 +471,8 @@ static int init_by_options(ares_channel channel, 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_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) @@ -499,14 +499,14 @@ static int init_by_options(ares_channel channel, if (options->nservers > 0) { channel->servers = - ares_malloc(options->nservers * sizeof(struct server_state)); + 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; - channel->servers[i].addr.udp_port = 0; - channel->servers[i].addr.tcp_port = 0; + 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)); @@ -523,13 +523,13 @@ static int init_by_options(ares_channel channel, /* Avoid zero size allocations at any cost */ if (options->ndomains > 0) { - channel->domains = ares_malloc(options->ndomains * sizeof(char *)); + channel->domains = ares_malloc(options->ndomains * sizeof(char *)); if (!channel->domains) return ARES_ENOMEM; for (i = 0; i < options->ndomains; i++) { channel->ndomains = i; - channel->domains[i] = ares_strdup(options->domains[i]); + channel->domains[i] = ares_strdup(options->domains[i]); if (!channel->domains[i]) return ARES_ENOMEM; } @@ -540,20 +540,20 @@ static int init_by_options(ares_channel channel, /* Set lookups, if given. */ if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups) { - channel->lookups = ares_strdup(options->lookups); + channel->lookups = ares_strdup(options->lookups); 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)); - if (!channel->sortlist) - return ARES_ENOMEM; - for (i = 0; i < options->nsort; i++) - channel->sortlist[i] = options->sortlist[i]; - } + if ((optmask & ARES_OPT_SORTLIST) && (channel->nsort == -1)) { + if (options->nsort > 0) { + channel->sortlist = ares_malloc(options->nsort * sizeof(struct apattern)); + if (!channel->sortlist) + return ARES_ENOMEM; + for (i = 0; i < options->nsort; i++) + channel->sortlist[i] = options->sortlist[i]; + } channel->nsort = options->nsort; } @@ -588,7 +588,7 @@ static int init_by_environment(ares_channel channel) { status = set_options(channel, res_options); if (status != ARES_SUCCESS) - return status; /* LCOV_EXCL_LINE: set_options() never fails */ + return status; /* LCOV_EXCL_LINE: set_options() never fails */ } return ARES_SUCCESS; @@ -617,22 +617,22 @@ static int get_REG_SZ(HKEY hKey, const char *leafKeyName, char **outptr) *outptr = NULL; /* Find out size of string stored in registry */ - res = RegQueryValueExA(hKey, leafKeyName, 0, NULL, NULL, &size); + 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 */ - *outptr = ares_malloc(size+1); + *outptr = ares_malloc(size+1); if (!*outptr) return 0; /* Get the value for real */ - res = RegQueryValueExA(hKey, leafKeyName, 0, NULL, + res = RegQueryValueExA(hKey, leafKeyName, 0, NULL, (unsigned char *)*outptr, &size); if ((res != ERROR_SUCCESS) || (size == 1)) { - ares_free(*outptr); + ares_free(*outptr); *outptr = NULL; return 0; } @@ -659,22 +659,22 @@ static int get_REG_SZ_9X(HKEY hKey, const char *leafKeyName, char **outptr) *outptr = NULL; /* Find out size of string stored in registry */ - res = RegQueryValueExA(hKey, leafKeyName, 0, &dataType, NULL, &size); + 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 */ - *outptr = ares_malloc(size+1); + *outptr = ares_malloc(size+1); if (!*outptr) return 0; /* Get the value for real */ - res = RegQueryValueExA(hKey, leafKeyName, 0, &dataType, + res = RegQueryValueExA(hKey, leafKeyName, 0, &dataType, (unsigned char *)*outptr, &size); if ((res != ERROR_SUCCESS) || (size == 1)) { - ares_free(*outptr); + ares_free(*outptr); *outptr = NULL; return 0; } @@ -715,11 +715,11 @@ static int get_enum_REG_SZ(HKEY hKeyParent, const char *leafKeyName, for(;;) { enumKeyNameBuffSize = sizeof(enumKeyName); - res = RegEnumKeyExA(hKeyParent, enumKeyIdx++, enumKeyName, + res = RegEnumKeyExA(hKeyParent, enumKeyIdx++, enumKeyName, &enumKeyNameBuffSize, 0, NULL, NULL, NULL); if (res != ERROR_SUCCESS) break; - res = RegOpenKeyExA(hKeyParent, enumKeyName, 0, KEY_QUERY_VALUE, + res = RegOpenKeyExA(hKeyParent, enumKeyName, 0, KEY_QUERY_VALUE, &hKeyEnum); if (res != ERROR_SUCCESS) continue; @@ -750,7 +750,7 @@ static int get_DNS_Registry_9X(char **outptr) *outptr = NULL; - res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_9X, 0, KEY_READ, + res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_9X, 0, KEY_READ, &hKey_VxD_MStcp); if (res != ERROR_SUCCESS) return 0; @@ -782,7 +782,7 @@ static int get_DNS_Registry_NT(char **outptr) *outptr = NULL; - res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ, + res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ, &hKey_Tcpip_Parameters); if (res != ERROR_SUCCESS) return 0; @@ -804,7 +804,7 @@ static int get_DNS_Registry_NT(char **outptr) goto done; /* Try adapter specific parameters */ - res = RegOpenKeyExA(hKey_Tcpip_Parameters, "Interfaces", 0, + res = RegOpenKeyExA(hKey_Tcpip_Parameters, "Interfaces", 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey_Interfaces); if (res != ERROR_SUCCESS) @@ -864,24 +864,24 @@ static int get_DNS_Registry(char **outptr) return 1; } -static void commanjoin(char** dst, const char* const src, const size_t len) -{ - char *newbuf; - size_t newsize; - - /* 1 for terminating 0 and 2 for , and terminating 0 */ - newsize = len + (*dst ? (strlen(*dst) + 2) : 1); - newbuf = ares_realloc(*dst, newsize); - if (!newbuf) - return; - if (*dst == NULL) - *newbuf = '\0'; - *dst = newbuf; - if (strlen(*dst) != 0) - strcat(*dst, ","); - strncat(*dst, src, len); -} - +static void commanjoin(char** dst, const char* const src, const size_t len) +{ + char *newbuf; + size_t newsize; + + /* 1 for terminating 0 and 2 for , and terminating 0 */ + newsize = len + (*dst ? (strlen(*dst) + 2) : 1); + newbuf = ares_realloc(*dst, newsize); + if (!newbuf) + return; + if (*dst == NULL) + *newbuf = '\0'; + *dst = newbuf; + if (strlen(*dst) != 0) + strcat(*dst, ","); + strncat(*dst, src, len); +} + /* * commajoin() * @@ -889,7 +889,7 @@ static void commanjoin(char** dst, const char* const src, const size_t len) */ static void commajoin(char **dst, const char *src) { - commanjoin(dst, src, strlen(src)); + commanjoin(dst, src, strlen(src)); } /* @@ -923,7 +923,7 @@ static int get_DNS_NetworkParams(char **outptr) if (ares_fpGetNetworkParams == ZERO_NULL) return 0; - fi = ares_malloc(size); + fi = ares_malloc(size); if (!fi) return 0; @@ -931,7 +931,7 @@ static int get_DNS_NetworkParams(char **outptr) if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS)) goto done; - newfi = ares_realloc(fi, size); + newfi = ares_realloc(fi, size); if (!newfi) goto done; @@ -968,7 +968,7 @@ static int get_DNS_NetworkParams(char **outptr) done: if (fi) - ares_free(fi); + ares_free(fi); if (!*outptr) return 0; @@ -976,131 +976,131 @@ done: return 1; } -static BOOL ares_IsWindowsVistaOrGreater(void) -{ - OSVERSIONINFO vinfo; - memset(&vinfo, 0, sizeof(vinfo)); - vinfo.dwOSVersionInfoSize = sizeof(vinfo); -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4996) /* warning C4996: 'GetVersionExW': was declared deprecated */ -#endif - if (!GetVersionEx(&vinfo) || vinfo.dwMajorVersion < 6) - return FALSE; - return TRUE; -#ifdef _MSC_VER -#pragma warning(pop) -#endif -} - -/* A structure to hold the string form of IPv4 and IPv6 addresses so we can - * sort them by a metric. - */ -typedef struct -{ - /* The metric we sort them by. */ - ULONG metric; - - /* Original index of the item, used as a secondary sort parameter to make - * qsort() stable if the metrics are equal */ - size_t orig_idx; - - /* Room enough for the string form of any IPv4 or IPv6 address that - * ares_inet_ntop() will create. Based on the existing c-ares practice. - */ - char text[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; -} Address; - -/* Sort Address values \a left and \a right by metric, returning the usual - * indicators for qsort(). - */ -static int compareAddresses(const void *arg1, - const void *arg2) -{ - const Address * const left = arg1; - const Address * const right = arg2; - /* Lower metric the more preferred */ - if(left->metric < right->metric) return -1; - if(left->metric > right->metric) return 1; - /* If metrics are equal, lower original index more preferred */ - if(left->orig_idx < right->orig_idx) return -1; - if(left->orig_idx > right->orig_idx) return 1; - return 0; -} - -/* There can be multiple routes to "the Internet". And there can be different - * DNS servers associated with each of the interfaces that offer those routes. - * We have to assume that any DNS server can serve any request. But, some DNS - * servers may only respond if requested over their associated interface. But - * we also want to use "the preferred route to the Internet" whenever possible - * (and not use DNS servers on a non-preferred route even by forcing request - * to go out on the associated non-preferred interface). i.e. We want to use - * the DNS servers associated with the same interface that we would use to - * make a general request to anything else. - * - * But, Windows won't sort the DNS servers by the metrics associated with the - * routes and interfaces _even_ though it obviously sends IP packets based on - * those same routes and metrics. So, we must do it ourselves. - * - * So, we sort the DNS servers by the same metric values used to determine how - * an outgoing IP packet will go, thus effectively using the DNS servers - * associated with the interface that the DNS requests themselves will - * travel. This gives us optimal routing and avoids issues where DNS servers - * won't respond to requests that don't arrive via some specific subnetwork - * (and thus some specific interface). - * - * This function computes the metric we use to sort. On the interface - * identified by \a luid, it determines the best route to \a dest and combines - * that route's metric with \a interfaceMetric to compute a metric for the - * destination address on that interface. This metric can be used as a weight - * to sort the DNS server addresses associated with each interface (lower is - * better). - * - * Note that by restricting the route search to the specific interface with - * which the DNS servers are associated, this function asks the question "What - * is the metric for sending IP packets to this DNS server?" which allows us - * to sort the DNS servers correctly. - */ -static ULONG getBestRouteMetric(IF_LUID * const luid, /* Can't be const :( */ - const SOCKADDR_INET * const dest, - const ULONG interfaceMetric) -{ - /* On this interface, get the best route to that destination. */ - MIB_IPFORWARD_ROW2 row; - SOCKADDR_INET ignored; - if(!ares_fpGetBestRoute2 || - ares_fpGetBestRoute2(/* The interface to use. The index is ignored since we are - * passing a LUID. - */ - luid, 0, - /* No specific source address. */ - NULL, - /* Our destination address. */ - dest, - /* No options. */ - 0, - /* The route row. */ - &row, - /* The best source address, which we don't need. */ - &ignored) != NO_ERROR - /* If the metric is "unused" (-1) or too large for us to add the two - * metrics, use the worst possible, thus sorting this last. - */ - || row.Metric == (ULONG)-1 - || row.Metric > ((ULONG)-1) - interfaceMetric) { - /* Return the worst possible metric. */ - return (ULONG)-1; - } - - /* Return the metric value from that row, plus the interface metric. - * - * See - * http://msdn.microsoft.com/en-us/library/windows/desktop/aa814494(v=vs.85).aspx - * which describes the combination as a "sum". - */ - return row.Metric + interfaceMetric; -} - +static BOOL ares_IsWindowsVistaOrGreater(void) +{ + OSVERSIONINFO vinfo; + memset(&vinfo, 0, sizeof(vinfo)); + vinfo.dwOSVersionInfoSize = sizeof(vinfo); +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4996) /* warning C4996: 'GetVersionExW': was declared deprecated */ +#endif + if (!GetVersionEx(&vinfo) || vinfo.dwMajorVersion < 6) + return FALSE; + return TRUE; +#ifdef _MSC_VER +#pragma warning(pop) +#endif +} + +/* A structure to hold the string form of IPv4 and IPv6 addresses so we can + * sort them by a metric. + */ +typedef struct +{ + /* The metric we sort them by. */ + ULONG metric; + + /* Original index of the item, used as a secondary sort parameter to make + * qsort() stable if the metrics are equal */ + size_t orig_idx; + + /* Room enough for the string form of any IPv4 or IPv6 address that + * ares_inet_ntop() will create. Based on the existing c-ares practice. + */ + char text[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; +} Address; + +/* Sort Address values \a left and \a right by metric, returning the usual + * indicators for qsort(). + */ +static int compareAddresses(const void *arg1, + const void *arg2) +{ + const Address * const left = arg1; + const Address * const right = arg2; + /* Lower metric the more preferred */ + if(left->metric < right->metric) return -1; + if(left->metric > right->metric) return 1; + /* If metrics are equal, lower original index more preferred */ + if(left->orig_idx < right->orig_idx) return -1; + if(left->orig_idx > right->orig_idx) return 1; + return 0; +} + +/* There can be multiple routes to "the Internet". And there can be different + * DNS servers associated with each of the interfaces that offer those routes. + * We have to assume that any DNS server can serve any request. But, some DNS + * servers may only respond if requested over their associated interface. But + * we also want to use "the preferred route to the Internet" whenever possible + * (and not use DNS servers on a non-preferred route even by forcing request + * to go out on the associated non-preferred interface). i.e. We want to use + * the DNS servers associated with the same interface that we would use to + * make a general request to anything else. + * + * But, Windows won't sort the DNS servers by the metrics associated with the + * routes and interfaces _even_ though it obviously sends IP packets based on + * those same routes and metrics. So, we must do it ourselves. + * + * So, we sort the DNS servers by the same metric values used to determine how + * an outgoing IP packet will go, thus effectively using the DNS servers + * associated with the interface that the DNS requests themselves will + * travel. This gives us optimal routing and avoids issues where DNS servers + * won't respond to requests that don't arrive via some specific subnetwork + * (and thus some specific interface). + * + * This function computes the metric we use to sort. On the interface + * identified by \a luid, it determines the best route to \a dest and combines + * that route's metric with \a interfaceMetric to compute a metric for the + * destination address on that interface. This metric can be used as a weight + * to sort the DNS server addresses associated with each interface (lower is + * better). + * + * Note that by restricting the route search to the specific interface with + * which the DNS servers are associated, this function asks the question "What + * is the metric for sending IP packets to this DNS server?" which allows us + * to sort the DNS servers correctly. + */ +static ULONG getBestRouteMetric(IF_LUID * const luid, /* Can't be const :( */ + const SOCKADDR_INET * const dest, + const ULONG interfaceMetric) +{ + /* On this interface, get the best route to that destination. */ + MIB_IPFORWARD_ROW2 row; + SOCKADDR_INET ignored; + if(!ares_fpGetBestRoute2 || + ares_fpGetBestRoute2(/* The interface to use. The index is ignored since we are + * passing a LUID. + */ + luid, 0, + /* No specific source address. */ + NULL, + /* Our destination address. */ + dest, + /* No options. */ + 0, + /* The route row. */ + &row, + /* The best source address, which we don't need. */ + &ignored) != NO_ERROR + /* If the metric is "unused" (-1) or too large for us to add the two + * metrics, use the worst possible, thus sorting this last. + */ + || row.Metric == (ULONG)-1 + || row.Metric > ((ULONG)-1) - interfaceMetric) { + /* Return the worst possible metric. */ + return (ULONG)-1; + } + + /* Return the metric value from that row, plus the interface metric. + * + * See + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa814494(v=vs.85).aspx + * which describes the combination as a "sum". + */ + return row.Metric + interfaceMetric; +} + /* * get_DNS_AdaptersAddresses() * @@ -1127,13 +1127,13 @@ static int get_DNS_AdaptersAddresses(char **outptr) int trying = IPAA_MAX_TRIES; int res; - /* The capacity of addresses, in elements. */ - size_t addressesSize; - /* The number of elements in addresses. */ - size_t addressesIndex = 0; - /* The addresses we will sort. */ - Address *addresses; - + /* The capacity of addresses, in elements. */ + size_t addressesSize; + /* The number of elements in addresses. */ + size_t addressesIndex = 0; + /* The addresses we will sort. */ + Address *addresses; + union { struct sockaddr *sa; struct sockaddr_in *sa4; @@ -1146,21 +1146,21 @@ static int get_DNS_AdaptersAddresses(char **outptr) if (ares_fpGetAdaptersAddresses == ZERO_NULL) return 0; - ipaa = ares_malloc(Bufsz); + ipaa = ares_malloc(Bufsz); if (!ipaa) return 0; - /* Start with enough room for a few DNS server addresses and we'll grow it - * as we encounter more. - */ - addressesSize = 4; - addresses = (Address*)ares_malloc(sizeof(Address) * addressesSize); - if(addresses == NULL) { - /* We need room for at least some addresses to function. */ - ares_free(ipaa); - return 0; - } - + /* Start with enough room for a few DNS server addresses and we'll grow it + * as we encounter more. + */ + addressesSize = 4; + addresses = (Address*)ares_malloc(sizeof(Address) * addressesSize); + if(addresses == NULL) { + /* We need room for at least some addresses to function. */ + ares_free(ipaa); + return 0; + } + /* Usually this call suceeds with initial buffer size */ res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL, ipaa, &ReqBufsz); @@ -1171,7 +1171,7 @@ static int get_DNS_AdaptersAddresses(char **outptr) { if (Bufsz < ReqBufsz) { - newipaa = ares_realloc(ipaa, ReqBufsz); + newipaa = ares_realloc(ipaa, ReqBufsz); if (!newipaa) goto done; Bufsz = ReqBufsz; @@ -1187,15 +1187,15 @@ static int get_DNS_AdaptersAddresses(char **outptr) for (ipaaEntry = ipaa; ipaaEntry; ipaaEntry = ipaaEntry->Next) { - if(ipaaEntry->OperStatus != IfOperStatusUp) - continue; - - /* For each interface, find any associated DNS servers as IPv4 or IPv6 - * addresses. For each found address, find the best route to that DNS - * server address _on_ _that_ _interface_ (at this moment in time) and - * compute the resulting total metric, just as Windows routing will do. - * Then, sort all the addresses found by the metric. - */ + if(ipaaEntry->OperStatus != IfOperStatusUp) + continue; + + /* For each interface, find any associated DNS servers as IPv4 or IPv6 + * addresses. For each found address, find the best route to that DNS + * server address _on_ _that_ _interface_ (at this moment in time) and + * 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) @@ -1207,124 +1207,124 @@ static int get_DNS_AdaptersAddresses(char **outptr) 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) { - const size_t newSize = addressesSize + 4; + + /* Allocate room for another address, if necessary, else skip. */ + if(addressesIndex == addressesSize) { + const size_t newSize = addressesSize + 4; Address * const newMem = - (Address*)ares_realloc(addresses, sizeof(Address) * newSize); - if(newMem == NULL) { - continue; - } - addresses = newMem; - addressesSize = newSize; - } - - /* Vista required for Luid or Ipv4Metric */ - if (ares_IsWindowsVistaOrGreater()) - { - /* Save the address as the next element in addresses. */ - addresses[addressesIndex].metric = - getBestRouteMetric(&ipaaEntry->Luid, - (SOCKADDR_INET*)(namesrvr.sa), - ipaaEntry->Ipv4Metric); - } - else - { + (Address*)ares_realloc(addresses, sizeof(Address) * newSize); + if(newMem == NULL) { + continue; + } + addresses = newMem; + addressesSize = newSize; + } + + /* Vista required for Luid or Ipv4Metric */ + if (ares_IsWindowsVistaOrGreater()) + { + /* Save the address as the next element in addresses. */ + addresses[addressesIndex].metric = + getBestRouteMetric(&ipaaEntry->Luid, + (SOCKADDR_INET*)(namesrvr.sa), + ipaaEntry->Ipv4Metric); + } + else + { addresses[addressesIndex].metric = (ULONG)-1; - } - - /* Record insertion index to make qsort stable */ - addresses[addressesIndex].orig_idx = addressesIndex; - + } + + /* Record insertion index to make qsort stable */ + addresses[addressesIndex].orig_idx = addressesIndex; + if (! ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr, - addresses[addressesIndex].text, - sizeof(addresses[0].text))) { + addresses[addressesIndex].text, + sizeof(addresses[0].text))) { continue; - } - ++addressesIndex; + } + ++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; - - /* Allocate room for another address, if necessary, else skip. */ - if(addressesIndex == addressesSize) { - const size_t newSize = addressesSize + 4; - Address * const newMem = - (Address*)ares_realloc(addresses, sizeof(Address) * newSize); - if(newMem == NULL) { - continue; - } - addresses = newMem; - addressesSize = newSize; - } - - /* Vista required for Luid or Ipv4Metric */ - if (ares_IsWindowsVistaOrGreater()) - { - /* Save the address as the next element in addresses. */ - addresses[addressesIndex].metric = - getBestRouteMetric(&ipaaEntry->Luid, + + /* Allocate room for another address, if necessary, else skip. */ + if(addressesIndex == addressesSize) { + const size_t newSize = addressesSize + 4; + Address * const newMem = + (Address*)ares_realloc(addresses, sizeof(Address) * newSize); + if(newMem == NULL) { + continue; + } + addresses = newMem; + addressesSize = newSize; + } + + /* Vista required for Luid or Ipv4Metric */ + if (ares_IsWindowsVistaOrGreater()) + { + /* Save the address as the next element in addresses. */ + addresses[addressesIndex].metric = + getBestRouteMetric(&ipaaEntry->Luid, (SOCKADDR_INET*)(namesrvr.sa), - ipaaEntry->Ipv6Metric); - } - else - { + ipaaEntry->Ipv6Metric); + } + else + { addresses[addressesIndex].metric = (ULONG)-1; - } - - /* Record insertion index to make qsort stable */ - addresses[addressesIndex].orig_idx = addressesIndex; - + } + + /* Record insertion index to make qsort stable */ + addresses[addressesIndex].orig_idx = addressesIndex; + if (! ares_inet_ntop(AF_INET6, &namesrvr.sa6->sin6_addr, - addresses[addressesIndex].text, - sizeof(addresses[0].text))) { + addresses[addressesIndex].text, + sizeof(addresses[0].text))) { continue; - } - ++addressesIndex; + } + ++addressesIndex; } - else { - /* Skip non-IPv4/IPv6 addresses completely. */ + else { + /* Skip non-IPv4/IPv6 addresses completely. */ 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; - for(i = 0; i < addressesIndex; ++i) { - size_t j; - /* Look for this address text appearing previously in the results. */ - for(j = 0; j < i; ++j) { - if(strcmp(addresses[j].text, addresses[i].text) == 0) { - break; - } - } - /* Iff we didn't emit this address already, emit it now. */ - if(j == i) { - /* Add that to outptr (if we can). */ - commajoin(outptr, addresses[i].text); - } + } + } + } + + /* 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; + for(i = 0; i < addressesIndex; ++i) { + size_t j; + /* Look for this address text appearing previously in the results. */ + for(j = 0; j < i; ++j) { + if(strcmp(addresses[j].text, addresses[i].text) == 0) { + break; + } + } + /* Iff we didn't emit this address already, emit it now. */ + if(j == i) { + /* Add that to outptr (if we can). */ + commajoin(outptr, addresses[i].text); + } } } done: - ares_free(addresses); + ares_free(addresses); if (ipaa) - ares_free(ipaa); + ares_free(ipaa); - if (!*outptr) { + if (!*outptr) { return 0; - } + } return 1; } @@ -1345,49 +1345,49 @@ done: */ 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. */ + /* 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; - /* Try using IP helper API GetNetworkParams(). IPv4 only. */ + /* 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); } - -/* - * get_SuffixList_Windows() - * - * Reads the "DNS Suffix Search List" from registry and writes the list items - * whitespace separated to outptr. If the Search List is empty, the - * "Primary Dns Suffix" is written to outptr. - * - * Returns 0 and nullifies *outptr upon inability to return the suffix list. - * - * Returns 1 and sets *outptr when returning a dynamically allocated string. - * + +/* + * get_SuffixList_Windows() + * + * Reads the "DNS Suffix Search List" from registry and writes the list items + * whitespace separated to outptr. If the Search List is empty, the + * "Primary Dns Suffix" is written to outptr. + * + * Returns 0 and nullifies *outptr upon inability to return the suffix list. + * + * Returns 1 and sets *outptr when returning a dynamically allocated string. + * * Implementation supports Windows Server 2003 and newer - */ -static int get_SuffixList_Windows(char **outptr) -{ - HKEY hKey, hKeyEnum; - char keyName[256]; - DWORD keyNameBuffSize; - DWORD keyIdx = 0; - char *p = NULL; - - *outptr = NULL; - - if (ares__getplatform() != WIN_NT) - return 0; - - /* 1. Global DNS Suffix Search List */ - if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, - KEY_READ, &hKey) == ERROR_SUCCESS) - { + */ +static int get_SuffixList_Windows(char **outptr) +{ + HKEY hKey, hKeyEnum; + char keyName[256]; + DWORD keyNameBuffSize; + DWORD keyIdx = 0; + char *p = NULL; + + *outptr = NULL; + + if (ares__getplatform() != WIN_NT) + return 0; + + /* 1. Global DNS Suffix Search List */ + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, + KEY_READ, &hKey) == ERROR_SUCCESS) + { get_REG_SZ(hKey, SEARCHLIST_KEY, outptr); if (get_REG_SZ(hKey, DOMAIN_KEY, &p)) { @@ -1395,9 +1395,9 @@ static int get_SuffixList_Windows(char **outptr) ares_free(p); p = NULL; } - RegCloseKey(hKey); - } - + RegCloseKey(hKey); + } + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NT_DNSCLIENT, 0, KEY_READ, &hKey) == ERROR_SUCCESS) { @@ -1410,26 +1410,26 @@ static int get_SuffixList_Windows(char **outptr) RegCloseKey(hKey); } - /* 2. Connection Specific Search List composed of: - * a. Primary DNS Suffix */ - if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_DNSCLIENT, 0, - KEY_READ, &hKey) == ERROR_SUCCESS) - { + /* 2. Connection Specific Search List composed of: + * a. Primary DNS Suffix */ + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_DNSCLIENT, 0, + KEY_READ, &hKey) == ERROR_SUCCESS) + { if (get_REG_SZ(hKey, PRIMARYDNSSUFFIX_KEY, &p)) { commajoin(outptr, p); ares_free(p); p = NULL; } - RegCloseKey(hKey); - } - - /* b. Interface SearchList, Domain, DhcpDomain */ + RegCloseKey(hKey); + } + + /* b. Interface SearchList, Domain, DhcpDomain */ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY "\\" INTERFACES_KEY, 0, - KEY_READ, &hKey) == ERROR_SUCCESS) - { + KEY_READ, &hKey) == ERROR_SUCCESS) + { for(;;) - { + { keyNameBuffSize = sizeof(keyName); if (RegEnumKeyExA(hKey, keyIdx++, keyName, &keyNameBuffSize, 0, NULL, NULL, NULL) @@ -1438,13 +1438,13 @@ static int get_SuffixList_Windows(char **outptr) if (RegOpenKeyExA(hKey, keyName, 0, KEY_QUERY_VALUE, &hKeyEnum) != ERROR_SUCCESS) continue; - /* p can be comma separated (SearchList) */ + /* p can be comma separated (SearchList) */ if (get_REG_SZ(hKeyEnum, SEARCHLIST_KEY, &p)) - { + { commajoin(outptr, p); ares_free(p); p = NULL; - } + } if (get_REG_SZ(hKeyEnum, DOMAIN_KEY, &p)) { commajoin(outptr, p); @@ -1458,19 +1458,19 @@ static int get_SuffixList_Windows(char **outptr) p = NULL; } RegCloseKey(hKeyEnum); - } + } RegCloseKey(hKey); - } - - return *outptr != NULL; -} + } + return *outptr != NULL; +} + #endif static int init_by_resolv_conf(ares_channel channel) { -#if !defined(ANDROID) && !defined(__ANDROID__) && !defined(WATT32) && \ - !defined(CARES_USE_LIBRESOLV) +#if !defined(ANDROID) && !defined(__ANDROID__) && !defined(WATT32) && \ + !defined(CARES_USE_LIBRESOLV) char *line = NULL; #endif int status = -1, nservers = 0, nsort = 0; @@ -1485,15 +1485,15 @@ static int init_by_resolv_conf(ares_channel channel) 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); + 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 @@ -1509,7 +1509,7 @@ static int init_by_resolv_conf(ares_channel channel) line = getenv("Inet$Resolvers"); status = ARES_EOF; if (line) { - char *resolvers = ares_strdup(line), *pos, *space; + char *resolvers = ares_strdup(line), *pos, *space; if (!resolvers) return ARES_ENOMEM; @@ -1528,7 +1528,7 @@ static int init_by_resolv_conf(ares_channel channel) if (status == ARES_SUCCESS) status = ARES_EOF; - ares_free(resolvers); + ares_free(resolvers); } #elif defined(WATT32) @@ -1541,136 +1541,136 @@ static int init_by_resolv_conf(ares_channel channel) return ARES_SUCCESS; /* use localhost DNS server */ nservers = i; - servers = ares_malloc(sizeof(struct server_state)); + servers = ares_malloc(sizeof(struct server_state)); if (!servers) return ARES_ENOMEM; - memset(servers, 0, sizeof(struct server_state)); + 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; - servers[i].addr.udp_port = 0; - servers[i].addr.tcp_port = 0; + servers[i].addr.udp_port = 0; + servers[i].addr.tcp_port = 0; } status = ARES_EOF; #elif defined(ANDROID) || defined(__ANDROID__) unsigned int i; - char **dns_servers; + 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 - * improves privacy. Apps now need the ACCESS_NETWORK_STATE - * permission and must use the ConnectivityManager which - * is Java only. */ - dns_servers = ares_get_android_server_list(MAX_DNS_PROPERTIES, &num_servers); - if (dns_servers != NULL) - { - for (i = 0; i < num_servers; i++) - { - status = config_nameserver(&servers, &nservers, dns_servers[i]); - if (status != ARES_SUCCESS) - break; + 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 + * improves privacy. Apps now need the ACCESS_NETWORK_STATE + * permission and must use the ConnectivityManager which + * is Java only. */ + dns_servers = ares_get_android_server_list(MAX_DNS_PROPERTIES, &num_servers); + if (dns_servers != NULL) + { + for (i = 0; i < num_servers; i++) + { + status = config_nameserver(&servers, &nservers, dns_servers[i]); + if (status != ARES_SUCCESS) + break; status = ARES_EOF; } - for (i = 0; i < num_servers; i++) - { - ares_free(dns_servers[i]); - } - ares_free(dns_servers); - } + for (i = 0; i < num_servers; i++) + { + ares_free(dns_servers[i]); + } + ares_free(dns_servers); + } if (channel->ndomains == -1) { domains = ares_get_android_search_domains_list(); set_search(channel, domains); ares_free(domains); } - -# ifdef HAVE___SYSTEM_PROPERTY_GET - /* Old way using the system property still in place as - * a fallback. Older android versions can still use this. - * it's possible for older apps not not have added the new - * permission and we want to try to avoid breaking those. - * - * We'll only run this if we don't have any dns servers - * because this will get the same ones (if it works). */ - if (status != ARES_EOF) { + +# ifdef HAVE___SYSTEM_PROPERTY_GET + /* Old way using the system property still in place as + * a fallback. Older android versions can still use this. + * it's possible for older apps not not have added the new + * permission and we want to try to avoid breaking those. + * + * We'll only run this if we don't have any dns servers + * because this will get the same ones (if it works). */ + if (status != ARES_EOF) { char propname[PROP_NAME_MAX]; char propvalue[PROP_VALUE_MAX]=""; - for (i = 1; i <= MAX_DNS_PROPERTIES; i++) { - snprintf(propname, sizeof(propname), "%s%u", DNS_PROP_NAME_PREFIX, i); - if (__system_property_get(propname, propvalue) < 1) { - status = ARES_EOF; - break; - } - - status = config_nameserver(&servers, &nservers, propvalue); - if (status != ARES_SUCCESS) - break; - status = ARES_EOF; - } - } -# endif /* HAVE___SYSTEM_PROPERTY_GET */ -#elif defined(CARES_USE_LIBRESOLV) - struct __res_state res; - memset(&res, 0, sizeof(res)); - int result = res_ninit(&res); - if (result == 0 && (res.options & RES_INIT)) { + for (i = 1; i <= MAX_DNS_PROPERTIES; i++) { + snprintf(propname, sizeof(propname), "%s%u", DNS_PROP_NAME_PREFIX, i); + if (__system_property_get(propname, propvalue) < 1) { + status = ARES_EOF; + break; + } + + status = config_nameserver(&servers, &nservers, propvalue); + if (status != ARES_SUCCESS) + break; + status = ARES_EOF; + } + } +# endif /* HAVE___SYSTEM_PROPERTY_GET */ +#elif defined(CARES_USE_LIBRESOLV) + struct __res_state res; + memset(&res, 0, sizeof(res)); + int result = res_ninit(&res); + if (result == 0 && (res.options & RES_INIT)) { status = ARES_EOF; - - if (channel->nservers == -1) { - union res_sockaddr_union addr[MAXNS]; - int nscount = res_getservers(&res, addr, MAXNS); - for (int i = 0; i < nscount; ++i) { - char str[INET6_ADDRSTRLEN]; - int config_status; - sa_family_t family = addr[i].sin.sin_family; - if (family == AF_INET) { - ares_inet_ntop(family, &addr[i].sin.sin_addr, str, sizeof(str)); - } else if (family == AF_INET6) { - ares_inet_ntop(family, &addr[i].sin6.sin6_addr, str, sizeof(str)); - } else { - continue; - } - - config_status = config_nameserver(&servers, &nservers, str); - if (config_status != ARES_SUCCESS) { - status = config_status; - break; - } - } - } - if (channel->ndomains == -1) { - int entries = 0; - while ((entries < MAXDNSRCH) && res.dnsrch[entries]) - entries++; - - channel->domains = ares_malloc(entries * sizeof(char *)); - if (!channel->domains) { - status = ARES_ENOMEM; - } else { - channel->ndomains = entries; - for (int i = 0; i < channel->ndomains; ++i) { - channel->domains[i] = ares_strdup(res.dnsrch[i]); - if (!channel->domains[i]) - status = ARES_ENOMEM; - } - } - } - if (channel->ndots == -1) - channel->ndots = res.ndots; - if (channel->tries == -1) - channel->tries = res.retry; - if (channel->rotate == -1) - channel->rotate = res.options & RES_ROTATE; - if (channel->timeout == -1) - channel->timeout = res.retrans * 1000; - - res_ndestroy(&res); + + if (channel->nservers == -1) { + union res_sockaddr_union addr[MAXNS]; + int nscount = res_getservers(&res, addr, MAXNS); + for (int i = 0; i < nscount; ++i) { + char str[INET6_ADDRSTRLEN]; + int config_status; + sa_family_t family = addr[i].sin.sin_family; + if (family == AF_INET) { + ares_inet_ntop(family, &addr[i].sin.sin_addr, str, sizeof(str)); + } else if (family == AF_INET6) { + ares_inet_ntop(family, &addr[i].sin6.sin6_addr, str, sizeof(str)); + } else { + continue; + } + + config_status = config_nameserver(&servers, &nservers, str); + if (config_status != ARES_SUCCESS) { + status = config_status; + break; + } + } + } + if (channel->ndomains == -1) { + int entries = 0; + while ((entries < MAXDNSRCH) && res.dnsrch[entries]) + entries++; + + channel->domains = ares_malloc(entries * sizeof(char *)); + if (!channel->domains) { + status = ARES_ENOMEM; + } else { + channel->ndomains = entries; + for (int i = 0; i < channel->ndomains; ++i) { + channel->domains[i] = ares_strdup(res.dnsrch[i]); + if (!channel->domains[i]) + status = ARES_ENOMEM; + } + } + } + if (channel->ndots == -1) + channel->ndots = res.ndots; + if (channel->tries == -1) + channel->tries = res.retry; + if (channel->rotate == -1) + channel->rotate = res.options & RES_ROTATE; + if (channel->timeout == -1) + channel->timeout = res.retrans * 1000; + + res_ndestroy(&res); } #else { @@ -1678,16 +1678,16 @@ static int init_by_resolv_conf(ares_channel channel) FILE *fp; size_t linesize; int error; - int update_domains; + 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; - /* Only update search domains if they're not already specified */ - update_domains = (channel->ndomains == -1); - + /* Only update search domains if they're not already specified */ + update_domains = (channel->ndomains == -1); + /* Support path for resolvconf filename set by ares_init_options */ if(channel->resolvconf_path) { resolvconf_path = channel->resolvconf_path; @@ -1699,11 +1699,11 @@ static int init_by_resolv_conf(ares_channel channel) if (fp) { while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { - if ((p = try_config(line, "domain", ';')) && update_domains) + if ((p = try_config(line, "domain", ';')) && update_domains) 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 = 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", ';')) && channel->nservers == -1) @@ -1743,7 +1743,7 @@ static int init_by_resolv_conf(ares_channel channel) ARES_SUCCESS) { if ((p = try_config(line, "hosts:", '\0')) && !channel->lookups) - (void)config_lookup(channel, p, "dns", "resolve", "files"); + (void)config_lookup(channel, p, "dns", "resolve", "files"); } fclose(fp); } @@ -1759,9 +1759,9 @@ static int init_by_resolv_conf(ares_channel channel) 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; + + /* ignore error, maybe we will get luck in next if clause */ + status = ARES_EOF; } } @@ -1774,7 +1774,7 @@ static int init_by_resolv_conf(ares_channel channel) { if ((p = try_config(line, "order", '\0')) && !channel->lookups) /* ignore errors */ - (void)config_lookup(channel, p, "bind", NULL, "hosts"); + (void)config_lookup(channel, p, "bind", NULL, "hosts"); } fclose(fp); } @@ -1790,9 +1790,9 @@ static int init_by_resolv_conf(ares_channel channel) 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; + + /* ignore error, maybe we will get luck in next if clause */ + status = ARES_EOF; } } @@ -1805,7 +1805,7 @@ static int init_by_resolv_conf(ares_channel channel) { if ((p = try_config(line, "hosts=", '\0')) && !channel->lookups) /* ignore errors */ - (void)config_lookup(channel, p, "bind", NULL, "local"); + (void)config_lookup(channel, p, "bind", NULL, "local"); } fclose(fp); } @@ -1820,14 +1820,14 @@ static int init_by_resolv_conf(ares_channel channel) 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; + + /* ignore error, default value will be chosen for `channel->lookups` */ + status = ARES_EOF; } } if(line) - ares_free(line); + ares_free(line); } #endif @@ -1836,9 +1836,9 @@ static int init_by_resolv_conf(ares_channel channel) if (status != ARES_EOF) { if (servers != NULL) - ares_free(servers); + ares_free(servers); if (sortlist != NULL) - ares_free(sortlist); + ares_free(sortlist); return status; } @@ -1887,15 +1887,15 @@ static int init_by_defaults(ares_channel channel) if (channel->nservers == -1) { /* If nobody specified servers, try a local named. */ - channel->servers = ares_malloc(sizeof(struct server_state)); + 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); - channel->servers[0].addr.udp_port = 0; - channel->servers[0].addr.tcp_port = 0; + channel->servers[0].addr.udp_port = 0; + channel->servers[0].addr.tcp_port = 0; channel->nservers = 1; } @@ -1920,7 +1920,7 @@ static int init_by_defaults(ares_channel channel) int res; channel->ndomains = 0; /* default to none */ - hostname = ares_malloc(len); + hostname = ares_malloc(len); if(!hostname) { rc = ARES_ENOMEM; goto error; @@ -1933,7 +1933,7 @@ static int init_by_defaults(ares_channel channel) char *p; len *= 2; lenv *= 2; - p = ares_realloc(hostname, len); + p = ares_realloc(hostname, len); if(!p) { rc = ARES_ENOMEM; goto error; @@ -1942,23 +1942,23 @@ static int init_by_defaults(ares_channel channel) 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; + /* Lets not treat a gethostname failure as critical, since we + * are ok if gethostname doesn't even exist */ + *hostname = '\0'; + break; } - } while (res != 0); + } while (res != 0); dot = strchr(hostname, '.'); if (dot) { /* a dot was found */ - channel->domains = ares_malloc(sizeof(char *)); + channel->domains = ares_malloc(sizeof(char *)); if (!channel->domains) { rc = ARES_ENOMEM; goto error; } - channel->domains[0] = ares_strdup(dot + 1); + channel->domains[0] = ares_strdup(dot + 1); if (!channel->domains[0]) { rc = ARES_ENOMEM; goto error; @@ -1974,7 +1974,7 @@ static int init_by_defaults(ares_channel channel) } if (!channel->lookups) { - channel->lookups = ares_strdup("fb"); + channel->lookups = ares_strdup("fb"); if (!channel->lookups) rc = ARES_ENOMEM; } @@ -1982,19 +1982,19 @@ static int init_by_defaults(ares_channel channel) error: if(rc) { if(channel->servers) { - ares_free(channel->servers); + ares_free(channel->servers); channel->servers = NULL; } if(channel->domains && channel->domains[0]) - ares_free(channel->domains[0]); + ares_free(channel->domains[0]); if(channel->domains) { - ares_free(channel->domains); + ares_free(channel->domains); channel->domains = NULL; } if(channel->lookups) { - ares_free(channel->lookups); + ares_free(channel->lookups); channel->lookups = NULL; } @@ -2005,13 +2005,13 @@ static int init_by_defaults(ares_channel channel) } if(hostname) - ares_free(hostname); + ares_free(hostname); return rc; } #if !defined(WIN32) && !defined(WATT32) && \ - !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV) + !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV) static int config_domain(ares_channel channel, char *str) { char *q; @@ -2033,16 +2033,16 @@ static int config_domain(ares_channel channel, char *str) #endif static int config_lookup(ares_channel channel, const char *str, - const char *bindch, const char *altbindch, - const char *filech) + const char *bindch, const char *altbindch, + const char *filech) { char lookups[3], *l; const char *vqualifier p; int found; - if (altbindch == NULL) - altbindch = bindch; - + 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. @@ -2052,8 +2052,8 @@ static int config_lookup(ares_channel channel, const char *str, found = 0; while (*p) { - if ((*p == *bindch || *p == *altbindch || *p == *filech) && l < lookups + 2) { - if (*p == *bindch || *p == *altbindch) *l++ = 'b'; + if ((*p == *bindch || *p == *altbindch || *p == *filech) && l < lookups + 2) { + if (*p == *bindch || *p == *altbindch) *l++ = 'b'; else *l++ = 'f'; found = 1; } @@ -2065,10 +2065,10 @@ static int config_lookup(ares_channel channel, const char *str, if (!found) return ARES_ENOTINITIALIZED; *l = '\0'; - channel->lookups = ares_strdup(lookups); + channel->lookups = ares_strdup(lookups); return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM; } -#endif /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ & !CARES_USE_LIBRESOLV */ +#endif /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ & !CARES_USE_LIBRESOLV */ #ifndef WATT32 /* Validate that the ip address matches the subnet (network base and network @@ -2184,15 +2184,15 @@ static int config_nameserver(struct server_state **servers, int *nservers, continue; /* Resize servers state array. */ - newserv = ares_realloc(*servers, (*nservers + 1) * - sizeof(struct server_state)); + newserv = ares_realloc(*servers, (*nservers + 1) * + sizeof(struct server_state)); 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; + 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)); @@ -2207,7 +2207,7 @@ static int config_nameserver(struct server_state **servers, int *nservers, return ARES_SUCCESS; } -#endif /* !WATT32 */ +#endif /* !WATT32 */ static int config_sortlist(struct apattern **sortlist, int *nsort, const char *str) @@ -2247,11 +2247,11 @@ static int config_sortlist(struct apattern **sortlist, int *nsort, 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; + if (!sortlist_alloc(sortlist, nsort, &pat)) { + ares_free(*sortlist); + *sortlist = NULL; return ARES_ENOMEM; - } + } } else if (ipbufpfx[0] && (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addrV4, @@ -2260,11 +2260,11 @@ static int config_sortlist(struct apattern **sortlist, int *nsort, 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; + if (!sortlist_alloc(sortlist, nsort, &pat)) { + ares_free(*sortlist); + *sortlist = NULL; return ARES_ENOMEM; - } + } } /* See if it is just a regular IP */ else if (ip_addr(ipbuf, q-str, &pat.addrV4) == 0) @@ -2280,11 +2280,11 @@ static int config_sortlist(struct apattern **sortlist, int *nsort, natural_mask(&pat); pat.family = AF_INET; pat.type = PATTERN_MASK; - if (!sortlist_alloc(sortlist, nsort, &pat)) { - ares_free(*sortlist); - *sortlist = NULL; + if (!sortlist_alloc(sortlist, nsort, &pat)) { + ares_free(*sortlist); + *sortlist = NULL; return ARES_ENOMEM; - } + } } else { @@ -2304,12 +2304,12 @@ static int set_search(ares_channel channel, const char *str) size_t cnt; if(channel->ndomains != -1) { - /* LCOV_EXCL_START: all callers check ndomains == -1 */ + /* LCOV_EXCL_START: all callers check ndomains == -1 */ /* if we already have some domains present, free them first */ ares_strsplit_free(channel->domains, channel->ndomains); channel->domains = NULL; channel->ndomains = -1; - } /* LCOV_EXCL_STOP */ + } /* LCOV_EXCL_STOP */ channel->domains = ares_strsplit(str, ", ", 1, &cnt); channel->ndomains = (int)cnt; @@ -2370,7 +2370,7 @@ static const char *try_option(const char *p, const char *q, const char *opt) } #if !defined(WIN32) && !defined(WATT32) && \ - !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV) + !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV) static char *try_config(char *s, const char *opt, char scc) { size_t len; @@ -2379,7 +2379,7 @@ static char *try_config(char *s, const char *opt, char scc) if (!s || !opt) /* no line or no option */ - return NULL; /* LCOV_EXCL_LINE */ + 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. */ @@ -2411,7 +2411,7 @@ static char *try_config(char *s, const char *opt, char scc) if ((len = strlen(opt)) == 0) /* empty option */ - return NULL; /* LCOV_EXCL_LINE */ + return NULL; /* LCOV_EXCL_LINE */ if (strncmp(p, opt, len) != 0) /* line and option do not match */ @@ -2422,7 +2422,7 @@ static char *try_config(char *s, const char *opt, char scc) if (!*p) /* no option value */ - return NULL; /* LCOV_EXCL_LINE */ + return NULL; /* LCOV_EXCL_LINE */ if ((opt[len-1] != ':') && (opt[len-1] != '=') && !ISSPACE(*p)) /* whitespace between option name and value is mandatory @@ -2440,9 +2440,9 @@ static char *try_config(char *s, const char *opt, char scc) /* return pointer to option value */ return p; } -#endif /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ */ +#endif /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ */ -static int ip_addr(const char *ipbuf, ares_ssize_t len, struct in_addr *addr) +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. */ @@ -2475,19 +2475,19 @@ static void natural_mask(struct apattern *pat) pat->mask.addr4.s_addr = htonl(IN_CLASSC_NET); } -static int sortlist_alloc(struct apattern **sortlist, int *nsort, - struct apattern *pat) -{ - struct apattern *newsort; - newsort = ares_realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern)); - if (!newsort) - return 0; - newsort[*nsort] = *pat; - *sortlist = newsort; - (*nsort)++; - return 1; -} - +static int sortlist_alloc(struct apattern **sortlist, int *nsort, + struct apattern *pat) +{ + struct apattern *newsort; + newsort = ares_realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern)); + if (!newsort) + return 0; + newsort[*nsort] = *pat; + *sortlist = newsort; + (*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 @@ -2519,7 +2519,7 @@ static void randomize_key(unsigned char* key,int key_data_len) if (!randomized) { for (;counter<key_data_len;counter++) - key[counter]=(unsigned char)(rand() % 256); /* LCOV_EXCL_LINE */ + key[counter]=(unsigned char)(rand() % 256); /* LCOV_EXCL_LINE */ } } @@ -2531,10 +2531,10 @@ static int init_id_key(rc4_key* key,int key_data_len) short counter; unsigned char *key_data_ptr = 0; - key_data_ptr = ares_malloc(key_data_len); + key_data_ptr = ares_malloc(key_data_len); if (!key_data_ptr) return ARES_ENOMEM; - memset(key_data_ptr, 0, key_data_len); + memset(key_data_ptr, 0, key_data_len); state = &key->state[0]; for(counter = 0; counter < 256; counter++) @@ -2553,7 +2553,7 @@ static int init_id_key(rc4_key* key,int key_data_len) index1 = (unsigned char)((index1 + 1) % key_data_len); } - ares_free(key_data_ptr); + ares_free(key_data_ptr); return ARES_SUCCESS; } @@ -2587,41 +2587,41 @@ void ares_set_socket_callback(ares_channel channel, channel->sock_create_cb_data = data; } -void ares_set_socket_configure_callback(ares_channel channel, - ares_sock_config_callback cb, - void *data) -{ - channel->sock_config_cb = cb; - channel->sock_config_cb_data = data; -} - -void ares_set_socket_functions(ares_channel channel, - const struct ares_socket_functions * funcs, - void *data) -{ - channel->sock_funcs = funcs; - channel->sock_func_cb_data = data; -} - -int ares_set_sortlist(ares_channel channel, const char *sortstr) -{ - int nsort = 0; - struct apattern *sortlist = NULL; - int status; - - if (!channel) - return ARES_ENODATA; - - status = config_sortlist(&sortlist, &nsort, sortstr); - if (status == ARES_SUCCESS && sortlist) { - if (channel->sortlist) - ares_free(channel->sortlist); - channel->sortlist = sortlist; - channel->nsort = nsort; - } - return status; -} - +void ares_set_socket_configure_callback(ares_channel channel, + ares_sock_config_callback cb, + void *data) +{ + channel->sock_config_cb = cb; + channel->sock_config_cb_data = data; +} + +void ares_set_socket_functions(ares_channel channel, + const struct ares_socket_functions * funcs, + void *data) +{ + channel->sock_funcs = funcs; + channel->sock_func_cb_data = data; +} + +int ares_set_sortlist(ares_channel channel, const char *sortstr) +{ + int nsort = 0; + struct apattern *sortlist = NULL; + int status; + + if (!channel) + return ARES_ENODATA; + + status = config_sortlist(&sortlist, &nsort, sortstr); + if (status == ARES_SUCCESS && sortlist) { + if (channel->sortlist) + ares_free(channel->sortlist); + channel->sortlist = sortlist; + channel->nsort = nsort; + } + return status; +} + void ares__init_servers_state(ares_channel channel) { struct server_state *server; |