Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:15-SP4
nodejs10.25441
cares_172.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File cares_172.patch of Package nodejs10.25441
diff --git a/deps/cares/src/AUTHORS b/deps/cares/AUTHORS similarity index 100% rename from deps/cares/src/AUTHORS rename to deps/cares/AUTHORS diff --git a/deps/cares/src/NEWS b/deps/cares/NEWS similarity index 100% rename from deps/cares/src/NEWS rename to deps/cares/NEWS diff --git a/deps/cares/src/README.cares b/deps/cares/README.cares similarity index 100% rename from deps/cares/src/README.cares rename to deps/cares/README.cares diff --git a/deps/cares/src/README.md b/deps/cares/README.md similarity index 92% rename from deps/cares/src/README.md rename to deps/cares/README.md index 93c1f5f812..148338f9e1 100644 --- a/deps/cares/src/README.md +++ b/deps/cares/README.md @@ -2,9 +2,10 @@ c-ares ====== [![Build Status](https://travis-ci.org/c-ares/c-ares.svg?branch=master)](https://travis-ci.org/c-ares/c-ares) -[![Windows Build Status](https://ci.appveyor.com/api/projects/status/03i7151772eq3wn3/branch/master?svg=true)](https://ci.appveyor.com/project/c-ares/c-ares) +[![Windows Build Status](https://ci.appveyor.com/api/projects/status/aevgc5914tm72pvs/branch/master?svg=true)](https://ci.appveyor.com/project/c-ares/c-ares/branch/master) [![Coverage Status](https://coveralls.io/repos/c-ares/c-ares/badge.svg?branch=master&service=github)](https://coveralls.io/github/c-ares/c-ares?branch=master) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/291/badge)](https://bestpractices.coreinfrastructure.org/projects/291) +[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/c-ares.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:c-ares) [![Releases](https://coderelease.io/badge/c-ares/c-ares)](https://coderelease.io/github/repository/c-ares/c-ares) This is c-ares, an asynchronous resolver library. It is intended for diff --git a/deps/cares/src/README.msvc b/deps/cares/README.msvc similarity index 66% rename from deps/cares/src/README.msvc rename to deps/cares/README.msvc index 4ff8700cb8..396f497db4 100644 --- a/deps/cares/src/README.msvc +++ b/deps/cares/README.msvc @@ -1,6 +1,6 @@ - ___ __ _ _ __ ___ ___ + ___ __ _ _ __ ___ ___ / __| ___ / _` | '__/ _ \/ __| | (_ |___| (_| | | | __/\__ \ \___| \__,_|_| \___||___/ @@ -64,46 +64,6 @@ to c-ares source folder where Makefile.msvc file is located. - How to build using Visual Studio 6 IDE - -------------------------------------- - - A VC++ 6.0 reference workspace (vc6aws.dsw) is available within the 'vc' - folder to allow proper building of the library and sample programs. - - 1) Open the vc6aws.dsw workspace with MSVC6's IDE. - 2) Select 'Build' from top menu. - 3) Select 'Batch Build' from dropdown menu. - 4) Make sure that the sixteen project configurations are 'checked'. - 5) Click on the 'Build' button. - 6) Once the sixteen project configurations are built you are done. - - Dynamic and static c-ares libraries are built in debug and release flavours, - and can be located each one in its own subdirectory, dll-debug, dll-release, - lib-debug and lib-release, all of them below the 'vc\cares' subdirectory. - - In the same way four executable versions of each sample program are built, - each using its respective library. The resulting sample executables are - located in its own subdirectory, dll-debug, dll-release, lib-debug and - lib-release, below the 'vc\acountry', 'vc\adig' and 'vc\ahost'folders. - - These reference VC++ 6.0 configurations are generated using the dynamic CRT. - - - How to build using Visual Studio 2003 or newer IDE - -------------------------------------------------- - - First you have to convert the VC++ 6.0 reference workspace and project files - to the Visual Studio IDE version you are using, following next steps: - - 1) Open vc\vc6aws.dsw with VS20XX. - 2) Allow VS20XX to update all projects and workspaces. - 3) Save ALL and close VS20XX. - 4) Open vc\vc6aws.sln with VS20XX. - 5) Select batch build, check 'all' projects and click 'build' button. - - Same comments relative to generated files and folders as done above for - Visual Studio 6 IDE apply here. - Relationship between c-ares library file names and versions ----------------------------------------------------------- @@ -139,4 +99,4 @@ Have Fun! - + diff --git a/deps/cares/RELEASE-NOTES b/deps/cares/RELEASE-NOTES new file mode 100644 index 0000000000..e1885425ae --- /dev/null +++ b/deps/cares/RELEASE-NOTES @@ -0,0 +1,68 @@ +c-ares version 1.17.1 + +Due to a packaging issue with 1.17.0, we have released 1.17.1 to address that +issue. See 1.17.0 release notes below.. + + +c-ares version 1.17.0 + +Security: + o avoid read-heap-buffer-overflow in ares_parse_soa_reply found during + fuzzing [2] [3] + o Avoid theoretical buffer overflow in RC4 loop comparison [5] + o Empty hquery->name could lead to invalid memory access [15] + o ares_parse_{a,aaaa}_reply() could return a larger *naddrttls than was + passed in [17] + +Changes: + o Update help information for adig, acountry, and ahost [4] + o Test Suite now uses dynamic system-assigned ports rather than hardcoded + ports to prevent failures in containers [10] + o Detect remote DNS server does not support EDNS using rules from RFC 6891 [12] + o Source tree has been reorganized to use a more modern layout [13] + o Allow parsing of CAA Resource Record [14] + +Bug fixes: + o readaddrinfo bad sizeof() [1] + o Test cases should honor HAVE_WRITEV flag, not depend on WIN32 [6] + o FQDN with trailing period should be queried first [7] + o ares_getaddrinfo() was returning members of the struct as garbage values if + unset, and was not honoring ai_socktype and ai_protocol hints. [8] [9] + o ares_gethostbyname() with AF_UNSPEC and an ip address would fail [11] + o Properly document ares_set_local_ip4() uses host byte order [16] + +Thanks go to these friendly people for their efforts and contributions: + @anonymoushelpishere + Anthony Penniston (@apenn-msft) + Brad House (@bradh352) + Bulat Gaifullin (@bgaifullin) + Daniela Sonnenschein (@lxdicted) + Daniel Stenberg (@bagder) + David Hotham (@dimbleby) + Fionn Fitzmaurice (@fionn) + Gisle Vanem (@gavenm) + Ivan Baidakou (@basiliscos) + Jonathan Maye-Hobbs (@wheelpharoah) + Łukasz Marszał (@lmarszal) + lutianxiong (@ltx2018) + Seraphime Kirkovski (@Seraphime) +(14 contributors) + +References to bug reports and discussions on issues: + [1] = https://github.com/c-ares/c-ares/pull/331 + [2] = https://github.com/c-ares/c-ares/pull/332 + [3] = https://github.com/c-ares/c-ares/issues/333 + [4] = https://github.com/c-ares/c-ares/pull/334 + [5] = https://github.com/c-ares/c-ares/pull/336 + [6] = https://github.com/c-ares/c-ares/pull/344 + [7] = https://github.com/c-ares/c-ares/pull/345 + [8] = https://github.com/c-ares/c-ares/issues/343 + [9] = https://github.com/c-ares/c-ares/issues/317 + [10] = https://github.com/c-ares/c-ares/pull/346 + [11] = https://github.com/c-ares/c-ares/pull/204 + [12] = https://github.com/c-ares/c-ares/pull/244 + [13] = https://github.com/c-ares/c-ares/pull/349 + [14] = https://github.com/c-ares/c-ares/pull/360 + [15] = https://github.com/c-ares/c-ares/pull/367 + [16] = https://github.com/c-ares/c-ares/pull/368 + [17] = https://github.com/c-ares/c-ares/issues/371 diff --git a/deps/cares/src/TODO b/deps/cares/TODO similarity index 100% rename from deps/cares/src/TODO rename to deps/cares/TODO diff --git a/deps/cares/cares.gyp b/deps/cares/cares.gyp index be7931f774..643f9a133f 100644 --- a/deps/cares/cares.gyp +++ b/deps/cares/cares.gyp @@ -30,80 +30,85 @@ { 'target_name': 'cares', 'type': '<(library)', - 'include_dirs': [ 'include', 'src' ], + 'include_dirs': [ 'include', 'src/lib' ], 'direct_dependent_settings': { - 'include_dirs': [ 'include' ] + 'include_dirs': [ 'include', 'src/lib' ] }, 'sources': [ 'include/ares.h', + 'include/ares_dns.h', 'include/ares_rules.h', 'include/ares_version.h', - 'include/nameser.h', - 'src/ares_android.c', - 'src/ares_cancel.c', - 'src/ares__close_sockets.c', - 'src/ares_create_query.c', - 'src/ares_data.c', - 'src/ares_data.h', - 'src/ares_destroy.c', - 'src/ares_dns.h', - 'src/ares_expand_name.c', - 'src/ares_expand_string.c', - 'src/ares_fds.c', - 'src/ares_free_hostent.c', - 'src/ares_free_string.c', - 'src/ares_getenv.h', - 'src/ares_gethostbyaddr.c', - 'src/ares_gethostbyname.c', - 'src/ares__get_hostent.c', - 'src/ares_getnameinfo.c', - 'src/ares_getopt.c', - 'src/ares_getopt.h', - 'src/ares_getsock.c', - 'src/ares_init.c', - 'src/ares_ipv6.h', - 'src/ares_library_init.c', - 'src/ares_library_init.h', - 'src/ares_llist.c', - 'src/ares_llist.h', - 'src/ares_mkquery.c', - 'src/ares_nowarn.c', - 'src/ares_nowarn.h', - 'src/ares_options.c', - 'src/ares_parse_aaaa_reply.c', - 'src/ares_parse_a_reply.c', - 'src/ares_parse_mx_reply.c', - 'src/ares_parse_naptr_reply.c', - 'src/ares_parse_ns_reply.c', - 'src/ares_parse_ptr_reply.c', - 'src/ares_parse_soa_reply.c', - 'src/ares_parse_srv_reply.c', - 'src/ares_parse_txt_reply.c', - 'src/ares_platform.h', - 'src/ares_private.h', - 'src/ares_process.c', - 'src/ares_query.c', - 'src/ares__read_line.c', - 'src/ares_search.c', - 'src/ares_send.c', - 'src/ares_setup.h', - 'src/ares_strcasecmp.c', - 'src/ares_strcasecmp.h', - 'src/ares_strdup.c', - 'src/ares_strdup.h', - 'src/ares_strerror.c', - 'src/ares_strsplit.c', - 'src/ares_timeout.c', - 'src/ares__timeval.c', - 'src/ares_version.c', - 'src/ares_writev.c', - 'src/ares_writev.h', - 'src/bitncmp.c', - 'src/bitncmp.h', - 'src/inet_net_pton.c', - 'src/inet_ntop.c', - 'src/ares_inet_net_pton.h', - 'src/setup_once.h', + 'src/lib/ares_android.c', + 'src/lib/ares_cancel.c', + 'src/lib/ares__close_sockets.c', + 'src/lib/ares_create_query.c', + 'src/lib/ares_data.c', + 'src/lib/ares_data.h', + 'src/lib/ares_destroy.c', + 'src/lib/ares_expand_name.c', + 'src/lib/ares_expand_string.c', + 'src/lib/ares_fds.c', + 'src/lib/ares_free_hostent.c', + 'src/lib/ares_free_string.c', + 'src/lib/ares_freeaddrinfo.c', + 'src/lib/ares_getenv.h', + 'src/lib/ares_getaddrinfo.c', + 'src/lib/ares_gethostbyaddr.c', + 'src/lib/ares_gethostbyname.c', + 'src/lib/ares__get_hostent.c', + 'src/lib/ares_getnameinfo.c', + 'src/lib/ares_getsock.c', + 'src/lib/ares_init.c', + 'src/lib/ares_ipv6.h', + 'src/lib/ares_library_init.c', + 'src/lib/ares_library_init.h', + 'src/lib/ares_llist.c', + 'src/lib/ares_llist.h', + 'src/lib/ares_mkquery.c', + 'src/lib/ares_nowarn.c', + 'src/lib/ares_nowarn.h', + 'src/lib/ares_options.c', + 'src/lib/ares__parse_into_addrinfo.c', + 'src/lib/ares_parse_aaaa_reply.c', + 'src/lib/ares_parse_a_reply.c', + 'src/lib/ares_parse_mx_reply.c', + 'src/lib/ares_parse_naptr_reply.c', + 'src/lib/ares_parse_ns_reply.c', + 'src/lib/ares_parse_ptr_reply.c', + 'src/lib/ares_parse_soa_reply.c', + 'src/lib/ares_parse_srv_reply.c', + 'src/lib/ares_parse_txt_reply.c', + 'src/lib/ares_platform.h', + 'src/lib/ares_private.h', + 'src/lib/ares_process.c', + 'src/lib/ares_query.c', + 'src/lib/ares__read_line.c', + 'src/lib/ares__readaddrinfo.c', + 'src/lib/ares_search.c', + 'src/lib/ares_send.c', + 'src/lib/ares_setup.h', + 'src/lib/ares__sortaddrinfo.c', + 'src/lib/ares_strcasecmp.c', + 'src/lib/ares_strcasecmp.h', + 'src/lib/ares_strdup.c', + 'src/lib/ares_strdup.h', + 'src/lib/ares_strerror.c', + 'src/lib/ares_strsplit.c', + 'src/lib/ares_timeout.c', + 'src/lib/ares__timeval.c', + 'src/lib/ares_version.c', + 'src/lib/ares_writev.c', + 'src/lib/ares_writev.h', + 'src/lib/bitncmp.c', + 'src/lib/bitncmp.h', + 'src/lib/inet_net_pton.c', + 'src/lib/inet_ntop.c', + 'src/lib/ares_inet_net_pton.h', + 'src/lib/nameser.h', + 'src/lib/setup_once.h', + 'src/tools/ares_getopt.c', + 'src/tools/ares_getopt.h', ], 'conditions': [ [ 'library=="static_library"', { @@ -112,14 +117,17 @@ 'defines': [ 'CARES_BUILDING_LIBRARY' ] }], [ 'OS=="win"', { - 'defines': [ 'CARES_PULL_WS2TCPIP_H=1' ], + 'defines': [ + 'CARES_PULL_WS2TCPIP_H=1', + '_WINSOCK_DEPRECATED_NO_WARNINGS', + ], 'include_dirs': [ 'config/win32' ], 'sources': [ - 'src/config-win32.h', - 'src/windows_port.c', - 'src/ares_getenv.c', - 'src/ares_iphlpapi.h', - 'src/ares_platform.c' + 'src/lib/config-win32.h', + 'src/lib/windows_port.c', + 'src/lib/ares_getenv.c', + 'src/lib/ares_iphlpapi.h', + 'src/lib/ares_platform.c' ], 'libraries': [ '-lws2_32.lib', diff --git a/deps/cares/include/ares.h b/deps/cares/include/ares.h index 06f60b3330..2c0925f84a 100644 --- a/deps/cares/include/ares.h +++ b/deps/cares/include/ares.h @@ -39,7 +39,7 @@ #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ - defined(__QNXNTO__) + defined(__QNXNTO__) || defined(__MVS__) #include <sys/select.h> #endif #if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) @@ -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. diff --git a/deps/cares/src/ares_dns.h b/deps/cares/include/ares_dns.h similarity index 95% rename from deps/cares/src/ares_dns.h rename to deps/cares/include/ares_dns.h index 79f993b904..bc8aa7b109 100644 --- a/deps/cares/src/ares_dns.h +++ b/deps/cares/include/ares_dns.h @@ -16,6 +16,15 @@ * without express or implied warranty. */ +/* + * NOTE TO INTEGRATORS: + * + * This header is made public due to legacy projects relying on it. + * Please do not use the macros within this header, or include this + * header in your project as it may be removed in the future. + */ + + /* * Macro DNS__16BIT reads a network short (16 bit) given in network * byte order, and returns its value as an unsigned short. diff --git a/deps/cares/include/ares_version.h b/deps/cares/include/ares_version.h index 3fe5b00a11..4b16a62cc6 100644 --- a/deps/cares/include/ares_version.h +++ b/deps/cares/include/ares_version.h @@ -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 17 #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.17.0" #if (ARES_VERSION >= 0x010700) # define CARES_HAVE_ARES_LIBRARY_INIT 1 diff --git a/deps/cares/src/RELEASE-NOTES b/deps/cares/src/RELEASE-NOTES deleted file mode 100644 index 62276fdf4e..0000000000 --- a/deps/cares/src/RELEASE-NOTES +++ /dev/null @@ -1,43 +0,0 @@ -c-ares version 1.15.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] - -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 - -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) - -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 - [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 - diff --git a/deps/cares/src/ares_parse_a_reply.c b/deps/cares/src/ares_parse_a_reply.c deleted file mode 100644 index 0422bd3828..0000000000 --- a/deps/cares/src/ares_parse_a_reply.c +++ /dev/null @@ -1,264 +0,0 @@ - -/* Copyright 1998 by the Massachusetts Institute of Technology. - * - * 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_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; - - /* Set *host to NULL for all failure cases. */ - if (host) - *host = NULL; - /* Same with *naddrttls. */ - if (naddrttls) - *naddrttls = 0; - - /* 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); - if (status != ARES_SUCCESS) - return status; - if (aptr + len + QFIXEDSZ > abuf + alen) - { - ares_free(hostname); - return ARES_EBADRESP; - } - aptr += len + QFIXEDSZ; - - if (host) - { - /* Allocate addresses and aliases; ancount gives an upper bound for - both. */ - addrs = ares_malloc(ancount * sizeof(struct in_addr)); - if (!addrs) - { - ares_free(hostname); - return ARES_ENOMEM; - } - aliases = ares_malloc((ancount + 1) * sizeof(char *)); - if (!aliases) - { - ares_free(hostname); - ares_free(addrs); - return ARES_ENOMEM; - } - } - 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_A - && rr_len == sizeof(struct in_addr) - && strcasecmp(rr_name, hostname) == 0) - { - if (addrs) - { - 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) - { - /* 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; - } - ares_free(hostent); - } - status = ARES_ENOMEM; - } - } - if (aliases) - { - for (i = 0; i < naliases; i++) - ares_free(aliases[i]); - ares_free(aliases); - } - ares_free(addrs); - ares_free(hostname); - return status; -} diff --git a/deps/cares/src/ares_parse_aaaa_reply.c b/deps/cares/src/ares_parse_aaaa_reply.c deleted file mode 100644 index 5b38bb571e..0000000000 --- a/deps/cares/src/ares_parse_aaaa_reply.c +++ /dev/null @@ -1,264 +0,0 @@ - -/* Copyright 1998 by the Massachusetts Institute of Technology. - * Copyright 2005 Dominick Meglio - * - * 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_inet_net_pton.h" -#include "ares_private.h" - -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; - - /* Set *host to NULL for all failure cases. */ - if (host) - *host = NULL; - /* Same with *naddrttls. */ - if (naddrttls) - *naddrttls = 0; - - /* 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); - if (status != ARES_SUCCESS) - return status; - if (aptr + len + QFIXEDSZ > abuf + alen) - { - ares_free(hostname); - return ARES_EBADRESP; - } - aptr += len + QFIXEDSZ; - - /* Allocate addresses and aliases; ancount gives an upper bound for both. */ - if (host) - { - addrs = ares_malloc(ancount * sizeof(struct ares_in6_addr)); - if (!addrs) - { - ares_free(hostname); - return ARES_ENOMEM; - } - aliases = ares_malloc((ancount + 1) * sizeof(char *)); - if (!aliases) - { - ares_free(hostname); - ares_free(addrs); - return ARES_ENOMEM; - } - } - 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 */ - } - - /* 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) - { - /* 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) - { - /* 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; - } - ares_free(hostent); - } - status = ARES_ENOMEM; - } - } - if (aliases) - { - for (i = 0; i < naliases; i++) - ares_free(aliases[i]); - ares_free(aliases); - } - ares_free(addrs); - ares_free(hostname); - return status; -} diff --git a/deps/cares/src/ares_parse_soa_reply.c b/deps/cares/src/ares_parse_soa_reply.c deleted file mode 100644 index 35af0a75c0..0000000000 --- a/deps/cares/src/ares_parse_soa_reply.c +++ /dev/null @@ -1,133 +0,0 @@ - -/* Copyright 1998 by the Massachusetts Institute of Technology. - * Copyright (C) 2012 Marko Kreen <markokr@gmail.com> - * - * 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 - -#include "ares.h" -#include "ares_dns.h" -#include "ares_data.h" -#include "ares_private.h" - -int -ares_parse_soa_reply(const unsigned char *abuf, int alen, - struct ares_soa_reply **soa_out) -{ - const unsigned char *aptr; - long len; - char *qname = NULL, *rr_name = NULL; - struct ares_soa_reply *soa = NULL; - int qdcount, ancount; - int status; - - if (alen < HFIXEDSZ) - return ARES_EBADRESP; - - /* parse message header */ - qdcount = DNS_HEADER_QDCOUNT(abuf); - ancount = DNS_HEADER_ANCOUNT(abuf); - if (qdcount != 1 || ancount != 1) - return ARES_EBADRESP; - aptr = abuf + HFIXEDSZ; - - /* query name */ - status = ares__expand_name_for_response(aptr, abuf, alen, &qname, &len); - if (status != ARES_SUCCESS) - goto failed_stat; - aptr += len; - - /* 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) - goto failed; - aptr += RRFIXEDSZ; - - /* allocate result struct */ - soa = ares_malloc_data(ARES_DATATYPE_SOA_REPLY); - if (!soa) - { - 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; - - /* hostmaster */ - status = ares__expand_name_for_response(aptr, abuf, alen, &soa->hostmaster, &len); - if (status != ARES_SUCCESS) - 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); - - ares_free(qname); - ares_free(rr_name); - - *soa_out = soa; - - return ARES_SUCCESS; - -failed: - status = ARES_EBADRESP; - -failed_stat: - ares_free_data(soa); - if (qname) - ares_free(qname); - if (rr_name) - ares_free(rr_name); - return status; -} - diff --git a/deps/cares/src/ares__close_sockets.c b/deps/cares/src/lib/ares__close_sockets.c similarity index 94% rename from deps/cares/src/ares__close_sockets.c rename to deps/cares/src/lib/ares__close_sockets.c index f07904e873..0477174e3e 100644 --- a/deps/cares/src/ares__close_sockets.c +++ b/deps/cares/src/lib/ares__close_sockets.c @@ -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; } } diff --git a/deps/cares/src/ares__get_hostent.c b/deps/cares/src/lib/ares__get_hostent.c similarity index 98% rename from deps/cares/src/ares__get_hostent.c rename to deps/cares/src/lib/ares__get_hostent.c index d2f9503493..367f39037b 100644 --- a/deps/cares/src/ares__get_hostent.c +++ b/deps/cares/src/lib/ares__get_hostent.c @@ -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; diff --git a/deps/cares/src/lib/ares__parse_into_addrinfo.c b/deps/cares/src/lib/ares__parse_into_addrinfo.c new file mode 100644 index 0000000000..7550abab4a --- /dev/null +++ b/deps/cares/src/lib/ares__parse_into_addrinfo.c @@ -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_nameser.h" + +#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, 0); + 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, 0); + 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, 1); + 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; +} diff --git a/deps/cares/src/ares__read_line.c b/deps/cares/src/lib/ares__read_line.c similarity index 100% rename from deps/cares/src/ares__read_line.c rename to deps/cares/src/lib/ares__read_line.c diff --git a/deps/cares/src/lib/ares__readaddrinfo.c b/deps/cares/src/lib/ares__readaddrinfo.c new file mode 100644 index 0000000000..2b5bb40c3d --- /dev/null +++ b/deps/cares/src/lib/ares__readaddrinfo.c @@ -0,0 +1,264 @@ +/* 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; + } + + /* Zero-out 'addr' struct, as there are members that we may not set, especially + * for ipv6. We don't want garbage data */ + memset(&addr, 0, sizeof(addr)); + + /* + * 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(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(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; +} diff --git a/deps/cares/src/lib/ares__sortaddrinfo.c b/deps/cares/src/lib/ares__sortaddrinfo.c new file mode 100644 index 0000000000..6e56cc9023 --- /dev/null +++ b/deps/cares/src/lib/ares__sortaddrinfo.c @@ -0,0 +1,499 @@ +/* + * 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 = CARES_INADDR_CAST(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 = CARES_INADDR_CAST(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 = CARES_INADDR_CAST(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 = CARES_INADDR_CAST(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 = + CARES_INADDR_CAST(const struct sockaddr_in6 *, a1->ai->ai_addr); + const struct sockaddr_in6 *a2_src = &a2->src_addr.sa6; + const struct sockaddr_in6 *a2_dst = + CARES_INADDR_CAST(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) +{ + ares_socket_t 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 == ARES_SOCKET_BAD) + { + 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) != 0) + { + 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; + } + + if (!nelem) + return ARES_ENODATA; + + 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; +} diff --git a/deps/cares/src/ares__timeval.c b/deps/cares/src/lib/ares__timeval.c similarity index 100% rename from deps/cares/src/ares__timeval.c rename to deps/cares/src/lib/ares__timeval.c diff --git a/deps/cares/src/ares_android.c b/deps/cares/src/lib/ares_android.c similarity index 99% rename from deps/cares/src/ares_android.c rename to deps/cares/src/lib/ares_android.c index bf77131b58..5b00b8065c 100644 --- a/deps/cares/src/ares_android.c +++ b/deps/cares/src/lib/ares_android.c @@ -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; diff --git a/deps/cares/src/ares_android.h b/deps/cares/src/lib/ares_android.h similarity index 100% rename from deps/cares/src/ares_android.h rename to deps/cares/src/lib/ares_android.h diff --git a/deps/cares/src/ares_cancel.c b/deps/cares/src/lib/ares_cancel.c similarity index 100% rename from deps/cares/src/ares_cancel.c rename to deps/cares/src/lib/ares_cancel.c diff --git a/deps/cares/src/ares_create_query.c b/deps/cares/src/lib/ares_create_query.c similarity index 94% rename from deps/cares/src/ares_create_query.c rename to deps/cares/src/lib/ares_create_query.c index 9efce17cfa..e3d874b450 100644 --- a/deps/cares/src/ares_create_query.c +++ b/deps/cares/src/lib/ares_create_query.c @@ -19,22 +19,13 @@ #ifdef HAVE_NETINET_IN_H # include <netinet/in.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 + +#include "ares_nameser.h" #include "ares.h" #include "ares_dns.h" #include "ares_private.h" -#ifndef T_OPT -# define T_OPT 41 /* EDNS0 option (meta-RR) */ -#endif /* Header format, from RFC 1035: * 1 1 1 1 1 1 @@ -57,7 +48,7 @@ * of the remaining fields: * ID Identifier to match responses with queries * QR Query (0) or response (1) - * Opcode For our purposes, always QUERY + * Opcode For our purposes, always O_QUERY * RD Recursion desired * Z Reserved (zero) * QDCOUNT Number of queries @@ -116,7 +107,7 @@ int ares_create_query(const char *name, int dnsclass, int type, q = buf; memset(q, 0, HFIXEDSZ); DNS_HEADER_SET_QID(q, id); - DNS_HEADER_SET_OPCODE(q, QUERY); + DNS_HEADER_SET_OPCODE(q, O_QUERY); if (rd) { DNS_HEADER_SET_RD(q, 1); } diff --git a/deps/cares/src/ares_data.c b/deps/cares/src/lib/ares_data.c similarity index 100% rename from deps/cares/src/ares_data.c rename to deps/cares/src/lib/ares_data.c diff --git a/deps/cares/src/ares_data.h b/deps/cares/src/lib/ares_data.h similarity index 100% rename from deps/cares/src/ares_data.h rename to deps/cares/src/lib/ares_data.h diff --git a/deps/cares/src/ares_destroy.c b/deps/cares/src/lib/ares_destroy.c similarity index 100% rename from deps/cares/src/ares_destroy.c rename to deps/cares/src/lib/ares_destroy.c diff --git a/deps/cares/src/ares_expand_name.c b/deps/cares/src/lib/ares_expand_name.c similarity index 65% rename from deps/cares/src/ares_expand_name.c rename to deps/cares/src/lib/ares_expand_name.c index 3a38e6737e..a62c982e04 100644 --- a/deps/cares/src/ares_expand_name.c +++ b/deps/cares/src/lib/ares_expand_name.c @@ -19,14 +19,8 @@ #ifdef HAVE_NETINET_IN_H # include <netinet/in.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 + +#include "ares_nameser.h" #include "ares.h" #include "ares_nowarn.h" @@ -36,7 +30,52 @@ #define MAX_INDIRS 50 static int name_length(const unsigned char *encoded, const unsigned char *abuf, - int alen); + int alen, int is_hostname); + +/* Reserved characters for names that need to be escaped */ +static int is_reservedch(int ch) +{ + switch (ch) { + case '"': + case '.': + case ';': + case '\\': + case '(': + case ')': + case '@': + case '$': + return 1; + default: + break; + } + + return 0; +} + +static int ares__isprint(int ch) +{ + if (ch >= 0x20 && ch <= 0x7E) + return 1; + return 0; +} + +/* Character set allowed by hostnames */ +static int is_hostnamech(int ch) +{ + /* [A-Za-z0-9-.] + * Don't use isalnum() as it is locale-specific + */ + if (ch >= 'A' && ch <= 'Z') + return 1; + if (ch >= 'a' && ch <= 'z') + return 1; + if (ch >= '0' && ch <= '9') + return 1; + if (ch == '-' || ch == '.') + return 1; + + return 0; +} /* Expand an RFC1035-encoded domain name given by encoded. The * containing message is given by abuf and alen. The result given by @@ -60,10 +99,15 @@ static int name_length(const unsigned char *encoded, const unsigned char *abuf, * * Since the expanded name uses '.' as a label separator, we use * backslashes to escape periods or backslashes in the expanded name. + * + * If the result is expected to be a hostname, then no escaped data is allowed + * and will return error. */ -int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf, - int alen, char **s, long *enclen) +int ares__expand_name_validated(const unsigned char *encoded, + const unsigned char *abuf, + int alen, char **s, long *enclen, + int is_hostname) { int len, indir = 0; char *q; @@ -73,7 +117,7 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf, size_t uns; } nlen; - nlen.sig = name_length(encoded, abuf, alen); + nlen.sig = name_length(encoded, abuf, alen, is_hostname); if (nlen.sig < 0) return ARES_EBADNAME; @@ -113,18 +157,36 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf, } else { - len = *p; + int name_len = *p; + len = name_len; p++; + while (len--) { - if (*p == '.' || *p == '\\') - *q++ = '\\'; - *q++ = *p; + /* Output as \DDD for consistency with RFC1035 5.1, except + * for the special case of a root name response */ + if (!ares__isprint(*p) && !(name_len == 1 && *p == 0)) + { + *q++ = '\\'; + *q++ = '0' + *p / 100; + *q++ = '0' + (*p % 100) / 10; + *q++ = '0' + (*p % 10); + } + else if (is_reservedch(*p)) + { + *q++ = '\\'; + *q++ = *p; + } + else + { + *q++ = *p; + } p++; } *q++ = '.'; } - } + } + if (!indir) *enclen = aresx_uztosl(p + 1U - encoded); @@ -137,11 +199,18 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf, return ARES_SUCCESS; } + +int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf, + int alen, char **s, long *enclen) +{ + return ares__expand_name_validated(encoded, abuf, alen, s, enclen, 0); +} + /* Return the length of the expansion of an encoded domain name, or * -1 if the encoding is invalid. */ static int name_length(const unsigned char *encoded, const unsigned char *abuf, - int alen) + int alen, int is_hostname) { int n = 0, offset, indir = 0, top; @@ -171,15 +240,35 @@ static int name_length(const unsigned char *encoded, const unsigned char *abuf, } else if (top == 0x00) { - offset = *encoded; + int name_len = *encoded; + offset = name_len; if (encoded + offset + 1 >= abuf + alen) return -1; encoded++; + while (offset--) { - n += (*encoded == '.' || *encoded == '\\') ? 2 : 1; + if (!ares__isprint(*encoded) && !(name_len == 1 && *encoded == 0)) + { + if (is_hostname) + return -1; + n += 4; + } + else if (is_reservedch(*encoded)) + { + if (is_hostname) + return -1; + n += 2; + } + else + { + if (is_hostname && !is_hostnamech(*encoded)) + return -1; + n += 1; + } encoded++; } + n++; } else @@ -197,12 +286,14 @@ static int name_length(const unsigned char *encoded, const unsigned char *abuf, return (n) ? n - 1 : n; } -/* Like ares_expand_name but returns EBADRESP in case of invalid input. */ +/* Like ares_expand_name_validated but returns EBADRESP in case of invalid + * input. */ int ares__expand_name_for_response(const unsigned char *encoded, const unsigned char *abuf, int alen, - char **s, long *enclen) + char **s, long *enclen, int is_hostname) { - int status = ares_expand_name(encoded, abuf, alen, s, enclen); + int status = ares__expand_name_validated(encoded, abuf, alen, s, enclen, + is_hostname); if (status == ARES_EBADNAME) status = ARES_EBADRESP; return status; diff --git a/deps/cares/src/ares_expand_string.c b/deps/cares/src/lib/ares_expand_string.c similarity index 95% rename from deps/cares/src/ares_expand_string.c rename to deps/cares/src/lib/ares_expand_string.c index d35df75248..03e3929975 100644 --- a/deps/cares/src/ares_expand_string.c +++ b/deps/cares/src/lib/ares_expand_string.c @@ -19,11 +19,8 @@ #ifdef HAVE_NETINET_IN_H # include <netinet/in.h> #endif -#ifdef HAVE_ARPA_NAMESER_H -# include <arpa/nameser.h> -#else -# include "nameser.h" -#endif + +#include "ares_nameser.h" #include "ares.h" #include "ares_private.h" /* for the memdebug */ diff --git a/deps/cares/src/ares_fds.c b/deps/cares/src/lib/ares_fds.c similarity index 100% rename from deps/cares/src/ares_fds.c rename to deps/cares/src/lib/ares_fds.c diff --git a/deps/cares/src/ares_free_hostent.c b/deps/cares/src/lib/ares_free_hostent.c similarity index 79% rename from deps/cares/src/ares_free_hostent.c rename to deps/cares/src/lib/ares_free_hostent.c index cfc5f81feb..ea28ff0e2c 100644 --- a/deps/cares/src/ares_free_hostent.c +++ b/deps/cares/src/lib/ares_free_hostent.c @@ -31,11 +31,13 @@ void ares_free_hostent(struct hostent *host) return; ares_free((char *)(host->h_name)); - for (p = host->h_aliases; *p; p++) + for (p = host->h_aliases; p && *p; p++) ares_free(*p); ares_free(host->h_aliases); - ares_free(host->h_addr_list[0]); /* no matter if there is one or many entries, - there is only one malloc for all of them */ - ares_free(host->h_addr_list); + if (host->h_addr_list) { + ares_free(host->h_addr_list[0]); /* no matter if there is one or many entries, + there is only one malloc for all of them */ + ares_free(host->h_addr_list); + } ares_free(host); } diff --git a/deps/cares/src/ares_free_string.c b/deps/cares/src/lib/ares_free_string.c similarity index 100% rename from deps/cares/src/ares_free_string.c rename to deps/cares/src/lib/ares_free_string.c diff --git a/deps/cares/src/lib/ares_freeaddrinfo.c b/deps/cares/src/lib/ares_freeaddrinfo.c new file mode 100644 index 0000000000..d8891bbf8a --- /dev/null +++ b/deps/cares/src/lib/ares_freeaddrinfo.c @@ -0,0 +1,59 @@ + +/* 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) +{ + if (ai == NULL) + return; + ares__freeaddrinfo_cnames(ai->cnames); + ares__freeaddrinfo_nodes(ai->nodes); + ares_free(ai); +} diff --git a/deps/cares/src/lib/ares_getaddrinfo.c b/deps/cares/src/lib/ares_getaddrinfo.c new file mode 100644 index 0000000000..db17a67086 --- /dev/null +++ b/deps/cares/src/lib/ares_getaddrinfo.c @@ -0,0 +1,772 @@ + +/* 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 + +#include "ares_nameser.h" + +#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; + } + } + + node->ai_socktype = hints->ai_socktype; + node->ai_protocol = hints->ai_protocol; + + 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) && hquery->ai->nodes) + { + 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) + { + next->ai_socktype = hquery->hints.ai_socktype; + next->ai_protocol = hquery->hints.ai_protocol; + if (next->ai_family == AF_INET) + { + (CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr))->sin_port = htons(hquery->port); + } + else + { + (CARES_INADDR_CAST(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 (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ, + &hkeyHosts) == ERROR_SUCCESS) + { + DWORD dwLength = MAX_PATH; + RegQueryValueExA(hkeyHosts, DATABASEPATH, NULL, NULL, (LPBYTE)tmp, + &dwLength); + ExpandEnvironmentStringsA(tmp, PATH_HOSTS, MAX_PATH); + RegCloseKey(hkeyHosts); + } + } + else if (platform == WIN_9X) + GetWindowsDirectoryA(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); + } + + 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 if (status == ARES_EDESTRUCTION) + { + /* NOTE: Could also be ARES_EDESTRUCTION. We need to only call this + * once all queries (there can be multiple for getaddrinfo) are + * terminated. */ + end_hquery(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; + size_t nname = strlen(hquery->name); + for (p = hquery->name; *p; p++) + { + if (*p == '.') + { + ndots++; + } + } + if (nname && hquery->name[nname-1] == '.') + { + /* prevent ARES_EBADNAME for valid FQDN, where ndots < channel->ndots */ + return 1; + } + return ndots >= hquery->channel->ndots; +} diff --git a/deps/cares/src/ares_getenv.c b/deps/cares/src/lib/ares_getenv.c similarity index 97% rename from deps/cares/src/ares_getenv.c rename to deps/cares/src/lib/ares_getenv.c index 1b2e85d2be..f6e4dc2952 100644 --- a/deps/cares/src/ares_getenv.c +++ b/deps/cares/src/lib/ares_getenv.c @@ -22,9 +22,7 @@ char *ares_getenv(const char *name) { -#ifdef _WIN32_WCE return NULL; -#endif } #endif diff --git a/deps/cares/src/ares_getenv.h b/deps/cares/src/lib/ares_getenv.h similarity index 100% rename from deps/cares/src/ares_getenv.h rename to deps/cares/src/lib/ares_getenv.h diff --git a/deps/cares/src/ares_gethostbyaddr.c b/deps/cares/src/lib/ares_gethostbyaddr.c similarity index 97% rename from deps/cares/src/ares_gethostbyaddr.c rename to deps/cares/src/lib/ares_gethostbyaddr.c index a8ca0f5744..c62d230d96 100644 --- a/deps/cares/src/ares_gethostbyaddr.c +++ b/deps/cares/src/lib/ares_gethostbyaddr.c @@ -24,14 +24,8 @@ #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 + +#include "ares_nameser.h" #include "ares.h" #include "ares_inet_net_pton.h" @@ -208,7 +202,6 @@ static int file_lookup(struct ares_addr *addr, struct hostent **host) strcat(PATH_HOSTS, WIN_PATH_HOSTS); #elif defined(WATT32) - extern const char *_w32_GetHostsFile (void); const char *PATH_HOSTS = _w32_GetHostsFile(); if (!PATH_HOSTS) diff --git a/deps/cares/src/ares_gethostbyname.c b/deps/cares/src/lib/ares_gethostbyname.c similarity index 95% rename from deps/cares/src/ares_gethostbyname.c rename to deps/cares/src/lib/ares_gethostbyname.c index 8187746bb1..e09363632e 100644 --- a/deps/cares/src/ares_gethostbyname.c +++ b/deps/cares/src/lib/ares_gethostbyname.c @@ -25,14 +25,8 @@ #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 + +#include "ares_nameser.h" #ifdef HAVE_STRINGS_H #include <strings.h> @@ -211,6 +205,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 || @@ -251,7 +252,7 @@ static int fake_hostent(const char *name, int family, struct in_addr in; struct ares_in6_addr in6; - if (family == AF_INET || family == AF_INET6) + if (family == AF_INET || family == AF_UNSPEC) { /* It only looks like an IP address if it's all numbers and dots. */ int numdots = 0, valid = 1; @@ -267,15 +268,19 @@ 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) + if (numdots != 3 || !valid) { result = 0; - else - result = ((in.s_addr = inet_addr(name)) == INADDR_NONE ? 0 : 1); + } else { + result = (ares_inet_pton(AF_INET, name, &in) < 1 ? 0 : 1); + } - if (result) - family = AF_INET; + /* + * Set address family in case of failure, + * as we will try to convert it later afterwards + */ + family = result ? AF_INET : AF_INET6; } if (family == AF_INET6) result = (ares_inet_pton(AF_INET6, name, &in6) < 1 ? 0 : 1); @@ -346,10 +351,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; @@ -380,13 +381,17 @@ static int file_lookup(const char *name, int family, struct hostent **host) strcat(PATH_HOSTS, WIN_PATH_HOSTS); #elif defined(WATT32) - extern const char *_w32_GetHostsFile (void); const char *PATH_HOSTS = _w32_GetHostsFile(); if (!PATH_HOSTS) 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) { diff --git a/deps/cares/src/ares_getnameinfo.c b/deps/cares/src/lib/ares_getnameinfo.c similarity index 98% rename from deps/cares/src/ares_getnameinfo.c rename to deps/cares/src/lib/ares_getnameinfo.c index aa08941706..966919ac23 100644 --- a/deps/cares/src/ares_getnameinfo.c +++ b/deps/cares/src/lib/ares_getnameinfo.c @@ -31,14 +31,8 @@ #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 + +#include "ares_nameser.h" #ifdef HAVE_NET_IF_H #include <net/if.h> @@ -92,13 +86,13 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, if ((sa->sa_family == AF_INET) && (salen == sizeof(struct sockaddr_in))) { - addr = (struct sockaddr_in *)sa; + addr = CARES_INADDR_CAST(struct sockaddr_in *, sa); port = addr->sin_port; } else if ((sa->sa_family == AF_INET6) && (salen == sizeof(struct sockaddr_in6))) { - addr6 = (struct sockaddr_in6 *)sa; + addr6 = CARES_INADDR_CAST(struct sockaddr_in6 *, sa); port = addr6->sin6_port; } else diff --git a/deps/cares/src/ares_getsock.c b/deps/cares/src/lib/ares_getsock.c similarity index 100% rename from deps/cares/src/ares_getsock.c rename to deps/cares/src/lib/ares_getsock.c diff --git a/deps/cares/src/ares_inet_net_pton.h b/deps/cares/src/lib/ares_inet_net_pton.h similarity index 100% rename from deps/cares/src/ares_inet_net_pton.h rename to deps/cares/src/lib/ares_inet_net_pton.h diff --git a/deps/cares/src/ares_init.c b/deps/cares/src/lib/ares_init.c similarity index 97% rename from deps/cares/src/ares_init.c rename to deps/cares/src/lib/ares_init.c index c2c00d6523..0917dce2fe 100644 --- a/deps/cares/src/ares_init.c +++ b/deps/cares/src/lib/ares_init.c @@ -33,14 +33,7 @@ #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 +#include "ares_nameser.h" #if defined(ANDROID) || defined(__ANDROID__) #include <sys/system_properties.h> @@ -115,20 +108,6 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options, int status = ARES_SUCCESS; struct timeval now; -#ifdef CURLDEBUG - const char *env = getenv("CARES_MEMDEBUG"); - - if (env) - curl_memdebug(env); - env = getenv("CARES_MEMLIMIT"); - if (env) { - char *endptr; - long num = strtol(env, &endptr, 10); - if((endptr != env) && (endptr == env + strlen(env)) && (num > 0)) - curl_memlimit(num); - } -#endif - if (ares_library_initialized() != ARES_SUCCESS) return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */ @@ -1486,6 +1465,57 @@ static int init_by_resolv_conf(ares_channel channel) /* Catch the case when all the above checks fail (which happens when there is no network card or the cable is unplugged) */ status = ARES_EFILE; +#elif defined(__MVS__) + + struct __res_state *res = 0; + int count4, count6; + __STATEEXTIPV6 *v6; + struct server_state *pserver + if (0 == res) { + int rc = res_init(); + while (rc == -1 && h_errno == TRY_AGAIN) { + rc = res_init(); + } + if (rc == -1) { + return ARES_ENOMEM; + } + res = __res(); + } + + v6 = res->__res_extIPv6; + count4 = res->nscount; + if (v6) { + count6 = v6->__stat_nscount; + } else { + count6 = 0; + } + + nservers = count4 + count6; + servers = ares_malloc(nservers * sizeof(struct server_state)); + if (!servers) + return ARES_ENOMEM; + + memset(servers, 0, nservers * sizeof(struct server_state)); + + pserver = servers; + for (int i = 0; i < count4; ++i, ++pserver) { + struct sockaddr_in *addr_in = &(res->nsaddr_list[i]); + pserver->addr.addrV4.s_addr = addr_in->sin_addr.s_addr; + pserver->addr.family = AF_INET; + pserver->addr.udp_port = addr_in->sin_port; + pserver->addr.tcp_port = addr_in->sin_port; + } + + for (int j = 0; j < count6; ++j, ++pserver) { + struct sockaddr_in6 *addr_in = &(v6->__stat_nsaddr_list[j]); + memcpy(&(pserver->addr.addr.addr6), &(addr_in->sin6_addr), + sizeof(addr_in->sin6_addr)); + pserver->addr.family = AF_INET6; + pserver->addr.udp_port = addr_in->sin6_port; + pserver->addr.tcp_port = addr_in->sin6_port; + } + + status = ARES_EOF; #elif defined(__riscos__) @@ -1543,8 +1573,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 +1615,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) { @@ -1611,7 +1641,8 @@ static int init_by_resolv_conf(ares_channel channel) if (channel->nservers == -1) { union res_sockaddr_union addr[MAXNS]; int nscount = res_getservers(&res, addr, MAXNS); - for (int i = 0; i < nscount; ++i) { + int i; + for (i = 0; i < nscount; ++i) { char str[INET6_ADDRSTRLEN]; int config_status; sa_family_t family = addr[i].sin.sin_family; @@ -1634,16 +1665,18 @@ static int init_by_resolv_conf(ares_channel channel) int entries = 0; while ((entries < MAXDNSRCH) && res.dnsrch[entries]) entries++; - - channel->domains = ares_malloc(entries * sizeof(char *)); - if (!channel->domains) { - status = ARES_ENOMEM; - } else { - channel->ndomains = entries; - for (int i = 0; i < channel->ndomains; ++i) { - channel->domains[i] = ares_strdup(res.dnsrch[i]); - if (!channel->domains[i]) - status = ARES_ENOMEM; + if(entries) { + channel->domains = ares_malloc(entries * sizeof(char *)); + if (!channel->domains) { + status = ARES_ENOMEM; + } else { + int i; + channel->ndomains = entries; + for (i = 0; i < channel->ndomains; ++i) { + channel->domains[i] = ares_strdup(res.dnsrch[i]); + if (!channel->domains[i]) + status = ARES_ENOMEM; + } } } } @@ -2024,6 +2057,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 +2068,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 +2456,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; } @@ -2477,9 +2515,10 @@ static void randomize_key(unsigned char* key,int key_data_len) randomized = 1; } #else /* !WIN32 */ -#ifdef RANDOM_FILE - FILE *f = fopen(RANDOM_FILE, "rb"); +#ifdef CARES_RANDOM_FILE + FILE *f = fopen(CARES_RANDOM_FILE, "rb"); if(f) { + setvbuf(f, NULL, _IONBF, 0); counter = aresx_uztosi(fread(key, 1, key_data_len, f)); fclose(f); } diff --git a/deps/cares/src/ares_iphlpapi.h b/deps/cares/src/lib/ares_iphlpapi.h similarity index 100% rename from deps/cares/src/ares_iphlpapi.h rename to deps/cares/src/lib/ares_iphlpapi.h diff --git a/deps/cares/src/ares_ipv6.h b/deps/cares/src/lib/ares_ipv6.h similarity index 94% rename from deps/cares/src/ares_ipv6.h rename to deps/cares/src/lib/ares_ipv6.h index b0017f16c7..fdbc21fe8f 100644 --- a/deps/cares/src/ares_ipv6.h +++ b/deps/cares/src/lib/ares_ipv6.h @@ -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 { diff --git a/deps/cares/src/ares_library_init.c b/deps/cares/src/lib/ares_library_init.c similarity index 94% rename from deps/cares/src/ares_library_init.c rename to deps/cares/src/lib/ares_library_init.c index 67563499be..e0055d44a1 100644 --- a/deps/cares/src/ares_library_init.c +++ b/deps/cares/src/lib/ares_library_init.c @@ -40,13 +40,18 @@ static unsigned int ares_initialized; static int ares_init_flags; /* library-private global vars with visibility across the whole library */ + +/* Some systems may return either NULL or a valid pointer on malloc(0). c-ares should + * never call malloc(0) so lets return NULL so we're more likely to find an issue if it + * were to occur. */ + +static void *default_malloc(size_t size) { if (size == 0) { return NULL; } return malloc(size); } + #if defined(WIN32) /* We need indirections to handle Windows DLL rules. */ -static void *default_malloc(size_t size) { return malloc(size); } static void *default_realloc(void *p, size_t size) { return realloc(p, size); } static void default_free(void *p) { free(p); } #else -# define default_malloc malloc # define default_realloc realloc # define default_free free #endif diff --git a/deps/cares/src/ares_library_init.h b/deps/cares/src/lib/ares_library_init.h similarity index 98% rename from deps/cares/src/ares_library_init.h rename to deps/cares/src/lib/ares_library_init.h index 2a2ba118b5..b3896d9f7b 100644 --- a/deps/cares/src/ares_library_init.h +++ b/deps/cares/src/lib/ares_library_init.h @@ -23,7 +23,7 @@ #ifdef USE_WINSOCK #include <iphlpapi.h> -#include <ares_iphlpapi.h> +#include "ares_iphlpapi.h" typedef DWORD (WINAPI *fpGetNetworkParams_t) (FIXED_INFO*, DWORD*); typedef BOOLEAN (APIENTRY *fpSystemFunction036_t) (void*, ULONG); diff --git a/deps/cares/src/ares_llist.c b/deps/cares/src/lib/ares_llist.c similarity index 100% rename from deps/cares/src/ares_llist.c rename to deps/cares/src/lib/ares_llist.c diff --git a/deps/cares/src/ares_llist.h b/deps/cares/src/lib/ares_llist.h similarity index 100% rename from deps/cares/src/ares_llist.h rename to deps/cares/src/lib/ares_llist.h diff --git a/deps/cares/src/ares_mkquery.c b/deps/cares/src/lib/ares_mkquery.c similarity index 100% rename from deps/cares/src/ares_mkquery.c rename to deps/cares/src/lib/ares_mkquery.c diff --git a/deps/cares/src/lib/ares_nameser.h b/deps/cares/src/lib/ares_nameser.h new file mode 100644 index 0000000000..5270e5a3a6 --- /dev/null +++ b/deps/cares/src/lib/ares_nameser.h @@ -0,0 +1,482 @@ + +#ifndef ARES_NAMESER_H +#define ARES_NAMESER_H + +#ifdef HAVE_ARPA_NAMESER_H +# include <arpa/nameser.h> +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +# include <arpa/nameser_compat.h> +#endif + +/* ============================================================================ + * arpa/nameser.h may or may not provide ALL of the below defines, so check + * each one individually and set if not + * ============================================================================ + */ + +#ifndef NS_PACKETSZ +# define NS_PACKETSZ 512 /* maximum packet size */ +#endif + +#ifndef NS_MAXDNAME +# define NS_MAXDNAME 256 /* maximum domain name */ +#endif + +#ifndef NS_MAXCDNAME +# define NS_MAXCDNAME 255 /* maximum compressed domain name */ +#endif + +#ifndef NS_MAXLABEL +# define NS_MAXLABEL 63 +#endif + +#ifndef NS_HFIXEDSZ +# define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */ +#endif + +#ifndef NS_QFIXEDSZ +# define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */ +#endif + +#ifndef NS_RRFIXEDSZ +# define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ +#endif + +#ifndef NS_INT16SZ +# define NS_INT16SZ 2 +#endif + +#ifndef NS_INADDRSZ +# define NS_INADDRSZ 4 +#endif + +#ifndef NS_IN6ADDRSZ +# define NS_IN6ADDRSZ 16 +#endif + +#ifndef NS_CMPRSFLGS +# define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */ +#endif + +#ifndef NS_DEFAULTPORT +# define NS_DEFAULTPORT 53 /* For both TCP and UDP. */ +#endif + +/* ============================================================================ + * arpa/nameser.h should provide these enumerations always, so if not found, + * provide them + * ============================================================================ + */ +#ifndef HAVE_ARPA_NAMESER_H + +typedef enum __ns_class { + ns_c_invalid = 0, /* Cookie. */ + ns_c_in = 1, /* Internet. */ + ns_c_2 = 2, /* unallocated/unsupported. */ + ns_c_chaos = 3, /* MIT Chaos-net. */ + ns_c_hs = 4, /* MIT Hesiod. */ + /* Query class values which do not appear in resource records */ + ns_c_none = 254, /* for prereq. sections in update requests */ + ns_c_any = 255, /* Wildcard match. */ + ns_c_max = 65536 +} ns_class; + +typedef enum __ns_type { + ns_t_invalid = 0, /* Cookie. */ + ns_t_a = 1, /* Host address. */ + ns_t_ns = 2, /* Authoritative server. */ + ns_t_md = 3, /* Mail destination. */ + ns_t_mf = 4, /* Mail forwarder. */ + ns_t_cname = 5, /* Canonical name. */ + ns_t_soa = 6, /* Start of authority zone. */ + ns_t_mb = 7, /* Mailbox domain name. */ + ns_t_mg = 8, /* Mail group member. */ + ns_t_mr = 9, /* Mail rename name. */ + ns_t_null = 10, /* Null resource record. */ + ns_t_wks = 11, /* Well known service. */ + ns_t_ptr = 12, /* Domain name pointer. */ + ns_t_hinfo = 13, /* Host information. */ + ns_t_minfo = 14, /* Mailbox information. */ + ns_t_mx = 15, /* Mail routing information. */ + ns_t_txt = 16, /* Text strings. */ + ns_t_rp = 17, /* Responsible person. */ + ns_t_afsdb = 18, /* AFS cell database. */ + ns_t_x25 = 19, /* X_25 calling address. */ + ns_t_isdn = 20, /* ISDN calling address. */ + ns_t_rt = 21, /* Router. */ + ns_t_nsap = 22, /* NSAP address. */ + ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */ + ns_t_sig = 24, /* Security signature. */ + ns_t_key = 25, /* Security key. */ + ns_t_px = 26, /* X.400 mail mapping. */ + ns_t_gpos = 27, /* Geographical position (withdrawn). */ + ns_t_aaaa = 28, /* Ip6 Address. */ + ns_t_loc = 29, /* Location Information. */ + ns_t_nxt = 30, /* Next domain (security). */ + ns_t_eid = 31, /* Endpoint identifier. */ + ns_t_nimloc = 32, /* Nimrod Locator. */ + ns_t_srv = 33, /* Server Selection. */ + ns_t_atma = 34, /* ATM Address */ + ns_t_naptr = 35, /* Naming Authority PoinTeR */ + ns_t_kx = 36, /* Key Exchange */ + ns_t_cert = 37, /* Certification record */ + ns_t_a6 = 38, /* IPv6 address (deprecates AAAA) */ + ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */ + ns_t_sink = 40, /* Kitchen sink (experimentatl) */ + ns_t_opt = 41, /* EDNS0 option (meta-RR) */ + ns_t_apl = 42, /* Address prefix list (RFC3123) */ + ns_t_ds = 43, /* Delegation Signer (RFC4034) */ + ns_t_sshfp = 44, /* SSH Key Fingerprint (RFC4255) */ + ns_t_rrsig = 46, /* Resource Record Signature (RFC4034) */ + ns_t_nsec = 47, /* Next Secure (RFC4034) */ + ns_t_dnskey = 48, /* DNS Public Key (RFC4034) */ + ns_t_tkey = 249, /* Transaction key */ + ns_t_tsig = 250, /* Transaction signature. */ + ns_t_ixfr = 251, /* Incremental zone transfer. */ + ns_t_axfr = 252, /* Transfer zone of authority. */ + ns_t_mailb = 253, /* Transfer mailbox records. */ + ns_t_maila = 254, /* Transfer mail agent records. */ + ns_t_any = 255, /* Wildcard match. */ + ns_t_zxfr = 256, /* BIND-specific, nonstandard. */ + ns_t_caa = 257, /* Certification Authority Authorization. */ + ns_t_max = 65536 +} ns_type; + +typedef enum __ns_opcode { + ns_o_query = 0, /* Standard query. */ + ns_o_iquery = 1, /* Inverse query (deprecated/unsupported). */ + ns_o_status = 2, /* Name server status query (unsupported). */ + /* Opcode 3 is undefined/reserved. */ + ns_o_notify = 4, /* Zone change notification. */ + ns_o_update = 5, /* Zone update message. */ + ns_o_max = 6 +} ns_opcode; + +typedef enum __ns_rcode { + ns_r_noerror = 0, /* No error occurred. */ + ns_r_formerr = 1, /* Format error. */ + ns_r_servfail = 2, /* Server failure. */ + ns_r_nxdomain = 3, /* Name error. */ + ns_r_notimpl = 4, /* Unimplemented. */ + ns_r_refused = 5, /* Operation refused. */ + /* these are for BIND_UPDATE */ + ns_r_yxdomain = 6, /* Name exists */ + ns_r_yxrrset = 7, /* RRset exists */ + ns_r_nxrrset = 8, /* RRset does not exist */ + ns_r_notauth = 9, /* Not authoritative for zone */ + ns_r_notzone = 10, /* Zone of record different from zone section */ + ns_r_max = 11, + /* The following are TSIG extended errors */ + ns_r_badsig = 16, + ns_r_badkey = 17, + ns_r_badtime = 18 +} ns_rcode; + +#endif /* HAVE_ARPA_NAMESER_H */ + + +/* ============================================================================ + * arpa/nameser_compat.h typically sets these. However on some systems + * arpa/nameser.h does, but may not set all of them. Lets conditionally + * define each + * ============================================================================ + */ + +#ifndef PACKETSZ +# define PACKETSZ NS_PACKETSZ +#endif + +#ifndef MAXDNAME +# define MAXDNAME NS_MAXDNAME +#endif + +#ifndef MAXCDNAME +# define MAXCDNAME NS_MAXCDNAME +#endif + +#ifndef MAXLABEL +# define MAXLABEL NS_MAXLABEL +#endif + +#ifndef HFIXEDSZ +# define HFIXEDSZ NS_HFIXEDSZ +#endif + +#ifndef QFIXEDSZ +# define QFIXEDSZ NS_QFIXEDSZ +#endif + +#ifndef RRFIXEDSZ +# define RRFIXEDSZ NS_RRFIXEDSZ +#endif + +#ifndef INDIR_MASK +# define INDIR_MASK NS_CMPRSFLGS +#endif + +#ifndef NAMESERVER_PORT +# define NAMESERVER_PORT NS_DEFAULTPORT +#endif + + +/* opcodes */ +#ifndef O_QUERY +# define O_QUERY 0 /* ns_o_query */ +#endif +#ifndef O_IQUERY +# define O_IQUERY 1 /* ns_o_iquery */ +#endif +#ifndef O_STATUS +# define O_STATUS 2 /* ns_o_status */ +#endif +#ifndef O_NOTIFY +# define O_NOTIFY 4 /* ns_o_notify */ +#endif +#ifndef O_UPDATE +# define O_UPDATE 5 /* ns_o_update */ +#endif + + +/* response codes */ +#ifndef SERVFAIL +# define SERVFAIL ns_r_servfail +#endif +#ifndef NOTIMP +# define NOTIMP ns_r_notimpl +#endif +#ifndef REFUSED +# define REFUSED ns_r_refused +#endif +#if defined(_WIN32) && !defined(HAVE_ARPA_NAMESER_COMPAT_H) && defined(NOERROR) +# undef NOERROR /* it seems this is already defined in winerror.h */ +#endif +#ifndef NOERROR +# define NOERROR ns_r_noerror +#endif +#ifndef FORMERR +# define FORMERR ns_r_formerr +#endif +#ifndef NXDOMAIN +# define NXDOMAIN ns_r_nxdomain +#endif +/* Non-standard response codes, use numeric values */ +#ifndef YXDOMAIN +# define YXDOMAIN 6 /* ns_r_yxdomain */ +#endif +#ifndef YXRRSET +# define YXRRSET 7 /* ns_r_yxrrset */ +#endif +#ifndef NXRRSET +# define NXRRSET 8 /* ns_r_nxrrset */ +#endif +#ifndef NOTAUTH +# define NOTAUTH 9 /* ns_r_notauth */ +#endif +#ifndef NOTZONE +# define NOTZONE 10 /* ns_r_notzone */ +#endif +#ifndef TSIG_BADSIG +# define TSIG_BADSIG 16 /* ns_r_badsig */ +#endif +#ifndef TSIG_BADKEY +# define TSIG_BADKEY 17 /* ns_r_badkey */ +#endif +#ifndef TSIG_BADTIME +# define TSIG_BADTIME 18 /* ns_r_badtime */ +#endif + + +/* classes */ +#ifndef C_IN +# define C_IN 1 /* ns_c_in */ +#endif +#ifndef C_CHAOS +# define C_CHAOS 3 /* ns_c_chaos */ +#endif +#ifndef C_HS +# define C_HS 4 /* ns_c_hs */ +#endif +#ifndef C_NONE +# define C_NONE 254 /* ns_c_none */ +#endif +#ifndef C_ANY +# define C_ANY 255 /* ns_c_any */ +#endif + + +/* types */ +#ifndef T_A +# define T_A 1 /* ns_t_a */ +#endif +#ifndef T_NS +# define T_NS 2 /* ns_t_ns */ +#endif +#ifndef T_MD +# define T_MD 3 /* ns_t_md */ +#endif +#ifndef T_MF +# define T_MF 4 /* ns_t_mf */ +#endif +#ifndef T_CNAME +# define T_CNAME 5 /* ns_t_cname */ +#endif +#ifndef T_SOA +# define T_SOA 6 /* ns_t_soa */ +#endif +#ifndef T_MB +# define T_MB 7 /* ns_t_mb */ +#endif +#ifndef T_MG +# define T_MG 8 /* ns_t_mg */ +#endif +#ifndef T_MR +# define T_MR 9 /* ns_t_mr */ +#endif +#ifndef T_NULL +# define T_NULL 10 /* ns_t_null */ +#endif +#ifndef T_WKS +# define T_WKS 11 /* ns_t_wks */ +#endif +#ifndef T_PTR +# define T_PTR 12 /* ns_t_ptr */ +#endif +#ifndef T_HINFO +# define T_HINFO 13 /* ns_t_hinfo */ +#endif +#ifndef T_MINFO +# define T_MINFO 14 /* ns_t_minfo */ +#endif +#ifndef T_MX +# define T_MX 15 /* ns_t_mx */ +#endif +#ifndef T_TXT +# define T_TXT 16 /* ns_t_txt */ +#endif +#ifndef T_RP +# define T_RP 17 /* ns_t_rp */ +#endif +#ifndef T_AFSDB +# define T_AFSDB 18 /* ns_t_afsdb */ +#endif +#ifndef T_X25 +# define T_X25 19 /* ns_t_x25 */ +#endif +#ifndef T_ISDN +# define T_ISDN 20 /* ns_t_isdn */ +#endif +#ifndef T_RT +# define T_RT 21 /* ns_t_rt */ +#endif +#ifndef T_NSAP +# define T_NSAP 22 /* ns_t_nsap */ +#endif +#ifndef T_NSAP_PTR +# define T_NSAP_PTR 23 /* ns_t_nsap_ptr */ +#endif +#ifndef T_SIG +# define T_SIG 24 /* ns_t_sig */ +#endif +#ifndef T_KEY +# define T_KEY 25 /* ns_t_key */ +#endif +#ifndef T_PX +# define T_PX 26 /* ns_t_px */ +#endif +#ifndef T_GPOS +# define T_GPOS 27 /* ns_t_gpos */ +#endif +#ifndef T_AAAA +# define T_AAAA 28 /* ns_t_aaaa */ +#endif +#ifndef T_LOC +# define T_LOC 29 /* ns_t_loc */ +#endif +#ifndef T_NXT +# define T_NXT 30 /* ns_t_nxt */ +#endif +#ifndef T_EID +# define T_EID 31 /* ns_t_eid */ +#endif +#ifndef T_NIMLOC +# define T_NIMLOC 32 /* ns_t_nimloc */ +#endif +#ifndef T_SRV +# define T_SRV 33 /* ns_t_srv */ +#endif +#ifndef T_ATMA +# define T_ATMA 34 /* ns_t_atma */ +#endif +#ifndef T_NAPTR +# define T_NAPTR 35 /* ns_t_naptr */ +#endif +#ifndef T_KX +# define T_KX 36 /* ns_t_kx */ +#endif +#ifndef T_CERT +# define T_CERT 37 /* ns_t_cert */ +#endif +#ifndef T_A6 +# define T_A6 38 /* ns_t_a6 */ +#endif +#ifndef T_DNAME +# define T_DNAME 39 /* ns_t_dname */ +#endif +#ifndef T_SINK +# define T_SINK 40 /* ns_t_sink */ +#endif +#ifndef T_OPT +# define T_OPT 41 /* ns_t_opt */ +#endif +#ifndef T_APL +# define T_APL 42 /* ns_t_apl */ +#endif +#ifndef T_DS +# define T_DS 43 /* ns_t_ds */ +#endif +#ifndef T_SSHFP +# define T_SSHFP 44 /* ns_t_sshfp */ +#endif +#ifndef T_RRSIG +# define T_RRSIG 46 /* ns_t_rrsig */ +#endif +#ifndef T_NSEC +# define T_NSEC 47 /* ns_t_nsec */ +#endif +#ifndef T_DNSKEY +# define T_DNSKEY 48 /* ns_t_dnskey */ +#endif +#ifndef T_TKEY +# define T_TKEY 249 /* ns_t_tkey */ +#endif +#ifndef T_TSIG +# define T_TSIG 250 /* ns_t_tsig */ +#endif +#ifndef T_IXFR +# define T_IXFR 251 /* ns_t_ixfr */ +#endif +#ifndef T_AXFR +# define T_AXFR 252 /* ns_t_axfr */ +#endif +#ifndef T_MAILB +# define T_MAILB 253 /* ns_t_mailb */ +#endif +#ifndef T_MAILA +# define T_MAILA 254 /* ns_t_maila */ +#endif +#ifndef T_ANY +# define T_ANY 255 /* ns_t_any */ +#endif +#ifndef T_ZXFR +# define T_ZXFR 256 /* ns_t_zxfr */ +#endif +#ifndef T_CAA +# define T_CAA 257 /* ns_t_caa */ +#endif +#ifndef T_MAX +# define T_MAX 65536 /* ns_t_max */ +#endif + + +#endif /* ARES_NAMESER_H */ diff --git a/deps/cares/src/ares_nowarn.c b/deps/cares/src/lib/ares_nowarn.c similarity index 100% rename from deps/cares/src/ares_nowarn.c rename to deps/cares/src/lib/ares_nowarn.c diff --git a/deps/cares/src/ares_nowarn.h b/deps/cares/src/lib/ares_nowarn.h similarity index 100% rename from deps/cares/src/ares_nowarn.h rename to deps/cares/src/lib/ares_nowarn.h diff --git a/deps/cares/src/ares_options.c b/deps/cares/src/lib/ares_options.c similarity index 100% rename from deps/cares/src/ares_options.c rename to deps/cares/src/lib/ares_options.c diff --git a/deps/cares/src/lib/ares_parse_a_reply.c b/deps/cares/src/lib/ares_parse_a_reply.c new file mode 100644 index 0000000000..b08ac8760f --- /dev/null +++ b/deps/cares/src/lib/ares_parse_a_reply.c @@ -0,0 +1,209 @@ + +/* 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_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_nameser.h" + +#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_a_reply(const unsigned char *abuf, int alen, + struct hostent **host, + struct ares_addrttl *addrttls, int *naddrttls) +{ + 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; + + memset(&ai, 0, sizeof(ai)); + + status = ares__parse_into_addrinfo2(abuf, alen, &question_hostname, &ai); + if (status != ARES_SUCCESS) + { + ares_free(question_hostname); + + if (naddrttls) + { + *naddrttls = 0; + } + + return status; + } + + hostent = ares_malloc(sizeof(struct hostent)); + if (!hostent) + { + goto enomem; + } + + next = ai.nodes; + while (next) + { + if (next->ai_family == AF_INET) + { + ++naddrs; + } + 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) + { + if(next_cname->alias) + aliases[alias++] = ares_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 = ares_strdup(ai.cnames->name); + ares_free(question_hostname); + } + else + { + hostent->h_name = question_hostname; + } + + hostent->h_aliases = aliases; + hostent->h_addrtype = AF_INET; + hostent->h_length = sizeof(struct in_addr); + + if (naddrs) + { + addrs = ares_malloc(naddrs * sizeof(struct in_addr)); + if (!addrs) + { + goto enomem; + } + + i = 0; + next = ai.nodes; + while (next) + { + if (next->ai_family == AF_INET) + { + hostent->h_addr_list[i] = (char *)&addrs[i]; + memcpy(hostent->h_addr_list[i], + &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr), + sizeof(struct in_addr)); + if (naddrttls && i < *naddrttls) + { + if (next->ai_ttl > cname_ttl) + addrttls[i].ttl = cname_ttl; + else + addrttls[i].ttl = next->ai_ttl; + + memcpy(&addrttls[i].ipaddr, + &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr), + sizeof(struct in_addr)); + } + ++i; + } + next = next->ai_next; + } + if (i == 0) + { + ares_free(addrs); + } + } + + if (host) + { + *host = hostent; + } + else + { + ares_free_hostent(hostent); + } + + if (naddrttls) + { + /* Truncated to at most *naddrttls entries */ + *naddrttls = (naddrs > *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; +} diff --git a/deps/cares/src/lib/ares_parse_aaaa_reply.c b/deps/cares/src/lib/ares_parse_aaaa_reply.c new file mode 100644 index 0000000000..6f4744a8dc --- /dev/null +++ b/deps/cares/src/lib/ares_parse_aaaa_reply.c @@ -0,0 +1,212 @@ + +/* 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 + * 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_nameser.h" + +#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_inet_net_pton.h" +#include "ares_private.h" + +int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, + struct hostent **host, struct ares_addr6ttl *addrttls, + int *naddrttls) +{ + 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; + + memset(&ai, 0, sizeof(ai)); + + status = ares__parse_into_addrinfo2(abuf, alen, &question_hostname, &ai); + if (status != ARES_SUCCESS) + { + ares_free(question_hostname); + + if (naddrttls) + { + *naddrttls = 0; + } + + return status; + } + + hostent = ares_malloc(sizeof(struct hostent)); + if (!hostent) + { + goto enomem; + } + + next = ai.nodes; + while (next) + { + if(next->ai_family == AF_INET6) + { + ++naddrs; + } + 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) + { + if(next_cname->alias) + aliases[alias++] = ares_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 = ares_strdup(ai.cnames->name); + ares_free(question_hostname); + } + else + { + hostent->h_name = question_hostname; + } + + hostent->h_aliases = aliases; + hostent->h_addrtype = AF_INET6; + hostent->h_length = sizeof(struct ares_in6_addr); + + if (naddrs) + { + addrs = ares_malloc(naddrs * sizeof(struct ares_in6_addr)); + if (!addrs) + { + goto enomem; + } + + i = 0; + next = ai.nodes; + while (next) + { + if(next->ai_family == AF_INET6) + { + hostent->h_addr_list[i] = (char*)&addrs[i]; + memcpy(hostent->h_addr_list[i], + &(CARES_INADDR_CAST(struct sockaddr_in6 *, next->ai_addr)->sin6_addr), + sizeof(struct ares_in6_addr)); + if (naddrttls && i < *naddrttls) + { + if(next->ai_ttl > cname_ttl) + addrttls[i].ttl = cname_ttl; + else + addrttls[i].ttl = next->ai_ttl; + + memcpy(&addrttls[i].ip6addr, + &(CARES_INADDR_CAST(struct sockaddr_in6 *, next->ai_addr)->sin6_addr), + sizeof(struct ares_in6_addr)); + } + ++i; + } + next = next->ai_next; + } + + if (i == 0) + { + ares_free(addrs); + } + } + + if (host) + { + *host = hostent; + } + else + { + ares_free_hostent(hostent); + } + + if (naddrttls) + { + /* Truncated to at most *naddrttls entries */ + *naddrttls = (naddrs > *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; +} diff --git a/deps/cares/src/lib/ares_parse_caa_reply.c b/deps/cares/src/lib/ares_parse_caa_reply.c new file mode 100644 index 0000000000..f6d4d3c61f --- /dev/null +++ b/deps/cares/src/lib/ares_parse_caa_reply.c @@ -0,0 +1,199 @@ + +/* Copyright 2020 by <danny.sonnenschein@platynum.ch> + * + * 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_nameser.h" + +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif + +#include "ares.h" +#include "ares_dns.h" +#include "ares_data.h" +#include "ares_private.h" + +int +ares_parse_caa_reply (const unsigned char *abuf, int alen, + struct ares_caa_reply **caa_out) +{ + unsigned int qdcount, ancount, i; + const unsigned char *aptr; + const unsigned char *strptr; + int status, rr_type, rr_class, rr_len; + long len; + char *hostname = NULL, *rr_name = NULL; + struct ares_caa_reply *caa_head = NULL; + struct ares_caa_reply *caa_last = NULL; + struct ares_caa_reply *caa_curr; + + /* Set *caa_out to NULL for all failure cases. */ + *caa_out = 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; + if (ancount == 0) + return ARES_ENODATA; + + /* Expand the name from the question, and skip past the question. */ + aptr = abuf + HFIXEDSZ; + status = ares_expand_name (aptr, abuf, alen, &hostname, &len); + if (status != ARES_SUCCESS) + return status; + + if (aptr + len + QFIXEDSZ > abuf + alen) + { + ares_free (hostname); + return ARES_EBADRESP; + } + aptr += len + QFIXEDSZ; + + /* Examine each answer resource record (RR) in turn. */ + for (i = 0; i < ancount; i++) + { + /* Decode the RR up to the data field. */ + status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); + if (status != ARES_SUCCESS) + { + break; + } + aptr += len; + if (aptr + RRFIXEDSZ > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + 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) + { + status = ARES_EBADRESP; + break; + } + + /* Check if we are really looking at a CAA record */ + if ((rr_class == C_IN || rr_class == C_CHAOS) && rr_type == T_CAA) + { + strptr = aptr; + + /* Allocate storage for this CAA answer appending it to the list */ + caa_curr = ares_malloc_data(ARES_DATATYPE_CAA_REPLY); + if (!caa_curr) + { + status = ARES_ENOMEM; + break; + } + if (caa_last) + { + caa_last->next = caa_curr; + } + else + { + caa_head = caa_curr; + } + caa_last = caa_curr; + if (rr_len < 2) + { + status = ARES_EBADRESP; + break; + } + caa_curr->critical = (int)*strptr++; + caa_curr->plength = (int)*strptr++; + if (caa_curr->plength <= 0 || (int)caa_curr->plength >= rr_len - 2) + { + status = ARES_EBADRESP; + break; + } + caa_curr->property = ares_malloc (caa_curr->plength + 1/* Including null byte */); + if (caa_curr->property == NULL) + { + status = ARES_ENOMEM; + break; + } + memcpy ((char *) caa_curr->property, strptr, caa_curr->plength); + /* Make sure we NULL-terminate */ + caa_curr->property[caa_curr->plength] = 0; + strptr += caa_curr->plength; + + caa_curr->length = rr_len - caa_curr->plength - 2; + if (caa_curr->length <= 0) + { + status = ARES_EBADRESP; + break; + } + caa_curr->value = ares_malloc (caa_curr->length + 1/* Including null byte */); + if (caa_curr->value == NULL) + { + status = ARES_ENOMEM; + break; + } + memcpy ((char *) caa_curr->value, strptr, caa_curr->length); + /* Make sure we NULL-terminate */ + caa_curr->value[caa_curr->length] = 0; + } + + /* Propagate any failures */ + if (status != ARES_SUCCESS) + { + break; + } + + /* Don't lose memory in the next iteration */ + ares_free (rr_name); + rr_name = NULL; + + /* Move on to the next record */ + aptr += rr_len; + } + + if (hostname) + ares_free (hostname); + if (rr_name) + ares_free (rr_name); + + /* clean up on error */ + if (status != ARES_SUCCESS) + { + if (caa_head) + ares_free_data (caa_head); + return status; + } + + /* everything looks fine, return the data */ + *caa_out = caa_head; + + return ARES_SUCCESS; +} diff --git a/deps/cares/src/ares_parse_mx_reply.c b/deps/cares/src/lib/ares_parse_mx_reply.c similarity index 96% rename from deps/cares/src/ares_parse_mx_reply.c rename to deps/cares/src/lib/ares_parse_mx_reply.c index e6336473e0..a497f55873 100644 --- a/deps/cares/src/ares_parse_mx_reply.c +++ b/deps/cares/src/lib/ares_parse_mx_reply.c @@ -26,14 +26,8 @@ #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 + +#include "ares_nameser.h" #include "ares.h" #include "ares_dns.h" diff --git a/deps/cares/src/ares_parse_naptr_reply.c b/deps/cares/src/lib/ares_parse_naptr_reply.c similarity index 94% rename from deps/cares/src/ares_parse_naptr_reply.c rename to deps/cares/src/lib/ares_parse_naptr_reply.c index a14c226a9e..dd984c0fea 100644 --- a/deps/cares/src/ares_parse_naptr_reply.c +++ b/deps/cares/src/lib/ares_parse_naptr_reply.c @@ -26,25 +26,14 @@ #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 + +#include "ares_nameser.h" #include "ares.h" #include "ares_dns.h" #include "ares_data.h" #include "ares_private.h" -/* AIX portability check */ -#ifndef T_NAPTR - #define T_NAPTR 35 /* naming authority pointer */ -#endif - int ares_parse_naptr_reply (const unsigned char *abuf, int alen, struct ares_naptr_reply **naptr_out) diff --git a/deps/cares/src/ares_parse_ns_reply.c b/deps/cares/src/lib/ares_parse_ns_reply.c similarity index 95% rename from deps/cares/src/ares_parse_ns_reply.c rename to deps/cares/src/lib/ares_parse_ns_reply.c index 7bb51429db..47d12994c9 100644 --- a/deps/cares/src/ares_parse_ns_reply.c +++ b/deps/cares/src/lib/ares_parse_ns_reply.c @@ -29,14 +29,8 @@ #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 + +#include "ares_nameser.h" #include "ares.h" #include "ares_dns.h" @@ -68,7 +62,7 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen, /* 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__expand_name_for_response( aptr, abuf, alen, &hostname, &len, 0); if ( status != ARES_SUCCESS ) return status; if ( aptr + len + QFIXEDSZ > abuf + alen ) @@ -91,7 +85,7 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen, 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 ); + status = ares__expand_name_for_response( aptr, abuf, alen, &rr_name, &len, 0); if ( status != ARES_SUCCESS ) break; aptr += len; @@ -116,7 +110,7 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen, { /* Decode the RR data and add it to the nameservers list */ status = ares__expand_name_for_response( aptr, abuf, alen, &rr_data, - &len); + &len, 1); if ( status != ARES_SUCCESS ) { ares_free(rr_name); diff --git a/deps/cares/src/ares_parse_ptr_reply.c b/deps/cares/src/lib/ares_parse_ptr_reply.c similarity index 74% rename from deps/cares/src/ares_parse_ptr_reply.c rename to deps/cares/src/lib/ares_parse_ptr_reply.c index 29e22cb17b..ae78edf195 100644 --- a/deps/cares/src/ares_parse_ptr_reply.c +++ b/deps/cares/src/lib/ares_parse_ptr_reply.c @@ -22,14 +22,8 @@ #ifdef HAVE_NETDB_H # include <netdb.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 + +#include "ares_nameser.h" #ifdef HAVE_STRINGS_H # include <strings.h> @@ -48,7 +42,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, long len; const unsigned char *aptr; char *ptrname, *hostname, *rr_name, *rr_data; - struct hostent *hostent; + struct hostent *hostent = NULL; int aliascnt = 0; int alias_alloc = 8; char ** aliases; @@ -69,7 +63,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, /* Expand the name from the question, and skip past the question. */ aptr = abuf + HFIXEDSZ; - status = ares__expand_name_for_response(aptr, abuf, alen, &ptrname, &len); + status = ares__expand_name_for_response(aptr, abuf, alen, &ptrname, &len, 0); if (status != ARES_SUCCESS) return status; if (aptr + len + QFIXEDSZ > abuf + alen) @@ -90,7 +84,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, 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); + status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len, 0); if (status != ARES_SUCCESS) break; aptr += len; @@ -116,7 +110,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, { /* Decode the RR data and set hostname to it. */ status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data, - &len); + &len, 1); if (status != ARES_SUCCESS) { ares_free(rr_name); @@ -152,7 +146,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, { /* Decode the RR data and replace ptrname with it. */ status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data, - &len); + &len, 1); if (status != ARES_SUCCESS) { ares_free(rr_name); @@ -175,41 +169,54 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, status = ARES_ENODATA; if (status == ARES_SUCCESS) { - /* We got our answer. Allocate memory to build the host entry. */ - hostent = ares_malloc(sizeof(struct hostent)); - if (hostent) - { - hostent->h_addr_list = ares_malloc(2 * sizeof(char *)); - if (hostent->h_addr_list) - { - hostent->h_addr_list[0] = ares_malloc(addrlen); - if (hostent->h_addr_list[0]) - { - hostent->h_aliases = ares_malloc((aliascnt+1) * sizeof (char *)); - if (hostent->h_aliases) - { - /* Fill in the hostent and return successfully. */ - hostent->h_name = hostname; - for (i=0 ; i<aliascnt ; i++) - hostent->h_aliases[i] = aliases[i]; - hostent->h_aliases[aliascnt] = NULL; - hostent->h_addrtype = aresx_sitoss(family); - hostent->h_length = aresx_sitoss(addrlen); - memcpy(hostent->h_addr_list[0], addr, addrlen); - hostent->h_addr_list[1] = NULL; - *host = hostent; - ares_free(aliases); - ares_free(ptrname); - return ARES_SUCCESS; - } - ares_free(hostent->h_addr_list[0]); - } - ares_free(hostent->h_addr_list); - } - ares_free(hostent); - } + /* If we don't reach the end, we must have failed due to out of memory */ status = ARES_ENOMEM; + + /* We got our answer. Allocate memory to build the host entry. */ + hostent = ares_malloc(sizeof(*hostent)); + if (!hostent) + goto fail; + + /* If we don't memset here, cleanups may fail */ + memset(hostent, 0, sizeof(*hostent)); + + hostent->h_addr_list = ares_malloc(2 * sizeof(char *)); + if (!hostent->h_addr_list) + goto fail; + + + if (addr && addrlen) { + hostent->h_addr_list[0] = ares_malloc(addrlen); + if (!hostent->h_addr_list[0]) + goto fail; + } else { + hostent->h_addr_list[0] = NULL; + } + + hostent->h_aliases = ares_malloc((aliascnt+1) * sizeof (char *)); + if (!hostent->h_aliases) + goto fail; + + /* Fill in the hostent and return successfully. */ + hostent->h_name = hostname; + for (i=0 ; i<aliascnt ; i++) + hostent->h_aliases[i] = aliases[i]; + hostent->h_aliases[aliascnt] = NULL; + hostent->h_addrtype = aresx_sitoss(family); + hostent->h_length = aresx_sitoss(addrlen); + if (addr && addrlen) + memcpy(hostent->h_addr_list[0], addr, addrlen); + hostent->h_addr_list[1] = NULL; + *host = hostent; + ares_free(aliases); + ares_free(ptrname); + + return ARES_SUCCESS; } + +fail: + ares_free_hostent(hostent); + for (i=0 ; i<aliascnt ; i++) if (aliases[i]) ares_free(aliases[i]); diff --git a/deps/cares/src/lib/ares_parse_soa_reply.c b/deps/cares/src/lib/ares_parse_soa_reply.c new file mode 100644 index 0000000000..3935eec9db --- /dev/null +++ b/deps/cares/src/lib/ares_parse_soa_reply.c @@ -0,0 +1,179 @@ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2012 Marko Kreen <markokr@gmail.com> + * + * 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_nameser.h" + +#include "ares.h" +#include "ares_dns.h" +#include "ares_data.h" +#include "ares_private.h" + +int +ares_parse_soa_reply(const unsigned char *abuf, int alen, + struct ares_soa_reply **soa_out) +{ + const unsigned char *aptr; + long len; + char *qname = NULL, *rr_name = NULL; + struct ares_soa_reply *soa = NULL; + int qdcount, ancount, qclass; + int status, i, rr_type, rr_class, rr_len; + + if (alen < HFIXEDSZ) + return ARES_EBADRESP; + + /* parse message header */ + qdcount = DNS_HEADER_QDCOUNT(abuf); + ancount = DNS_HEADER_ANCOUNT(abuf); + + if (qdcount != 1) + return ARES_EBADRESP; + if (ancount == 0) + return ARES_EBADRESP; + + aptr = abuf + HFIXEDSZ; + + /* query name */ + status = ares__expand_name_for_response(aptr, abuf, alen, &qname, &len, 0); + if (status != ARES_SUCCESS) + goto failed_stat; + + if (alen <= len + HFIXEDSZ + 1) + goto failed; + aptr += len; + + qclass = DNS_QUESTION_TYPE(aptr); + + /* skip qtype & qclass */ + if (aptr + QFIXEDSZ > abuf + alen) + goto failed; + aptr += QFIXEDSZ; + + /* qclass of SOA with multiple answers */ + if (qclass == T_SOA && ancount > 1) + goto failed; + + /* 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, 0); + if (status != ARES_SUCCESS) + { + ares_free(rr_name); + goto failed_stat; + } + + aptr += len; + if ( aptr + RRFIXEDSZ > abuf + alen ) + { + 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, 0); + 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, 0); + if (status != ARES_SUCCESS) + { + ares_free(rr_name); + goto failed_stat; + } + aptr += len; + + /* 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); + + *soa_out = soa; + + 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: + if (soa) + ares_free_data(soa); + if (qname) + ares_free(qname); + return status; +} diff --git a/deps/cares/src/ares_parse_srv_reply.c b/deps/cares/src/lib/ares_parse_srv_reply.c similarity index 94% rename from deps/cares/src/ares_parse_srv_reply.c rename to deps/cares/src/lib/ares_parse_srv_reply.c index 824ff3aedf..0d8f4d2098 100644 --- a/deps/cares/src/ares_parse_srv_reply.c +++ b/deps/cares/src/lib/ares_parse_srv_reply.c @@ -26,25 +26,14 @@ #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 + +#include "ares_nameser.h" #include "ares.h" #include "ares_dns.h" #include "ares_data.h" #include "ares_private.h" -/* AIX portability check */ -#ifndef T_SRV -# define T_SRV 33 /* server selection */ -#endif - int ares_parse_srv_reply (const unsigned char *abuf, int alen, struct ares_srv_reply **srv_out) diff --git a/deps/cares/src/ares_parse_txt_reply.c b/deps/cares/src/lib/ares_parse_txt_reply.c similarity index 96% rename from deps/cares/src/ares_parse_txt_reply.c rename to deps/cares/src/lib/ares_parse_txt_reply.c index 4856b4cea3..6848a092bb 100644 --- a/deps/cares/src/ares_parse_txt_reply.c +++ b/deps/cares/src/lib/ares_parse_txt_reply.c @@ -26,14 +26,8 @@ #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 + +#include "ares_nameser.h" #ifdef HAVE_STRINGS_H # include <strings.h> @@ -113,7 +107,7 @@ ares__parse_txt_reply (const unsigned char *abuf, int alen, } /* Check if we are really looking at a TXT record */ - if (rr_class == C_IN && rr_type == T_TXT) + if ((rr_class == C_IN || rr_class == C_CHAOS) && rr_type == T_TXT) { /* * There may be multiple substrings in a single TXT record. Each diff --git a/deps/cares/src/ares_platform.c b/deps/cares/src/lib/ares_platform.c similarity index 100% rename from deps/cares/src/ares_platform.c rename to deps/cares/src/lib/ares_platform.c diff --git a/deps/cares/src/ares_platform.h b/deps/cares/src/lib/ares_platform.h similarity index 100% rename from deps/cares/src/ares_platform.h rename to deps/cares/src/lib/ares_platform.h diff --git a/deps/cares/src/ares_private.h b/deps/cares/src/lib/ares_private.h similarity index 80% rename from deps/cares/src/ares_private.h rename to deps/cares/src/lib/ares_private.h index 1990f6902f..09f65062f0 100644 --- a/deps/cares/src/ares_private.h +++ b/deps/cares/src/lib/ares_private.h @@ -50,6 +50,11 @@ #define STATIC_TESTABLE static #endif +/* By using a double cast, we can get rid of the bogus warning of + * warning: cast from 'const struct sockaddr *' to 'const struct sockaddr_in6 *' increases required alignment from 1 to 4 [-Wcast-align] + */ +#define CARES_INADDR_CAST(type, var) ((type)((void *)var)) + #if defined(WIN32) && !defined(WATT32) #define WIN_NS_9X "System\\CurrentControlSet\\Services\\VxD\\MSTCP" @@ -69,6 +74,7 @@ #elif defined(WATT32) #define PATH_RESOLV_CONF "/dev/ENV/etc/resolv.conf" +W32_FUNC const char *_w32_GetHostsFile (void); #elif defined(NETWARE) @@ -350,16 +356,60 @@ int ares__read_line(FILE *fp, char **buf, size_t *bufsize); void ares__free_query(struct query *query); unsigned short ares__generate_new_id(rc4_key* key); struct timeval ares__tvnow(void); +int ares__expand_name_validated(const unsigned char *encoded, + const unsigned char *abuf, + int alen, char **s, long *enclen, + int is_hostname); int ares__expand_name_for_response(const unsigned char *encoded, const unsigned char *abuf, int alen, - char **s, long *enclen); + char **s, long *enclen, int is_hostname); 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; } @@ -370,13 +420,4 @@ void ares__socket_close(ares_channel, ares_socket_t); (c)->sock_state_cb((c)->sock_state_cb_data, (s), (r), (w)); \ } WHILE_FALSE -#ifdef CURLDEBUG -/* This is low-level hard-hacking memory leak tracking and similar. Using the - libcurl lowlevel code from within library is ugly and only works when - c-ares is built and linked with a similarly curldebug-enabled libcurl, - but we do this anyway for convenience. */ -#define HEADER_CURL_SETUP_ONCE_H -#include "../lib/memdebug.h" -#endif - #endif /* __ARES_PRIVATE_H */ diff --git a/deps/cares/src/ares_process.c b/deps/cares/src/lib/ares_process.c similarity index 92% rename from deps/cares/src/ares_process.c rename to deps/cares/src/lib/ares_process.c index df9f290bb1..87329e3588 100644 --- a/deps/cares/src/ares_process.c +++ b/deps/cares/src/lib/ares_process.c @@ -32,14 +32,8 @@ #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 + +#include "ares_nameser.h" #ifdef HAVE_STRINGS_H # include <strings.h> @@ -87,6 +81,7 @@ static int open_udp_socket(ares_channel channel, struct server_state *server); static int same_questions(const unsigned char *qbuf, int qlen, const unsigned char *abuf, int alen); static int same_address(struct sockaddr *sa, struct ares_addr *aa); +static int has_opt_rr(const unsigned char *abuf, int alen); static void end_query(ares_channel channel, struct query *query, int status, unsigned char *abuf, int alen); @@ -608,14 +603,13 @@ static void process_answer(ares_channel channel, unsigned char *abuf, return; packetsz = PACKETSZ; - /* If we use EDNS and server answers with one of these RCODES, the protocol + /* If we use EDNS and server answers with FORMERR without an OPT RR, the protocol * extension is not understood by the responder. We must retry the query - * without EDNS enabled. - */ + * without EDNS enabled. */ if (channel->flags & ARES_FLAG_EDNS) { packetsz = channel->ednspsz; - if (rcode == NOTIMP || rcode == FORMERR || rcode == SERVFAIL) + if (rcode == FORMERR && has_opt_rr(abuf, alen) != 1) { int qlen = (query->tcplen - 2) - EDNSFIXEDSZ; channel->flags ^= ARES_FLAG_EDNS; @@ -1039,30 +1033,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 +1077,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 +1101,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 +1112,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 +1135,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 +1190,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 +1207,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 +1230,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; } } @@ -1361,13 +1331,13 @@ static int same_address(struct sockaddr *sa, struct ares_addr *aa) { case AF_INET: addr1 = &aa->addrV4; - addr2 = &((struct sockaddr_in *)sa)->sin_addr; + addr2 = &(CARES_INADDR_CAST(struct sockaddr_in *, sa))->sin_addr; if (memcmp(addr1, addr2, sizeof(aa->addrV4)) == 0) return 1; /* match */ break; case AF_INET6: addr1 = &aa->addrV6; - addr2 = &((struct sockaddr_in6 *)sa)->sin6_addr; + addr2 = &(CARES_INADDR_CAST(struct sockaddr_in6 *, sa))->sin6_addr; if (memcmp(addr1, addr2, sizeof(aa->addrV6)) == 0) return 1; /* match */ break; @@ -1378,6 +1348,85 @@ static int same_address(struct sockaddr *sa, struct ares_addr *aa) return 0; /* different */ } +/* search for an OPT RR in the response */ +static int has_opt_rr(const unsigned char *abuf, int alen) +{ + unsigned int qdcount, ancount, nscount, arcount, i; + const unsigned char *aptr; + int status; + + if (alen < HFIXEDSZ) + return -1; + + /* Parse the answer header. */ + qdcount = DNS_HEADER_QDCOUNT(abuf); + ancount = DNS_HEADER_ANCOUNT(abuf); + nscount = DNS_HEADER_NSCOUNT(abuf); + arcount = DNS_HEADER_ARCOUNT(abuf); + + aptr = abuf + HFIXEDSZ; + + /* skip the questions */ + for (i = 0; i < qdcount; i++) + { + char* name; + long len; + status = ares_expand_name(aptr, abuf, alen, &name, &len); + if (status != ARES_SUCCESS) + return -1; + ares_free_string(name); + if (aptr + len + QFIXEDSZ > abuf + alen) + return -1; + aptr += len + QFIXEDSZ; + } + + /* skip the ancount and nscount */ + for (i = 0; i < ancount + nscount; i++) + { + char* name; + long len; + int dlen; + status = ares_expand_name(aptr, abuf, alen, &name, &len); + if (status != ARES_SUCCESS) + return -1; + ares_free_string(name); + if (aptr + len + RRFIXEDSZ > abuf + alen) + return -1; + aptr += len; + dlen = DNS_RR_LEN(aptr); + aptr += RRFIXEDSZ; + if (aptr + dlen > abuf + alen) + return -1; + aptr += dlen; + } + + /* search for rr type (41) - opt */ + for (i = 0; i < arcount; i++) + { + char* name; + long len; + int dlen; + status = ares_expand_name(aptr, abuf, alen, &name, &len); + if (status != ARES_SUCCESS) + return -1; + ares_free_string(name); + if (aptr + len + RRFIXEDSZ > abuf + alen) + return -1; + aptr += len; + + if (DNS_RR_TYPE(aptr) == T_OPT) + return 1; + + dlen = DNS_RR_LEN(aptr); + aptr += RRFIXEDSZ; + if (aptr + dlen > abuf + alen) + return -1; + aptr += dlen; + } + + return 0; +} + static void end_query (ares_channel channel, struct query *query, int status, unsigned char *abuf, int alen) { @@ -1464,7 +1513,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); diff --git a/deps/cares/src/ares_query.c b/deps/cares/src/lib/ares_query.c similarity index 96% rename from deps/cares/src/ares_query.c rename to deps/cares/src/lib/ares_query.c index b38b8a6c22..508274db36 100644 --- a/deps/cares/src/ares_query.c +++ b/deps/cares/src/lib/ares_query.c @@ -19,14 +19,8 @@ #ifdef HAVE_NETINET_IN_H # include <netinet/in.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 + +#include "ares_nameser.h" #include "ares.h" #include "ares_dns.h" @@ -45,7 +39,7 @@ static void rc4(rc4_key* key, unsigned char *buffer_ptr, int buffer_len) unsigned char y; unsigned char* state; unsigned char xorIndex; - short counter; + int counter; x = key->x; y = key->y; diff --git a/deps/cares/src/ares_search.c b/deps/cares/src/lib/ares_search.c similarity index 95% rename from deps/cares/src/ares_search.c rename to deps/cares/src/lib/ares_search.c index 001c3482a7..c4b0424f5b 100644 --- a/deps/cares/src/ares_search.c +++ b/deps/cares/src/lib/ares_search.c @@ -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; diff --git a/deps/cares/src/ares_send.c b/deps/cares/src/lib/ares_send.c similarity index 95% rename from deps/cares/src/ares_send.c rename to deps/cares/src/lib/ares_send.c index f4f1f95119..75ba9e4cc6 100644 --- a/deps/cares/src/ares_send.c +++ b/deps/cares/src/lib/ares_send.c @@ -19,14 +19,8 @@ #ifdef HAVE_NETINET_IN_H # include <netinet/in.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 + +#include "ares_nameser.h" #include "ares.h" #include "ares_dns.h" diff --git a/deps/cares/src/ares_setup.h b/deps/cares/src/lib/ares_setup.h similarity index 95% rename from deps/cares/src/ares_setup.h rename to deps/cares/src/lib/ares_setup.h index 4df796116a..6ad2cee6a8 100644 --- a/deps/cares/src/ares_setup.h +++ b/deps/cares/src/lib/ares_setup.h @@ -178,8 +178,11 @@ /* * Android does have the arpa/nameser.h header which is detected by configure * but it appears to be empty with recent NDK r7b / r7c, so we undefine here. + * z/OS does have the arpa/nameser.h header which is detected by configure + * but it is not fully implemented and missing identifiers, so udefine here. */ -#if (defined(ANDROID) || defined(__ANDROID__)) && defined(HAVE_ARPA_NAMESER_H) +#if (defined(ANDROID) || defined(__ANDROID__) || defined(__MVS__)) && \ + defined(HAVE_ARPA_NAMESER_H) # undef HAVE_ARPA_NAMESER_H #endif diff --git a/deps/cares/src/ares_strcasecmp.c b/deps/cares/src/lib/ares_strcasecmp.c similarity index 100% rename from deps/cares/src/ares_strcasecmp.c rename to deps/cares/src/lib/ares_strcasecmp.c diff --git a/deps/cares/src/ares_strcasecmp.h b/deps/cares/src/lib/ares_strcasecmp.h similarity index 100% rename from deps/cares/src/ares_strcasecmp.h rename to deps/cares/src/lib/ares_strcasecmp.h diff --git a/deps/cares/src/ares_strdup.c b/deps/cares/src/lib/ares_strdup.c similarity index 100% rename from deps/cares/src/ares_strdup.c rename to deps/cares/src/lib/ares_strdup.c diff --git a/deps/cares/src/ares_strdup.h b/deps/cares/src/lib/ares_strdup.h similarity index 100% rename from deps/cares/src/ares_strdup.h rename to deps/cares/src/lib/ares_strdup.h diff --git a/deps/cares/src/ares_strerror.c b/deps/cares/src/lib/ares_strerror.c similarity index 100% rename from deps/cares/src/ares_strerror.c rename to deps/cares/src/lib/ares_strerror.c diff --git a/deps/cares/src/ares_strsplit.c b/deps/cares/src/lib/ares_strsplit.c similarity index 98% rename from deps/cares/src/ares_strsplit.c rename to deps/cares/src/lib/ares_strsplit.c index b57a30f2a9..97b4e5d5bb 100644 --- a/deps/cares/src/ares_strsplit.c +++ b/deps/cares/src/lib/ares_strsplit.c @@ -13,6 +13,10 @@ * without express or implied warranty. */ +#if defined(__MVS__) +#include <strings.h> +#endif + #include "ares_setup.h" #include "ares_strsplit.h" #include "ares.h" diff --git a/deps/cares/src/ares_strsplit.h b/deps/cares/src/lib/ares_strsplit.h similarity index 99% rename from deps/cares/src/ares_strsplit.h rename to deps/cares/src/lib/ares_strsplit.h index da286a9aef..e00fd14dd5 100644 --- a/deps/cares/src/ares_strsplit.h +++ b/deps/cares/src/lib/ares_strsplit.h @@ -40,3 +40,4 @@ void ares_strsplit_free(char **elms, size_t num_elm); #endif /* HEADER_CARES_STRSPLIT_H */ + diff --git a/deps/cares/src/ares_timeout.c b/deps/cares/src/lib/ares_timeout.c similarity index 100% rename from deps/cares/src/ares_timeout.c rename to deps/cares/src/lib/ares_timeout.c diff --git a/deps/cares/src/ares_version.c b/deps/cares/src/lib/ares_version.c similarity index 100% rename from deps/cares/src/ares_version.c rename to deps/cares/src/lib/ares_version.c diff --git a/deps/cares/src/ares_writev.c b/deps/cares/src/lib/ares_writev.c similarity index 100% rename from deps/cares/src/ares_writev.c rename to deps/cares/src/lib/ares_writev.c diff --git a/deps/cares/src/ares_writev.h b/deps/cares/src/lib/ares_writev.h similarity index 100% rename from deps/cares/src/ares_writev.h rename to deps/cares/src/lib/ares_writev.h diff --git a/deps/cares/src/bitncmp.c b/deps/cares/src/lib/bitncmp.c similarity index 100% rename from deps/cares/src/bitncmp.c rename to deps/cares/src/lib/bitncmp.c diff --git a/deps/cares/src/bitncmp.h b/deps/cares/src/lib/bitncmp.h similarity index 100% rename from deps/cares/src/bitncmp.h rename to deps/cares/src/lib/bitncmp.h diff --git a/deps/cares/src/config-win32.h b/deps/cares/src/lib/config-win32.h similarity index 100% rename from deps/cares/src/config-win32.h rename to deps/cares/src/lib/config-win32.h diff --git a/deps/cares/src/inet_net_pton.c b/deps/cares/src/lib/inet_net_pton.c similarity index 98% rename from deps/cares/src/inet_net_pton.c rename to deps/cares/src/lib/inet_net_pton.c index af1a534a05..840de50652 100644 --- a/deps/cares/src/inet_net_pton.c +++ b/deps/cares/src/lib/inet_net_pton.c @@ -24,14 +24,8 @@ #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 + +#include "ares_nameser.h" #include "ares.h" #include "ares_ipv6.h" diff --git a/deps/cares/src/inet_ntop.c b/deps/cares/src/lib/inet_ntop.c similarity index 97% rename from deps/cares/src/inet_ntop.c rename to deps/cares/src/lib/inet_ntop.c index 1935a871ce..6645c0a467 100644 --- a/deps/cares/src/inet_ntop.c +++ b/deps/cares/src/lib/inet_ntop.c @@ -23,14 +23,8 @@ #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 + +#include "ares_nameser.h" #include "ares.h" #include "ares_ipv6.h" diff --git a/deps/cares/include/nameser.h b/deps/cares/src/lib/nameser.h similarity index 97% rename from deps/cares/include/nameser.h rename to deps/cares/src/lib/nameser.h index a0302fd398..d6c192c58f 100644 --- a/deps/cares/include/nameser.h +++ b/deps/cares/src/lib/nameser.h @@ -88,6 +88,7 @@ typedef enum __ns_type { ns_t_maila = 254, /* Transfer mail agent records. */ ns_t_any = 255, /* Wildcard match. */ ns_t_zxfr = 256, /* BIND-specific, nonstandard. */ + ns_t_caa = 257, /* Certification Authority Authorization. */ ns_t_max = 65536 } ns_type; @@ -208,4 +209,9 @@ typedef enum __ns_rcode { #endif /* HAVE_ARPA_NAMESER_COMPAT_H */ +/* Android's bionic arpa/nameser_compat.h, nor glibc versions prior to 2.25 have T_OPT defined */ +#ifndef T_OPT +# define T_OPT ns_t_opt +#endif + #endif /* ARES_NAMESER_H */ diff --git a/deps/cares/src/setup_once.h b/deps/cares/src/lib/setup_once.h similarity index 100% rename from deps/cares/src/setup_once.h rename to deps/cares/src/lib/setup_once.h diff --git a/deps/cares/src/windows_port.c b/deps/cares/src/lib/windows_port.c similarity index 100% rename from deps/cares/src/windows_port.c rename to deps/cares/src/lib/windows_port.c diff --git a/deps/cares/src/ares_getopt.c b/deps/cares/src/tools/ares_getopt.c similarity index 100% rename from deps/cares/src/ares_getopt.c rename to deps/cares/src/tools/ares_getopt.c diff --git a/deps/cares/src/ares_getopt.h b/deps/cares/src/tools/ares_getopt.h similarity index 100% rename from deps/cares/src/ares_getopt.h rename to deps/cares/src/tools/ares_getopt.h
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor