mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
deps: upgrade to c-ares v1.16.0
Refs: https://github.com/c-ares/c-ares/releases/tag/cares-1_16_0 PR-URL: https://github.com/nodejs/node/pull/32246 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com>
This commit is contained in:
5
deps/cares/cares.gyp
vendored
5
deps/cares/cares.gyp
vendored
@@ -52,7 +52,9 @@
|
||||
'src/ares_fds.c',
|
||||
'src/ares_free_hostent.c',
|
||||
'src/ares_free_string.c',
|
||||
'src/ares_freeaddrinfo.c',
|
||||
'src/ares_getenv.h',
|
||||
'src/ares_getaddrinfo.c',
|
||||
'src/ares_gethostbyaddr.c',
|
||||
'src/ares_gethostbyname.c',
|
||||
'src/ares__get_hostent.c',
|
||||
@@ -70,6 +72,7 @@
|
||||
'src/ares_nowarn.c',
|
||||
'src/ares_nowarn.h',
|
||||
'src/ares_options.c',
|
||||
'src/ares__parse_into_addrinfo.c',
|
||||
'src/ares_parse_aaaa_reply.c',
|
||||
'src/ares_parse_a_reply.c',
|
||||
'src/ares_parse_mx_reply.c',
|
||||
@@ -84,9 +87,11 @@
|
||||
'src/ares_process.c',
|
||||
'src/ares_query.c',
|
||||
'src/ares__read_line.c',
|
||||
'src/ares__readaddrinfo.c',
|
||||
'src/ares_search.c',
|
||||
'src/ares_send.c',
|
||||
'src/ares_setup.h',
|
||||
'src/ares__sortaddrinfo.c',
|
||||
'src/ares_strcasecmp.c',
|
||||
'src/ares_strcasecmp.h',
|
||||
'src/ares_strdup.c',
|
||||
|
||||
59
deps/cares/include/ares.h
vendored
59
deps/cares/include/ares.h
vendored
@@ -135,6 +135,9 @@ extern "C" {
|
||||
/* More error codes */
|
||||
#define ARES_ECANCELLED 24 /* introduced in 1.7.0 */
|
||||
|
||||
/* More ares_getaddrinfo error codes */
|
||||
#define ARES_ESERVICE 25 /* introduced in 1.?.0 */
|
||||
|
||||
/* Flag values */
|
||||
#define ARES_FLAG_USEVC (1 << 0)
|
||||
#define ARES_FLAG_PRIMARY (1 << 1)
|
||||
@@ -192,6 +195,8 @@ extern "C" {
|
||||
#define ARES_AI_V4MAPPED (1 << 4)
|
||||
#define ARES_AI_ALL (1 << 5)
|
||||
#define ARES_AI_ADDRCONFIG (1 << 6)
|
||||
#define ARES_AI_NOSORT (1 << 7)
|
||||
#define ARES_AI_ENVHOSTS (1 << 8)
|
||||
/* Reserved for future use */
|
||||
#define ARES_AI_IDN (1 << 10)
|
||||
#define ARES_AI_IDN_ALLOW_UNASSIGNED (1 << 11)
|
||||
@@ -278,6 +283,8 @@ struct hostent;
|
||||
struct timeval;
|
||||
struct sockaddr;
|
||||
struct ares_channeldata;
|
||||
struct ares_addrinfo;
|
||||
struct ares_addrinfo_hints;
|
||||
|
||||
typedef struct ares_channeldata *ares_channel;
|
||||
|
||||
@@ -306,6 +313,11 @@ typedef int (*ares_sock_config_callback)(ares_socket_t socket_fd,
|
||||
int type,
|
||||
void *data);
|
||||
|
||||
typedef void (*ares_addrinfo_callback)(void *arg,
|
||||
int status,
|
||||
int timeouts,
|
||||
struct ares_addrinfo *res);
|
||||
|
||||
CARES_EXTERN int ares_library_init(int flags);
|
||||
|
||||
CARES_EXTERN int ares_library_init_mem(int flags,
|
||||
@@ -369,6 +381,15 @@ CARES_EXTERN void ares_set_socket_configure_callback(ares_channel channel,
|
||||
CARES_EXTERN int ares_set_sortlist(ares_channel channel,
|
||||
const char *sortstr);
|
||||
|
||||
CARES_EXTERN void ares_getaddrinfo(ares_channel channel,
|
||||
const char* node,
|
||||
const char* service,
|
||||
const struct ares_addrinfo_hints* hints,
|
||||
ares_addrinfo_callback callback,
|
||||
void* arg);
|
||||
|
||||
CARES_EXTERN void ares_freeaddrinfo(struct ares_addrinfo* ai);
|
||||
|
||||
/*
|
||||
* Virtual function set to have user-managed socket IO.
|
||||
* Note that all functions need to be defined, and when
|
||||
@@ -558,6 +579,44 @@ struct ares_soa_reply {
|
||||
unsigned int minttl;
|
||||
};
|
||||
|
||||
/*
|
||||
* Similar to addrinfo, but with extra ttl and missing canonname.
|
||||
*/
|
||||
struct ares_addrinfo_node {
|
||||
int ai_ttl;
|
||||
int ai_flags;
|
||||
int ai_family;
|
||||
int ai_socktype;
|
||||
int ai_protocol;
|
||||
ares_socklen_t ai_addrlen;
|
||||
struct sockaddr *ai_addr;
|
||||
struct ares_addrinfo_node *ai_next;
|
||||
};
|
||||
|
||||
/*
|
||||
* alias - label of the resource record.
|
||||
* name - value (canonical name) of the resource record.
|
||||
* See RFC2181 10.1.1. CNAME terminology.
|
||||
*/
|
||||
struct ares_addrinfo_cname {
|
||||
int ttl;
|
||||
char *alias;
|
||||
char *name;
|
||||
struct ares_addrinfo_cname *next;
|
||||
};
|
||||
|
||||
struct ares_addrinfo {
|
||||
struct ares_addrinfo_cname *cnames;
|
||||
struct ares_addrinfo_node *nodes;
|
||||
};
|
||||
|
||||
struct ares_addrinfo_hints {
|
||||
int ai_flags;
|
||||
int ai_family;
|
||||
int ai_socktype;
|
||||
int ai_protocol;
|
||||
};
|
||||
|
||||
/*
|
||||
** Parse the buffer, starting at *abuf and of length alen bytes, previously
|
||||
** obtained from an ares_search call. Put the results in *host, if nonnull.
|
||||
|
||||
6
deps/cares/include/ares_version.h
vendored
6
deps/cares/include/ares_version.h
vendored
@@ -3,15 +3,15 @@
|
||||
#define ARES__VERSION_H
|
||||
|
||||
/* This is the global package copyright */
|
||||
#define ARES_COPYRIGHT "2004 - 2018 Daniel Stenberg, <daniel@haxx.se>."
|
||||
#define ARES_COPYRIGHT "2004 - 2020 Daniel Stenberg, <daniel@haxx.se>."
|
||||
|
||||
#define ARES_VERSION_MAJOR 1
|
||||
#define ARES_VERSION_MINOR 15
|
||||
#define ARES_VERSION_MINOR 16
|
||||
#define ARES_VERSION_PATCH 0
|
||||
#define ARES_VERSION ((ARES_VERSION_MAJOR<<16)|\
|
||||
(ARES_VERSION_MINOR<<8)|\
|
||||
(ARES_VERSION_PATCH))
|
||||
#define ARES_VERSION_STR "1.15.0"
|
||||
#define ARES_VERSION_STR "1.16.0"
|
||||
|
||||
#if (ARES_VERSION >= 0x010700)
|
||||
# define CARES_HAVE_ARES_LIBRARY_INIT 1
|
||||
|
||||
3
deps/cares/src/README.md
vendored
3
deps/cares/src/README.md
vendored
@@ -2,9 +2,10 @@ c-ares
|
||||
======
|
||||
|
||||
[](https://travis-ci.org/c-ares/c-ares)
|
||||
[](https://ci.appveyor.com/project/c-ares/c-ares)
|
||||
[](https://ci.appveyor.com/project/c-ares/c-ares/branch/master)
|
||||
[](https://coveralls.io/github/c-ares/c-ares?branch=master)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/291)
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:c-ares)
|
||||
[](https://coderelease.io/github/repository/c-ares/c-ares)
|
||||
|
||||
This is c-ares, an asynchronous resolver library. It is intended for
|
||||
|
||||
108
deps/cares/src/RELEASE-NOTES
vendored
108
deps/cares/src/RELEASE-NOTES
vendored
@@ -1,43 +1,85 @@
|
||||
c-ares version 1.15.0
|
||||
c-ares version 1.16.0
|
||||
|
||||
Changes:
|
||||
o Add ares_init_options() configurability for path to resolv.conf file [1]
|
||||
o Ability to exclude building of tools (adig, ahost, acountry) in CMake [3]
|
||||
o Android: Support for domain search suffix [4]
|
||||
o Report ARES_ENOTFOUND for .onion domain names as per RFC7686. [13]
|
||||
o Introduction of ares_getaddrinfo() API which provides similar output
|
||||
(including proper sorting as per RFC 6724) to the system native API, but
|
||||
utilizes different data structures in order to provide additional information
|
||||
such as TTLs and all aliases. Please reference the respective man pages for
|
||||
usage details. [3] [4] [5] [7] [8] [13] [14] [15] [16] [17] [22]
|
||||
o Parse SOA records from ns_t_any response [29] [30]
|
||||
o CMake: Provide c-ares version in package export file [24]
|
||||
o CMake: Add CPACK functionality for DEB and RPM [28]
|
||||
o CMake: Generate PDB files during build [33] [34]
|
||||
o CMake: Support manpage installation [37] [38]
|
||||
|
||||
Bug fixes:
|
||||
o AIX build fix for trying to include both nameser_compat.h and
|
||||
onameser_compat.h [2]
|
||||
o Windows: Improve DNS suffixes extracting from WinNT registry [5]
|
||||
o Fix modern GCC warnings [6]
|
||||
o Apply the IPv6 server blacklist to all nameserver sources, not just Windows
|
||||
[7]
|
||||
o Fix warnings emitted by MSVC when using -W4 [8]
|
||||
o Prevent changing name servers while queries are outstanding [9]
|
||||
o Harden and rationalize c-ares timeout computation [10]
|
||||
o Distribute ares_android.h [11]
|
||||
o ares_set_servers_csv() on failure should not leave channel in a bad state
|
||||
[12]
|
||||
o Add missing docs to distribution
|
||||
o Fix bad expectation in IPv6 localhost test. [1] [2]
|
||||
o AutoTools: use XC_CHECK_BUILD_FLAGS instead of XC_CHECK_USER_FLAGS to prevent
|
||||
complaints about CPPFLAGS in CFLAGS. [6]
|
||||
o Fix .onion handling
|
||||
o Command line usage was out of date for adig and ahost. [18]
|
||||
o Typos in manpages [19] [20]
|
||||
o If ares_getenv is defined, it must return a value on all platforms [21]
|
||||
o If /etc/resolv.conf has invalid lookup values, use the defaults. [23]
|
||||
o Tests: Separate live tests from SetServers* tests as only live tests should
|
||||
require internet access. [25]
|
||||
o ares_gethostbyname() should return ENODATA if no valid A or AAAA record is
|
||||
found, but a CNAME was found. [26] [27]
|
||||
o CMake: Rework library function checking to prevent unintended linking with
|
||||
system libraries that aren't needed. [31] [32]
|
||||
o Due to use of inet_addr() it was not possible to return 255.255.255.255 from
|
||||
ares_gethostbyname(). [35] [36]
|
||||
o CMake: Fix building of tests on Windows
|
||||
|
||||
Thanks go to these friendly people for their efforts and contributions:
|
||||
@afalin, Andi Schnebinger, Ben Noordhuis, Brad House, Brad Spencer,
|
||||
David Hotham, @flyingdutchman23, John Schember, Ruslan Baratov,
|
||||
Sarat Addepalli, Tobias Nießen (11 contributors)
|
||||
Abhishek Arya (@inferno-chromium), Adam Majer (@AdamMajer),
|
||||
Andrew Selivanov (@ki11roy), Ben Noordhuis (@bnoordhuis),
|
||||
Brad House (@bradh352), Christian Ammer (@ChristianAmmer), Dan Noé (@dnoe),
|
||||
Daniel Stenberg (@bagder), Darrin Cullop (@dwcullop),
|
||||
Dron Rathore (@DronRathore), Fabrice Fontaine (@ffontaine),
|
||||
Gregor Jasny (@gjasny), @kedixa, Khaidi Chu (@XadillaX),
|
||||
Kyle Edwards (@KyleFromKitware), @lifenjoiner, Michal Rostecki (@mrostecki),
|
||||
Peter Eisentraut (@petere), Piotr Pietraszkiewicz (@ppietrasa),
|
||||
Stephen Bryant (@bf-bryants), @tjwalton, Vy Nguyen (@oontvoo)
|
||||
(22 contributors)
|
||||
|
||||
References to bug reports and discussions on issues:
|
||||
[1] = https://github.com/c-ares/c-ares/issues/220
|
||||
[2] = https://github.com/c-ares/c-ares/issues/224
|
||||
[3] = https://github.com/c-ares/c-ares/issues/200
|
||||
[4] = https://github.com/c-ares/c-ares/issues/207
|
||||
[5] = https://github.com/c-ares/c-ares/pull/202
|
||||
[6] = https://github.com/c-ares/c-ares/pull/201
|
||||
[7] = https://github.com/c-ares/c-ares/pull/193
|
||||
[8] = https://github.com/c-ares/c-ares/pull/192
|
||||
[9] = https://github.com/c-ares/c-ares/pull/191
|
||||
[1] = https://github.com/c-ares/c-ares/pull/227
|
||||
[2] = https://github.com/c-ares/c-ares/issues/85
|
||||
[3] = https://github.com/c-ares/c-ares/pull/112
|
||||
[4] = https://github.com/c-ares/c-ares/pull/233
|
||||
[5] = https://github.com/c-ares/c-ares/pull/234
|
||||
[6] = https://github.com/c-ares/c-ares/pull/236
|
||||
[7] = https://github.com/c-ares/c-ares/pull/235
|
||||
[8] = https://github.com/c-ares/c-ares/pull/239
|
||||
[9] = https://github.com/c-ares/c-ares/pull/241
|
||||
[10] = https://github.com/c-ares/c-ares/pull/187
|
||||
[11] = https://c-ares.haxx.se/mail/c-ares-archive-2018-04/0000.shtml
|
||||
[12] = https://c-ares.haxx.se/mail/c-ares-archive-2018-03/0000.shtml
|
||||
[13] = https://github.com/c-ares/c-ares/issues/196
|
||||
[11] = https://github.com/c-ares/c-ares/pull/252
|
||||
[12] = https://github.com/c-ares/c-ares/issues/251
|
||||
[13] = https://github.com/c-ares/c-ares/pull/258
|
||||
[14] = https://github.com/c-ares/c-ares/pull/257
|
||||
[15] = https://github.com/c-ares/c-ares/pull/262
|
||||
[16] = https://github.com/c-ares/c-ares/pull/264
|
||||
[17] = https://github.com/c-ares/c-ares/pull/265
|
||||
[18] = https://github.com/c-ares/c-ares/pull/256
|
||||
[19] = https://github.com/c-ares/c-ares/pull/269
|
||||
[20] = https://github.com/c-ares/c-ares/pull/275
|
||||
[21] = https://github.com/c-ares/c-ares/pull/279
|
||||
[22] = https://github.com/c-ares/c-ares/pull/290
|
||||
[23] = https://github.com/c-ares/c-ares/pull/274
|
||||
[24] = https://github.com/c-ares/c-ares/pull/296
|
||||
[25] = https://github.com/c-ares/c-ares/pull/299
|
||||
[26] = https://github.com/c-ares/c-ares/pull/304
|
||||
[27] = https://github.com/c-ares/c-ares/issues/303
|
||||
[28] = https://github.com/c-ares/c-ares/pull/283
|
||||
[29] = https://github.com/c-ares/c-ares/pull/103
|
||||
[30] = https://github.com/c-ares/c-ares/issues/102
|
||||
[31] = https://github.com/c-ares/c-ares/pull/310
|
||||
[32] = https://github.com/c-ares/c-ares/issues/307
|
||||
[33] = https://github.com/c-ares/c-ares/pull/311
|
||||
[34] = https://github.com/c-ares/c-ares/issues/245
|
||||
[35] = https://github.com/c-ares/c-ares/issues/309
|
||||
[36] = https://github.com/c-ares/c-ares/pull/312
|
||||
[37] = https://github.com/c-ares/c-ares/issues/297
|
||||
[38] = https://github.com/c-ares/c-ares/pull/314
|
||||
|
||||
|
||||
4
deps/cares/src/ares__close_sockets.c
vendored
4
deps/cares/src/ares__close_sockets.c
vendored
@@ -48,14 +48,14 @@ void ares__close_sockets(ares_channel channel, struct server_state *server)
|
||||
if (server->tcp_socket != ARES_SOCKET_BAD)
|
||||
{
|
||||
SOCK_STATE_CALLBACK(channel, server->tcp_socket, 0, 0);
|
||||
ares__socket_close(channel, server->tcp_socket);
|
||||
ares__close_socket(channel, server->tcp_socket);
|
||||
server->tcp_socket = ARES_SOCKET_BAD;
|
||||
server->tcp_connection_generation = ++channel->tcp_connection_generation;
|
||||
}
|
||||
if (server->udp_socket != ARES_SOCKET_BAD)
|
||||
{
|
||||
SOCK_STATE_CALLBACK(channel, server->udp_socket, 0, 0);
|
||||
ares__socket_close(channel, server->udp_socket);
|
||||
ares__close_socket(channel, server->udp_socket);
|
||||
server->udp_socket = ARES_SOCKET_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
3
deps/cares/src/ares__get_hostent.c
vendored
3
deps/cares/src/ares__get_hostent.c
vendored
@@ -138,8 +138,7 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host)
|
||||
addr.addrV4.s_addr = INADDR_NONE;
|
||||
if ((family == AF_INET) || (family == AF_UNSPEC))
|
||||
{
|
||||
addr.addrV4.s_addr = inet_addr(txtaddr);
|
||||
if (addr.addrV4.s_addr != INADDR_NONE)
|
||||
if (ares_inet_pton(AF_INET, txtaddr, &addr.addrV4) > 0)
|
||||
{
|
||||
/* Actual network address family and length. */
|
||||
addr.family = AF_INET;
|
||||
|
||||
266
deps/cares/src/ares__parse_into_addrinfo.c
vendored
Normal file
266
deps/cares/src/ares__parse_into_addrinfo.c
vendored
Normal file
@@ -0,0 +1,266 @@
|
||||
/* Copyright (C) 2019 by Andrew Selivanov
|
||||
*
|
||||
* 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_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
|
||||
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#include "ares.h"
|
||||
#include "ares_dns.h"
|
||||
#include "ares_private.h"
|
||||
|
||||
int ares__parse_into_addrinfo2(const unsigned char *abuf,
|
||||
int alen,
|
||||
char **question_hostname,
|
||||
struct ares_addrinfo *ai)
|
||||
{
|
||||
unsigned int qdcount, ancount;
|
||||
int status, i, rr_type, rr_class, rr_len, rr_ttl;
|
||||
int got_a = 0, got_aaaa = 0, got_cname = 0;
|
||||
long len;
|
||||
const unsigned char *aptr;
|
||||
char *hostname, *rr_name = NULL, *rr_data;
|
||||
struct ares_addrinfo_cname *cname, *cnames = NULL;
|
||||
struct ares_addrinfo_node *node, *nodes = NULL;
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
*question_hostname = NULL;
|
||||
|
||||
/* Give up if abuf doesn't have room for a header. */
|
||||
if (alen < HFIXEDSZ)
|
||||
return ARES_EBADRESP;
|
||||
|
||||
/* Fetch the question and answer count from the header. */
|
||||
qdcount = DNS_HEADER_QDCOUNT(abuf);
|
||||
ancount = DNS_HEADER_ANCOUNT(abuf);
|
||||
if (qdcount != 1)
|
||||
return ARES_EBADRESP;
|
||||
|
||||
|
||||
/* Expand the name from the question, and skip past the question. */
|
||||
aptr = abuf + HFIXEDSZ;
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen, question_hostname, &len);
|
||||
if (status != ARES_SUCCESS)
|
||||
return status;
|
||||
if (aptr + len + QFIXEDSZ > abuf + alen)
|
||||
{
|
||||
return ARES_EBADRESP;
|
||||
}
|
||||
|
||||
hostname = *question_hostname;
|
||||
|
||||
aptr += len + QFIXEDSZ;
|
||||
|
||||
/* Examine each answer resource record (RR) in turn. */
|
||||
for (i = 0; i < (int)ancount; i++)
|
||||
{
|
||||
/* Decode the RR up to the data field. */
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len);
|
||||
if (status != ARES_SUCCESS)
|
||||
{
|
||||
rr_name = NULL;
|
||||
goto failed_stat;
|
||||
}
|
||||
|
||||
aptr += len;
|
||||
if (aptr + RRFIXEDSZ > abuf + alen)
|
||||
{
|
||||
status = ARES_EBADRESP;
|
||||
goto failed_stat;
|
||||
}
|
||||
rr_type = DNS_RR_TYPE(aptr);
|
||||
rr_class = DNS_RR_CLASS(aptr);
|
||||
rr_len = DNS_RR_LEN(aptr);
|
||||
rr_ttl = DNS_RR_TTL(aptr);
|
||||
aptr += RRFIXEDSZ;
|
||||
if (aptr + rr_len > abuf + alen)
|
||||
{
|
||||
status = ARES_EBADRESP;
|
||||
goto failed_stat;
|
||||
}
|
||||
|
||||
if (rr_class == C_IN && rr_type == T_A
|
||||
&& rr_len == sizeof(struct in_addr)
|
||||
&& strcasecmp(rr_name, hostname) == 0)
|
||||
{
|
||||
got_a = 1;
|
||||
if (aptr + sizeof(struct in_addr) > abuf + alen)
|
||||
{ /* LCOV_EXCL_START: already checked above */
|
||||
status = ARES_EBADRESP;
|
||||
goto failed_stat;
|
||||
} /* LCOV_EXCL_STOP */
|
||||
|
||||
node = ares__append_addrinfo_node(&nodes);
|
||||
if (!node)
|
||||
{
|
||||
status = ARES_ENOMEM;
|
||||
goto failed_stat;
|
||||
}
|
||||
|
||||
sin = ares_malloc(sizeof(struct sockaddr_in));
|
||||
if (!sin)
|
||||
{
|
||||
status = ARES_ENOMEM;
|
||||
goto failed_stat;
|
||||
}
|
||||
memset(sin, 0, sizeof(struct sockaddr_in));
|
||||
memcpy(&sin->sin_addr.s_addr, aptr, sizeof(struct in_addr));
|
||||
sin->sin_family = AF_INET;
|
||||
|
||||
node->ai_addr = (struct sockaddr *)sin;
|
||||
node->ai_family = AF_INET;
|
||||
node->ai_addrlen = sizeof(struct sockaddr_in);
|
||||
|
||||
node->ai_ttl = rr_ttl;
|
||||
|
||||
status = ARES_SUCCESS;
|
||||
}
|
||||
else if (rr_class == C_IN && rr_type == T_AAAA
|
||||
&& rr_len == sizeof(struct ares_in6_addr)
|
||||
&& strcasecmp(rr_name, hostname) == 0)
|
||||
{
|
||||
got_aaaa = 1;
|
||||
if (aptr + sizeof(struct ares_in6_addr) > abuf + alen)
|
||||
{ /* LCOV_EXCL_START: already checked above */
|
||||
status = ARES_EBADRESP;
|
||||
goto failed_stat;
|
||||
} /* LCOV_EXCL_STOP */
|
||||
|
||||
node = ares__append_addrinfo_node(&nodes);
|
||||
if (!node)
|
||||
{
|
||||
status = ARES_ENOMEM;
|
||||
goto failed_stat;
|
||||
}
|
||||
|
||||
sin6 = ares_malloc(sizeof(struct sockaddr_in6));
|
||||
if (!sin6)
|
||||
{
|
||||
status = ARES_ENOMEM;
|
||||
goto failed_stat;
|
||||
}
|
||||
|
||||
memset(sin6, 0, sizeof(struct sockaddr_in6));
|
||||
memcpy(&sin6->sin6_addr.s6_addr, aptr, sizeof(struct ares_in6_addr));
|
||||
sin6->sin6_family = AF_INET6;
|
||||
|
||||
node->ai_addr = (struct sockaddr *)sin6;
|
||||
node->ai_family = AF_INET6;
|
||||
node->ai_addrlen = sizeof(struct sockaddr_in6);
|
||||
|
||||
node->ai_ttl = rr_ttl;
|
||||
|
||||
status = ARES_SUCCESS;
|
||||
}
|
||||
|
||||
if (rr_class == C_IN && rr_type == T_CNAME)
|
||||
{
|
||||
got_cname = 1;
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data,
|
||||
&len);
|
||||
if (status != ARES_SUCCESS)
|
||||
{
|
||||
goto failed_stat;
|
||||
}
|
||||
|
||||
/* Decode the RR data and replace the hostname with it. */
|
||||
/* SA: Seems wrong as it introduses order dependency. */
|
||||
hostname = rr_data;
|
||||
|
||||
cname = ares__append_addrinfo_cname(&cnames);
|
||||
if (!cname)
|
||||
{
|
||||
status = ARES_ENOMEM;
|
||||
ares_free(rr_data);
|
||||
goto failed_stat;
|
||||
}
|
||||
cname->ttl = rr_ttl;
|
||||
cname->alias = rr_name;
|
||||
cname->name = rr_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
ares_free(rr_name);
|
||||
}
|
||||
|
||||
|
||||
aptr += rr_len;
|
||||
if (aptr > abuf + alen)
|
||||
{ /* LCOV_EXCL_START: already checked above */
|
||||
status = ARES_EBADRESP;
|
||||
goto failed_stat;
|
||||
} /* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
if (status == ARES_SUCCESS)
|
||||
{
|
||||
ares__addrinfo_cat_nodes(&ai->nodes, nodes);
|
||||
if (got_cname)
|
||||
{
|
||||
ares__addrinfo_cat_cnames(&ai->cnames, cnames);
|
||||
return status;
|
||||
}
|
||||
else if (got_a == 0 && got_aaaa == 0)
|
||||
{
|
||||
/* the check for naliases to be zero is to make sure CNAME responses
|
||||
don't get caught here */
|
||||
status = ARES_ENODATA;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
failed_stat:
|
||||
ares_free(rr_name);
|
||||
ares__freeaddrinfo_cnames(cnames);
|
||||
ares__freeaddrinfo_nodes(nodes);
|
||||
return status;
|
||||
}
|
||||
|
||||
int ares__parse_into_addrinfo(const unsigned char *abuf,
|
||||
int alen,
|
||||
struct ares_addrinfo *ai)
|
||||
{
|
||||
int status;
|
||||
char *question_hostname;
|
||||
status = ares__parse_into_addrinfo2(abuf, alen, &question_hostname, ai);
|
||||
ares_free(question_hostname);
|
||||
return status;
|
||||
}
|
||||
260
deps/cares/src/ares__readaddrinfo.c
vendored
Normal file
260
deps/cares/src/ares__readaddrinfo.c
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
/* Copyright (C) 2019 by Andrew Selivanov
|
||||
*
|
||||
* 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_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
|
||||
|
||||
#include "ares.h"
|
||||
#include "ares_inet_net_pton.h"
|
||||
#include "ares_nowarn.h"
|
||||
#include "ares_private.h"
|
||||
|
||||
#define MAX_ALIASES 40
|
||||
|
||||
int ares__readaddrinfo(FILE *fp,
|
||||
const char *name,
|
||||
unsigned short port,
|
||||
const struct ares_addrinfo_hints *hints,
|
||||
struct ares_addrinfo *ai)
|
||||
{
|
||||
char *line = NULL, *p, *q;
|
||||
char *txtaddr, *txthost, *txtalias;
|
||||
char *aliases[MAX_ALIASES];
|
||||
unsigned int i, alias_count;
|
||||
int status;
|
||||
size_t linesize;
|
||||
ares_sockaddr addr;
|
||||
struct ares_addrinfo_cname *cname = NULL, *cnames = NULL;
|
||||
struct ares_addrinfo_node *node = NULL, *nodes = NULL;
|
||||
int match_with_alias, match_with_canonical;
|
||||
int want_cname = hints->ai_flags & ARES_AI_CANONNAME;
|
||||
|
||||
/* Validate family */
|
||||
switch (hints->ai_family) {
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
case AF_UNSPEC:
|
||||
break;
|
||||
default:
|
||||
return ARES_EBADFAMILY;
|
||||
}
|
||||
|
||||
|
||||
while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
|
||||
{
|
||||
match_with_alias = 0;
|
||||
match_with_canonical = 0;
|
||||
alias_count = 0;
|
||||
/* Trim line comment. */
|
||||
p = line;
|
||||
while (*p && (*p != '#'))
|
||||
p++;
|
||||
*p = '\0';
|
||||
|
||||
/* Trim trailing whitespace. */
|
||||
q = p - 1;
|
||||
while ((q >= line) && ISSPACE(*q))
|
||||
q--;
|
||||
*++q = '\0';
|
||||
|
||||
/* Skip leading whitespace. */
|
||||
p = line;
|
||||
while (*p && ISSPACE(*p))
|
||||
p++;
|
||||
if (!*p)
|
||||
/* Ignore line if empty. */
|
||||
continue;
|
||||
|
||||
/* Pointer to start of IPv4 or IPv6 address part. */
|
||||
txtaddr = p;
|
||||
|
||||
/* Advance past address part. */
|
||||
while (*p && !ISSPACE(*p))
|
||||
p++;
|
||||
if (!*p)
|
||||
/* Ignore line if reached end of line. */
|
||||
continue;
|
||||
|
||||
/* Null terminate address part. */
|
||||
*p = '\0';
|
||||
|
||||
/* Advance to host name */
|
||||
p++;
|
||||
while (*p && ISSPACE(*p))
|
||||
p++;
|
||||
if (!*p)
|
||||
/* Ignore line if reached end of line. */
|
||||
continue; /* LCOV_EXCL_LINE: trailing whitespace already stripped */
|
||||
|
||||
/* Pointer to start of host name. */
|
||||
txthost = p;
|
||||
|
||||
/* Advance past host name. */
|
||||
while (*p && !ISSPACE(*p))
|
||||
p++;
|
||||
|
||||
/* Pointer to start of first alias. */
|
||||
txtalias = NULL;
|
||||
if (*p)
|
||||
{
|
||||
q = p + 1;
|
||||
while (*q && ISSPACE(*q))
|
||||
q++;
|
||||
if (*q)
|
||||
txtalias = q;
|
||||
}
|
||||
|
||||
/* Null terminate host name. */
|
||||
*p = '\0';
|
||||
|
||||
/* Find out if host name matches with canonical host name. */
|
||||
if (strcasecmp(txthost, name) == 0)
|
||||
{
|
||||
match_with_canonical = 1;
|
||||
}
|
||||
|
||||
/* Find out if host name matches with one of the aliases. */
|
||||
while (txtalias)
|
||||
{
|
||||
p = txtalias;
|
||||
while (*p && !ISSPACE(*p))
|
||||
p++;
|
||||
q = p;
|
||||
while (*q && ISSPACE(*q))
|
||||
q++;
|
||||
*p = '\0';
|
||||
if (strcasecmp(txtalias, name) == 0)
|
||||
{
|
||||
match_with_alias = 1;
|
||||
if (!want_cname)
|
||||
break;
|
||||
}
|
||||
if (alias_count < MAX_ALIASES)
|
||||
{
|
||||
aliases[alias_count++] = txtalias;
|
||||
}
|
||||
txtalias = *q ? q : NULL;
|
||||
}
|
||||
|
||||
/* Try next line if host does not match. */
|
||||
if (!match_with_alias && !match_with_canonical)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert address string to network address for the requested families.
|
||||
* Actual address family possible values are AF_INET and AF_INET6 only.
|
||||
*/
|
||||
if ((hints->ai_family == AF_INET) || (hints->ai_family == AF_UNSPEC))
|
||||
{
|
||||
addr.sa4.sin_port = htons(port);
|
||||
if (ares_inet_pton(AF_INET, txtaddr, &addr.sa4.sin_addr) > 0)
|
||||
{
|
||||
node = ares__append_addrinfo_node(&nodes);
|
||||
if(!node)
|
||||
{
|
||||
goto enomem;
|
||||
}
|
||||
|
||||
node->ai_family = addr.sa.sa_family = AF_INET;
|
||||
node->ai_addrlen = sizeof(sizeof(addr.sa4));
|
||||
node->ai_addr = ares_malloc(sizeof(addr.sa4));
|
||||
if (!node->ai_addr)
|
||||
{
|
||||
goto enomem;
|
||||
}
|
||||
memcpy(node->ai_addr, &addr.sa4, sizeof(addr.sa4));
|
||||
}
|
||||
}
|
||||
if ((hints->ai_family == AF_INET6) || (hints->ai_family == AF_UNSPEC))
|
||||
{
|
||||
addr.sa6.sin6_port = htons(port);
|
||||
if (ares_inet_pton(AF_INET6, txtaddr, &addr.sa6.sin6_addr) > 0)
|
||||
{
|
||||
node = ares__append_addrinfo_node(&nodes);
|
||||
if (!node)
|
||||
{
|
||||
goto enomem;
|
||||
}
|
||||
|
||||
node->ai_family = addr.sa.sa_family = AF_INET6;
|
||||
node->ai_addrlen = sizeof(sizeof(addr.sa6));
|
||||
node->ai_addr = ares_malloc(sizeof(addr.sa6));
|
||||
if (!node->ai_addr)
|
||||
{
|
||||
goto enomem;
|
||||
}
|
||||
memcpy(node->ai_addr, &addr.sa6, sizeof(addr.sa6));
|
||||
}
|
||||
}
|
||||
if (!node)
|
||||
/* Ignore line if invalid address string for the requested family. */
|
||||
continue;
|
||||
|
||||
if (want_cname)
|
||||
{
|
||||
for (i = 0; i < alias_count; ++i)
|
||||
{
|
||||
cname = ares__append_addrinfo_cname(&cnames);
|
||||
if (!cname)
|
||||
{
|
||||
goto enomem;
|
||||
}
|
||||
cname->alias = ares_strdup(aliases[i]);
|
||||
cname->name = ares_strdup(txthost);
|
||||
}
|
||||
/* No aliases, cname only. */
|
||||
if(!alias_count)
|
||||
{
|
||||
cname = ares__append_addrinfo_cname(&cnames);
|
||||
if (!cname)
|
||||
{
|
||||
goto enomem;
|
||||
}
|
||||
cname->name = ares_strdup(txthost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Last read failed. */
|
||||
if (status == ARES_ENOMEM)
|
||||
{
|
||||
goto enomem;
|
||||
}
|
||||
|
||||
/* Free line buffer. */
|
||||
ares_free(line);
|
||||
|
||||
ares__addrinfo_cat_cnames(&ai->cnames, cnames);
|
||||
ares__addrinfo_cat_nodes(&ai->nodes, nodes);
|
||||
|
||||
return node ? ARES_SUCCESS : ARES_ENOTFOUND;
|
||||
|
||||
enomem:
|
||||
ares_free(line);
|
||||
ares__freeaddrinfo_cnames(cnames);
|
||||
ares__freeaddrinfo_nodes(nodes);
|
||||
return ARES_ENOMEM;
|
||||
}
|
||||
494
deps/cares/src/ares__sortaddrinfo.c
vendored
Normal file
494
deps/cares/src/ares__sortaddrinfo.c
vendored
Normal file
@@ -0,0 +1,494 @@
|
||||
/*
|
||||
* Original file name getaddrinfo.c
|
||||
* Lifted from the 'Android Bionic' project with the BSD license.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
* Copyright (C) 2019 by Andrew Selivanov
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ares_setup.h"
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "ares.h"
|
||||
#include "ares_private.h"
|
||||
|
||||
struct addrinfo_sort_elem
|
||||
{
|
||||
struct ares_addrinfo_node *ai;
|
||||
int has_src_addr;
|
||||
ares_sockaddr src_addr;
|
||||
int original_order;
|
||||
};
|
||||
|
||||
#define ARES_IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f)
|
||||
|
||||
#define ARES_IPV6_ADDR_SCOPE_NODELOCAL 0x01
|
||||
#define ARES_IPV6_ADDR_SCOPE_INTFACELOCAL 0x01
|
||||
#define ARES_IPV6_ADDR_SCOPE_LINKLOCAL 0x02
|
||||
#define ARES_IPV6_ADDR_SCOPE_SITELOCAL 0x05
|
||||
#define ARES_IPV6_ADDR_SCOPE_ORGLOCAL 0x08
|
||||
#define ARES_IPV6_ADDR_SCOPE_GLOBAL 0x0e
|
||||
|
||||
#define ARES_IN_LOOPBACK(a) ((((long int)(a)) & 0xff000000) == 0x7f000000)
|
||||
|
||||
/* RFC 4193. */
|
||||
#define ARES_IN6_IS_ADDR_ULA(a) (((a)->s6_addr[0] & 0xfe) == 0xfc)
|
||||
|
||||
/* These macros are modelled after the ones in <netinet/in6.h>. */
|
||||
/* RFC 4380, section 2.6 */
|
||||
#define ARES_IN6_IS_ADDR_TEREDO(a) \
|
||||
((*(const unsigned int *)(const void *)(&(a)->s6_addr[0]) == ntohl(0x20010000)))
|
||||
/* RFC 3056, section 2. */
|
||||
#define ARES_IN6_IS_ADDR_6TO4(a) \
|
||||
(((a)->s6_addr[0] == 0x20) && ((a)->s6_addr[1] == 0x02))
|
||||
/* 6bone testing address area (3ffe::/16), deprecated in RFC 3701. */
|
||||
#define ARES_IN6_IS_ADDR_6BONE(a) \
|
||||
(((a)->s6_addr[0] == 0x3f) && ((a)->s6_addr[1] == 0xfe))
|
||||
|
||||
static int get_scope(const struct sockaddr *addr)
|
||||
{
|
||||
if (addr->sa_family == AF_INET6)
|
||||
{
|
||||
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
|
||||
if (IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr))
|
||||
{
|
||||
return ARES_IPV6_ADDR_MC_SCOPE(&addr6->sin6_addr);
|
||||
}
|
||||
else if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr) ||
|
||||
IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr))
|
||||
{
|
||||
/*
|
||||
* RFC 4291 section 2.5.3 says loopback is to be treated as having
|
||||
* link-local scope.
|
||||
*/
|
||||
return ARES_IPV6_ADDR_SCOPE_LINKLOCAL;
|
||||
}
|
||||
else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr))
|
||||
{
|
||||
return ARES_IPV6_ADDR_SCOPE_SITELOCAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ARES_IPV6_ADDR_SCOPE_GLOBAL;
|
||||
}
|
||||
}
|
||||
else if (addr->sa_family == AF_INET)
|
||||
{
|
||||
const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
|
||||
unsigned long int na = ntohl(addr4->sin_addr.s_addr);
|
||||
if (ARES_IN_LOOPBACK(na) || /* 127.0.0.0/8 */
|
||||
(na & 0xffff0000) == 0xa9fe0000) /* 169.254.0.0/16 */
|
||||
{
|
||||
return ARES_IPV6_ADDR_SCOPE_LINKLOCAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* RFC 6724 section 3.2. Other IPv4 addresses, including private
|
||||
* addresses and shared addresses (100.64.0.0/10), are assigned global
|
||||
* scope.
|
||||
*/
|
||||
return ARES_IPV6_ADDR_SCOPE_GLOBAL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* This should never happen.
|
||||
* Return a scope with low priority as a last resort.
|
||||
*/
|
||||
return ARES_IPV6_ADDR_SCOPE_NODELOCAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int get_label(const struct sockaddr *addr)
|
||||
{
|
||||
if (addr->sa_family == AF_INET)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
else if (addr->sa_family == AF_INET6)
|
||||
{
|
||||
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
|
||||
if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr))
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
else if (ARES_IN6_IS_ADDR_6TO4(&addr6->sin6_addr))
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else if (ARES_IN6_IS_ADDR_TEREDO(&addr6->sin6_addr))
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
else if (ARES_IN6_IS_ADDR_ULA(&addr6->sin6_addr))
|
||||
{
|
||||
return 13;
|
||||
}
|
||||
else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr))
|
||||
{
|
||||
return 11;
|
||||
}
|
||||
else if (ARES_IN6_IS_ADDR_6BONE(&addr6->sin6_addr))
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All other IPv6 addresses, including global unicast addresses. */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* This should never happen.
|
||||
* Return a semi-random label as a last resort.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the precedence for a given IPv4/IPv6 address.
|
||||
* RFC 6724, section 2.1.
|
||||
*/
|
||||
static int get_precedence(const struct sockaddr *addr)
|
||||
{
|
||||
if (addr->sa_family == AF_INET)
|
||||
{
|
||||
return 35;
|
||||
}
|
||||
else if (addr->sa_family == AF_INET6)
|
||||
{
|
||||
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
|
||||
if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr))
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr))
|
||||
{
|
||||
return 35;
|
||||
}
|
||||
else if (ARES_IN6_IS_ADDR_6TO4(&addr6->sin6_addr))
|
||||
{
|
||||
return 30;
|
||||
}
|
||||
else if (ARES_IN6_IS_ADDR_TEREDO(&addr6->sin6_addr))
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
else if (ARES_IN6_IS_ADDR_ULA(&addr6->sin6_addr))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr) ||
|
||||
IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr) ||
|
||||
ARES_IN6_IS_ADDR_6BONE(&addr6->sin6_addr))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All other IPv6 addresses, including global unicast addresses. */
|
||||
return 40;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find number of matching initial bits between the two addresses a1 and a2.
|
||||
*/
|
||||
static int common_prefix_len(const struct in6_addr *a1,
|
||||
const struct in6_addr *a2)
|
||||
{
|
||||
const char *p1 = (const char *)a1;
|
||||
const char *p2 = (const char *)a2;
|
||||
unsigned i;
|
||||
for (i = 0; i < sizeof(*a1); ++i)
|
||||
{
|
||||
int x, j;
|
||||
if (p1[i] == p2[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
x = p1[i] ^ p2[i];
|
||||
for (j = 0; j < CHAR_BIT; ++j)
|
||||
{
|
||||
if (x & (1 << (CHAR_BIT - 1)))
|
||||
{
|
||||
return i * CHAR_BIT + j;
|
||||
}
|
||||
x <<= 1;
|
||||
}
|
||||
}
|
||||
return sizeof(*a1) * CHAR_BIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two source/destination address pairs.
|
||||
* RFC 6724, section 6.
|
||||
*/
|
||||
static int rfc6724_compare(const void *ptr1, const void *ptr2)
|
||||
{
|
||||
const struct addrinfo_sort_elem *a1 = (const struct addrinfo_sort_elem *)ptr1;
|
||||
const struct addrinfo_sort_elem *a2 = (const struct addrinfo_sort_elem *)ptr2;
|
||||
int scope_src1, scope_dst1, scope_match1;
|
||||
int scope_src2, scope_dst2, scope_match2;
|
||||
int label_src1, label_dst1, label_match1;
|
||||
int label_src2, label_dst2, label_match2;
|
||||
int precedence1, precedence2;
|
||||
int prefixlen1, prefixlen2;
|
||||
|
||||
/* Rule 1: Avoid unusable destinations. */
|
||||
if (a1->has_src_addr != a2->has_src_addr)
|
||||
{
|
||||
return a2->has_src_addr - a1->has_src_addr;
|
||||
}
|
||||
|
||||
/* Rule 2: Prefer matching scope. */
|
||||
scope_src1 = get_scope(&a1->src_addr.sa);
|
||||
scope_dst1 = get_scope(a1->ai->ai_addr);
|
||||
scope_match1 = (scope_src1 == scope_dst1);
|
||||
|
||||
scope_src2 = get_scope(&a2->src_addr.sa);
|
||||
scope_dst2 = get_scope(a2->ai->ai_addr);
|
||||
scope_match2 = (scope_src2 == scope_dst2);
|
||||
|
||||
if (scope_match1 != scope_match2)
|
||||
{
|
||||
return scope_match2 - scope_match1;
|
||||
}
|
||||
|
||||
/* Rule 3: Avoid deprecated addresses. */
|
||||
|
||||
/* Rule 4: Prefer home addresses. */
|
||||
|
||||
/* Rule 5: Prefer matching label. */
|
||||
label_src1 = get_label(&a1->src_addr.sa);
|
||||
label_dst1 = get_label(a1->ai->ai_addr);
|
||||
label_match1 = (label_src1 == label_dst1);
|
||||
|
||||
label_src2 = get_label(&a2->src_addr.sa);
|
||||
label_dst2 = get_label(a2->ai->ai_addr);
|
||||
label_match2 = (label_src2 == label_dst2);
|
||||
|
||||
if (label_match1 != label_match2)
|
||||
{
|
||||
return label_match2 - label_match1;
|
||||
}
|
||||
|
||||
/* Rule 6: Prefer higher precedence. */
|
||||
precedence1 = get_precedence(a1->ai->ai_addr);
|
||||
precedence2 = get_precedence(a2->ai->ai_addr);
|
||||
if (precedence1 != precedence2)
|
||||
{
|
||||
return precedence2 - precedence1;
|
||||
}
|
||||
|
||||
/* Rule 7: Prefer native transport. */
|
||||
|
||||
/* Rule 8: Prefer smaller scope. */
|
||||
if (scope_dst1 != scope_dst2)
|
||||
{
|
||||
return scope_dst1 - scope_dst2;
|
||||
}
|
||||
|
||||
/* Rule 9: Use longest matching prefix. */
|
||||
if (a1->has_src_addr && a1->ai->ai_addr->sa_family == AF_INET6 &&
|
||||
a2->has_src_addr && a2->ai->ai_addr->sa_family == AF_INET6)
|
||||
{
|
||||
const struct sockaddr_in6 *a1_src = &a1->src_addr.sa6;
|
||||
const struct sockaddr_in6 *a1_dst =
|
||||
(const struct sockaddr_in6 *)a1->ai->ai_addr;
|
||||
const struct sockaddr_in6 *a2_src = &a2->src_addr.sa6;
|
||||
const struct sockaddr_in6 *a2_dst =
|
||||
(const struct sockaddr_in6 *)a2->ai->ai_addr;
|
||||
prefixlen1 = common_prefix_len(&a1_src->sin6_addr, &a1_dst->sin6_addr);
|
||||
prefixlen2 = common_prefix_len(&a2_src->sin6_addr, &a2_dst->sin6_addr);
|
||||
if (prefixlen1 != prefixlen2)
|
||||
{
|
||||
return prefixlen2 - prefixlen1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Rule 10: Leave the order unchanged.
|
||||
* We need this since qsort() is not necessarily stable.
|
||||
*/
|
||||
return a1->original_order - a2->original_order;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the source address that will be used if trying to connect to the given
|
||||
* address.
|
||||
*
|
||||
* Returns 1 if a source address was found, 0 if the address is unreachable,
|
||||
* and -1 if a fatal error occurred. If 0 or 1, the contents of src_addr are
|
||||
* undefined.
|
||||
*/
|
||||
static int find_src_addr(ares_channel channel,
|
||||
const struct sockaddr *addr,
|
||||
struct sockaddr *src_addr)
|
||||
{
|
||||
int sock;
|
||||
int ret;
|
||||
ares_socklen_t len;
|
||||
|
||||
switch (addr->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
len = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
case AF_INET6:
|
||||
len = sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
default:
|
||||
/* No known usable source address for non-INET families. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
sock = ares__open_socket(channel, addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (sock == -1)
|
||||
{
|
||||
if (errno == EAFNOSUPPORT)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
ret = ares__connect_socket(channel, sock, addr, len);
|
||||
}
|
||||
while (ret == -1 && errno == EINTR);
|
||||
|
||||
if (ret == -1)
|
||||
{
|
||||
ares__close_socket(channel, sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (getsockname(sock, src_addr, &len) == -1)
|
||||
{
|
||||
ares__close_socket(channel, sock);
|
||||
return -1;
|
||||
}
|
||||
ares__close_socket(channel, sock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort the linked list starting at sentinel->ai_next in RFC6724 order.
|
||||
* Will leave the list unchanged if an error occurs.
|
||||
*/
|
||||
int ares__sortaddrinfo(ares_channel channel, struct ares_addrinfo_node *list_sentinel)
|
||||
{
|
||||
struct ares_addrinfo_node *cur;
|
||||
int nelem = 0, i;
|
||||
int has_src_addr;
|
||||
struct addrinfo_sort_elem *elems;
|
||||
|
||||
cur = list_sentinel->ai_next;
|
||||
while (cur)
|
||||
{
|
||||
++nelem;
|
||||
cur = cur->ai_next;
|
||||
}
|
||||
elems = (struct addrinfo_sort_elem *)ares_malloc(
|
||||
nelem * sizeof(struct addrinfo_sort_elem));
|
||||
if (!elems)
|
||||
{
|
||||
return ARES_ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the linked list to an array that also contains the candidate
|
||||
* source address for each destination address.
|
||||
*/
|
||||
for (i = 0, cur = list_sentinel->ai_next; i < nelem; ++i, cur = cur->ai_next)
|
||||
{
|
||||
assert(cur != NULL);
|
||||
elems[i].ai = cur;
|
||||
elems[i].original_order = i;
|
||||
has_src_addr = find_src_addr(channel, cur->ai_addr, &elems[i].src_addr.sa);
|
||||
if (has_src_addr == -1)
|
||||
{
|
||||
ares_free(elems);
|
||||
return ARES_ENOTFOUND;
|
||||
}
|
||||
elems[i].has_src_addr = has_src_addr;
|
||||
}
|
||||
|
||||
/* Sort the addresses, and rearrange the linked list so it matches the sorted
|
||||
* order. */
|
||||
qsort((void *)elems, nelem, sizeof(struct addrinfo_sort_elem),
|
||||
rfc6724_compare);
|
||||
|
||||
list_sentinel->ai_next = elems[0].ai;
|
||||
for (i = 0; i < nelem - 1; ++i)
|
||||
{
|
||||
elems[i].ai->ai_next = elems[i + 1].ai;
|
||||
}
|
||||
elems[nelem - 1].ai->ai_next = NULL;
|
||||
|
||||
ares_free(elems);
|
||||
return ARES_SUCCESS;
|
||||
}
|
||||
2
deps/cares/src/ares_android.c
vendored
2
deps/cares/src/ares_android.c
vendored
@@ -360,8 +360,6 @@ char *ares_get_android_search_domains_list(void)
|
||||
jstring domains = NULL;
|
||||
const char *domain;
|
||||
int res;
|
||||
size_t i;
|
||||
size_t cnt = 0;
|
||||
char *domain_list = NULL;
|
||||
int need_detatch = 0;
|
||||
|
||||
|
||||
57
deps/cares/src/ares_freeaddrinfo.c
vendored
Normal file
57
deps/cares/src/ares_freeaddrinfo.c
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
/* Copyright 1998 by the Massachusetts Institute of Technology.
|
||||
* Copyright (C) 2019 by Andrew Selivanov
|
||||
*
|
||||
* 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_NETDB_H
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include "ares.h"
|
||||
#include "ares_private.h"
|
||||
|
||||
void ares__freeaddrinfo_cnames(struct ares_addrinfo_cname *head)
|
||||
{
|
||||
struct ares_addrinfo_cname *current;
|
||||
while (head)
|
||||
{
|
||||
current = head;
|
||||
head = head->next;
|
||||
ares_free(current->alias);
|
||||
ares_free(current->name);
|
||||
ares_free(current);
|
||||
}
|
||||
}
|
||||
|
||||
void ares__freeaddrinfo_nodes(struct ares_addrinfo_node *head)
|
||||
{
|
||||
struct ares_addrinfo_node *current;
|
||||
while (head)
|
||||
{
|
||||
current = head;
|
||||
head = head->ai_next;
|
||||
ares_free(current->ai_addr);
|
||||
ares_free(current);
|
||||
}
|
||||
}
|
||||
|
||||
void ares_freeaddrinfo(struct ares_addrinfo *ai)
|
||||
{
|
||||
ares__freeaddrinfo_cnames(ai->cnames);
|
||||
ares__freeaddrinfo_nodes(ai->nodes);
|
||||
ares_free(ai);
|
||||
}
|
||||
764
deps/cares/src/ares_getaddrinfo.c
vendored
Normal file
764
deps/cares/src/ares_getaddrinfo.c
vendored
Normal file
@@ -0,0 +1,764 @@
|
||||
|
||||
/* Copyright 1998, 2011, 2013 by the Massachusetts Institute of Technology.
|
||||
* Copyright (C) 2017 - 2018 by Christian Ammer
|
||||
* Copyright (C) 2019 by Andrew Selivanov
|
||||
*
|
||||
* 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_GETSERVBYNAME_R
|
||||
# if !defined(GETSERVBYNAME_R_ARGS) || \
|
||||
(GETSERVBYNAME_R_ARGS < 4) || (GETSERVBYNAME_R_ARGS > 6)
|
||||
# error "you MUST specifiy a valid number of arguments for getservbyname_r"
|
||||
# endif
|
||||
#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
|
||||
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#include "ares.h"
|
||||
#include "bitncmp.h"
|
||||
#include "ares_private.h"
|
||||
|
||||
#ifdef WATT32
|
||||
#undef WIN32
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
# include "ares_platform.h"
|
||||
#endif
|
||||
|
||||
struct host_query
|
||||
{
|
||||
ares_channel channel;
|
||||
char *name;
|
||||
unsigned short port; /* in host order */
|
||||
ares_addrinfo_callback callback;
|
||||
void *arg;
|
||||
struct ares_addrinfo_hints hints;
|
||||
int sent_family; /* this family is what was is being used */
|
||||
int timeouts; /* number of timeouts we saw for this request */
|
||||
const char *remaining_lookups; /* types of lookup we need to perform ("fb" by
|
||||
default, file and dns respectively) */
|
||||
struct ares_addrinfo *ai; /* store results between lookups */
|
||||
int remaining; /* number of DNS answers waiting for */
|
||||
int next_domain; /* next search domain to try */
|
||||
};
|
||||
|
||||
static const struct ares_addrinfo_hints default_hints = {
|
||||
0, /* ai_flags */
|
||||
AF_UNSPEC, /* ai_family */
|
||||
0, /* ai_socktype */
|
||||
0, /* ai_protocol */
|
||||
};
|
||||
|
||||
static const struct ares_addrinfo_cname empty_addrinfo_cname = {
|
||||
INT_MAX, /* ttl */
|
||||
NULL, /* alias */
|
||||
NULL, /* name */
|
||||
NULL, /* next */
|
||||
};
|
||||
|
||||
static const struct ares_addrinfo_node empty_addrinfo_node = {
|
||||
0, /* ai_ttl */
|
||||
0, /* ai_flags */
|
||||
0, /* ai_family */
|
||||
0, /* ai_socktype */
|
||||
0, /* ai_protocol */
|
||||
0, /* ai_addrlen */
|
||||
NULL, /* ai_addr */
|
||||
NULL /* ai_next */
|
||||
};
|
||||
|
||||
static const struct ares_addrinfo empty_addrinfo = {
|
||||
NULL, /* cnames */
|
||||
NULL /* nodes */
|
||||
};
|
||||
|
||||
/* forward declarations */
|
||||
static void host_callback(void *arg, int status, int timeouts,
|
||||
unsigned char *abuf, int alen);
|
||||
static int as_is_first(const struct host_query *hquery);
|
||||
static int next_dns_lookup(struct host_query *hquery);
|
||||
|
||||
struct ares_addrinfo_cname *ares__malloc_addrinfo_cname()
|
||||
{
|
||||
struct ares_addrinfo_cname *cname = ares_malloc(sizeof(struct ares_addrinfo_cname));
|
||||
if (!cname)
|
||||
return NULL;
|
||||
|
||||
*cname = empty_addrinfo_cname;
|
||||
return cname;
|
||||
}
|
||||
|
||||
struct ares_addrinfo_cname *ares__append_addrinfo_cname(struct ares_addrinfo_cname **head)
|
||||
{
|
||||
struct ares_addrinfo_cname *tail = ares__malloc_addrinfo_cname();
|
||||
struct ares_addrinfo_cname *last = *head;
|
||||
if (!last)
|
||||
{
|
||||
*head = tail;
|
||||
return tail;
|
||||
}
|
||||
|
||||
while (last->next)
|
||||
{
|
||||
last = last->next;
|
||||
}
|
||||
|
||||
last->next = tail;
|
||||
return tail;
|
||||
}
|
||||
|
||||
void ares__addrinfo_cat_cnames(struct ares_addrinfo_cname **head,
|
||||
struct ares_addrinfo_cname *tail)
|
||||
{
|
||||
struct ares_addrinfo_cname *last = *head;
|
||||
if (!last)
|
||||
{
|
||||
*head = tail;
|
||||
return;
|
||||
}
|
||||
|
||||
while (last->next)
|
||||
{
|
||||
last = last->next;
|
||||
}
|
||||
|
||||
last->next = tail;
|
||||
}
|
||||
|
||||
struct ares_addrinfo *ares__malloc_addrinfo()
|
||||
{
|
||||
struct ares_addrinfo *ai = ares_malloc(sizeof(struct ares_addrinfo));
|
||||
if (!ai)
|
||||
return NULL;
|
||||
|
||||
*ai = empty_addrinfo;
|
||||
return ai;
|
||||
}
|
||||
|
||||
struct ares_addrinfo_node *ares__malloc_addrinfo_node()
|
||||
{
|
||||
struct ares_addrinfo_node *node =
|
||||
ares_malloc(sizeof(struct ares_addrinfo_node));
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
*node = empty_addrinfo_node;
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Allocate new addrinfo and append to the tail. */
|
||||
struct ares_addrinfo_node *ares__append_addrinfo_node(struct ares_addrinfo_node **head)
|
||||
{
|
||||
struct ares_addrinfo_node *tail = ares__malloc_addrinfo_node();
|
||||
struct ares_addrinfo_node *last = *head;
|
||||
if (!last)
|
||||
{
|
||||
*head = tail;
|
||||
return tail;
|
||||
}
|
||||
|
||||
while (last->ai_next)
|
||||
{
|
||||
last = last->ai_next;
|
||||
}
|
||||
|
||||
last->ai_next = tail;
|
||||
return tail;
|
||||
}
|
||||
|
||||
void ares__addrinfo_cat_nodes(struct ares_addrinfo_node **head,
|
||||
struct ares_addrinfo_node *tail)
|
||||
{
|
||||
struct ares_addrinfo_node *last = *head;
|
||||
if (!last)
|
||||
{
|
||||
*head = tail;
|
||||
return;
|
||||
}
|
||||
|
||||
while (last->ai_next)
|
||||
{
|
||||
last = last->ai_next;
|
||||
}
|
||||
|
||||
last->ai_next = tail;
|
||||
}
|
||||
|
||||
/* Resolve service name into port number given in host byte order.
|
||||
* If not resolved, return 0.
|
||||
*/
|
||||
static unsigned short lookup_service(const char *service, int flags)
|
||||
{
|
||||
const char *proto;
|
||||
struct servent *sep;
|
||||
#ifdef HAVE_GETSERVBYNAME_R
|
||||
struct servent se;
|
||||
char tmpbuf[4096];
|
||||
#endif
|
||||
|
||||
if (service)
|
||||
{
|
||||
if (flags & ARES_NI_UDP)
|
||||
proto = "udp";
|
||||
else if (flags & ARES_NI_SCTP)
|
||||
proto = "sctp";
|
||||
else if (flags & ARES_NI_DCCP)
|
||||
proto = "dccp";
|
||||
else
|
||||
proto = "tcp";
|
||||
#ifdef HAVE_GETSERVBYNAME_R
|
||||
memset(&se, 0, sizeof(se));
|
||||
sep = &se;
|
||||
memset(tmpbuf, 0, sizeof(tmpbuf));
|
||||
#if GETSERVBYNAME_R_ARGS == 6
|
||||
if (getservbyname_r(service, proto, &se, (void *)tmpbuf, sizeof(tmpbuf),
|
||||
&sep) != 0)
|
||||
sep = NULL; /* LCOV_EXCL_LINE: buffer large so this never fails */
|
||||
#elif GETSERVBYNAME_R_ARGS == 5
|
||||
sep =
|
||||
getservbyname_r(service, proto, &se, (void *)tmpbuf, sizeof(tmpbuf));
|
||||
#elif GETSERVBYNAME_R_ARGS == 4
|
||||
if (getservbyname_r(service, proto, &se, (void *)tmpbuf) != 0)
|
||||
sep = NULL;
|
||||
#else
|
||||
/* Lets just hope the OS uses TLS! */
|
||||
sep = getservbyname(service, proto);
|
||||
#endif
|
||||
#else
|
||||
/* Lets just hope the OS uses TLS! */
|
||||
#if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
|
||||
sep = getservbyname(service, (char *)proto);
|
||||
#else
|
||||
sep = getservbyname(service, proto);
|
||||
#endif
|
||||
#endif
|
||||
return (sep ? ntohs((unsigned short)sep->s_port) : 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the name looks like an IP address or an error occured,
|
||||
* fake up a host entry, end the query immediately, and return true.
|
||||
* Otherwise return false.
|
||||
*/
|
||||
static int fake_addrinfo(const char *name,
|
||||
unsigned short port,
|
||||
const struct ares_addrinfo_hints *hints,
|
||||
struct ares_addrinfo *ai,
|
||||
ares_addrinfo_callback callback,
|
||||
void *arg)
|
||||
{
|
||||
struct ares_addrinfo_cname *cname;
|
||||
struct ares_addrinfo_node *node;
|
||||
ares_sockaddr addr;
|
||||
size_t addrlen;
|
||||
int result = 0;
|
||||
int family = hints->ai_family;
|
||||
if (family == AF_INET || family == AF_INET6 || family == AF_UNSPEC)
|
||||
{
|
||||
/* It only looks like an IP address if it's all numbers and dots. */
|
||||
int numdots = 0, valid = 1;
|
||||
const char *p;
|
||||
for (p = name; *p; p++)
|
||||
{
|
||||
if (!ISDIGIT(*p) && *p != '.')
|
||||
{
|
||||
valid = 0;
|
||||
break;
|
||||
}
|
||||
else if (*p == '.')
|
||||
{
|
||||
numdots++;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
/* if we don't have 3 dots, it is illegal
|
||||
* (although inet_pton doesn't think so).
|
||||
*/
|
||||
if (numdots != 3 || !valid)
|
||||
result = 0;
|
||||
else
|
||||
result =
|
||||
(ares_inet_pton(AF_INET, name, &addr.sa4.sin_addr) < 1 ? 0 : 1);
|
||||
|
||||
if (result)
|
||||
{
|
||||
family = addr.sa.sa_family = AF_INET;
|
||||
addr.sa4.sin_port = htons(port);
|
||||
addrlen = sizeof(addr.sa4);
|
||||
}
|
||||
}
|
||||
|
||||
if (family == AF_INET6 || family == AF_UNSPEC)
|
||||
{
|
||||
result =
|
||||
(ares_inet_pton(AF_INET6, name, &addr.sa6.sin6_addr) < 1 ? 0 : 1);
|
||||
addr.sa6.sin6_family = AF_INET6;
|
||||
addr.sa6.sin6_port = htons(port);
|
||||
addrlen = sizeof(addr.sa6);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
return 0;
|
||||
|
||||
node = ares__malloc_addrinfo_node();
|
||||
if (!node)
|
||||
{
|
||||
ares_freeaddrinfo(ai);
|
||||
callback(arg, ARES_ENOMEM, 0, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ai->nodes = node;
|
||||
|
||||
node->ai_addr = ares_malloc(addrlen);
|
||||
if (!node->ai_addr)
|
||||
{
|
||||
ares_freeaddrinfo(ai);
|
||||
callback(arg, ARES_ENOMEM, 0, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
node->ai_addrlen = (unsigned int)addrlen;
|
||||
node->ai_family = addr.sa.sa_family;
|
||||
if (addr.sa.sa_family == AF_INET)
|
||||
memcpy(node->ai_addr, &addr.sa4, sizeof(addr.sa4));
|
||||
else
|
||||
memcpy(node->ai_addr, &addr.sa6, sizeof(addr.sa6));
|
||||
|
||||
if (hints->ai_flags & ARES_AI_CANONNAME)
|
||||
{
|
||||
cname = ares__append_addrinfo_cname(&ai->cnames);
|
||||
if (!cname)
|
||||
{
|
||||
ares_freeaddrinfo(ai);
|
||||
callback(arg, ARES_ENOMEM, 0, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Duplicate the name, to avoid a constness violation. */
|
||||
cname->name = ares_strdup(name);
|
||||
if (!cname->name)
|
||||
{
|
||||
ares_freeaddrinfo(ai);
|
||||
callback(arg, ARES_ENOMEM, 0, NULL);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
callback(arg, ARES_SUCCESS, 0, ai);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void end_hquery(struct host_query *hquery, int status)
|
||||
{
|
||||
struct ares_addrinfo_node sentinel;
|
||||
struct ares_addrinfo_node *next;
|
||||
if (status == ARES_SUCCESS)
|
||||
{
|
||||
if (!(hquery->hints.ai_flags & ARES_AI_NOSORT))
|
||||
{
|
||||
sentinel.ai_next = hquery->ai->nodes;
|
||||
ares__sortaddrinfo(hquery->channel, &sentinel);
|
||||
hquery->ai->nodes = sentinel.ai_next;
|
||||
}
|
||||
next = hquery->ai->nodes;
|
||||
/* Set port into each address (resolved separately). */
|
||||
while (next)
|
||||
{
|
||||
if (next->ai_family == AF_INET)
|
||||
{
|
||||
((struct sockaddr_in *)next->ai_addr)->sin_port = htons(hquery->port);
|
||||
}
|
||||
else
|
||||
{
|
||||
((struct sockaddr_in6 *)next->ai_addr)->sin6_port = htons(hquery->port);
|
||||
}
|
||||
next = next->ai_next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clean up what we have collected by so far. */
|
||||
ares_freeaddrinfo(hquery->ai);
|
||||
hquery->ai = NULL;
|
||||
}
|
||||
|
||||
hquery->callback(hquery->arg, status, hquery->timeouts, hquery->ai);
|
||||
ares_free(hquery->name);
|
||||
ares_free(hquery);
|
||||
}
|
||||
|
||||
static int file_lookup(struct host_query *hquery)
|
||||
{
|
||||
FILE *fp;
|
||||
int error;
|
||||
int status;
|
||||
const char *path_hosts = NULL;
|
||||
|
||||
if (hquery->hints.ai_flags & ARES_AI_ENVHOSTS)
|
||||
{
|
||||
path_hosts = getenv("CARES_HOSTS");
|
||||
}
|
||||
|
||||
if (!path_hosts)
|
||||
{
|
||||
#ifdef WIN32
|
||||
char PATH_HOSTS[MAX_PATH];
|
||||
win_platform platform;
|
||||
|
||||
PATH_HOSTS[0] = '\0';
|
||||
|
||||
platform = ares__getplatform();
|
||||
|
||||
if (platform == WIN_NT)
|
||||
{
|
||||
char tmp[MAX_PATH];
|
||||
HKEY hkeyHosts;
|
||||
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ,
|
||||
&hkeyHosts) == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD dwLength = MAX_PATH;
|
||||
RegQueryValueEx(hkeyHosts, DATABASEPATH, NULL, NULL, (LPBYTE)tmp,
|
||||
&dwLength);
|
||||
ExpandEnvironmentStrings(tmp, PATH_HOSTS, MAX_PATH);
|
||||
RegCloseKey(hkeyHosts);
|
||||
}
|
||||
}
|
||||
else if (platform == WIN_9X)
|
||||
GetWindowsDirectory(PATH_HOSTS, MAX_PATH);
|
||||
else
|
||||
return ARES_ENOTFOUND;
|
||||
|
||||
strcat(PATH_HOSTS, WIN_PATH_HOSTS);
|
||||
path_hosts = PATH_HOSTS;
|
||||
|
||||
#elif defined(WATT32)
|
||||
const char *PATH_HOSTS = _w32_GetHostsFile();
|
||||
|
||||
if (!PATH_HOSTS)
|
||||
return ARES_ENOTFOUND;
|
||||
#endif
|
||||
path_hosts = PATH_HOSTS;
|
||||
}
|
||||
|
||||
fp = fopen(path_hosts, "r");
|
||||
if (!fp)
|
||||
{
|
||||
error = ERRNO;
|
||||
switch (error)
|
||||
{
|
||||
case ENOENT:
|
||||
case ESRCH:
|
||||
return ARES_ENOTFOUND;
|
||||
default:
|
||||
DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error,
|
||||
strerror(error)));
|
||||
DEBUGF(fprintf(stderr, "Error opening file: %s\n", path_hosts));
|
||||
return ARES_EFILE;
|
||||
}
|
||||
}
|
||||
status = ares__readaddrinfo(fp, hquery->name, hquery->port, &hquery->hints, hquery->ai);
|
||||
fclose(fp);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void next_lookup(struct host_query *hquery, int status)
|
||||
{
|
||||
switch (*hquery->remaining_lookups)
|
||||
{
|
||||
case 'b':
|
||||
/* DNS lookup */
|
||||
if (next_dns_lookup(hquery))
|
||||
break;
|
||||
hquery->remaining_lookups++;
|
||||
next_lookup(hquery, status);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
/* Host file lookup */
|
||||
if (file_lookup(hquery) == ARES_SUCCESS)
|
||||
{
|
||||
end_hquery(hquery, ARES_SUCCESS);
|
||||
break;
|
||||
}
|
||||
hquery->remaining_lookups++;
|
||||
next_lookup(hquery, status);
|
||||
break;
|
||||
default:
|
||||
/* No lookup left */
|
||||
end_hquery(hquery, status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void host_callback(void *arg, int status, int timeouts,
|
||||
unsigned char *abuf, int alen)
|
||||
{
|
||||
struct host_query *hquery = (struct host_query*)arg;
|
||||
int addinfostatus = ARES_SUCCESS;
|
||||
hquery->timeouts += timeouts;
|
||||
hquery->remaining--;
|
||||
|
||||
if (status == ARES_SUCCESS)
|
||||
{
|
||||
addinfostatus = ares__parse_into_addrinfo(abuf, alen, hquery->ai);
|
||||
}
|
||||
else if (status == ARES_EDESTRUCTION)
|
||||
{
|
||||
end_hquery(hquery, status);
|
||||
}
|
||||
|
||||
if (!hquery->remaining)
|
||||
{
|
||||
if (addinfostatus != ARES_SUCCESS)
|
||||
{
|
||||
/* error in parsing result e.g. no memory */
|
||||
end_hquery(hquery, addinfostatus);
|
||||
}
|
||||
else if (hquery->ai->nodes)
|
||||
{
|
||||
/* at least one query ended with ARES_SUCCESS */
|
||||
end_hquery(hquery, ARES_SUCCESS);
|
||||
}
|
||||
else if (status == ARES_ENOTFOUND)
|
||||
{
|
||||
next_lookup(hquery, status);
|
||||
}
|
||||
else
|
||||
{
|
||||
end_hquery(hquery, status);
|
||||
}
|
||||
}
|
||||
|
||||
/* at this point we keep on waiting for the next query to finish */
|
||||
}
|
||||
|
||||
void ares_getaddrinfo(ares_channel channel,
|
||||
const char* name, const char* service,
|
||||
const struct ares_addrinfo_hints* hints,
|
||||
ares_addrinfo_callback callback, void* arg)
|
||||
{
|
||||
struct host_query *hquery;
|
||||
unsigned short port = 0;
|
||||
int family;
|
||||
struct ares_addrinfo *ai;
|
||||
|
||||
if (!hints)
|
||||
{
|
||||
hints = &default_hints;
|
||||
}
|
||||
|
||||
family = hints->ai_family;
|
||||
|
||||
/* Right now we only know how to look up Internet addresses
|
||||
and unspec means try both basically. */
|
||||
if (family != AF_INET &&
|
||||
family != AF_INET6 &&
|
||||
family != AF_UNSPEC)
|
||||
{
|
||||
callback(arg, ARES_ENOTIMP, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ares__is_onion_domain(name))
|
||||
{
|
||||
callback(arg, ARES_ENOTFOUND, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (service)
|
||||
{
|
||||
if (hints->ai_flags & ARES_AI_NUMERICSERV)
|
||||
{
|
||||
port = (unsigned short)strtoul(service, NULL, 0);
|
||||
if (!port)
|
||||
{
|
||||
callback(arg, ARES_ESERVICE, 0, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
port = lookup_service(service, 0);
|
||||
if (!port)
|
||||
{
|
||||
port = (unsigned short)strtoul(service, NULL, 0);
|
||||
if (!port)
|
||||
{
|
||||
callback(arg, ARES_ESERVICE, 0, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ai = ares__malloc_addrinfo();
|
||||
if (!ai)
|
||||
{
|
||||
callback(arg, ARES_ENOMEM, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fake_addrinfo(name, port, hints, ai, callback, arg))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate and fill in the host query structure. */
|
||||
hquery = ares_malloc(sizeof(struct host_query));
|
||||
if (!hquery)
|
||||
{
|
||||
ares_freeaddrinfo(ai);
|
||||
callback(arg, ARES_ENOMEM, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
hquery->name = ares_strdup(name);
|
||||
if (!hquery->name)
|
||||
{
|
||||
ares_free(hquery);
|
||||
ares_freeaddrinfo(ai);
|
||||
callback(arg, ARES_ENOMEM, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
hquery->port = port;
|
||||
hquery->channel = channel;
|
||||
hquery->hints = *hints;
|
||||
hquery->sent_family = -1; /* nothing is sent yet */
|
||||
hquery->callback = callback;
|
||||
hquery->arg = arg;
|
||||
hquery->remaining_lookups = channel->lookups;
|
||||
hquery->timeouts = 0;
|
||||
hquery->ai = ai;
|
||||
hquery->next_domain = -1;
|
||||
hquery->remaining = 0;
|
||||
|
||||
/* Start performing lookups according to channel->lookups. */
|
||||
next_lookup(hquery, ARES_ECONNREFUSED /* initial error code */);
|
||||
}
|
||||
|
||||
static int next_dns_lookup(struct host_query *hquery)
|
||||
{
|
||||
char *s = NULL;
|
||||
int is_s_allocated = 0;
|
||||
int status;
|
||||
|
||||
/* if next_domain == -1 and as_is_first is true, try hquery->name */
|
||||
if (hquery->next_domain == -1)
|
||||
{
|
||||
if (as_is_first(hquery))
|
||||
{
|
||||
s = hquery->name;
|
||||
}
|
||||
hquery->next_domain = 0;
|
||||
}
|
||||
|
||||
/* if as_is_first is false, try hquery->name at last */
|
||||
if (!s && hquery->next_domain == hquery->channel->ndomains) {
|
||||
if (!as_is_first(hquery))
|
||||
{
|
||||
s = hquery->name;
|
||||
}
|
||||
hquery->next_domain++;
|
||||
}
|
||||
|
||||
if (!s && hquery->next_domain < hquery->channel->ndomains)
|
||||
{
|
||||
status = ares__cat_domain(
|
||||
hquery->name,
|
||||
hquery->channel->domains[hquery->next_domain++],
|
||||
&s);
|
||||
if (status == ARES_SUCCESS)
|
||||
{
|
||||
is_s_allocated = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (s)
|
||||
{
|
||||
switch (hquery->hints.ai_family)
|
||||
{
|
||||
case AF_INET:
|
||||
hquery->remaining += 1;
|
||||
ares_query(hquery->channel, s, C_IN, T_A, host_callback, hquery);
|
||||
break;
|
||||
case AF_INET6:
|
||||
hquery->remaining += 1;
|
||||
ares_query(hquery->channel, s, C_IN, T_AAAA, host_callback, hquery);
|
||||
break;
|
||||
case AF_UNSPEC:
|
||||
hquery->remaining += 2;
|
||||
ares_query(hquery->channel, s, C_IN, T_A, host_callback, hquery);
|
||||
ares_query(hquery->channel, s, C_IN, T_AAAA, host_callback, hquery);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (is_s_allocated)
|
||||
{
|
||||
ares_free(s);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!hquery->ai->nodes);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int as_is_first(const struct host_query* hquery)
|
||||
{
|
||||
char* p;
|
||||
int ndots = 0;
|
||||
for (p = hquery->name; *p; p++)
|
||||
{
|
||||
if (*p == '.')
|
||||
{
|
||||
ndots++;
|
||||
}
|
||||
}
|
||||
return ndots >= hquery->channel->ndots;
|
||||
}
|
||||
2
deps/cares/src/ares_getenv.c
vendored
2
deps/cares/src/ares_getenv.c
vendored
@@ -22,9 +22,7 @@
|
||||
|
||||
char *ares_getenv(const char *name)
|
||||
{
|
||||
#ifdef _WIN32_WCE
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
20
deps/cares/src/ares_gethostbyname.c
vendored
20
deps/cares/src/ares_gethostbyname.c
vendored
@@ -211,6 +211,13 @@ static void host_callback(void *arg, int status, int timeouts,
|
||||
if (host && channel->nsort)
|
||||
sort6_addresses(host, channel->sortlist, channel->nsort);
|
||||
}
|
||||
if (status == ARES_SUCCESS && host && host->h_addr_list[0] == NULL)
|
||||
{
|
||||
/* The query returned something but had no A/AAAA record
|
||||
(even after potentially retrying AAAA with A)
|
||||
so we should treat this as an error */
|
||||
status = ARES_ENODATA;
|
||||
}
|
||||
end_hquery(hquery, status, host);
|
||||
}
|
||||
else if ((status == ARES_ENODATA || status == ARES_EBADRESP ||
|
||||
@@ -267,12 +274,12 @@ static int fake_hostent(const char *name, int family,
|
||||
}
|
||||
|
||||
/* if we don't have 3 dots, it is illegal
|
||||
* (although inet_addr doesn't think so).
|
||||
* (although inet_pton doesn't think so).
|
||||
*/
|
||||
if (numdots != 3 || !valid)
|
||||
result = 0;
|
||||
else
|
||||
result = ((in.s_addr = inet_addr(name)) == INADDR_NONE ? 0 : 1);
|
||||
result = (ares_inet_pton(AF_INET, name, &in) < 1 ? 0 : 1);
|
||||
|
||||
if (result)
|
||||
family = AF_INET;
|
||||
@@ -346,10 +353,6 @@ static int file_lookup(const char *name, int family, struct hostent **host)
|
||||
int status;
|
||||
int error;
|
||||
|
||||
/* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */
|
||||
if (ares__is_onion_domain(name))
|
||||
return ARES_ENOTFOUND;
|
||||
|
||||
#ifdef WIN32
|
||||
char PATH_HOSTS[MAX_PATH];
|
||||
win_platform platform;
|
||||
@@ -387,6 +390,11 @@ static int file_lookup(const char *name, int family, struct hostent **host)
|
||||
return ARES_ENOTFOUND;
|
||||
#endif
|
||||
|
||||
/* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */
|
||||
if (ares__is_onion_domain(name))
|
||||
return ARES_ENOTFOUND;
|
||||
|
||||
|
||||
fp = fopen(PATH_HOSTS, "r");
|
||||
if (!fp)
|
||||
{
|
||||
|
||||
13
deps/cares/src/ares_init.c
vendored
13
deps/cares/src/ares_init.c
vendored
@@ -1543,8 +1543,6 @@ static int init_by_resolv_conf(ares_channel channel)
|
||||
|
||||
#elif defined(ANDROID) || defined(__ANDROID__)
|
||||
unsigned int i;
|
||||
char propname[PROP_NAME_MAX];
|
||||
char propvalue[PROP_VALUE_MAX]="";
|
||||
char **dns_servers;
|
||||
char *domains;
|
||||
size_t num_servers;
|
||||
@@ -1587,6 +1585,8 @@ static int init_by_resolv_conf(ares_channel channel)
|
||||
* 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) {
|
||||
@@ -2024,6 +2024,7 @@ static int config_lookup(ares_channel channel, const char *str,
|
||||
{
|
||||
char lookups[3], *l;
|
||||
const char *vqualifier p;
|
||||
int found;
|
||||
|
||||
if (altbindch == NULL)
|
||||
altbindch = bindch;
|
||||
@@ -2034,17 +2035,21 @@ static int config_lookup(ares_channel channel, const char *str,
|
||||
*/
|
||||
l = lookups;
|
||||
p = str;
|
||||
found = 0;
|
||||
while (*p)
|
||||
{
|
||||
if ((*p == *bindch || *p == *altbindch || *p == *filech) && l < lookups + 2) {
|
||||
if (*p == *bindch || *p == *altbindch) *l++ = 'b';
|
||||
else *l++ = 'f';
|
||||
found = 1;
|
||||
}
|
||||
while (*p && !ISSPACE(*p) && (*p != ','))
|
||||
p++;
|
||||
while (*p && (ISSPACE(*p) || (*p == ',')))
|
||||
p++;
|
||||
}
|
||||
if (!found)
|
||||
return ARES_ENOTINITIALIZED;
|
||||
*l = '\0';
|
||||
channel->lookups = ares_strdup(lookups);
|
||||
return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM;
|
||||
@@ -2418,9 +2423,9 @@ static int ip_addr(const char *ipbuf, ares_ssize_t len, struct in_addr *addr)
|
||||
if (len > 15)
|
||||
return -1;
|
||||
|
||||
addr->s_addr = inet_addr(ipbuf);
|
||||
if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0)
|
||||
if (ares_inet_pton(AF_INET, ipbuf, addr) < 1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
7
deps/cares/src/ares_ipv6.h
vendored
7
deps/cares/src/ares_ipv6.h
vendored
@@ -32,6 +32,13 @@ struct sockaddr_in6
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sa4;
|
||||
struct sockaddr_in6 sa6;
|
||||
} ares_sockaddr;
|
||||
|
||||
#ifndef HAVE_STRUCT_ADDRINFO
|
||||
struct addrinfo
|
||||
{
|
||||
|
||||
318
deps/cares/src/ares_parse_a_reply.c
vendored
318
deps/cares/src/ares_parse_a_reply.c
vendored
@@ -1,5 +1,6 @@
|
||||
|
||||
/* Copyright 1998 by the Massachusetts Institute of Technology.
|
||||
* Copyright (C) 2019 by Andrew Selivanov
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose and without
|
||||
@@ -50,215 +51,164 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
|
||||
struct hostent **host,
|
||||
struct ares_addrttl *addrttls, int *naddrttls)
|
||||
{
|
||||
unsigned int qdcount, ancount;
|
||||
int status, i, rr_type, rr_class, rr_len, rr_ttl, naddrs;
|
||||
int cname_ttl = INT_MAX; /* the TTL imposed by the CNAME chain */
|
||||
int naliases;
|
||||
long len;
|
||||
const unsigned char *aptr;
|
||||
char *hostname, *rr_name, *rr_data, **aliases;
|
||||
struct in_addr *addrs;
|
||||
struct hostent *hostent;
|
||||
const int max_addr_ttls = (addrttls && naddrttls) ? *naddrttls : 0;
|
||||
struct ares_addrinfo ai;
|
||||
struct ares_addrinfo_node *next;
|
||||
struct ares_addrinfo_cname *next_cname;
|
||||
char **aliases = NULL;
|
||||
char *question_hostname = NULL;
|
||||
struct hostent *hostent = NULL;
|
||||
struct in_addr *addrs = NULL;
|
||||
int naliases = 0, naddrs = 0, alias = 0, i;
|
||||
int cname_ttl = INT_MAX;
|
||||
int status;
|
||||
|
||||
/* Set *host to NULL for all failure cases. */
|
||||
if (host)
|
||||
*host = NULL;
|
||||
/* Same with *naddrttls. */
|
||||
if (naddrttls)
|
||||
*naddrttls = 0;
|
||||
memset(&ai, 0, sizeof(ai));
|
||||
|
||||
/* Give up if abuf doesn't have room for a header. */
|
||||
if (alen < HFIXEDSZ)
|
||||
return ARES_EBADRESP;
|
||||
|
||||
/* Fetch the question and answer count from the header. */
|
||||
qdcount = DNS_HEADER_QDCOUNT(abuf);
|
||||
ancount = DNS_HEADER_ANCOUNT(abuf);
|
||||
if (qdcount != 1)
|
||||
return ARES_EBADRESP;
|
||||
|
||||
/* Expand the name from the question, and skip past the question. */
|
||||
aptr = abuf + HFIXEDSZ;
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen, &hostname, &len);
|
||||
status = ares__parse_into_addrinfo2(abuf, alen, &question_hostname, &ai);
|
||||
if (status != ARES_SUCCESS)
|
||||
return status;
|
||||
if (aptr + len + QFIXEDSZ > abuf + alen)
|
||||
{
|
||||
ares_free(hostname);
|
||||
return ARES_EBADRESP;
|
||||
}
|
||||
aptr += len + QFIXEDSZ;
|
||||
ares_free(question_hostname);
|
||||
|
||||
if (host)
|
||||
if (naddrttls)
|
||||
{
|
||||
*naddrttls = 0;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
hostent = ares_malloc(sizeof(struct hostent));
|
||||
if (!hostent)
|
||||
{
|
||||
/* Allocate addresses and aliases; ancount gives an upper bound for
|
||||
both. */
|
||||
addrs = ares_malloc(ancount * sizeof(struct in_addr));
|
||||
if (!addrs)
|
||||
goto enomem;
|
||||
}
|
||||
|
||||
next = ai.nodes;
|
||||
while (next)
|
||||
{
|
||||
if (next->ai_family == AF_INET)
|
||||
{
|
||||
ares_free(hostname);
|
||||
return ARES_ENOMEM;
|
||||
++naddrs;
|
||||
}
|
||||
aliases = ares_malloc((ancount + 1) * sizeof(char *));
|
||||
if (!aliases)
|
||||
next = next->ai_next;
|
||||
}
|
||||
|
||||
next_cname = ai.cnames;
|
||||
while (next_cname)
|
||||
{
|
||||
if(next_cname->alias)
|
||||
++naliases;
|
||||
next_cname = next_cname->next;
|
||||
}
|
||||
|
||||
aliases = ares_malloc((naliases + 1) * sizeof(char *));
|
||||
if (!aliases)
|
||||
{
|
||||
goto enomem;
|
||||
}
|
||||
|
||||
if (naliases)
|
||||
{
|
||||
next_cname = ai.cnames;
|
||||
while (next_cname)
|
||||
{
|
||||
ares_free(hostname);
|
||||
ares_free(addrs);
|
||||
return ARES_ENOMEM;
|
||||
if(next_cname->alias)
|
||||
aliases[alias++] = strdup(next_cname->alias);
|
||||
if(next_cname->ttl < cname_ttl)
|
||||
cname_ttl = next_cname->ttl;
|
||||
next_cname = next_cname->next;
|
||||
}
|
||||
}
|
||||
|
||||
aliases[alias] = NULL;
|
||||
|
||||
hostent->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *));
|
||||
if (!hostent->h_addr_list)
|
||||
{
|
||||
goto enomem;
|
||||
}
|
||||
|
||||
for (i = 0; i < naddrs + 1; ++i)
|
||||
{
|
||||
hostent->h_addr_list[i] = NULL;
|
||||
}
|
||||
|
||||
if (ai.cnames)
|
||||
{
|
||||
hostent->h_name = strdup(ai.cnames->name);
|
||||
ares_free(question_hostname);
|
||||
}
|
||||
else
|
||||
{
|
||||
addrs = NULL;
|
||||
aliases = NULL;
|
||||
hostent->h_name = question_hostname;
|
||||
}
|
||||
|
||||
naddrs = 0;
|
||||
naliases = 0;
|
||||
hostent->h_aliases = aliases;
|
||||
hostent->h_addrtype = AF_INET;
|
||||
hostent->h_length = sizeof(struct in_addr);
|
||||
|
||||
/* Examine each answer resource record (RR) in turn. */
|
||||
for (i = 0; i < (int)ancount; i++)
|
||||
if (naddrs)
|
||||
{
|
||||
/* Decode the RR up to the data field. */
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len);
|
||||
if (status != ARES_SUCCESS)
|
||||
break;
|
||||
aptr += len;
|
||||
if (aptr + RRFIXEDSZ > abuf + alen)
|
||||
addrs = ares_malloc(naddrs * sizeof(struct in_addr));
|
||||
if (!addrs)
|
||||
{
|
||||
ares_free(rr_name);
|
||||
status = ARES_EBADRESP;
|
||||
break;
|
||||
}
|
||||
rr_type = DNS_RR_TYPE(aptr);
|
||||
rr_class = DNS_RR_CLASS(aptr);
|
||||
rr_len = DNS_RR_LEN(aptr);
|
||||
rr_ttl = DNS_RR_TTL(aptr);
|
||||
aptr += RRFIXEDSZ;
|
||||
if (aptr + rr_len > abuf + alen)
|
||||
{
|
||||
ares_free(rr_name);
|
||||
status = ARES_EBADRESP;
|
||||
break;
|
||||
goto enomem;
|
||||
}
|
||||
|
||||
if (rr_class == C_IN && rr_type == T_A
|
||||
&& rr_len == sizeof(struct in_addr)
|
||||
&& strcasecmp(rr_name, hostname) == 0)
|
||||
i = 0;
|
||||
next = ai.nodes;
|
||||
while (next)
|
||||
{
|
||||
if (addrs)
|
||||
if (next->ai_family == AF_INET)
|
||||
{
|
||||
if (aptr + sizeof(struct in_addr) > abuf + alen)
|
||||
{ /* LCOV_EXCL_START: already checked above */
|
||||
ares_free(rr_name);
|
||||
status = ARES_EBADRESP;
|
||||
break;
|
||||
} /* LCOV_EXCL_STOP */
|
||||
memcpy(&addrs[naddrs], aptr, sizeof(struct in_addr));
|
||||
}
|
||||
if (naddrs < max_addr_ttls)
|
||||
{
|
||||
struct ares_addrttl * const at = &addrttls[naddrs];
|
||||
if (aptr + sizeof(struct in_addr) > abuf + alen)
|
||||
{ /* LCOV_EXCL_START: already checked above */
|
||||
ares_free(rr_name);
|
||||
status = ARES_EBADRESP;
|
||||
break;
|
||||
} /* LCOV_EXCL_STOP */
|
||||
memcpy(&at->ipaddr, aptr, sizeof(struct in_addr));
|
||||
at->ttl = rr_ttl;
|
||||
}
|
||||
naddrs++;
|
||||
status = ARES_SUCCESS;
|
||||
}
|
||||
|
||||
if (rr_class == C_IN && rr_type == T_CNAME)
|
||||
{
|
||||
/* Record the RR name as an alias. */
|
||||
if (aliases)
|
||||
aliases[naliases] = rr_name;
|
||||
else
|
||||
ares_free(rr_name);
|
||||
naliases++;
|
||||
|
||||
/* Decode the RR data and replace the hostname with it. */
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data,
|
||||
&len);
|
||||
if (status != ARES_SUCCESS)
|
||||
break;
|
||||
ares_free(hostname);
|
||||
hostname = rr_data;
|
||||
|
||||
/* Take the min of the TTLs we see in the CNAME chain. */
|
||||
if (cname_ttl > rr_ttl)
|
||||
cname_ttl = rr_ttl;
|
||||
}
|
||||
else
|
||||
ares_free(rr_name);
|
||||
|
||||
aptr += rr_len;
|
||||
if (aptr > abuf + alen)
|
||||
{ /* LCOV_EXCL_START: already checked above */
|
||||
status = ARES_EBADRESP;
|
||||
break;
|
||||
} /* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
if (status == ARES_SUCCESS && naddrs == 0 && naliases == 0)
|
||||
/* the check for naliases to be zero is to make sure CNAME responses
|
||||
don't get caught here */
|
||||
status = ARES_ENODATA;
|
||||
if (status == ARES_SUCCESS)
|
||||
{
|
||||
/* We got our answer. */
|
||||
if (naddrttls)
|
||||
{
|
||||
const int n = naddrs < max_addr_ttls ? naddrs : max_addr_ttls;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
/* Ensure that each A TTL is no larger than the CNAME TTL. */
|
||||
if (addrttls[i].ttl > cname_ttl)
|
||||
addrttls[i].ttl = cname_ttl;
|
||||
}
|
||||
*naddrttls = n;
|
||||
}
|
||||
if (aliases)
|
||||
aliases[naliases] = NULL;
|
||||
if (host)
|
||||
{
|
||||
/* Allocate memory to build the host entry. */
|
||||
hostent = ares_malloc(sizeof(struct hostent));
|
||||
if (hostent)
|
||||
{
|
||||
hostent->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *));
|
||||
if (hostent->h_addr_list)
|
||||
hostent->h_addr_list[i] = (char *)&addrs[i];
|
||||
memcpy(hostent->h_addr_list[i],
|
||||
&(((struct sockaddr_in *)next->ai_addr)->sin_addr),
|
||||
sizeof(struct in_addr));
|
||||
if (naddrttls && i < *naddrttls)
|
||||
{
|
||||
/* Fill in the hostent and return successfully. */
|
||||
hostent->h_name = hostname;
|
||||
hostent->h_aliases = aliases;
|
||||
hostent->h_addrtype = AF_INET;
|
||||
hostent->h_length = sizeof(struct in_addr);
|
||||
for (i = 0; i < naddrs; i++)
|
||||
hostent->h_addr_list[i] = (char *) &addrs[i];
|
||||
hostent->h_addr_list[naddrs] = NULL;
|
||||
if (!naddrs && addrs)
|
||||
ares_free(addrs);
|
||||
*host = hostent;
|
||||
return ARES_SUCCESS;
|
||||
if (next->ai_ttl > cname_ttl)
|
||||
addrttls[i].ttl = cname_ttl;
|
||||
else
|
||||
addrttls[i].ttl = next->ai_ttl;
|
||||
|
||||
memcpy(&addrttls[i].ipaddr,
|
||||
&(((struct sockaddr_in *)next->ai_addr)->sin_addr),
|
||||
sizeof(struct in_addr));
|
||||
}
|
||||
ares_free(hostent);
|
||||
++i;
|
||||
}
|
||||
status = ARES_ENOMEM;
|
||||
next = next->ai_next;
|
||||
}
|
||||
if (i == 0)
|
||||
{
|
||||
ares_free(addrs);
|
||||
}
|
||||
}
|
||||
if (aliases)
|
||||
{
|
||||
for (i = 0; i < naliases; i++)
|
||||
ares_free(aliases[i]);
|
||||
ares_free(aliases);
|
||||
}
|
||||
ares_free(addrs);
|
||||
ares_free(hostname);
|
||||
return status;
|
||||
|
||||
if (host)
|
||||
{
|
||||
*host = hostent;
|
||||
}
|
||||
else
|
||||
{
|
||||
ares_free_hostent(hostent);
|
||||
}
|
||||
|
||||
if (naddrttls)
|
||||
{
|
||||
*naddrttls = naddrs;
|
||||
}
|
||||
|
||||
ares__freeaddrinfo_cnames(ai.cnames);
|
||||
ares__freeaddrinfo_nodes(ai.nodes);
|
||||
return ARES_SUCCESS;
|
||||
|
||||
enomem:
|
||||
ares_free(aliases);
|
||||
ares_free(hostent);
|
||||
ares__freeaddrinfo_cnames(ai.cnames);
|
||||
ares__freeaddrinfo_nodes(ai.nodes);
|
||||
ares_free(question_hostname);
|
||||
return ARES_ENOMEM;
|
||||
}
|
||||
|
||||
317
deps/cares/src/ares_parse_aaaa_reply.c
vendored
317
deps/cares/src/ares_parse_aaaa_reply.c
vendored
@@ -1,6 +1,7 @@
|
||||
|
||||
/* Copyright 1998 by the Massachusetts Institute of Technology.
|
||||
* Copyright 2005 Dominick Meglio
|
||||
* Copyright (C) 2019 by Andrew Selivanov
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose and without
|
||||
@@ -52,213 +53,165 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
|
||||
struct hostent **host, struct ares_addr6ttl *addrttls,
|
||||
int *naddrttls)
|
||||
{
|
||||
unsigned int qdcount, ancount;
|
||||
int status, i, rr_type, rr_class, rr_len, rr_ttl, naddrs;
|
||||
int cname_ttl = INT_MAX; /* the TTL imposed by the CNAME chain */
|
||||
int naliases;
|
||||
long len;
|
||||
const unsigned char *aptr;
|
||||
char *hostname, *rr_name, *rr_data, **aliases;
|
||||
struct ares_in6_addr *addrs;
|
||||
struct hostent *hostent;
|
||||
const int max_addr_ttls = (addrttls && naddrttls) ? *naddrttls : 0;
|
||||
struct ares_addrinfo ai;
|
||||
struct ares_addrinfo_node *next;
|
||||
struct ares_addrinfo_cname *next_cname;
|
||||
char **aliases = NULL;
|
||||
char *question_hostname = NULL;
|
||||
struct hostent *hostent = NULL;
|
||||
struct ares_in6_addr *addrs = NULL;
|
||||
int naliases = 0, naddrs = 0, alias = 0, i;
|
||||
int cname_ttl = INT_MAX;
|
||||
int status;
|
||||
|
||||
/* Set *host to NULL for all failure cases. */
|
||||
if (host)
|
||||
*host = NULL;
|
||||
/* Same with *naddrttls. */
|
||||
if (naddrttls)
|
||||
*naddrttls = 0;
|
||||
memset(&ai, 0, sizeof(ai));
|
||||
|
||||
/* Give up if abuf doesn't have room for a header. */
|
||||
if (alen < HFIXEDSZ)
|
||||
return ARES_EBADRESP;
|
||||
|
||||
/* Fetch the question and answer count from the header. */
|
||||
qdcount = DNS_HEADER_QDCOUNT(abuf);
|
||||
ancount = DNS_HEADER_ANCOUNT(abuf);
|
||||
if (qdcount != 1)
|
||||
return ARES_EBADRESP;
|
||||
|
||||
/* Expand the name from the question, and skip past the question. */
|
||||
aptr = abuf + HFIXEDSZ;
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen, &hostname, &len);
|
||||
status = ares__parse_into_addrinfo2(abuf, alen, &question_hostname, &ai);
|
||||
if (status != ARES_SUCCESS)
|
||||
return status;
|
||||
if (aptr + len + QFIXEDSZ > abuf + alen)
|
||||
{
|
||||
ares_free(hostname);
|
||||
return ARES_EBADRESP;
|
||||
}
|
||||
aptr += len + QFIXEDSZ;
|
||||
ares_free(question_hostname);
|
||||
|
||||
/* Allocate addresses and aliases; ancount gives an upper bound for both. */
|
||||
if (host)
|
||||
if (naddrttls)
|
||||
{
|
||||
*naddrttls = 0;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
hostent = ares_malloc(sizeof(struct hostent));
|
||||
if (!hostent)
|
||||
{
|
||||
addrs = ares_malloc(ancount * sizeof(struct ares_in6_addr));
|
||||
if (!addrs)
|
||||
goto enomem;
|
||||
}
|
||||
|
||||
next = ai.nodes;
|
||||
while (next)
|
||||
{
|
||||
if(next->ai_family == AF_INET6)
|
||||
{
|
||||
ares_free(hostname);
|
||||
return ARES_ENOMEM;
|
||||
++naddrs;
|
||||
}
|
||||
aliases = ares_malloc((ancount + 1) * sizeof(char *));
|
||||
if (!aliases)
|
||||
next = next->ai_next;
|
||||
}
|
||||
|
||||
next_cname = ai.cnames;
|
||||
while (next_cname)
|
||||
{
|
||||
if(next_cname->alias)
|
||||
++naliases;
|
||||
next_cname = next_cname->next;
|
||||
}
|
||||
|
||||
aliases = ares_malloc((naliases + 1) * sizeof(char *));
|
||||
if (!aliases)
|
||||
{
|
||||
goto enomem;
|
||||
}
|
||||
|
||||
if (naliases)
|
||||
{
|
||||
next_cname = ai.cnames;
|
||||
while (next_cname)
|
||||
{
|
||||
ares_free(hostname);
|
||||
ares_free(addrs);
|
||||
return ARES_ENOMEM;
|
||||
if(next_cname->alias)
|
||||
aliases[alias++] = strdup(next_cname->alias);
|
||||
if(next_cname->ttl < cname_ttl)
|
||||
cname_ttl = next_cname->ttl;
|
||||
next_cname = next_cname->next;
|
||||
}
|
||||
}
|
||||
|
||||
aliases[alias] = NULL;
|
||||
|
||||
hostent->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *));
|
||||
if (!hostent->h_addr_list)
|
||||
{
|
||||
goto enomem;
|
||||
}
|
||||
|
||||
for (i = 0; i < naddrs + 1; ++i)
|
||||
{
|
||||
hostent->h_addr_list[i] = NULL;
|
||||
}
|
||||
|
||||
if (ai.cnames)
|
||||
{
|
||||
hostent->h_name = strdup(ai.cnames->name);
|
||||
ares_free(question_hostname);
|
||||
}
|
||||
else
|
||||
{
|
||||
addrs = NULL;
|
||||
aliases = NULL;
|
||||
}
|
||||
naddrs = 0;
|
||||
naliases = 0;
|
||||
|
||||
/* Examine each answer resource record (RR) in turn. */
|
||||
for (i = 0; i < (int)ancount; i++)
|
||||
{
|
||||
/* Decode the RR up to the data field. */
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len);
|
||||
if (status != ARES_SUCCESS)
|
||||
break;
|
||||
aptr += len;
|
||||
if (aptr + RRFIXEDSZ > abuf + alen)
|
||||
{
|
||||
ares_free(rr_name);
|
||||
status = ARES_EBADRESP;
|
||||
break;
|
||||
}
|
||||
rr_type = DNS_RR_TYPE(aptr);
|
||||
rr_class = DNS_RR_CLASS(aptr);
|
||||
rr_len = DNS_RR_LEN(aptr);
|
||||
rr_ttl = DNS_RR_TTL(aptr);
|
||||
aptr += RRFIXEDSZ;
|
||||
if (aptr + rr_len > abuf + alen)
|
||||
{
|
||||
ares_free(rr_name);
|
||||
status = ARES_EBADRESP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rr_class == C_IN && rr_type == T_AAAA
|
||||
&& rr_len == sizeof(struct ares_in6_addr)
|
||||
&& strcasecmp(rr_name, hostname) == 0)
|
||||
{
|
||||
if (addrs)
|
||||
{
|
||||
if (aptr + sizeof(struct ares_in6_addr) > abuf + alen)
|
||||
{ /* LCOV_EXCL_START: already checked above */
|
||||
ares_free(rr_name);
|
||||
status = ARES_EBADRESP;
|
||||
break;
|
||||
} /* LCOV_EXCL_STOP */
|
||||
memcpy(&addrs[naddrs], aptr, sizeof(struct ares_in6_addr));
|
||||
}
|
||||
if (naddrs < max_addr_ttls)
|
||||
{
|
||||
struct ares_addr6ttl * const at = &addrttls[naddrs];
|
||||
if (aptr + sizeof(struct ares_in6_addr) > abuf + alen)
|
||||
{ /* LCOV_EXCL_START: already checked above */
|
||||
ares_free(rr_name);
|
||||
status = ARES_EBADRESP;
|
||||
break;
|
||||
} /* LCOV_EXCL_STOP */
|
||||
memcpy(&at->ip6addr, aptr, sizeof(struct ares_in6_addr));
|
||||
at->ttl = rr_ttl;
|
||||
}
|
||||
naddrs++;
|
||||
status = ARES_SUCCESS;
|
||||
}
|
||||
|
||||
if (rr_class == C_IN && rr_type == T_CNAME)
|
||||
{
|
||||
/* Record the RR name as an alias. */
|
||||
if (aliases)
|
||||
aliases[naliases] = rr_name;
|
||||
else
|
||||
ares_free(rr_name);
|
||||
naliases++;
|
||||
|
||||
/* Decode the RR data and replace the hostname with it. */
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data,
|
||||
&len);
|
||||
if (status != ARES_SUCCESS)
|
||||
break;
|
||||
ares_free(hostname);
|
||||
hostname = rr_data;
|
||||
|
||||
/* Take the min of the TTLs we see in the CNAME chain. */
|
||||
if (cname_ttl > rr_ttl)
|
||||
cname_ttl = rr_ttl;
|
||||
}
|
||||
else
|
||||
ares_free(rr_name);
|
||||
|
||||
aptr += rr_len;
|
||||
if (aptr > abuf + alen)
|
||||
{ /* LCOV_EXCL_START: already checked above */
|
||||
status = ARES_EBADRESP;
|
||||
break;
|
||||
} /* LCOV_EXCL_STOP */
|
||||
hostent->h_name = question_hostname;
|
||||
}
|
||||
|
||||
/* the check for naliases to be zero is to make sure CNAME responses
|
||||
don't get caught here */
|
||||
if (status == ARES_SUCCESS && naddrs == 0 && naliases == 0)
|
||||
status = ARES_ENODATA;
|
||||
if (status == ARES_SUCCESS)
|
||||
hostent->h_aliases = aliases;
|
||||
hostent->h_addrtype = AF_INET6;
|
||||
hostent->h_length = sizeof(struct ares_in6_addr);
|
||||
|
||||
if (naddrs)
|
||||
{
|
||||
/* We got our answer. */
|
||||
if (naddrttls)
|
||||
addrs = ares_malloc(naddrs * sizeof(struct ares_in6_addr));
|
||||
if (!addrs)
|
||||
{
|
||||
const int n = naddrs < max_addr_ttls ? naddrs : max_addr_ttls;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
/* Ensure that each A TTL is no larger than the CNAME TTL. */
|
||||
if (addrttls[i].ttl > cname_ttl)
|
||||
addrttls[i].ttl = cname_ttl;
|
||||
}
|
||||
*naddrttls = n;
|
||||
goto enomem;
|
||||
}
|
||||
if (aliases)
|
||||
aliases[naliases] = NULL;
|
||||
if (host)
|
||||
|
||||
i = 0;
|
||||
next = ai.nodes;
|
||||
while (next)
|
||||
{
|
||||
/* Allocate memory to build the host entry. */
|
||||
hostent = ares_malloc(sizeof(struct hostent));
|
||||
if (hostent)
|
||||
if(next->ai_family == AF_INET6)
|
||||
{
|
||||
hostent->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *));
|
||||
if (hostent->h_addr_list)
|
||||
hostent->h_addr_list[i] = (char*)&addrs[i];
|
||||
memcpy(hostent->h_addr_list[i],
|
||||
&(((struct sockaddr_in6 *)next->ai_addr)->sin6_addr),
|
||||
sizeof(struct ares_in6_addr));
|
||||
if (naddrttls && i < *naddrttls)
|
||||
{
|
||||
/* Fill in the hostent and return successfully. */
|
||||
hostent->h_name = hostname;
|
||||
hostent->h_aliases = aliases;
|
||||
hostent->h_addrtype = AF_INET6;
|
||||
hostent->h_length = sizeof(struct ares_in6_addr);
|
||||
for (i = 0; i < naddrs; i++)
|
||||
hostent->h_addr_list[i] = (char *) &addrs[i];
|
||||
hostent->h_addr_list[naddrs] = NULL;
|
||||
if (!naddrs && addrs)
|
||||
ares_free(addrs);
|
||||
*host = hostent;
|
||||
return ARES_SUCCESS;
|
||||
if(next->ai_ttl > cname_ttl)
|
||||
addrttls[i].ttl = cname_ttl;
|
||||
else
|
||||
addrttls[i].ttl = next->ai_ttl;
|
||||
|
||||
memcpy(&addrttls[i].ip6addr,
|
||||
&(((struct sockaddr_in6 *)next->ai_addr)->sin6_addr),
|
||||
sizeof(struct ares_in6_addr));
|
||||
}
|
||||
ares_free(hostent);
|
||||
++i;
|
||||
}
|
||||
status = ARES_ENOMEM;
|
||||
next = next->ai_next;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
ares_free(addrs);
|
||||
}
|
||||
}
|
||||
if (aliases)
|
||||
|
||||
if (host)
|
||||
{
|
||||
for (i = 0; i < naliases; i++)
|
||||
ares_free(aliases[i]);
|
||||
ares_free(aliases);
|
||||
*host = hostent;
|
||||
}
|
||||
ares_free(addrs);
|
||||
ares_free(hostname);
|
||||
return status;
|
||||
else
|
||||
{
|
||||
ares_free_hostent(hostent);
|
||||
}
|
||||
|
||||
if (naddrttls)
|
||||
{
|
||||
*naddrttls = naddrs;
|
||||
}
|
||||
|
||||
ares__freeaddrinfo_cnames(ai.cnames);
|
||||
ares__freeaddrinfo_nodes(ai.nodes);
|
||||
return ARES_SUCCESS;
|
||||
|
||||
enomem:
|
||||
ares_free(aliases);
|
||||
ares_free(hostent);
|
||||
ares__freeaddrinfo_cnames(ai.cnames);
|
||||
ares__freeaddrinfo_nodes(ai.nodes);
|
||||
ares_free(question_hostname);
|
||||
return ARES_ENOMEM;
|
||||
}
|
||||
|
||||
133
deps/cares/src/ares_parse_soa_reply.c
vendored
133
deps/cares/src/ares_parse_soa_reply.c
vendored
@@ -48,8 +48,8 @@ ares_parse_soa_reply(const unsigned char *abuf, int alen,
|
||||
long len;
|
||||
char *qname = NULL, *rr_name = NULL;
|
||||
struct ares_soa_reply *soa = NULL;
|
||||
int qdcount, ancount;
|
||||
int status;
|
||||
int qdcount, ancount, qclass;
|
||||
int status, i, rr_type, rr_class, rr_len;
|
||||
|
||||
if (alen < HFIXEDSZ)
|
||||
return ARES_EBADRESP;
|
||||
@@ -57,8 +57,12 @@ ares_parse_soa_reply(const unsigned char *abuf, int alen,
|
||||
/* parse message header */
|
||||
qdcount = DNS_HEADER_QDCOUNT(abuf);
|
||||
ancount = DNS_HEADER_ANCOUNT(abuf);
|
||||
if (qdcount != 1 || ancount != 1)
|
||||
|
||||
if (qdcount != 1)
|
||||
return ARES_EBADRESP;
|
||||
if (ancount == 0)
|
||||
return ARES_EBADRESP;
|
||||
|
||||
aptr = abuf + HFIXEDSZ;
|
||||
|
||||
/* query name */
|
||||
@@ -67,67 +71,112 @@ ares_parse_soa_reply(const unsigned char *abuf, int alen,
|
||||
goto failed_stat;
|
||||
aptr += len;
|
||||
|
||||
qclass = DNS_QUESTION_TYPE(aptr);
|
||||
|
||||
/* skip qtype & qclass */
|
||||
if (aptr + QFIXEDSZ > abuf + alen)
|
||||
goto failed;
|
||||
aptr += QFIXEDSZ;
|
||||
|
||||
/* rr_name */
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len);
|
||||
if (status != ARES_SUCCESS)
|
||||
goto failed_stat;
|
||||
aptr += len;
|
||||
|
||||
/* skip rr_type, rr_class, rr_ttl, rr_rdlen */
|
||||
if (aptr + RRFIXEDSZ > abuf + alen)
|
||||
/* qclass of SOA with multiple answers */
|
||||
if (qclass == T_SOA && ancount > 1)
|
||||
goto failed;
|
||||
aptr += RRFIXEDSZ;
|
||||
|
||||
/* allocate result struct */
|
||||
soa = ares_malloc_data(ARES_DATATYPE_SOA_REPLY);
|
||||
if (!soa)
|
||||
/* examine all the records, break and return if found soa */
|
||||
for (i = 0; i < ancount; i++)
|
||||
{
|
||||
rr_name = NULL;
|
||||
status = ares__expand_name_for_response (aptr, abuf, alen, &rr_name, &len);
|
||||
if (status != ARES_SUCCESS)
|
||||
{
|
||||
ares_free(rr_name);
|
||||
goto failed_stat;
|
||||
}
|
||||
|
||||
aptr += len;
|
||||
if ( aptr + RRFIXEDSZ > abuf + alen )
|
||||
{
|
||||
status = ARES_ENOMEM;
|
||||
ares_free(rr_name);
|
||||
status = ARES_EBADRESP;
|
||||
goto failed_stat;
|
||||
}
|
||||
rr_type = DNS_RR_TYPE( aptr );
|
||||
rr_class = DNS_RR_CLASS( aptr );
|
||||
rr_len = DNS_RR_LEN( aptr );
|
||||
aptr += RRFIXEDSZ;
|
||||
if (aptr + rr_len > abuf + alen)
|
||||
{
|
||||
ares_free(rr_name);
|
||||
status = ARES_EBADRESP;
|
||||
goto failed_stat;
|
||||
}
|
||||
if ( rr_class == C_IN && rr_type == T_SOA )
|
||||
{
|
||||
/* allocate result struct */
|
||||
soa = ares_malloc_data(ARES_DATATYPE_SOA_REPLY);
|
||||
if (!soa)
|
||||
{
|
||||
ares_free(rr_name);
|
||||
status = ARES_ENOMEM;
|
||||
goto failed_stat;
|
||||
}
|
||||
|
||||
/* nsname */
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen, &soa->nsname, &len);
|
||||
if (status != ARES_SUCCESS)
|
||||
goto failed_stat;
|
||||
aptr += len;
|
||||
/* nsname */
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen, &soa->nsname,
|
||||
&len);
|
||||
if (status != ARES_SUCCESS)
|
||||
{
|
||||
ares_free(rr_name);
|
||||
goto failed_stat;
|
||||
}
|
||||
aptr += len;
|
||||
|
||||
/* hostmaster */
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen, &soa->hostmaster, &len);
|
||||
if (status != ARES_SUCCESS)
|
||||
goto failed_stat;
|
||||
aptr += len;
|
||||
/* hostmaster */
|
||||
status = ares__expand_name_for_response(aptr, abuf, alen,
|
||||
&soa->hostmaster, &len);
|
||||
if (status != ARES_SUCCESS)
|
||||
{
|
||||
ares_free(rr_name);
|
||||
goto failed_stat;
|
||||
}
|
||||
aptr += len;
|
||||
|
||||
/* integer fields */
|
||||
if (aptr + 5 * 4 > abuf + alen)
|
||||
goto failed;
|
||||
soa->serial = DNS__32BIT(aptr + 0 * 4);
|
||||
soa->refresh = DNS__32BIT(aptr + 1 * 4);
|
||||
soa->retry = DNS__32BIT(aptr + 2 * 4);
|
||||
soa->expire = DNS__32BIT(aptr + 3 * 4);
|
||||
soa->minttl = DNS__32BIT(aptr + 4 * 4);
|
||||
/* integer fields */
|
||||
if (aptr + 5 * 4 > abuf + alen)
|
||||
{
|
||||
ares_free(rr_name);
|
||||
goto failed;
|
||||
}
|
||||
soa->serial = DNS__32BIT(aptr + 0 * 4);
|
||||
soa->refresh = DNS__32BIT(aptr + 1 * 4);
|
||||
soa->retry = DNS__32BIT(aptr + 2 * 4);
|
||||
soa->expire = DNS__32BIT(aptr + 3 * 4);
|
||||
soa->minttl = DNS__32BIT(aptr + 4 * 4);
|
||||
|
||||
ares_free(qname);
|
||||
ares_free(rr_name);
|
||||
ares_free(qname);
|
||||
ares_free(rr_name);
|
||||
|
||||
*soa_out = soa;
|
||||
*soa_out = soa;
|
||||
|
||||
return ARES_SUCCESS;
|
||||
return ARES_SUCCESS;
|
||||
}
|
||||
aptr += rr_len;
|
||||
|
||||
ares_free(rr_name);
|
||||
|
||||
if (aptr > abuf + alen)
|
||||
goto failed_stat;
|
||||
}
|
||||
/* no SOA record found */
|
||||
status = ARES_EBADRESP;
|
||||
goto failed_stat;
|
||||
failed:
|
||||
status = ARES_EBADRESP;
|
||||
|
||||
failed_stat:
|
||||
ares_free_data(soa);
|
||||
if (soa)
|
||||
ares_free_data(soa);
|
||||
if (qname)
|
||||
ares_free(qname);
|
||||
if (rr_name)
|
||||
ares_free(rr_name);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
42
deps/cares/src/ares_private.h
vendored
42
deps/cares/src/ares_private.h
vendored
@@ -355,11 +355,51 @@ int ares__expand_name_for_response(const unsigned char *encoded,
|
||||
char **s, long *enclen);
|
||||
void ares__init_servers_state(ares_channel channel);
|
||||
void ares__destroy_servers_state(ares_channel channel);
|
||||
int ares__parse_qtype_reply(const unsigned char* abuf, int alen, int* qtype);
|
||||
int ares__single_domain(ares_channel channel, const char *name, char **s);
|
||||
int ares__cat_domain(const char *name, const char *domain, char **s);
|
||||
int ares__sortaddrinfo(ares_channel channel, struct ares_addrinfo_node *ai_node);
|
||||
int ares__readaddrinfo(FILE *fp, const char *name, unsigned short port,
|
||||
const struct ares_addrinfo_hints *hints,
|
||||
struct ares_addrinfo *ai);
|
||||
|
||||
struct ares_addrinfo *ares__malloc_addrinfo(void);
|
||||
|
||||
struct ares_addrinfo_node *ares__malloc_addrinfo_node(void);
|
||||
void ares__freeaddrinfo_nodes(struct ares_addrinfo_node *ai_node);
|
||||
|
||||
struct ares_addrinfo_node *ares__append_addrinfo_node(struct ares_addrinfo_node **ai_node);
|
||||
void ares__addrinfo_cat_nodes(struct ares_addrinfo_node **head,
|
||||
struct ares_addrinfo_node *tail);
|
||||
|
||||
struct ares_addrinfo_cname *ares__malloc_addrinfo_cname(void);
|
||||
void ares__freeaddrinfo_cnames(struct ares_addrinfo_cname *ai_cname);
|
||||
|
||||
struct ares_addrinfo_cname *ares__append_addrinfo_cname(struct ares_addrinfo_cname **ai_cname);
|
||||
|
||||
void ares__addrinfo_cat_cnames(struct ares_addrinfo_cname **head,
|
||||
struct ares_addrinfo_cname *tail);
|
||||
|
||||
int ares__parse_into_addrinfo(const unsigned char *abuf,
|
||||
int alen,
|
||||
struct ares_addrinfo *ai);
|
||||
|
||||
int ares__parse_into_addrinfo2(const unsigned char *abuf,
|
||||
int alen,
|
||||
char **question_hostname,
|
||||
struct ares_addrinfo *ai);
|
||||
|
||||
#if 0 /* Not used */
|
||||
long ares__tvdiff(struct timeval t1, struct timeval t2);
|
||||
#endif
|
||||
|
||||
void ares__socket_close(ares_channel, ares_socket_t);
|
||||
ares_socket_t ares__open_socket(ares_channel channel,
|
||||
int af, int type, int protocol);
|
||||
void ares__close_socket(ares_channel, ares_socket_t);
|
||||
int ares__connect_socket(ares_channel channel,
|
||||
ares_socket_t sockfd,
|
||||
const struct sockaddr *addr,
|
||||
ares_socklen_t addrlen);
|
||||
|
||||
#define ARES_SWAP_BYTE(a,b) \
|
||||
{ unsigned char swapByte = *(a); *(a) = *(b); *(b) = swapByte; }
|
||||
|
||||
78
deps/cares/src/ares_process.c
vendored
78
deps/cares/src/ares_process.c
vendored
@@ -1039,30 +1039,6 @@ static int configure_socket(ares_socket_t s, int family, ares_channel channel)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ares_socket_t open_socket(ares_channel channel, int af, int type, int protocol)
|
||||
{
|
||||
if (channel->sock_funcs != 0)
|
||||
return channel->sock_funcs->asocket(af,
|
||||
type,
|
||||
protocol,
|
||||
channel->sock_func_cb_data);
|
||||
|
||||
return socket(af, type, protocol);
|
||||
}
|
||||
|
||||
static int connect_socket(ares_channel channel, ares_socket_t sockfd,
|
||||
const struct sockaddr * addr,
|
||||
ares_socklen_t addrlen)
|
||||
{
|
||||
if (channel->sock_funcs != 0)
|
||||
return channel->sock_funcs->aconnect(sockfd,
|
||||
addr,
|
||||
addrlen,
|
||||
channel->sock_func_cb_data);
|
||||
|
||||
return connect(sockfd, addr, addrlen);
|
||||
}
|
||||
|
||||
static int open_tcp_socket(ares_channel channel, struct server_state *server)
|
||||
{
|
||||
ares_socket_t s;
|
||||
@@ -1107,14 +1083,14 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
|
||||
}
|
||||
|
||||
/* Acquire a socket. */
|
||||
s = open_socket(channel, server->addr.family, SOCK_STREAM, 0);
|
||||
s = ares__open_socket(channel, server->addr.family, SOCK_STREAM, 0);
|
||||
if (s == ARES_SOCKET_BAD)
|
||||
return -1;
|
||||
|
||||
/* Configure it. */
|
||||
if (configure_socket(s, server->addr.family, channel) < 0)
|
||||
{
|
||||
ares__socket_close(channel, s);
|
||||
ares__close_socket(channel, s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1131,7 +1107,7 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
|
||||
setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
|
||||
(void *)&opt, sizeof(opt)) == -1)
|
||||
{
|
||||
ares__socket_close(channel, s);
|
||||
ares__close_socket(channel, s);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@@ -1142,19 +1118,19 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
|
||||
channel->sock_config_cb_data);
|
||||
if (err < 0)
|
||||
{
|
||||
ares__socket_close(channel, s);
|
||||
ares__close_socket(channel, s);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Connect to the server. */
|
||||
if (connect_socket(channel, s, sa, salen) == -1)
|
||||
if (ares__connect_socket(channel, s, sa, salen) == -1)
|
||||
{
|
||||
int err = SOCKERRNO;
|
||||
|
||||
if (err != EINPROGRESS && err != EWOULDBLOCK)
|
||||
{
|
||||
ares__socket_close(channel, s);
|
||||
ares__close_socket(channel, s);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1165,7 +1141,7 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
|
||||
channel->sock_create_cb_data);
|
||||
if (err < 0)
|
||||
{
|
||||
ares__socket_close(channel, s);
|
||||
ares__close_socket(channel, s);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@@ -1220,14 +1196,14 @@ static int open_udp_socket(ares_channel channel, struct server_state *server)
|
||||
}
|
||||
|
||||
/* Acquire a socket. */
|
||||
s = open_socket(channel, server->addr.family, SOCK_DGRAM, 0);
|
||||
s = ares__open_socket(channel, server->addr.family, SOCK_DGRAM, 0);
|
||||
if (s == ARES_SOCKET_BAD)
|
||||
return -1;
|
||||
|
||||
/* Set the socket non-blocking. */
|
||||
if (configure_socket(s, server->addr.family, channel) < 0)
|
||||
{
|
||||
ares__socket_close(channel, s);
|
||||
ares__close_socket(channel, s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1237,19 +1213,19 @@ static int open_udp_socket(ares_channel channel, struct server_state *server)
|
||||
channel->sock_config_cb_data);
|
||||
if (err < 0)
|
||||
{
|
||||
ares__socket_close(channel, s);
|
||||
ares__close_socket(channel, s);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Connect to the server. */
|
||||
if (connect_socket(channel, s, sa, salen) == -1)
|
||||
if (ares__connect_socket(channel, s, sa, salen) == -1)
|
||||
{
|
||||
int err = SOCKERRNO;
|
||||
|
||||
if (err != EINPROGRESS && err != EWOULDBLOCK)
|
||||
{
|
||||
ares__socket_close(channel, s);
|
||||
ares__close_socket(channel, s);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1260,7 +1236,7 @@ static int open_udp_socket(ares_channel channel, struct server_state *server)
|
||||
channel->sock_create_cb_data);
|
||||
if (err < 0)
|
||||
{
|
||||
ares__socket_close(channel, s);
|
||||
ares__close_socket(channel, s);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@@ -1464,7 +1440,33 @@ void ares__free_query(struct query *query)
|
||||
ares_free(query);
|
||||
}
|
||||
|
||||
void ares__socket_close(ares_channel channel, ares_socket_t s)
|
||||
ares_socket_t ares__open_socket(ares_channel channel,
|
||||
int af, int type, int protocol)
|
||||
{
|
||||
if (channel->sock_funcs)
|
||||
return channel->sock_funcs->asocket(af,
|
||||
type,
|
||||
protocol,
|
||||
channel->sock_func_cb_data);
|
||||
else
|
||||
return socket(af, type, protocol);
|
||||
}
|
||||
|
||||
int ares__connect_socket(ares_channel channel,
|
||||
ares_socket_t sockfd,
|
||||
const struct sockaddr *addr,
|
||||
ares_socklen_t addrlen)
|
||||
{
|
||||
if (channel->sock_funcs)
|
||||
return channel->sock_funcs->aconnect(sockfd,
|
||||
addr,
|
||||
addrlen,
|
||||
channel->sock_func_cb_data);
|
||||
else
|
||||
return connect(sockfd, addr, addrlen);
|
||||
}
|
||||
|
||||
void ares__close_socket(ares_channel channel, ares_socket_t s)
|
||||
{
|
||||
if (channel->sock_funcs)
|
||||
channel->sock_funcs->aclose(s, channel->sock_func_cb_data);
|
||||
|
||||
12
deps/cares/src/ares_search.c
vendored
12
deps/cares/src/ares_search.c
vendored
@@ -43,8 +43,6 @@ static void search_callback(void *arg, int status, int timeouts,
|
||||
unsigned char *abuf, int alen);
|
||||
static void end_squery(struct search_query *squery, int status,
|
||||
unsigned char *abuf, int alen);
|
||||
static int cat_domain(const char *name, const char *domain, char **s);
|
||||
STATIC_TESTABLE int single_domain(ares_channel channel, const char *name, char **s);
|
||||
|
||||
void ares_search(ares_channel channel, const char *name, int dnsclass,
|
||||
int type, ares_callback callback, void *arg)
|
||||
@@ -64,7 +62,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
|
||||
/* If name only yields one domain to search, then we don't have
|
||||
* to keep extra state, so just do an ares_query().
|
||||
*/
|
||||
status = single_domain(channel, name, &s);
|
||||
status = ares__single_domain(channel, name, &s);
|
||||
if (status != ARES_SUCCESS)
|
||||
{
|
||||
callback(arg, status, 0, NULL, 0);
|
||||
@@ -126,7 +124,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
|
||||
/* Try the name as-is last; start with the first search domain. */
|
||||
squery->next_domain = 1;
|
||||
squery->trying_as_is = 0;
|
||||
status = cat_domain(name, channel->domains[0], &s);
|
||||
status = ares__cat_domain(name, channel->domains[0], &s);
|
||||
if (status == ARES_SUCCESS)
|
||||
{
|
||||
ares_query(channel, s, dnsclass, type, search_callback, squery);
|
||||
@@ -174,7 +172,7 @@ static void search_callback(void *arg, int status, int timeouts,
|
||||
if (squery->next_domain < channel->ndomains)
|
||||
{
|
||||
/* Try the next domain. */
|
||||
status = cat_domain(squery->name,
|
||||
status = ares__cat_domain(squery->name,
|
||||
channel->domains[squery->next_domain], &s);
|
||||
if (status != ARES_SUCCESS)
|
||||
end_squery(squery, status, NULL, 0);
|
||||
@@ -213,7 +211,7 @@ static void end_squery(struct search_query *squery, int status,
|
||||
}
|
||||
|
||||
/* Concatenate two domains. */
|
||||
static int cat_domain(const char *name, const char *domain, char **s)
|
||||
int ares__cat_domain(const char *name, const char *domain, char **s)
|
||||
{
|
||||
size_t nlen = strlen(name);
|
||||
size_t dlen = strlen(domain);
|
||||
@@ -232,7 +230,7 @@ static int cat_domain(const char *name, const char *domain, char **s)
|
||||
* the string we should query, in an allocated buffer. If not, set *s
|
||||
* to NULL.
|
||||
*/
|
||||
STATIC_TESTABLE int single_domain(ares_channel channel, const char *name, char **s)
|
||||
int ares__single_domain(ares_channel channel, const char *name, char **s)
|
||||
{
|
||||
size_t len = strlen(name);
|
||||
const char *hostaliases;
|
||||
|
||||
Reference in New Issue
Block a user